actions: tag-driven approve(ApplyCommit) flow

run_apply_commit walks the approval through the tag state
machine in applied: approved/<id> + building/<id> stamped
before the build, then git read-tree --reset to proposal/<id>
populates the working dir without moving HEAD. on rebuild
success deployed/<id> is planted and refs/heads/main fast-
forwards to the proposal. on failure failed/<id> is annotated
with the build error and the working tree resets back to main
so the agent stays evaluable. helper events Rebuilt +
ApprovalResolved both carry the terminal tag so the manager
can git-show the exact tree (and read the failure note from
an annotated tag) against its read-only applied.git mount.
finish_approval grows a terminal_tag param; spawn path passes
None. lifecycle::apply_commit deleted.
This commit is contained in:
müde 2026-05-15 23:00:01 +02:00
parent 35b0edaf27
commit 315d4289c7
2 changed files with 110 additions and 35 deletions

View file

@ -293,24 +293,6 @@ pub async fn setup_proposed(proposed_dir: &Path, name: &str) -> Result<()> {
Ok(())
}
/// Placeholder for the old file-copy apply path; the real
/// tag-driven flow lives in `actions::approve` and gets wired up
/// in a follow-up commit. Leaving this function as a hard error
/// keeps `actions.rs` compiling while the rewrite lands; an
/// ApplyCommit approval that races the deploy will surface a
/// clear failure note instead of silently no-op'ing.
#[allow(unused_variables)]
pub async fn apply_commit(
_applied_dir: &Path,
_proposed_dir: &Path,
_commit_ref: &str,
) -> Result<()> {
bail!(
"apply_commit not yet wired up to the tag-driven flow; \
approve again after the next deploy lands"
)
}
/// Set up the applied repo. Two responsibilities:
/// - First-spawn only: init the repo, pull proposed's initial commit
/// in via `git fetch`, tag it `deployed/0`. This is the *only* time