Skip to content

Commit 70ecc8c

Browse files
authored
Merge pull request #107 from DFanso/dev
Add: CI test workflow and build dependencies
2 parents 967e042 + ec65aa7 commit 70ecc8c

File tree

9 files changed

+198
-66
lines changed

9 files changed

+198
-66
lines changed

.github/workflows/build-and-release.yml

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,49 @@ jobs:
4141
echo "New tag: ${{ steps.tag_version.outputs.new_tag }}"
4242
echo "Tag created: ${{ steps.tag_version.outputs.new_tag != '' }}"
4343
44+
test:
45+
name: Test
46+
permissions:
47+
contents: read
48+
runs-on: ubuntu-latest
49+
needs: auto-tag
50+
# Always run tests, even if auto-tag was skipped
51+
if: always() && (needs.auto-tag.result == 'success' || needs.auto-tag.result == 'skipped')
52+
53+
steps:
54+
- name: Checkout code
55+
uses: actions/checkout@v4
56+
57+
- name: Set up Go
58+
uses: actions/setup-go@v5
59+
with:
60+
go-version: '1.23' # Use the appropriate Go version for your project
61+
62+
- name: Get dependencies
63+
run: go mod download
64+
65+
- name: Auto-format code
66+
run: |
67+
# Auto-format all Go files
68+
gofmt -s -w .
69+
70+
# Check if any files were formatted
71+
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
72+
echo "Some files were auto-formatted in the build process."
73+
git diff --name-only
74+
fi
75+
76+
- name: Run tests
77+
run: go test -v ./...
78+
4479
build:
4580
name: Build Go Binary
4681
permissions:
4782
contents: read
4883
runs-on: ${{ matrix.os }}
49-
needs: auto-tag
50-
# Always run build, even if auto-tag was skipped (e.g., for tag pushes)
51-
if: always() && (needs.auto-tag.result == 'success' || needs.auto-tag.result == 'skipped')
84+
needs: [auto-tag, test]
85+
# Only build if tests passed
86+
if: always() && (needs.auto-tag.result == 'success' || needs.auto-tag.result == 'skipped') && needs.test.result == 'success'
5287
strategy:
5388
matrix:
5489
os: [ubuntu-latest, windows-latest, macos-latest]

.github/workflows/test.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Test
2+
permissions:
3+
contents: read
4+
5+
on:
6+
push:
7+
branches: [ main, develop ]
8+
pull_request:
9+
branches: [ main, develop ]
10+
11+
jobs:
12+
test:
13+
name: Test
14+
runs-on: ubuntu-latest
15+
16+
strategy:
17+
matrix:
18+
go-version: ['1.21', '1.22', '1.23']
19+
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Go
25+
uses: actions/setup-go@v5
26+
with:
27+
go-version: ${{ matrix.go-version }}
28+
29+
- name: Cache Go modules
30+
uses: actions/cache@v4
31+
with:
32+
path: |
33+
~/.cache/go-build
34+
~/go/pkg/mod
35+
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
36+
restore-keys: |
37+
${{ runner.os }}-go-${{ matrix.go-version }}-
38+
39+
- name: Download dependencies
40+
run: go mod download
41+
42+
- name: Verify dependencies
43+
run: go mod verify
44+
45+
- name: Run go vet
46+
run: go vet ./...
47+
48+
- name: Run go fmt
49+
run: |
50+
# Auto-format all Go files
51+
gofmt -s -w .
52+
53+
# Check if any files were formatted (would indicate pre-existing formatting issues)
54+
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
55+
echo "Some files were auto-formatted. Consider running 'gofmt -s -w .' locally before committing."
56+
git diff --name-only
57+
fi
58+
59+
# Final check to ensure all files are properly formatted
60+
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
61+
echo "The following files are still not formatted after auto-format:"
62+
gofmt -s -l .
63+
exit 1
64+
fi
65+
66+
- name: Run tests
67+
run: go test -v -race -coverprofile=coverage.out ./...
68+
69+
- name: Run tests with short mode
70+
run: go test -v -short ./...
71+
72+
- name: Upload coverage to Codecov
73+
uses: codecov/codecov-action@v4
74+
with:
75+
file: ./coverage.out
76+
flags: unittests
77+
name: codecov-umbrella
78+
fail_ci_if_error: false
79+
80+
- name: Generate coverage report
81+
run: go tool cover -html=coverage.out -o coverage.html
82+
83+
- name: Upload coverage report
84+
uses: actions/upload-artifact@v4
85+
with:
86+
name: coverage-report-go${{ matrix.go-version }}
87+
path: coverage.html
88+
89+
test-build:
90+
name: Test Build
91+
runs-on: ubuntu-latest
92+
needs: test
93+
94+
steps:
95+
- name: Checkout code
96+
uses: actions/checkout@v4
97+
98+
- name: Set up Go
99+
uses: actions/setup-go@v5
100+
with:
101+
go-version: '1.23'
102+
103+
- name: Download dependencies
104+
run: go mod download
105+
106+
- name: Build
107+
run: go build -v -o commit ./cmd/commit-msg
108+
109+
- name: Verify binary
110+
run: ./commit --help || true

