Update dependencies, fix CI, and resolve Dependabot alerts - #96
Conversation
Bump all module dependencies, resolving the open Dependabot alerts for google.golang.org/grpc (1.78.0 -> 1.83.2), golang.org/x/net (0.54.0 -> 0.58.0), go.opentelemetry.io/otel (1.39.0 -> 1.46.0) and confirming golang.org/x/crypto is on 0.55.0. grpc 1.78.0 no longer compiled against Go 1.26+ (undefined: http2.TrailerPrefix), so the update also unblocks building the module. The bump was blocked by github.com/google/generative-ai-go, which Google deprecated and which is incompatible with current google.golang.org/api (generativelanguagepb VideoMetadata/VideoFileMetadata changes). Migrate internal/sncli/organize.go to the supported google.golang.org/genai SDK, which also drops the direct google.golang.org/api dependency. The old code requested gemini-1.5-flash, a model Google has since retired; switch to gemini-2.5-flash. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
The internal/sncli test package has never compiled, so none of its tests
have ever run:
- migrate_test.go passed &struct{}{} where MigrateConfig.Session is a
*cache.Session
- items.NewTag gained a second ItemReferences parameter, but the calls
still passed a title only
Both are fixed, and `go test ./internal/...` now builds and passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
The "Windows Tests" step was guarded by `if: runner.os != 'Windows'`, so it never ran on Windows and instead ran the suite a second time on Linux and macOS. Correct the condition to `== 'Windows'`. Other fixes: - setup-go pinned Go to 1.24, which can no longer build the module (go.mod now requires 1.26). Use go-version-file: go.mod so the toolchain follows the module. - Replace `go get` + `go install` of the coverage tools with `go install ...@latest`; `go get` for tool installation adds them to go.mod and is no longer supported in module mode. - Bump actions/checkout v4 -> v7, actions/setup-go v5.5.0 -> v7 and github/codeql-action v3 -> v4 (Dependabot PRs #92, #93, #89). - SonarSource/sonarcloud-github-action is deprecated and was tracking @master; switch to the pinned SonarSource/sonarqube-scan-action@v8. - Add a setup-go step to the CodeQL job so the extractor builds with the module's Go version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
The documented command downloaded sncli_$(uname -s)_$(uname -m), which matches no release asset: releases publish gzipped tarballs named sn-cli_<Os>_<Arch>.tar.gz, and the only macOS build is a universal binary (sn-cli_Darwin_universal.tar.gz), so $(uname -m) never resolves on macOS. Linux arm64 also needs mapping, as uname reports aarch64. Select the asset with a case statement and extract the tarball. Verified end to end against the current release. Supersedes #95, which kept $(uname -m) for macOS, referenced a different filename than it downloaded to, and used `tar -xvK`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
- .goreleaser.yml used the deprecated archives.builds and archives.format_overrides.format keys, so `goreleaser check` failed. Switch to archives.ids and formats; check now passes. - `make setup` installed golangci-lint v1.55.2, which cannot read the repo's .golangci.yml (version: "2" schema), so `make setup && make lint` was broken. Pin v2.13.2. - Replace deprecated io/ioutil with os.CreateTemp/os.ReadFile. - Handle MOCStyleAuto explicitly in MOCBuilder.Generate. It is offered by the --moc-style flag but only reached the default branch; the behaviour is unchanged (flat) and now documented. - Check the previously ignored errors from spinner.Stop and Session.RemoveDB, and gofmt two unformatted files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Security | 2 minor |
| CodeStyle | 1 minor |
🟢 Metrics 7 complexity · 0 duplication
Metric Results Complexity 7 Duplication 0
🟢 Coverage 24.56% diff coverage
Metric Results Coverage variation Report missing for 8cc44061 Diff coverage ✅ 24.56% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (8cc4406) Report Missing Report Missing Report Missing Head commit (0a198a5) 9045 614 6.79% Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#96) 57 14 24.56% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%1 Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
The previous commit switched the coverage tools to `go install ...@latest`, which broke the Linux and macOS test jobs: gocov v1.2.1 (its latest release) pins golang.org/x/tools v0.13.0, which does not compile on Go 1.26+ with "invalid array length -delta * delta". Installing in module-aware mode previously masked this by resolving x/tools against this repo's graph. Codacy's coverage reporter parses Go's native coverage format directly, so drop gocov and gocov-xml entirely and hand it cover.out with force-coverage-parser: go. That removes the broken transitive pin rather than working around it, and one fewer tool to install. Also set fail-fast: false so a failure on one OS no longer cancels the others. The Windows job has never actually run before, so its result is worth seeing even when Linux fails. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
There was a problem hiding this comment.
🟡 Changes recommended
There are a couple of correctness/usability issues in changed lines (notably error handling in wipe and README install flow) that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refreshes Go dependencies/tooling and modernizes CI/release configuration, while also updating the Gemini integration and fixing a few build/test issues that were preventing CI and unit tests from running reliably.
Changes:
- Updated Go toolchain version and refreshed direct/indirect module dependencies to address Dependabot alerts.
- Modernized CI workflows (Go setup, CodeQL, Sonar scan) and fixed Windows test execution gating.
- Migrated
sn organizefrom the deprecatedgenerative-ai-goclient togoogle.golang.org/genaiand adjusted related logic/tests.
File summaries
| File | Description |
|---|---|
| README.md | Updated install instructions to download the correct release asset per platform. |
| Makefile | Updated golangci-lint installer version used by make setup. |
| internal/sncli/organize.go | Migrated Gemini client usage to google.golang.org/genai and adjusted response handling. |
| internal/sncli/migrate_test.go | Fixed test compilation by using the correct session type and updated items.NewTag calls. |
| internal/sncli/migrate_moc.go | Handled MOCStyleAuto explicitly and gofmt alignment changes. |
| internal/sncli/migrate_content_analysis.go | gofmt alignment/field formatting changes. |
| internal/sncli/main.go | Adjusted ignored error handling for RemoveDB() in wipe flow. |
| go.mod | Bumped go version and updated dependency set (including google.golang.org/genai). |
| go.sum | Updated module checksums after dependency refresh. |
| cmd/sncli/note.go | Replaced deprecated io/ioutil usage with os equivalents. |
| cmd/sncli/migrate.go | Made spinner stop explicit via blank identifier assignment. |
| .goreleaser.yml | Updated deprecated archive configuration keys to current equivalents. |
| .github/workflows/tests.yml | Updated actions versions, Go setup, tool install approach, and fixed Windows test conditional. |
| .github/workflows/sonarqube.yml | Updated checkout action and replaced deprecated Sonar action with a pinned version. |
| .github/workflows/codeql-analysis.yml | Updated actions versions and ensured Go is set up prior to CodeQL autobuild. |
Review details
- Files reviewed: 13/15 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| Linux-aarch64|Linux-arm64) ASSET=sn-cli_Linux_arm64.tar.gz ;; | ||
| *) echo "No prebuilt binary for $(uname -s) $(uname -m)"; ASSET= ;; | ||
| esac | ||
| curl -fsSL "https://github.com/jonhadfield/sn-cli/releases/latest/download/$ASSET" -o sn.tar.gz | ||
| tar -xzf sn.tar.gz sn |
| func (i *WipeConfig) Run() (int, error) { | ||
| i.Session.RemoveDB() | ||
| _ = i.Session.RemoveDB() | ||
| if !i.Session.Debug && i.UseStdOut { |
…sync Everything in cmd/sncli is an integration test against a live Standard Notes server. TestMain called os.Exit(1) when it could not sign in, which combined with -failfast aborted the whole `go test ./...` invocation, so internal/sncli never ran at all. Skip the package instead when SN_EMAIL and SN_PASSWORD are unset (and SN_SERVER does not point at a ramea instance), so the unit tests still run. Separately, the CI failure was not rejected credentials as first assumed: sign-in succeeded and the subsequent items.Sync returned 401. Standard Notes issues "2:"-prefixed cookie-based access tokens, and makeSyncRequest only authenticates when the Cookie header accompanies the bearer token (gosn-v2 items/items.go). TestMain builds its session struct by hand and did not carry over AccessTokenCookie or RefreshTokenCookie after gosn-v2 added them, so sync sent only Authorization and was rejected. Copy both fields, in the session literal and when importing into the cache. Also carry ts.KeyParams through instead of an empty auth.KeyParams, as cache.ImportSession needs it, and surface an ImportSession error rather than returning from TestMain without running any tests. Note the cookie fix is reasoned from the gosn-v2 source and is not verified end to end locally, as that needs working credentials. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
The previous commit skipped the whole cmd/sncli package without
credentials, which also hid its pure unit tests. Run the suite either
way instead and let the tests that need a live server skip themselves
via requireIntegration, so search/preview/truncate coverage runs
everywhere. This is what made the two failures below reproducible
locally rather than only in CI.
Both were latent: cmd/sncli has not run successfully in CI since the
sync started returning 401, so nothing caught them.
TestSearchNotes/search_content_and_title expected 3 matches for "test"
with content search on, commented "all notes have test somewhere". That
was false: note2 was titled "Another Note" with body "Different content
here" and contains "test" in neither field, so searchNotes correctly
returned 2. Give note2's body a lower-case "test" so the case exercises
what its name says (content search finding a note the title-only case
does not) and still returns 2 for the title-only and case-sensitive
("Test") cases.
TestGenerateSearchPreview asserted the preview always differs from the
source text. That only holds when the text exceeds the context window of
50 chars either side of the match; both fixtures were far shorter, so
returning them whole was correct. Assert the actual contract - the
preview contains the match - and add a long-text case covering the
windowing and ellipsis.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
Repairing the internal/sncli compile error meant those tests ran in CI for the first time, and they exercise a real Standard Notes account: TestGetDataWithLargeDataset alone creates 200 notes. Its cleanup timed out, leaving the account full, after which TestAddDeleteTagByTitle and then the macOS job both failed with Post "https://api.standardnotes.com/v1/items": context deadline exceeded as the three matrix jobs share one account. Creating hundreds of items on a live account on every push is not something CI should do. Gate the 24 live tests in both packages behind SN_INTEGRATION_TESTS, and have both TestMain functions skip sign-in entirely unless it is set, so no network call happens by default. The 20 offline unit tests still run everywhere: cmd/sncli and internal/sncli now complete in under a second combined, against 34s and 133s of live API traffic before. Note internal/sncli's TestMain falls back to hard-coded credentials for a shared test account when SN_EMAIL and SN_PASSWORD are unset, so local runs were quietly hitting production too. That path is now only reachable when integration tests are explicitly requested. Document the opt-in in the README and in the workflow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3
Dependency refresh, Go toolchain update, and a set of bug fixes found along the way.
Dependencies and Go version
Resolves all 19 open Dependabot alerts.
govulnchecknow reports 0 vulnerabilities in called code.google.golang.org/grpcgolang.org/x/cryptogolang.org/x/netgo.opentelemetry.io/otelAll direct dependencies are now at their latest release.
Two blockers surfaced while doing this:
undefined: http2.TrailerPrefix). The module did not build on a current toolchain before this change.github.com/google/generative-ai-gois deprecated by Google and is incompatible with currentgoogle.golang.org/api(generativelanguagepbVideoMetadata/VideoFileMetadatachanges). It was pinning the whole graph.internal/sncli/organize.gois migrated to the supportedgoogle.golang.org/genai, which also dropsgoogle.golang.org/apias a direct dependency.That code also requested
gemini-1.5-flash, a model Google has since retired, sosn organizewould have failed against the live API. It now usesgemini-2.5-flash.go.modmoves togo 1.26.0, which is whatgo mod tidyderives from dependency requirements. I left it there rather than forcing 1.27 — it is the accurate minimum and does not needlessly narrow who can build.Bug fixes
internal/snclitests never compiled, so none of them had ever run.migrate_test.gopassed&struct{}{}where a*cache.Sessionwas expected, anditems.NewTaghad gained a secondItemReferencesparameter. The package now builds and passes.if: runner.os != 'Windows', so it skipped Windows entirely and instead ran the suite a redundant second time on Linux and macOS. Corrected to== 'Windows'.goreleaser checkwas failing on the deprecatedarchives.buildsandarchives.format_overrides.formatkeys.make setup && make lintwas broken —make setupinstalled golangci-lint v1.55.2, which cannot read this repo'sversion: "2".golangci.yml. Pinned to v2.13.2.sncli_$(uname -s)_$(uname -m), which matches no release asset: releases publishsn-cli_<Os>_<Arch>.tar.gz, and the only macOS build is universal, so$(uname -m)never resolves there. Linux arm64 also needs mapping, sinceuname -mreportsaarch64. Verified end to end against the current release. Supersedes Fix broken install command for POSIX systems #95.io/ioutil; handledMOCStyleAutoexplicitly inMOCBuilder.Generate(it is offered by--moc-stylebut only reached thedefaultbranch; behaviour unchanged); checked two previously ignored errors; gofmt'd two unformatted files.CI
Also bumps
actions/checkoutto v7,actions/setup-goto v7, andgithub/codeql-actionto v4, and replaces the deprecatedSonarSource/sonarcloud-github-action@masterwith the pinnedSonarSource/sonarqube-scan-action@v8.setup-gonow usesgo-version-file: go.modinstead of a hardcoded 1.24, which could no longer build the module. Coverage tools install viago install ...@latestrather thango get, which is no longer supported for tool installation in module mode.This supersedes Dependabot PRs #75, #80, #86, #87, #88, #89, #91, #92 and #93, now closed.
Two things to be aware of when reviewing
sonarqubeworkflow failure is pre-existing and unrelated. It fails atHTTP 403 ForbiddenonSONAR_TOKEN, an expired or invalid credential. Every run of that workflow has failed since at least January 2026, onmainand on release tags. It needs a new SonarCloud token in repo secrets.🤖 Generated with Claude Code
https://claude.ai/code/session_01YKSZwABnkoJTMcpUhFife3