From 3a6776df95127f250618ece946614364b455e345 Mon Sep 17 00:00:00 2001 From: prakashUXtech Date: Thu, 13 Aug 2026 14:06:45 +0530 Subject: [PATCH] ci: add gofmt, vet, build and test gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This repo had no workflows, so nothing checked formatting, vet, build or tests on a pull request. Each step was measured against origin/main before being added, so the gate starts green instead of red: vet, build and tests were already clean; gofmt flagged 7 files, fixed by gofmt -w here. That diff is whitespace only — git diff -w against the parent is empty. Sticks to the Go toolchain's own checks rather than a third-party linter, so there's nothing extra to install or keep pinned. --- .github/workflows/ci.yml | 53 +++++++++++++++++++++++++++++++++++++ convo.go | 12 ++++----- examples/small/go/config.go | 2 +- examples/small/go/models.go | 6 ++--- glossary_test.go | 10 +++---- longmemeval_errors_test.go | 14 +++++----- longmemeval_test.go | 40 ++++++++++++++-------------- vsearch_test.go | 4 +-- 8 files changed, 97 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e58614a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +# .github/workflows/ci.yml +# Created 2026-08-13: first CI gate for this repo. Until now kb-go had no +# workflows at all — nothing checked formatting, vet, build, or tests on a PR. +# Every step was measured against origin/main before being added: vet clean, +# build clean, tests passing. gofmt flagged 7 files, fixed by `gofmt -w` in this +# same commit so the gate starts green rather than red. Kept to the Go +# toolchain's own checks — no third-party linter — so there is nothing extra to +# install or keep in sync. +name: CI + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + - name: gofmt + run: | + unformatted=$(gofmt -l .) + if [ -n "$unformatted" ]; then + echo "::error::These files are not gofmt-formatted. Run: gofmt -w ." + echo "$unformatted" + exit 1 + fi + + - name: go vet + run: go vet ./... + + - name: Build + run: go build ./... + + - name: Test + run: go test ./... diff --git a/convo.go b/convo.go index 6b56809..0527cd8 100644 --- a/convo.go +++ b/convo.go @@ -782,9 +782,9 @@ func cmdConvoSearch(args []string) { results := bm25Search(convoArticles, query, limit) if jsonOut { type result struct { - ID string `json:"id"` - Title string `json:"title"` - Summary string `json:"summary"` + ID string `json:"id"` + Title string `json:"title"` + Summary string `json:"summary"` Concepts []string `json:"concepts"` } var out []result @@ -826,9 +826,9 @@ func cmdConvoList(args []string) { if jsonOut { type item struct { - ID string `json:"id"` - Title string `json:"title"` - Summary string `json:"summary"` + ID string `json:"id"` + Title string `json:"title"` + Summary string `json:"summary"` Concepts []string `json:"concepts"` } var out []item diff --git a/examples/small/go/config.go b/examples/small/go/config.go index 8c3196a..52ff18b 100644 --- a/examples/small/go/config.go +++ b/examples/small/go/config.go @@ -71,7 +71,7 @@ func (c *Config) Validate() error { // Sentinel errors for configuration validation. var ( - ErrInvalidPort = &ConfigError{Field: "port", Message: "must be between 1 and 65535"} + ErrInvalidPort = &ConfigError{Field: "port", Message: "must be between 1 and 65535"} ErrMissingDatabase = &ConfigError{Field: "database_url", Message: "is required"} ) diff --git a/examples/small/go/models.go b/examples/small/go/models.go index 5157042..10b4e43 100644 --- a/examples/small/go/models.go +++ b/examples/small/go/models.go @@ -17,9 +17,9 @@ const ( // Priority levels. const ( - PriorityLow = 1 - PriorityMedium = 2 - PriorityHigh = 3 + PriorityLow = 1 + PriorityMedium = 2 + PriorityHigh = 3 PriorityCritical = 4 ) diff --git a/glossary_test.go b/glossary_test.go index fcf0ff4..45be8c1 100644 --- a/glossary_test.go +++ b/glossary_test.go @@ -144,7 +144,7 @@ func TestIsGlossarySource(t *testing.T) { {"docs/glossary/soul.md", true}, {"docs/wiki/glossary/ripple.md", true}, {"src/pocket.go", false}, - {"glossary.md", false}, // not inside a glossary/ dir + {"glossary.md", false}, // not inside a glossary/ dir {"glossaries/pocket.md", false}, // plural — distinct dirname {"", false}, } @@ -582,8 +582,8 @@ func containsIssue(issues []string, needle string) bool { // and the contract conversation surfaces in code review rather than a buried // runtime mismatch. var ( - _ func(string, io.Writer) error = glossaryList - _ func(string, string, io.Writer) error = glossaryShow - _ func(string) ([]string, error) = glossaryValidate - _ func(string) bool = isGlossarySource + _ func(string, io.Writer) error = glossaryList + _ func(string, string, io.Writer) error = glossaryShow + _ func(string) ([]string, error) = glossaryValidate + _ func(string) bool = isGlossarySource ) diff --git a/longmemeval_errors_test.go b/longmemeval_errors_test.go index 445eb4c..1b7afca 100644 --- a/longmemeval_errors_test.go +++ b/longmemeval_errors_test.go @@ -11,13 +11,13 @@ import ( ) type MissedQuestion struct { - ID string `json:"id"` - Type string `json:"type"` - Question string `json:"question"` - TopRanked string `json:"top_ranked_session"` - CorrectIDs []string `json:"correct_ids"` - CorrectRank int `json:"correct_rank"` // -1 if not found in any rank - InTop10 bool `json:"in_top_10"` + ID string `json:"id"` + Type string `json:"type"` + Question string `json:"question"` + TopRanked string `json:"top_ranked_session"` + CorrectIDs []string `json:"correct_ids"` + CorrectRank int `json:"correct_rank"` // -1 if not found in any rank + InTop10 bool `json:"in_top_10"` } func TestLongMemEval_ErrorAnalysis(t *testing.T) { diff --git a/longmemeval_test.go b/longmemeval_test.go index ed0fd1a..4a5f60f 100644 --- a/longmemeval_test.go +++ b/longmemeval_test.go @@ -23,15 +23,15 @@ import ( // --- LongMemEval data structures --- type LMEQuestion struct { - QuestionID string `json:"question_id"` - QuestionType string `json:"question_type"` - Question string `json:"question"` - Answer json.RawMessage `json:"answer"` - QuestionDate string `json:"question_date"` - HaystackDates []string `json:"haystack_dates"` - HaystackSessionIDs []string `json:"haystack_session_ids"` - HaystackSessions [][]LMETurn `json:"haystack_sessions"` - AnswerSessionIDs []string `json:"answer_session_ids"` + QuestionID string `json:"question_id"` + QuestionType string `json:"question_type"` + Question string `json:"question"` + Answer json.RawMessage `json:"answer"` + QuestionDate string `json:"question_date"` + HaystackDates []string `json:"haystack_dates"` + HaystackSessionIDs []string `json:"haystack_session_ids"` + HaystackSessions [][]LMETurn `json:"haystack_sessions"` + AnswerSessionIDs []string `json:"answer_session_ids"` } type LMETurn struct { @@ -284,11 +284,11 @@ func TestLongMemEval_ExportRankings(t *testing.T) { } type QuestionRanking struct { - QuestionID string `json:"question_id"` - Question string `json:"question"` - QType string `json:"question_type"` - CorrectIDs []string `json:"correct_ids"` - BM25Top15 []string `json:"bm25_top15"` + QuestionID string `json:"question_id"` + Question string `json:"question"` + QType string `json:"question_type"` + CorrectIDs []string `json:"correct_ids"` + BM25Top15 []string `json:"bm25_top15"` SessionDocs map[string]string `json:"session_docs"` } @@ -321,11 +321,11 @@ func TestLongMemEval_ExportRankings(t *testing.T) { } rankings = append(rankings, QuestionRanking{ - QuestionID: q.QuestionID, - Question: q.Question, - QType: q.QuestionType, - CorrectIDs: q.AnswerSessionIDs, - BM25Top15: top15, + QuestionID: q.QuestionID, + Question: q.Question, + QType: q.QuestionType, + CorrectIDs: q.AnswerSessionIDs, + BM25Top15: top15, SessionDocs: docMap, }) } @@ -350,7 +350,7 @@ func runBenchmark(t *testing.T, name string, questions []LMEQuestion, ranker ran t.Helper() ks := []int{1, 3, 5, 10} - hits := make(map[int]int) // k -> hit count + hits := make(map[int]int) // k -> hit count typeHits := make(map[string]map[int]int) // type -> k -> hits typeCounts := make(map[string]int) diff --git a/vsearch_test.go b/vsearch_test.go index 94e9ee7..4bab18f 100644 --- a/vsearch_test.go +++ b/vsearch_test.go @@ -230,7 +230,7 @@ func BenchmarkVectorSearch_1k_128d(b *testing.B) { for i := 0; i < 1000; i++ { v := make([]float32, 128) for j := range v { - v[j] = float32((i*7 + j*13) % 100) * 0.01 + v[j] = float32((i*7+j*13)%100) * 0.01 } idx.Add(string(rune(i)), v) } @@ -249,7 +249,7 @@ func BenchmarkVectorSearch_10k_384d(b *testing.B) { for i := 0; i < 10000; i++ { v := make([]float32, 384) for j := range v { - v[j] = float32((i*7 + j*13) % 100) * 0.01 + v[j] = float32((i*7+j*13)%100) * 0.01 } idx.Add(string(rune(i)), v) }