cmd/cli/llmSetup.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import (
99
"github.com/manifoldco/promptui"
1010
)
1111

12-
13-
1412
// SetupLLM walks the user through selecting an LLM provider and storing the
1513
// corresponding API key or endpoint configuration.
1614
func SetupLLM(Store *store.StoreMethods) error {

cmd/cli/root.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
var Store *store.StoreMethods
1212

1313
//Initailize store
14-
func StoreInit(sm *store.StoreMethods){
14+
func StoreInit(sm *store.StoreMethods) {
1515
Store = sm
1616
}
1717

@@ -92,7 +92,7 @@ func init() {
9292

9393
// Cobra also supports local flags, which will only run
9494
// when this action is called directly.
95-
95+
9696
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
9797

9898
// Add --dry-run and --auto as persistent flags so they show in top-level help

cmd/cli/store/store.go

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,33 @@ import (
1414
StoreUtils "github.com/dfanso/commit-msg/utils"
1515
)
1616

17-
18-
1917
type StoreMethods struct {
2018
ring keyring.Keyring
2119
}
2220

2321
//Initializes Keyring instance
24-
func KeyringInit() (*StoreMethods, error){
22+
func KeyringInit() (*StoreMethods, error) {
2523
ring, err := keyring.Open(keyring.Config{
2624
ServiceName: "commit-msg",
2725
})
2826
if err != nil {
2927
return nil, fmt.Errorf("failed to open keyring: %w", err)
3028
}
31-
return &StoreMethods{ring:ring},nil
32-
}
33-
29+
return &StoreMethods{ring: ring}, nil
30+
}
3431

3532
// LLMProvider represents a single stored LLM provider and its credential.
3633
type LLMProvider struct {
3734
LLM types.LLMProvider `json:"model"`
3835
APIKey string `json:"api_key"`
3936
}
4037

41-
4238
// Config describes the on-disk structure for all saved LLM providers.
4339
type Config struct {
44-
Default types.LLMProvider `json:"default"`
45-
LLMProviders []types.LLMProvider `json:"models"`
40+
Default types.LLMProvider `json:"default"`
41+
LLMProviders []types.LLMProvider `json:"models"`
4642
}
4743

48-
4944
// Save persists or updates an LLM provider entry, marking it as the default.
5045
func (s *StoreMethods) Save(LLMConfig LLMProvider) error {
5146

@@ -78,13 +73,12 @@ func (s *StoreMethods) Save(LLMConfig LLMProvider) error {
7873
}
7974
}
8075

81-
8276
// If Model already present in config, update the apiKey
8377
updated := false
8478
for _, p := range cfg.LLMProviders {
8579
if p == LLMConfig.LLM {
8680
err := s.ring.Set(keyring.Item{ //save apiKey using keychain to OS credentials
87-
Key: string(LLMConfig.LLM),
81+
Key: string(LLMConfig.LLM),
8882
Data: []byte(LLMConfig.APIKey),
8983
})
9084
if err != nil {
@@ -98,13 +92,13 @@ func (s *StoreMethods) Save(LLMConfig LLMProvider) error {
9892
// If fresh Model is saved, means model not exists in config file
9993
if !updated {
10094
cfg.LLMProviders = append(cfg.LLMProviders, LLMConfig.LLM)
101-
err := s.ring.Set(keyring.Item{ //save apiKey using keychain to OS credentials
102-
Key: string(LLMConfig.LLM),
103-
Data: []byte(LLMConfig.APIKey),
104-
})
95+
err := s.ring.Set(keyring.Item{ //save apiKey using keychain to OS credentials
96+
Key: string(LLMConfig.LLM),
97+
Data: []byte(LLMConfig.APIKey),
98+
})
10599
if err != nil {
106-
return errors.New("error storing credentials")
107-
}
100+
return errors.New("error storing credentials")
101+
}
108102
}
109103

110104
cfg.Default = LLMConfig.LLM
@@ -117,11 +111,9 @@ func (s *StoreMethods) Save(LLMConfig LLMProvider) error {
117111
return os.WriteFile(configPath, data, 0600)
118112
}
119113

120-
121114
// DefaultLLMKey returns the currently selected default LLM provider, if any.
122115
func (s *StoreMethods) DefaultLLMKey() (*LLMProvider, error) {
123116

124-
125117
var cfg Config
126118
var useModel LLMProvider
127119

@@ -153,10 +145,10 @@ func (s *StoreMethods) DefaultLLMKey() (*LLMProvider, error) {
153145

154146
for i, p := range cfg.LLMProviders {
155147
if p == defaultLLM {
156-
useModel.LLM = cfg.LLMProviders[i] // Fetches default Model from config json
157-
i,err := s.ring.Get(string(useModel.LLM)) //Fetches apiKey from OS credential for default model
148+
useModel.LLM = cfg.LLMProviders[i] // Fetches default Model from config json
149+
i, err := s.ring.Get(string(useModel.LLM)) //Fetches apiKey from OS credential for default model
158150
if err != nil {
159-
return nil,err
151+
return nil, err
160152
}
161153
useModel.APIKey = string(i.Data)
162154
return &useModel, nil
@@ -280,8 +272,8 @@ func (s *StoreMethods) DeleteModel(Model types.LLMProvider) error {
280272
} else {
281273
err := s.ring.Remove(string(Model)) // Removes the apiKey from OS credentials
282274
if err != nil {
283-
return err
284-
}
275+
return err
276+
}
285277
return os.WriteFile(configPath, []byte("{}"), 0600)
286278
}
287279
} else {
@@ -292,7 +284,7 @@ func (s *StoreMethods) DeleteModel(Model types.LLMProvider) error {
292284
newCfg.LLMProviders = append(newCfg.LLMProviders, p)
293285
}
294286
}
295-
287+
296288
err := s.ring.Remove(string(Model)) //Remove the apiKey from OS credentials
297289
if err != nil {
298290
return err
@@ -338,8 +330,8 @@ func (s *StoreMethods) UpdateAPIKey(Model types.LLMProvider, APIKey string) erro
338330
updated := false
339331
for _, p := range cfg.LLMProviders {
340332
if p == Model {
341-
err := s.ring.Set(keyring.Item{ // Update the apiKey in OS credential
342-
Key: string(Model),
333+
err := s.ring.Set(keyring.Item{ // Update the apiKey in OS credential
334+
Key: string(Model),
343335
Data: []byte(APIKey),
344336
})
345337
if err != nil {
@@ -361,4 +353,3 @@ func (s *StoreMethods) UpdateAPIKey(Model types.LLMProvider, APIKey string) erro
361353
return os.WriteFile(configPath, data, 0600)
362354

363355
}
364-

cmd/commit-msg/main.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ import (
99

1010
// main is the entry point of the commit message generator
1111
func main() {
12-
12+
1313
//Initializes the OS credential manager
1414
KeyRing, err := store.KeyringInit()
15-
if err != nil {
16-
log.Fatalf("Failed to initilize Keyring store: %v", err)
17-
}
15+
if err != nil {
16+
log.Fatalf("Failed to initilize Keyring store: %v", err)
17+
}
1818
cmd.StoreInit(KeyRing) //Passes StoreMethods instance to root
1919
cmd.Execute()
20-
}
21-
22-
20+
}

0 commit comments

Comments
 (0)