Skip to content

fix(promotion): commit the files of transitions that applied when a later one fails - #65

Draft
scott-lowe-vapi wants to merge 1 commit into
mainfrom
fix/promotion-commit-applied-transitions
Draft

scott-lowe-vapi wants to merge 1 commit into
mainfrom
fix/promotion-commit-applied-transitions

Conversation

@scott-lowe-vapi

Copy link
Copy Markdown
Contributor

Value

V.A.L.U.E. tier: project — PR 9 of 10 for inline simulation PR checks (TEST-141). This is a fix to promotion, independent of the check stack (cut from main), and the promotion gate (PR 10) depends on it.

  • Problem: when a multi-transition promotion fails partway, the "Commit reconciled files and UUID state" step pushes nothing: not the UUID state, and not the files of transitions that already reached the platform.
    • Why: on failure the step stages only .vapi-state.*.json, but the failed transition's promotionPlanApply has already rewritten tracked files in its target org, so git pull --rebase refuses with "You have unstaged changes".
    • Result: git and the platform disagree, and the next promotion plans from stale files.
  • Who it affects: teams using promotion.yml with two or more transitions (dev → staging → prod), and anyone who adds the promotion gate in PR 10, where a failing gate is exactly a mid-run failure.
  • What changes:

Evidence of value

Red/green in a scratch repo.

  • Setup: a bare origin plus a clone; the pipeline is a → b → c, and c starts with a tracked assistants/intake.yml.
  • The run: promote --all --apply runs this branch's promote-cmd with a fake child runner. Apply into b succeeds (writing state and one extra file, as apply's pull can). Apply into c writes state, then fails.
  • Then: the workflow's real commit step, extracted from each ref's promotion.yml, runs with PROMOTION_OUTCOME=failure.
main (69c7e83) This branch
Commit step error: cannot pull with rebase: You have unstaged changes. exit 128 pushed, exit 0
origin/main unchanged (only base) chore: record promoted Vapi state [skip promotion]
.vapi-state.b.json / .c.json on origin {} / {} (state lost) uuid-b / uuid-c (both recorded)
resources/b/assistants/intake.yml, pulled-by-apply.yml missing committed
resources/c/assistants/intake.yml old content old content (the failed rewrite is discarded)
resources/c/assistants/pulled-by-apply.yml — removed by git clean

tmp/promotion-applied.txt after the run held exactly the two resources/b/... paths.

Tests: npm test goes from 355 to 358 passing.

Testing plan

  • tests/promote-cmd.test.ts (3 tests, a real temp git repo, injected child runner):
    • one transition applies and the next fails: only the applied transition's files are recorded, including a file apply rewrote that the plan didn't name;
    • every --apply run starts a fresh record, and a plan-only run leaves it alone;
    • deleted and renamed files are recorded by their current path.
  • The existing tests/promotion.test.ts (including its end-to-end promote-cmd spawn) still passes.
  • Not tested:
    • a real GitHub Actions promotion run (the step was executed locally with bash, from the YAML);
    • the edge case where two transitions in one run target the same org and the later one fails after rewriting a file the earlier one applied. The recorded path would then commit the failed content. Pipelines are forward-only, so this needs two pipelines sharing a target in one --all run.

This conflicts with #59 in src/promote-cmd.ts (#59 moves the connection helpers out). Whichever merges second rebases.

Refs TEST-141

🤖 Generated with Claude Code

…ater one fails

When a promotion failed partway, the workflow's commit step staged only
the UUID state, but the failing transition had already rewritten tracked
files in its target org, so `git pull --rebase` refused and nothing was
pushed — not the state, and not the files of transitions that had
already reached the platform.

- promote-cmd truncates tmp/promotion-applied.txt at the start of each
  --apply run and, after each successful apply.ts, appends the paths git
  reports changed under resources/<target>/ (from git, not the plan:
  apply's own pull and push can rewrite other files).
- On a non-success outcome, the commit step adds the state files plus
  exactly those paths, commits, then resets and cleans resources/ so the
  failed transition's rewrites can't block the rebase.
- promotionCommandRun(args, deps) takes an injectable child runner, used
  by the new tests/promote-cmd.test.ts.

Refs TEST-141

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

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