Skip to content

v0.9.0 compliance: full upgrade against core/go reference#6

Merged
Snider merged 0 commit into
mainfrom
dev
Apr 30, 2026
Merged

v0.9.0 compliance: full upgrade against core/go reference#6
Snider merged 0 commit into
mainfrom
dev

Conversation

@Snider

@Snider Snider commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Brings this repo to verdict: COMPLIANT against the v0.9.0 audit.

🤖 Generated with Claude Code + Codex
Co-Authored-By: Codex noreply@openai.com
Co-Authored-By: Virgil virgil@lethean.io

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved cache write reliability with automatic rollback on write failures for both binary and HTTP caches.
    • Enhanced error messages and handling across cache operations.
  • Chores

    • Updated core dependencies to latest versions.
    • Integrated SonarQube code quality analysis and Woodpecker CI pipeline.

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The pull request introduces continuous integration and code quality configuration alongside a comprehensive refactoring of the cache module. Changes include new CI pipeline definitions, updated dependency versions, hardened binary and HTTP cache write operations, centralised error handling and constants, expanded test coverage, and SonarQube analysis configuration.

Changes

Cohort / File(s) Summary
CI/CD & Code Quality
.woodpecker.yml, sonar-project.properties
Adds Woodpecker CI pipeline with Go lint, test, and SonarQube analysis steps. Introduces SonarQube project configuration targeting Go test patterns and coverage reporting.
Cache Implementation
cache.go
Refactors JSON indentation with dedicated builder and state tracking. Centralises error construction using operation-name and message constants. Restructures invalidation control flow with callback snapshots. Hardens binary and HTTP cache writes with rollback logic on failure. Updates HTTP response record parsing with envelope state detection.
Test Suite
cache_ax7_test.go, cache_test.go
Adds new comprehensive test suite validating cache constructors, path generation, entry encoding/decoding, core cache operations, invalidation mechanisms, HTTP cache persistence, and concurrency. Refactors existing test suite with centralised constants, helper functions for assertions, and improved test structure.
Dependencies
go.mod
Updates dappco.re/go/core and dappco.re/go/io from v0.8.0-alpha.1 to v0.9.0, consolidating to single umbrella module dependency.
Build Configuration
tests/cli/cache/Taskfile.yaml
Adds YAML document separator at file beginning.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'v0.9.0 compliance: full upgrade against core/go reference' accurately reflects the primary objective to achieve v0.9.0 compliance, which is the main purpose of this changeset across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Review rate limit: 2/5 reviews remaining, refill in 29 minutes and 41 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cache_test.go (1)

2967-3145: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

These race tests lock in an unsupported same-key write guarantee.

This block expects concurrent Set/Delete work on the same key to stay race-clean and internally serialised, but the cache contract says callers must synchronise same-key writes themselves. Please keep the concurrency coverage on distinct keys, or add explicit external synchronisation in the test harness.

