Skip to content

feat(tool): avoid importing every manifest to resolve tools.<name>.latest#498

Merged
purpleclay merged 1 commit into
mainfrom
492-per-tool-index
Jun 15, 2026
Merged

feat(tool): avoid importing every manifest to resolve tools.<name>.latest#498
purpleclay merged 1 commit into
mainfrom
492-per-tool-index

Conversation

@purpleclay

@purpleclay purpleclay commented Jun 15, 2026

Copy link
Copy Markdown
Owner

closes #492

Summary by CodeRabbit

  • Chores
    • Added auto-generated index.nix compatibility maps for Delve, gofumpt, golangci-lint, gopls, govulncheck, and staticcheck.
    • Updated the manifest/tool-loading workflow and generation process to include and consume the new index-based structure in generated updates.
  • Bug Fixes
    • Improved Go version compatibility resolution by preferring index data, with fallback to legacy manifest entries when needed.
  • Tests
    • Added coverage to verify correct index.nix generation via a golden-file check.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2b8207d2-e28e-4298-808d-e77ecc6401a5

📥 Commits

Reviewing files that changed from the base of the PR and between 9e30453 and 68db957.

📒 Files selected for processing (13)
  • .github/workflows/tools-update.yml
  • internal/cli/goscrape/modproxy/generate.go
  • internal/cli/goscrape/modproxy/index.go
  • internal/cli/goscrape/modproxy/index_test.go
  • internal/cli/goscrape/modproxy/testdata/index.nix.golden
  • lib/mk-tool-set.nix
  • lib/tool-manifests.nix
  • manifests/delve/index.nix
  • manifests/gofumpt/index.nix
  • manifests/golangci-lint/index.nix
  • manifests/gopls/index.nix
  • manifests/govulncheck/index.nix
  • manifests/staticcheck/index.nix

📝 Walkthrough

Walkthrough

Adds a writeIndex function to the modproxy CLI that generates a per-tool index.nix mapping each tool version to its required Go version. The Nix library is updated to load this index as a separate attribute and use it for Go-version compatibility checks instead of importing all individual manifests. Generated index.nix files are added for all tracked tools, and CI is updated to stage the new file.

Changes

Per-tool index.nix generation and consumption

Layer / File(s) Summary
writeIndex implementation and generate.go integration
internal/cli/goscrape/modproxy/index.go, internal/cli/goscrape/modproxy/generate.go, internal/cli/goscrape/modproxy/index_test.go, internal/cli/goscrape/modproxy/testdata/index.nix.golden
index.go implements writeIndex: scans manifest .nix files, extracts the go = "..." requirement via anchored regex, semver-sorts entries descending, renders index.nix from a text/template, and writes it with mode 0644. generate.go calls writeIndex(outputDir) after the per-version .nix files are written. Tests create fake manifests, invoke writeIndex, and assert against the golden file.
Nix library: load index.nix and switch compatibility lookup
lib/tool-manifests.nix, lib/mk-tool-set.nix
tool-manifests.nix excludes index.nix from the versioned manifest set and imports it as a new index attribute per tool. mk-tool-set.nix updates both compatibility predicates (latestCompatible and compatibleVersions filter) to read toolData.index.${v}.go instead of toolData.manifests.${v}.go.
Generated index.nix files and CI staging
manifests/delve/index.nix, manifests/gofumpt/index.nix, manifests/golangci-lint/index.nix, manifests/gopls/index.nix, manifests/govulncheck/index.nix, manifests/staticcheck/index.nix, .github/workflows/tools-update.yml
Auto-generated index.nix files added for all tracked tools, each mapping version strings to { go = "..."; }. The CI PR creation step now stages manifests/${name}/index.nix alongside the per-version manifest.

Sequence Diagram

