Skip to content

feat: release tracking (pin tracked upstream repos per bake) - #8

Merged
the-bokya merged 11 commits into
mainfrom
feat/release-tracking
Aug 13, 2026
Merged

feat: release tracking (pin tracked upstream repos per bake)#8
the-bokya merged 11 commits into
mainfrom
feat/release-tracking

Conversation

@the-bokya

Copy link
Copy Markdown
Member

Release tracking

Lets a recipe declare the upstream repos it installs and bake a specific, reproducible release of each, instead of whatever "latest" happens to be at bake time.

How it works

  • A recipe declares tracked repos with [[track]] repo = "…" (identity only). Composition unions these, so a golden that composes pilot tracks frappe/pilot too.
  • The pinned ref → commit lives in a runtime, API/UI-managed store (TrackedRelease), never in recipe.toml.
  • Refs resolve and validate through plain git ls-remote (chef/releases.py) — no GitHub API, no token.
  • A bake fails closed if a tracked repo has no pin. The resolved {ref, sha} is injected as host.data["chef_releases"] and recorded in each image's provenance. A per-bake releases override pins for a single bake without touching the store.

Surfaces

  • API/releases router (list / pin / clear / tag-picker); recipe detail exposes tracked pins; validate + bake creation gate on the fail-closed condition.
  • CLIchef releases list|set|refs, and chef bake -r repo=ref.
  • UI — a Releases page, per-bake override fields in the Bake dialog, and baked-in releases shown on the Images table.
  • pilot — now tracks frappe/pilot and installs the pinned release tarball directly.

Commits

11 small, layered commits (engine → store → resolver → schemas → API → worker → CLI → frontend → pilot → docs).

Tests

Full suite green: 126 passed. Adds test_releases.py, test_releases_api.py, test_release_tracking.py (31 release-specific tests) covering resolution, pin CRUD, the API, fail-closed bakes, provenance, and the pilot pin.

Note: uv.lock is intentionally left out — it's an untracked, never-committed generated file and pyproject.toml is unchanged (no new dependency).

🤖 Generated with Claude Code

the-bokya and others added 11 commits August 13, 2026 13:29
Recipes declare the upstream repos they install with '[[track]] repo = ...' (identity only). Adds Manifest.track, validates each entry has a repo, unions across a composed stack (dedup by repo), and exposes Recipe.tracked_repos().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
One row per repo (ref + resolved sha), managed at runtime, with get/list/set/delete_pin helpers. BakeRecord gains a releases dict for one-off {repo: ref} overrides that leave the store untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Turns a pinned ref into a commit SHA and lists a repo's tags (newest-first, cached ~60s) using plain git ls-remote — no GitHub API, no token. Dockerfile now installs git for this.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TrackedReleaseOut, SetPinRequest, RefsOut; plus releases overrides on BakeCreate/ValidateRequest and tracked pins on RecipeDetail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GET /releases (list pins), PUT /releases (validate+resolve a ref, 422 if not found), DELETE /releases/{repo}, GET /releases/refs (tag picker, 502 on ls-remote failure). Mounted under the same auth as the other routers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RecipeDetail joins each tracked repo with its store pin. Validation and bake creation report/reject an unpinned tracked repo (the fail-closed condition) and honour per-bake overrides; bake creation stays cheap (no network) since the worker re-resolves authoritatively.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ord provenance

Before acquiring a VM the pipeline resolves every tracked repo's effective ref (per-bake override else store pin) to a sha, failing closed if any is unpinned or unresolvable. The resolved {repo: {ref, sha}} is injected as host.data['chef_releases'] via run_phase and recorded in each image's provenance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Manage pins from the command line (set validates + resolves via ls-remote) and pin a tracked repo for a single inline bake with -r/--release repo=ref.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New Releases page (+ nav/route) to manage pins with a tag picker; BakeDialog gains per-bake release override fields; the Images table shows each snapshot's baked-in releases from provenance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pilot now tracks frappe/pilot and installs the pinned release tarball directly (a faithful stand-in for install.sh's install_for_user) instead of install.sh's unpinnable 'latest', so a bake is reproducible. Includes the end-to-end track/resolve/provenance tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Records the store/resolver/pipeline/API contract and the fail-closed, per-repo-pin design decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@the-bokya
the-bokya merged commit be42721 into main Aug 13, 2026
@the-bokya
the-bokya deleted the feat/release-tracking branch August 13, 2026 08:02
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