As per coding guidelines, The Cache struct has no mutex; concurrent reads are safe, but concurrent writes to the same key require external synchronization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cache_test.go` around lines 2967 - 3145, The tests
TestCache_ThreatTOCTOU_ConcurrentSetSameKeyRaceClean and
TestCache_ThreatTOCTOU_ConcurrentGetSetDeleteSameKeyRaceClean incorrectly assume
the Cache serializes concurrent writes to the same key; change the tests to
either (A) use distinct keys per goroutine (e.g. append the worker index to
"race/same" and testRaceMixedKey) so concurrent operations target different
keys, or (B) add explicit external synchronization around same-key mutations
(e.g. a shared sync.Mutex or a per-key lock map used by
runMixedRaceWorker/runMixedRaceOperation) so Set/Delete on the same key are
serialized; update related helpers (runMixedRaceWorker, runMixedRaceOperation,
checkMixedRaceRead) and the final assertions to reflect the chosen approach.
🧹 Nitpick comments (2)
.woodpecker.yml (1)

11-30: ⚡ Quick win

Pin the CI images instead of using latest.

Both golangci/golangci-lint:latest-alpine and sonarsource/sonar-scanner-cli:latest let upstream image changes alter a previously green pipeline with no repo change. Pin explicit tags here so linting and analysis stay reproducible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.woodpecker.yml around lines 11 - 30, Replace the floating image tags in the
CI config by pinning to explicit versions: update the image value for the
golangci lint step (currently "golangci/golangci-lint:latest-alpine") to a
specific released tag (e.g., "golangci/golangci-lint:v1.X.Y-alpine") and update
the sonar step image (currently "sonarsource/sonar-scanner-cli:latest") to a
specific scanner CLI tag (e.g., "sonarsource/sonar-scanner-cli:4.X"), ensuring
the job names "golangci-lint" and "sonar" keep the new pinned image strings so
the pipeline is reproducible.
cache_ax7_test.go (1)

5-11: 🏗️ Heavy lift

Keep this new suite on *testing.T rather than the custom test façade.

The file is built around *T and Assert*/Require*, which diverges from the repository’s test contract for _test.go files. I’d switch the new helpers and cases to *testing.T now, before this style spreads further.

As per coding guidelines, Use testing.T directly in tests, not testify.

Also applies to: 32-52

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cache_ax7_test.go` around lines 5 - 11, The tests are using the repository's
custom test façade and Assert*/Require* calls instead of the standard
*testing.T; update all test helpers, suite types, and test cases (including any
suite struct and methods like SetupTest/TearDownTest and helper functions used
across lines ~32-52) to accept t *testing.T and use testing.T APIs
(t.Errorf/t.Fatalf/t.Helper/t.Cleanup) instead of Assert*/Require*; change each
test function signature to func TestXxx(t *testing.T), update helper signatures
to take t *testing.T, replace assertions with equivalent t.* calls, and remove
reliance on the custom facade so the file uses testing.T directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.woodpecker.yml:
- Around line 1-3: The comment flags that an admin-scoped Sonar token is being
referenced in .woodpecker.yml; replace it with a project-scoped token by
creating a new Sonar token with only "project analysis" permissions in your
Sonar instance, update the CI secret (sonar_token) in Woodpecker to the new
project-scoped value, revoke/rotate the old admin-scoped token, and update the
comment in .woodpecker.yml to reflect the least-privilege token usage so the
sonar analysis step uses only project-scoped credentials.

In `@cache_ax7_test.go`:
- Around line 67-83: The tests TestCache_New_Ugly and
TestCache_NewCacheStorage_Ugly pass nil as the medium which causes cache.New and
cache.NewCacheStorage to use the real filesystem; replace the nil medium with a
mock medium by calling io.NewMockMedium() and pass that into cache.New and
cache.NewCacheStorage so the tests remain backend-agnostic and hermetic (i.e.,
use io.NewMockMedium() instead of nil when calling cache.New and
cache.NewCacheStorage).

---

Outside diff comments:
In `@cache_test.go`:
- Around line 2967-3145: The tests
TestCache_ThreatTOCTOU_ConcurrentSetSameKeyRaceClean and
TestCache_ThreatTOCTOU_ConcurrentGetSetDeleteSameKeyRaceClean incorrectly assume
the Cache serializes concurrent writes to the same key; change the tests to
either (A) use distinct keys per goroutine (e.g. append the worker index to
"race/same" and testRaceMixedKey) so concurrent operations target different
keys, or (B) add explicit external synchronization around same-key mutations
(e.g. a shared sync.Mutex or a per-key lock map used by
runMixedRaceWorker/runMixedRaceOperation) so Set/Delete on the same key are
serialized; update related helpers (runMixedRaceWorker, runMixedRaceOperation,
checkMixedRaceRead) and the final assertions to reflect the chosen approach.

---

