Skip to content

Commit d1bf315

Browse files
authored
refactor: replace context.TODO() with context.Background() and harden CI/CD (#26)
* refactor: replace context.TODO() with context.Background() and harden CI/CD - Replace all context.TODO() calls in production and test code with context.Background() or proper context propagation - Enable shadow and nilness govet linters; re-enable select staticcheck checks (SA4006, S1011, S1034) - Fix CI coverage threshold comment (50% -> 60%) - Extract markdownlint config to .markdownlint-cli2.jsonc - Pin actions/setup-go to SHA in setup-deps and hawk actions - Change setup-deps default branch from dev to main - Add tracking issue references to all t.Skip() calls * fix: resolve 145 golangci-lint shadow and nilness issues This commit resolves all 145 golangci-lint issues that surfaced when the shadow, nilness, and additional staticcheck checks were enabled: - 142 shadow (govet): renamed inner shadowed variables to context-specific names (statErr, writeErr, unmarshalErr, etc.) - 22 model/provider shadows: renamed to modelName/providerName - 2 nilness tautologies (non-nil != nil): removed redundant nil checks - 1 staticcheck SA4006 (unused value): removed dead assignment No function signatures, exported types, or behavior changed. No linters were disabled or skipped. .golangci.yml is unchanged. Build and lint pass cleanly. The CI lint check on PR #26 will now pass.
1 parent 03109fe commit d1bf315

93 files changed

Lines changed: 386 additions & 372 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-deps/action.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ runs:
1818
GH_TOKEN: ${{ inputs.token }}
1919
run: |
2020
clone_with_retry() {
21-
local repo=$1 dest=$2 branch=${3:-dev}
21+
local repo=$1 dest=$2 branch=${3:-main}
2222
for i in 1 2 3; do
2323
git clone --depth=1 --branch "$branch" "https://x-access-token:${GH_TOKEN}@github.com/GrayCodeAI/${repo}.git" "$dest" && return 0
2424
echo "Retry $i for $repo..." && sleep $((i * 5))
2525
done
2626
echo "Failed to clone $repo after 3 attempts" && return 1
2727
}
2828
mkdir -p external
29-
clone_with_retry eyrie external/eyrie dev
30-
clone_with_retry tok external/tok dev
31-
clone_with_retry yaad external/yaad dev
32-
clone_with_retry inspect external/inspect dev
33-
clone_with_retry sight external/sight dev
34-
clone_with_retry trace external/trace dev
29+
clone_with_retry eyrie external/eyrie main
30+
clone_with_retry tok external/tok main
31+
clone_with_retry yaad external/yaad main
32+
clone_with_retry inspect external/inspect main
33+
clone_with_retry sight external/sight main
34+
clone_with_retry trace external/trace main
3535
3636
- name: Set up Go
37-
uses: actions/setup-go@v5
37+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
3838
with:
3939
go-version: ${{ inputs.go-version }}
4040

.github/workflows/ci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ jobs:
159159
coverage=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%' | tail -1)
160160
echo "Coverage: ${coverage}%"
161161
echo "COVERAGE=${coverage}" >> "$GITHUB_ENV"
162-
- name: Coverage threshold (minimum 50%)
162+
- name: Coverage threshold (minimum 60%)
163163
run: |
164164
if (( $(echo "${COVERAGE} < 60" | bc -l) )); then
165165
echo "::error::Coverage ${COVERAGE}% is below minimum 60%"
@@ -253,7 +253,6 @@ jobs:
253253
- name: Run markdownlint-cli2
254254
run: |
255255
npm install -g markdownlint-cli2
256-
printf '%s\n' '{"config":{"default":true,"line-length":false,"no-inline-html":false,"first-line-h1":false,"no-duplicate-heading":false,"no-emphasis-as-heading":false,"blanks-around-headings":false,"blanks-around-lists":false,"blanks-around-fences":false,"fenced-code-language":false,"table-column-style":false,"no-space-in-emphasis":false,"ol-prefix":false,"link-fragments":false,"blanks-around-tables":false,"table-column-count":false,"single-trailing-newline":false}}' > .markdownlint-cli2.jsonc
257256
markdownlint-cli2 '**/*.md'
258257
259258
# -------------------------------------------------------------------------

.golangci.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ linters:
2121
enable-all: true
2222
disable:
2323
- fieldalignment
24-
- shadow
2524
- unusedwrite
26-
- nilness
2725
staticcheck:
2826
checks:
2927
- all
@@ -32,14 +30,11 @@ linters:
3230
- -ST1020
3331
- -ST1021
3432
- -ST1018
35-
- -SA4006
3633
- -SA5011
3734
- -SA1012
3835
- -SA2001
3936
- -SA4011
4037
- -S1039
41-
- -S1011
42-
- -S1034
4338
- -QF1003
4439
- -QF1011
4540
- -S1008

.markdownlint-cli2.jsonc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"config": {
3+
"default": true,
4+
"line-length": false,
5+
"no-inline-html": false,
6+
"first-line-h1": false,
7+
"no-duplicate-heading": false,
8+
"no-emphasis-as-heading": false,
9+
"blanks-around-headings": false,
10+
"blanks-around-lists": false,
11+
"blanks-around-fences": false,
12+
"fenced-code-language": false,
13+
"table-column-style": false,
14+
"no-space-in-emphasis": false,
15+
"ol-prefix": false,
16+
"link-fragments": false,
17+
"blanks-around-tables": false,
18+
"table-column-count": false,
19+
"single-trailing-newline": false
20+
}
21+
}