sequenceDiagram
  participant generate.go
  participant writeIndex
  participant fs as Manifest directory
  participant template as text/template
  generate.go->>writeIndex: writeIndex(outputDir)
  writeIndex->>fs: read *.nix files (exclude index.nix)
  fs-->>writeIndex: manifest file list
  writeIndex->>fs: read each manifest, extract go = "..." via regex
  writeIndex->>writeIndex: semver-sort entries descending
  writeIndex->>template: execute index.nix template
  template-->>writeIndex: rendered Nix attrset
  writeIndex->>fs: write index.nix (mode 0644)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • purpleclay/go-overlay#471: Both PRs modify internal/cli/goscrape/modproxy/generate.go's manifest-generation flow—one adding conditional index.nix generation and the other adjusting generateManifest/resolver execution.
  • purpleclay/go-overlay#398: Adds per-version manifest files like manifests/delve/1.26.2.nix that serve as inputs to this PR's index.nix generation logic.
  • purpleclay/go-overlay#419: Adds versioned manifest files that are scanned by the new writeIndex function to derive tool-to-Go version mappings.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly and concisely describes the main feature: avoiding the need to import every manifest file when resolving tools..latest, which directly addresses the performance problem described in the PR objectives.
Linked Issues check ✅ Passed All coding requirements from issue #492 are fully met: goscrape now emits per-tool index.nix files mapping versions to Go requirements [new files in manifests/*/index.nix]; Nix code updated to consult the index [lib/tool-manifests.nix, lib/mk-tool-set.nix]; workflow updated to stage generated index files [.github/workflows/tools-update.yml].
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the index mechanism: Go code for index generation, Nix code for consumption, generated index files, workflow updates for staging, and tests. No unrelated modifications detected.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 492-per-tool-index

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

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/mk-tool-set.nix`:
- Around line 61-62: The code assumes every version in `toolData.sortedVersions`
exists as a key in `toolData.index`, but if `index.nix` is stale or incomplete,
accessing `toolData.index.${v}.go` will fail with an attribute-missing error.
Guard the lookups by checking that the attribute exists in `toolData.index`
before accessing it, or use Nix's optional attribute access pattern (such as
`toolData.index.${v}` with a conditional check or hasAttr verification) to
safely skip versions that are not present in the index. Apply this guard to both
the map operation shown in the diff and the similar pattern occurring at the
other affected location.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: c4bb5997-7bbf-48b2-8587-c0cd87a5f733

📥 Commits

Reviewing files that changed from the base of the PR and between ef7a1f9 and 9e30453.

📒 Files selected for processing (13)
  • .github/workflows/tools-update.yml
  • internal/cli/goscrape/modproxy/generate.go
  • internal/cli/goscrape/modproxy/index.go
  • internal/cli/goscrape/modproxy/index_test.go
  • internal/cli/goscrape/modproxy/testdata/index.nix.golden
  • lib/mk-tool-set.nix
  • lib/tool-manifests.nix
  • manifests/delve/index.nix
  • manifests/gofumpt/index.nix
  • manifests/golangci-lint/index.nix
  • manifests/gopls/index.nix
  • manifests/govulncheck/index.nix
  • manifests/staticcheck/index.nix

Comment thread lib/mk-tool-set.nix Outdated
…test

Closes #492

`lib/mk-tool-set.nix` computed `compatibleVersions`/`latestCompatible`
by filtering over every manifest in a tool's directory, forcing Nix to
parse every <version>.nix file just to read its `go` requirement. For
golangci-lint (95 manifests, 5.6MB), this added ~54ms to every eval of
tools.golangci-lint.latest (442ms -> 389ms once fixed).

Add a per-tool manifests/<tool>/index.nix mapping version -> { go },
loaded by lib/tool-manifests.nix and consumed by lib/mk-tool-set.nix
instead of the full manifests. goscrape's mod-proxy generate now
(re)writes index.nix by scanning the go requirement out of every
manifest in the output directory, sorted newest-first via
golang.org/x/mod/semver, and tools-update.yml stages it alongside the
generated manifest.

Backfilled index.nix for all 6 existing tool directories.

Signed-off-by: purpleclay <purpleclaygh@gmail.com>
@purpleclay
purpleclay force-pushed the 492-per-tool-index branch from 9e30453 to 68db957 Compare June 15, 2026 07:16
@purpleclay
purpleclay merged commit 0e45df5 into main Jun 15, 2026
29 checks passed
@purpleclay
purpleclay deleted the 492-per-tool-index branch June 15, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nix eval tools.<name>.latest imports every manifest for that tool

1 participant