Nitpick comments:
In @.woodpecker.yml:
- Around line 11-30: Replace the floating image tags in the CI config by pinning
to explicit versions: update the image value for the golangci lint step
(currently "golangci/golangci-lint:latest-alpine") to a specific released tag
(e.g., "golangci/golangci-lint:v1.X.Y-alpine") and update the sonar step image
(currently "sonarsource/sonar-scanner-cli:latest") to a specific scanner CLI tag
(e.g., "sonarsource/sonar-scanner-cli:4.X"), ensuring the job names
"golangci-lint" and "sonar" keep the new pinned image strings so the pipeline is
reproducible.

In `@cache_ax7_test.go`:
- Around line 5-11: The tests are using the repository's custom test façade and
Assert*/Require* calls instead of the standard *testing.T; update all test
helpers, suite types, and test cases (including any suite struct and methods
like SetupTest/TearDownTest and helper functions used across lines ~32-52) to
accept t *testing.T and use testing.T APIs
(t.Errorf/t.Fatalf/t.Helper/t.Cleanup) instead of Assert*/Require*; change each
test function signature to func TestXxx(t *testing.T), update helper signatures
to take t *testing.T, replace assertions with equivalent t.* calls, and remove
reliance on the custom facade so the file uses testing.T directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 82056975-c372-4c09-b24f-d2612b28d1df

📥 Commits

Reviewing files that changed from the base of the PR and between 7852b8f and 32af9f2.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • .woodpecker.yml
  • cache.go
  • cache_ax7_test.go
  • cache_test.go
  • go.mod
  • sonar-project.properties
  • tests/cli/cache/Taskfile.yaml

Comment thread .woodpecker.yml
Comment on lines +1 to +3
# Woodpecker CI pipeline.
# Server: ci.lthn.sh. Lint + sonar in parallel, both depend only on clone.
# sonar_token is admin-scoped on the Woodpecker server.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use a least-privilege Sonar token here.

Line 3 documents an admin-scoped secret for a step that should only need project analysis rights. That unnecessarily increases the blast radius of any CI or branch compromise; please rotate this to a project-scoped token.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.woodpecker.yml around lines 1 - 3, The comment flags that an admin-scoped
Sonar token is being referenced in .woodpecker.yml; replace it with a
project-scoped token by creating a new Sonar token with only "project analysis"
permissions in your Sonar instance, update the CI secret (sonar_token) in
Woodpecker to the new project-scoped value, revoke/rotate the old admin-scoped
token, and update the comment in .woodpecker.yml to reflect the least-privilege
token usage so the sonar analysis step uses only project-scoped credentials.

Comment thread cache_ax7_test.go
Comment on lines +67 to +83
func TestCache_New_Ugly(t *T) {
dir := t.TempDir()
c, err := cache.New(nil, dir, 0)

AssertNoError(t, err)
AssertNotNil(t, c)
AssertNoError(t, c.Set("agent/defaults", "ready"))
}

func TestCache_NewCacheStorage_Ugly(t *T) {
dir := t.TempDir()
storage, err := cache.NewCacheStorage(nil, dir)

AssertNoError(t, err)
AssertNotNil(t, storage)
AssertNoError(t, storage.Close())
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Don't fall back to coreio.Local in these tests.

Passing nil here routes both cases to the real filesystem, which breaks the repo rule to keep tests on io.NewMockMedium(). Please inject a mock medium explicitly so these cases stay backend-agnostic and hermetic.

As per coding guidelines, Use io.NewMockMedium() for all tests instead of accessing the real filesystem.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cache_ax7_test.go` around lines 67 - 83, The tests TestCache_New_Ugly and
TestCache_NewCacheStorage_Ugly pass nil as the medium which causes cache.New and
cache.NewCacheStorage to use the real filesystem; replace the nil medium with a
mock medium by calling io.NewMockMedium() and pass that into cache.New and
cache.NewCacheStorage so the tests remain backend-agnostic and hermetic (i.e.,
use io.NewMockMedium() instead of nil when calling cache.New and
cache.NewCacheStorage).

@Snider Snider merged commit 32af9f2 into main Apr 30, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant