Skip to content

Deploy guard: build_app_bundle refuses stale/unrecorded trees - #994

Merged
aarontrowbridge merged 2 commits into
mainfrom
992-deploy-guard
Sep 10, 2026
Merged

Deploy guard: build_app_bundle refuses stale/unrecorded trees#994
aarontrowbridge merged 2 commits into
mainfrom
992-deploy-guard

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

Closes #992.

What

The 2026-09-10 deploy race — a local-tree deploy overwrote the recorded-main dist-app swap and the #987 crash returned — gets enforced at the moment of building:

Shape

The decision logic (evaluatePreflight, checkKnownFixes, buildDeployManifest, headRelation) lives in packages/extension/scripts/deploy_guard.mjs as pure functions, driven by both the script and test/deploy_guard.test.ts.

Verification (all run live)

  • vitest run test/deploy_guard.test.ts test/overlay_known_fixes_964.test.ts20/20 passed: refuse-on-behind, refuse-on-diverged, refuse-on-dirty, refuse-on-empty-override, refuse-on-whitespace-override, proceed-with-recorded-override, proceed-clean, manifest shape (override_reason serializes null), known-fixes pass + per-file refusals, fixture-list parity, headRelation mapping.
  • Real deploy runs (scratch clone + the guard worktree):
  • Hub dist-app redeployed through the guard (override honestly records the pre-merge state; dist content is the byte-identical b66d623 build); served surfaces verified.

Notes

  • The pre-merge hub deploy used AMICODE_DEPLOY_OVERRIDE with the reason stamped in the served deploy.json — after this merges, the next deploy should run clean (no override).
  • Follow-up: the deploy race's other half — whoever copies the staged dist to the service dir — could adopt the same manifest check (verify the served deploy.json before overwrite). Not in this slice.

…rded trees (#992)

The 2026-09-10 deploy race: a local-tree deploy overwrote the
recorded-main dist-app swap and a fixed crash returned — an unrecorded
build served over a recorded fix. The deploy flow now enforces the
doctrine (recorded main is canonical) at the moment of building:

- Pre-flight: fetch origin; refuse (exit 1, named reason + remedy) when
  HEAD ≠ origin/main or the tree is dirty. Override via
  AMICODE_DEPLOY_OVERRIDE — the reason MUST be non-empty (empty/missing
  with the flag set refuses: no silent overrides) and is recorded.
- Deploy manifest: every stage stamps dist-app/deploy.json {commit,
  branch, dirty, override_reason, built_at, deployed_by} so the served
  dist always traces to a recorded commit.
- Known-fixes check at deploy time: the #964 known-fixed hunks (the
  #929 3-arg translate callback, the #832 diff_version shape + guarded
  delete, the #832 exportTrace locales) are asserted against the
  overlay before any build; a tree missing a recorded fix refuses with
  the named-remedy shape. NEVER overridable. deploy_guard.mjs mirrors
  the fixture list from test/overlay_known_fixes_964.test.ts (the
  source of record) and the test suite cross-checks the two lists
  cannot drift silently.

The decision logic (evaluatePreflight, checkKnownFixes,
buildDeployManifest, headRelation) lives in scripts/deploy_guard.mjs as
pure functions, driven by both the script and test/deploy_guard.test.ts.
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

…uilds are not deploys)

The vsix-gate's packaging lane runs build:app from the PR MERGE REF —
legitimately ahead of origin/main and shallow-cloned, so the #992
pre-flight refused and broke packaging. That lane is a packaging build,
not a deploy: under CI the stale/dirty checks run advisory (printed,
recorded as the manifest's override_reason with the merge ref + branch)
while the #964 known-fixes check stays enforcing. Also unshallow-fetch
before the ancestry probes when the clone is shallow, so the relation
label is honest in both contexts.
@aarontrowbridge

Copy link
Copy Markdown
Member Author

Second commit b9374bfd: the vsix-gate caught the guard itself — CI packaging runs build:app from the PR merge ref (ahead of origin/main, shallow-cloned), so the pre-flight refused and broke packaging. Under CI the stale/dirty checks are now advisory (recorded in the manifest's override_reason with the merge ref + branch); the #964 known-fixes check stays enforcing. Also unshallow-fetches before the ancestry probes. CI green.

Live incident worth flagging (pre-existing, #964 class): running the full extension suite (pnpm test) executed overlay_sync.test.ts's --apply test against my worktree, which applied fork→overlay drift over 256 files and clobbered the #832 exportTrace fix mid-session — the deploy-time known-fixes check then correctly REFUSED the redeploy until the overlay was restored. The sync tool's own test suite can regenerate the exact regression #964 guards against. Recommend follow-up: make that test --check-only or run it in a temp dir.

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.

Deploy guard: build_app_bundle refuses stale/unrecorded trees — recorded main is canonical for the served dist

1 participant