cmd/autoinit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestAutoInitRunner_WritesContextFileOnce(t *testing.T) {
3737
}
3838

3939
ctxFile := filepath.Join(root, autoInitContextFile)
40-
if _, err := os.Stat(ctxFile); err != nil {
40+
if _, statErr := os.Stat(ctxFile); statErr != nil {
4141
t.Fatalf("expected context file %s to be written: %v", autoInitContextFile, err)
4242
}
4343

cmd/chat.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,8 @@ func newChatModel(ref *progRef, systemPrompt string, settings hawkconfig.Setting
273273
startup.MarkPhase("newChatModel:configureSession")
274274
syncSessionFromPersistedSelection(sess, settings)
275275
sess.SetLogger(logger.New(io.Discard, logger.Error))
276-
if err := configureSession(sess, settings); err != nil {
277-
return chatModel{}, err
276+
if cfgErr := configureSession(sess, settings); cfgErr != nil {
277+
return chatModel{}, cfgErr
278278
}
279279
startup.EndPhase("newChatModel:configureSession")
280280

@@ -399,15 +399,15 @@ func newChatModel(ref *progRef, systemPrompt string, settings hawkconfig.Setting
399399

400400
// Prefetch live models for the active provider so footer ctx/pricing stay current.
401401
go func() {
402-
provider := effectiveProvider
403-
entries, _ := runtime.ListModels(context.Background(), runtime.ListModelsOpts{ProviderID: provider, Source: runtime.ListSourceAuto})
402+
providerName := effectiveProvider
403+
entries, _ := runtime.ListModels(context.Background(), runtime.ListModelsOpts{ProviderID: providerName, Source: runtime.ListSourceAuto})
404404
opts := configModelOptionsFromEyrie(entries)
405405
if len(opts) > 0 {
406406
modelCacheMu.Lock()
407-
modelCache[provider] = opts
407+
modelCache[providerName] = opts
408408
modelCacheMu.Unlock()
409409
if ref != nil {
410-
ref.Send(modelsFetchedMsg{options: opts, provider: provider})
410+
ref.Send(modelsFetchedMsg{options: opts, provider: providerName})
411411
}
412412
}
413413
}()
@@ -1068,11 +1068,11 @@ func (m chatModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
10681068
}
10691069
m.viewDirty = true
10701070
m.updateViewportContent()
1071-
cmds := []tea.Cmd{compactTickCmd()}
1071+
localCmds := []tea.Cmd{compactTickCmd()}
10721072
if !m.input.Focused() {
1073-
cmds = append(cmds, m.input.Focus())
1073+
localCmds = append(localCmds, m.input.Focus())
10741074
}
1075-
return m, tea.Batch(cmds...)
1075+
return m, tea.Batch(localCmds...)
10761076
}
10771077
return m, nil
10781078

@@ -1306,7 +1306,7 @@ func autoIndexCodegraph() {
13061306
}
13071307

13081308
dbPath := filepath.Join(cwd, ".codegraph", "codegraph.db")
1309-
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
1309+
if _, statErr := os.Stat(dbPath); os.IsNotExist(statErr) {
13101310
return // Not initialized, skip
13111311
}
13121312

@@ -1367,9 +1367,9 @@ func runChat() error {
13671367
ctx, cancel := context.WithCancel(context.Background())
13681368
_ = cancel // will be cancelled when program exits
13691369
go func() {
1370-
ch, err := sess.Stream(ctx)
1371-
if err != nil {
1372-
p.Send(streamErrMsg{err: err})
1370+
ch, streamErr := sess.Stream(ctx)
1371+
if streamErr != nil {
1372+
p.Send(streamErrMsg{err: streamErr})
13731373
return
13741374
}
13751375
pumpStreamEvents(ref, ch)

cmd/chat_commands.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -802,9 +802,9 @@ Generate the recap:`, summary.String())
802802
case "/check":
803803
return m.startPromptCommand("/check", buildCheckPrompt())
804804
case "/design":
805-
parts := strings.Fields(text)
806-
if len(parts) >= 2 {
807-
switch parts[1] {
805+
fields := strings.Fields(text)
806+
if len(fields) >= 2 {
807+
switch fields[1] {
808808
case "screenshot":
809809
path := strings.TrimSpace(strings.TrimPrefix(text, "/design screenshot"))
810810
if path == "" {
@@ -922,11 +922,11 @@ Generate the recap:`, summary.String())
922922
m.messages = append(m.messages, displayMsg{role: "error", content: err.Error()})
923923
return m, nil
924924
}
925-
model, provider := effectiveModelAndProvider(settings)
926-
if provider == "" {
927-
provider = "auto"
925+
modelName, providerName := effectiveModelAndProvider(settings)
926+
if providerName == "" {
927+
providerName = "auto"
928928
}
929-
m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatEcosystemPanel(context.Background(), provider, model)})
929+
m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatEcosystemPanel(context.Background(), providerName, modelName)})
930930
return m, nil
931931
case "/path":
932932
m.messages = append(m.messages, displayMsg{role: "system", content: hawkconfig.FormatDeveloperPathReport(context.Background())})
@@ -1294,11 +1294,11 @@ Generate the recap:`, summary.String())
12941294
return
12951295
}
12961296

1297-
text := strings.TrimSpace(string(transcription))
1298-
if text != "" {
1299-
m.input.SetValue(text)
1297+
transcript := strings.TrimSpace(string(transcription))
1298+
if transcript != "" {
1299+
m.input.SetValue(transcript)
13001300
m.input.CursorEnd()
1301-
m.messages = append(m.messages, displayMsg{role: "system", content: fmt.Sprintf("Voice input: %s", text)})
1301+
m.messages = append(m.messages, displayMsg{role: "system", content: fmt.Sprintf("Voice input: %s", transcript)})
13021302
}
13031303
}()
13041304
}

cmd/chat_config_keys.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ func (m chatModel) configKeyDetailView() string {
3737
mutedStyle := configMutedStyle()
3838
accentStyle := configAccentStyle()
3939
activeStyle := configActiveStyle()
40-
provider := strings.TrimSpace(m.configProvider)
41-
displayName := hawkconfig.GatewayDisplayName(provider)
42-
masked := hawkconfig.MaskCredentialForProvider(context.Background(), provider)
40+
providerName := strings.TrimSpace(m.configProvider)
41+
displayName := hawkconfig.GatewayDisplayName(providerName)
42+
masked := hawkconfig.MaskCredentialForProvider(context.Background(), providerName)
4343

4444
var b strings.Builder
4545
b.WriteString(renderConfigBreadcrumb(displayName+" key") + "\n\n")
4646
b.WriteString(mutedStyle.Render(" Gateway: ") + accentStyle.Render(displayName) + "\n")
4747
b.WriteString(mutedStyle.Render(" Key: ") + activeStyle.Render(masked) + "\n")
4848
b.WriteString(mutedStyle.Render(" Stored in: "+credentialsStoreLabel()) + "\n")
49-
if provider == hawkconfig.ProviderXiaomiTokenPlan {
49+
if providerName == hawkconfig.ProviderXiaomiTokenPlan {
5050
reg := hawkconfig.XiaomiTokenPlanRegionLabel()
5151
if reg == "" {
5252
reg = "(not set — press g)"
@@ -111,61 +111,61 @@ func (m chatModel) clearConfigGatewayKeyRemove() chatModel {
111111
}
112112

113113
func (m chatModel) advanceConfigGatewayKeyRemove() (chatModel, tea.Cmd) {
114-
provider := strings.TrimSpace(m.configKeysPendingRemove)
115-
if provider == "" {
114+
trimmedProvider := strings.TrimSpace(m.configKeysPendingRemove)
115+
if trimmedProvider == "" {
116116
return m, nil
117117
}
118118
if m.configKeysRemoveStep < 2 {
119119
m.configKeysRemoveStep = 2
120-
name := hawkconfig.GatewayDisplayName(provider)
120+
name := hawkconfig.GatewayDisplayName(trimmedProvider)
121121
m.configNotice = configGatewayRemoveNotice(2, name)
122122
return m, nil
123123
}
124124
return m.confirmConfigGatewayKeyRemove()
125125
}
126126

127127
func (m chatModel) confirmConfigGatewayKeyRemove() (chatModel, tea.Cmd) {
128-
provider := strings.TrimSpace(m.configKeysPendingRemove)
129-
if provider == "" {
128+
trimmedProvider := strings.TrimSpace(m.configKeysPendingRemove)
129+
if trimmedProvider == "" {
130130
return m, nil
131131
}
132132
m.configKeysPendingRemove = ""
133133
m.configKeysRemoveStep = 0
134134
m.configSaving = true
135-
m.configNotice = fmt.Sprintf("Removing key for %s…", hawkconfig.GatewayDisplayName(provider))
135+
m.configNotice = fmt.Sprintf("Removing key for %s…", hawkconfig.GatewayDisplayName(trimmedProvider))
136136
if m.configEntry == configEntryKeyView {
137137
m.configEntry = configEntryNone
138138
m.configProvider = ""
139139
}
140-
return m, removeCredentialAsync(provider)
140+
return m, removeCredentialAsync(trimmedProvider)
141141
}
142142

143143
func (m chatModel) handleConfigKeyViewKey(msg tea.KeyMsg) (chatModel, tea.Cmd) {
144-
provider := strings.TrimSpace(m.configProvider)
144+
trimmedProvider := strings.TrimSpace(m.configProvider)
145145
switch msg.Type {
146146
case tea.KeyEsc:
147147
m.configEntry = configEntryNone
148148
m.configProvider = ""
149149
m = m.clearConfigGatewayKeyRemove()
150-
if idx := m.configGatewayRowIndex(provider); idx >= 0 {
150+
if idx := m.configGatewayRowIndex(trimmedProvider); idx >= 0 {
151151
m.configSel = idx
152152
}
153153
return m, nil
154154
case tea.KeyDelete, tea.KeyBackspace:
155-
if provider == "" {
155+
if trimmedProvider == "" {
156156
return m, nil
157157
}
158-
return m.beginConfigGatewayKeyRemove(provider), nil
158+
return m.beginConfigGatewayKeyRemove(trimmedProvider), nil
159159
case tea.KeyEnter:
160160
if m.configKeysPendingRemove != "" {
161161
return m.advanceConfigGatewayKeyRemove()
162162
}
163-
if provider == "" {
163+
if trimmedProvider == "" {
164164
return m, nil
165165
}
166-
return m.startConfigKeyReplace(provider)
166+
return m.startConfigKeyReplace(trimmedProvider)
167167
case tea.KeyRunes:
168-
if provider == hawkconfig.ProviderXiaomiTokenPlan && strings.EqualFold(string(msg.Runes), "g") {
168+
if trimmedProvider == hawkconfig.ProviderXiaomiTokenPlan && strings.EqualFold(string(msg.Runes), "g") {
169169
return m.startConfigXiaomiTokenPlanRegion(), nil
170170
}
171171
default:

0 commit comments

Comments
 (0)