mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-19 19:32:18 +02:00
fix: resolve workflow gaps exposed by frontier evals
Clarify plan-review ordering and fallback modes, preserve deploy readiness gates, honor configured merge methods, correct benchmark and canary contracts, and restore vendored installs on setup failure. Cover recovery with real-shell regressions. Co-Authored-By: OpenAI Codex <noreply@openai.com>
This commit is contained in:
co-authored by
OpenAI Codex
parent
a9f9ec5f08
commit
1f678a5b81
@@ -710,7 +710,7 @@ gh pr checks --json name,state,status,conclusion
|
||||
Parse the output:
|
||||
1. If any required checks are **FAILING**: **STOP.** "CI is failing on this PR. Here are the failing checks: {list}. Fix these before deploying — I won't merge code that hasn't passed CI."
|
||||
2. If required checks are **PENDING**: Tell the user "CI is still running. I'll wait for it to finish." Proceed to Step 3.
|
||||
3. If all checks pass (or no required checks): Tell the user "CI passed." Skip Step 3, go to Step 4.
|
||||
3. If all checks pass (or no required checks): Tell the user "CI passed." Skip only Step 3's wait loop; continue to Step 3.4, then Step 3.5 before merging.
|
||||
|
||||
Also check for merge conflicts:
|
||||
```bash
|
||||
@@ -730,7 +730,7 @@ gh pr checks --watch --fail-fast
|
||||
|
||||
Record the CI wait time for the deploy report.
|
||||
|
||||
If CI passes within the timeout: Tell the user "CI passed after {duration}. Moving to readiness checks." Continue to Step 4.
|
||||
If CI passes within the timeout: Tell the user "CI passed after {duration}. Moving to readiness checks." Continue to Step 3.4, then Step 3.5 before merging.
|
||||
If CI fails: **STOP.** "CI failed. Here's what broke: {failures}. This needs to pass before I can merge."
|
||||
If timeout (15 min): **STOP.** "CI has been running for over 15 minutes — that's unusual. Check the GitHub Actions tab to see if something is stuck."
|
||||
|
||||
@@ -936,7 +936,7 @@ git push origin <base>
|
||||
If the revert has conflicts: "The revert has merge conflicts — this can happen if other changes landed on {base} after your merge. You'll need to resolve the conflicts manually. The merge commit SHA is `<sha>` — run `git revert <sha>` to try again."
|
||||
|
||||
If the base branch has push protections: "This repo has branch protections, so I can't push the revert directly. I'll create a revert PR instead — merge it to roll back."
|
||||
Then create a revert PR: `gh pr create --title 'revert: <original PR title>'`
|
||||
Keep the local revert commit. Create a new branch at that commit (`git switch -c "revert/pr-<PR_NUMBER>-<timestamp>"`), push it with `git push -u origin HEAD`, then create the revert PR with `gh pr create --base <base> --title 'revert: <original PR title>'`. Report rollback as pending until this PR merges and deploys, not REVERTED.
|
||||
|
||||
After a successful revert: Tell the user "Revert pushed to {base}. The deploy should roll back automatically once CI passes. Keep an eye on the site to confirm." Note the revert commit SHA and continue to Step 9 with status REVERTED.
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ gh pr checks --json name,state,status,conclusion
|
||||
Parse the output:
|
||||
1. If any required checks are **FAILING**: **STOP.** "CI is failing on this PR. Here are the failing checks: {list}. Fix these before deploying — I won't merge code that hasn't passed CI."
|
||||
2. If required checks are **PENDING**: Tell the user "CI is still running. I'll wait for it to finish." Proceed to Step 3.
|
||||
3. If all checks pass (or no required checks): Tell the user "CI passed." Skip Step 3, go to Step 4.
|
||||
3. If all checks pass (or no required checks): Tell the user "CI passed." Skip only Step 3's wait loop; continue to Step 3.4, then Step 3.5 before merging.
|
||||
|
||||
Also check for merge conflicts:
|
||||
```bash
|
||||
@@ -179,7 +179,7 @@ gh pr checks --watch --fail-fast
|
||||
|
||||
Record the CI wait time for the deploy report.
|
||||
|
||||
If CI passes within the timeout: Tell the user "CI passed after {duration}. Moving to readiness checks." Continue to Step 4.
|
||||
If CI passes within the timeout: Tell the user "CI passed after {duration}. Moving to readiness checks." Continue to Step 3.4, then Step 3.5 before merging.
|
||||
If CI fails: **STOP.** "CI failed. Here's what broke: {failures}. This needs to pass before I can merge."
|
||||
If timeout (15 min): **STOP.** "CI has been running for over 15 minutes — that's unusual. Check the GitHub Actions tab to see if something is stuck."
|
||||
|
||||
@@ -383,7 +383,7 @@ git push origin <base>
|
||||
If the revert has conflicts: "The revert has merge conflicts — this can happen if other changes landed on {base} after your merge. You'll need to resolve the conflicts manually. The merge commit SHA is `<sha>` — run `git revert <sha>` to try again."
|
||||
|
||||
If the base branch has push protections: "This repo has branch protections, so I can't push the revert directly. I'll create a revert PR instead — merge it to roll back."
|
||||
Then create a revert PR: `gh pr create --title 'revert: <original PR title>'`
|
||||
Keep the local revert commit. Create a new branch at that commit (`git switch -c "revert/pr-<PR_NUMBER>-<timestamp>"`), push it with `git push -u origin HEAD`, then create the revert PR with `gh pr create --base <base> --title 'revert: <original PR title>'`. Report rollback as pending until this PR merges and deploys, not REVERTED.
|
||||
|
||||
After a successful revert: Tell the user "Revert pushed to {base}. The deploy should roll back automatically once CI passes. Keep an eye on the site to confirm." Note the revert commit SHA and continue to Step 9 with status REVERTED.
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ Record the start timestamp for timing data. Also record which merge path is take
|
||||
|
||||
Try auto-merge first (respects repo merge settings and merge queues):
|
||||
|
||||
Resolve `MERGE_METHOD` from Deploy Configuration, checking GitHub's allowed methods via `gh api repos/{owner}/{repo} --jq '{squash: .allow_squash_merge, merge: .allow_merge_commit, rebase: .allow_rebase_merge}'`. With no configured method, prefer squash, then merge, then rebase among allowed methods. If a configured method is disallowed or no method is allowed, stop and ask. Set `MERGE_FLAG` to exactly `--squash`, `--merge`, or `--rebase` accordingly.
|
||||
|
||||
```bash
|
||||
gh pr merge --squash --auto --delete-branch
|
||||
gh pr merge "$MERGE_FLAG" --auto --delete-branch
|
||||
```
|
||||
|
||||
If `--auto` succeeds: record `MERGE_PATH=auto`. This means the repo has auto-merge enabled
|
||||
@@ -29,16 +31,16 @@ the flow is unaffected — but do not report the second one as "auto-merge is di
|
||||
before this step runs.
|
||||
|
||||
```bash
|
||||
gh pr merge --squash --delete-branch
|
||||
gh pr merge "$MERGE_FLAG" --delete-branch
|
||||
```
|
||||
|
||||
If direct merge succeeds: record `MERGE_PATH=direct`. Tell the user: "PR merged successfully. The branch has been cleaned up."
|
||||
|
||||
If the merge fails with a permission error: **STOP.** "I don't have permission to merge this PR. You'll need a maintainer to merge it, or check your repo's branch protection rules."
|
||||
On any failure, run the state check below first. Only if it confirms the PR is still OPEN with no auto-merge request should a permission error stop the workflow.
|
||||
|
||||
### 4a-postfail: Post-failure PR-state check
|
||||
|
||||
**Universal invariant:** after ANY non-zero exit from `gh pr merge`, query authoritative PR state before retrying or stopping. Do NOT retry `gh pr merge`. Related: cli/cli#3442, cli/cli#13380.
|
||||
**Universal invariant:** after ANY non-zero exit from `gh pr merge`, query authoritative PR state before retrying or stopping. Do NOT retry blindly. The only permitted retry is the one direct attempt described above, after readback confirms OPEN with no auto-merge request and the original error is one of the two documented auto-merge rejections. All other failures use the branches below. Related: cli/cli#3442, cli/cli#13380.
|
||||
|
||||
```bash
|
||||
gh pr view --json state,mergeCommit,mergedAt,mergedBy
|
||||
@@ -98,7 +100,7 @@ Three outcomes — never read a failed check as a clean branch:
|
||||
- **Exit 0, one ref line** — the branch survived: the failed merge command never reached its `--delete-branch` half. If `<head-repository>` is the BASE repository, OFFER deletion, confirm-first (matching the worktree-cleanup posture above): "The remote branch `<head-branch>` still exists in `<head-repository>` — the failed merge never ran its --delete-branch half. Delete it?" Only on confirmation: `git push "https://github.com/<head-repository>.git" --delete "<head-branch>"`. If `<head-repository>` is a FORK, do not offer deletion — the branch belongs to the contributor and the maintainer typically has no push rights there; report instead: "The branch lives on the contributor's fork `<head-repository>` — leaving it to them." If a local branch of the same name exists, offer `git branch -d "<head-branch>"` alongside (`-d`, never `-D` — a non-fast-forwarded local branch is the user's call).
|
||||
- **Non-zero exit** — the check ITSELF failed (network, auth). Tell the user: "Couldn't verify remote branch state — leaving it alone." and skip the deletion offer entirely; a failed check is unknown state, not a clean branch.
|
||||
|
||||
Record `MERGE_PATH=direct`, then continue to §4a (CI auto-deploy detection).
|
||||
Record `MERGE_PATH=direct`, then continue to §4b (CI auto-deploy detection).
|
||||
|
||||
**If `state == "OPEN"`:**
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ Record the start timestamp for timing data. Also record which merge path is take
|
||||
|
||||
Try auto-merge first (respects repo merge settings and merge queues):
|
||||
|
||||
Resolve `MERGE_METHOD` from Deploy Configuration, checking GitHub's allowed methods via `gh api repos/{owner}/{repo} --jq '{squash: .allow_squash_merge, merge: .allow_merge_commit, rebase: .allow_rebase_merge}'`. With no configured method, prefer squash, then merge, then rebase among allowed methods. If a configured method is disallowed or no method is allowed, stop and ask. Set `MERGE_FLAG` to exactly `--squash`, `--merge`, or `--rebase` accordingly.
|
||||
|
||||
```bash
|
||||
gh pr merge --squash --auto --delete-branch
|
||||
gh pr merge "$MERGE_FLAG" --auto --delete-branch
|
||||
```
|
||||
|
||||
If `--auto` succeeds: record `MERGE_PATH=auto`. This means the repo has auto-merge enabled
|
||||
@@ -27,16 +29,16 @@ the flow is unaffected — but do not report the second one as "auto-merge is di
|
||||
before this step runs.
|
||||
|
||||
```bash
|
||||
gh pr merge --squash --delete-branch
|
||||
gh pr merge "$MERGE_FLAG" --delete-branch
|
||||
```
|
||||
|
||||
If direct merge succeeds: record `MERGE_PATH=direct`. Tell the user: "PR merged successfully. The branch has been cleaned up."
|
||||
|
||||
If the merge fails with a permission error: **STOP.** "I don't have permission to merge this PR. You'll need a maintainer to merge it, or check your repo's branch protection rules."
|
||||
On any failure, run the state check below first. Only if it confirms the PR is still OPEN with no auto-merge request should a permission error stop the workflow.
|
||||
|
||||
### 4a-postfail: Post-failure PR-state check
|
||||
|
||||
**Universal invariant:** after ANY non-zero exit from `gh pr merge`, query authoritative PR state before retrying or stopping. Do NOT retry `gh pr merge`. Related: cli/cli#3442, cli/cli#13380.
|
||||
**Universal invariant:** after ANY non-zero exit from `gh pr merge`, query authoritative PR state before retrying or stopping. Do NOT retry blindly. The only permitted retry is the one direct attempt described above, after readback confirms OPEN with no auto-merge request and the original error is one of the two documented auto-merge rejections. All other failures use the branches below. Related: cli/cli#3442, cli/cli#13380.
|
||||
|
||||
```bash
|
||||
gh pr view --json state,mergeCommit,mergedAt,mergedBy
|
||||
@@ -96,7 +98,7 @@ Three outcomes — never read a failed check as a clean branch:
|
||||
- **Exit 0, one ref line** — the branch survived: the failed merge command never reached its `--delete-branch` half. If `<head-repository>` is the BASE repository, OFFER deletion, confirm-first (matching the worktree-cleanup posture above): "The remote branch `<head-branch>` still exists in `<head-repository>` — the failed merge never ran its --delete-branch half. Delete it?" Only on confirmation: `git push "https://github.com/<head-repository>.git" --delete "<head-branch>"`. If `<head-repository>` is a FORK, do not offer deletion — the branch belongs to the contributor and the maintainer typically has no push rights there; report instead: "The branch lives on the contributor's fork `<head-repository>` — leaving it to them." If a local branch of the same name exists, offer `git branch -d "<head-branch>"` alongside (`-d`, never `-D` — a non-fast-forwarded local branch is the user's call).
|
||||
- **Non-zero exit** — the check ITSELF failed (network, auth). Tell the user: "Couldn't verify remote branch state — leaving it alone." and skip the deletion offer entirely; a failed check is unknown state, not a clean branch.
|
||||
|
||||
Record `MERGE_PATH=direct`, then continue to §4a (CI auto-deploy detection).
|
||||
Record `MERGE_PATH=direct`, then continue to §4b (CI auto-deploy detection).
|
||||
|
||||
**If `state == "OPEN"`:**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user