Skip to content

fix(auto-merge): add opt-in retention of queued evaluations - #1151

Merged
devantler merged 3 commits into
mainfrom
codex/actions-queue-725
Sep 5, 2026
Merged

fix(auto-merge): add opt-in retention of queued evaluations#1151
devantler merged 3 commits into
mainfrom
codex/actions-queue-725

Conversation

@devantler

@devantler devantler commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated by the Agentic Engineer

Bursts of auto-merge events can discard waiting evaluations, including a queued revocation. Add the temporary queue-pending-evaluations opt-in to retain pending work in both mutation jobs and non-cancelling workflow runs. It defaults to false, preserving existing callers and direct/required runs. Actor-enforced lifecycle and evidence-removal events keep their existing cancellation behavior.

Tests cover omitted, explicit-false, and enabled public calls, plus a credential-free three-job burst with an exact-attempt completion check. Documentation states the 100-pending limit, ordering behavior, and temporary flag lifecycle. Authorization, actor gates, and production permissions are preserved.

Validation: failing-before/passing-after queue and default-off guards, three removal controls, author/revocation/lifecycle/review-gate fixtures, credential boundaries, and required-check wiring. Both workflows pass GitHub's official parser; 3,780 expression combinations plus 144 empty-input cases preserve cancellation and legacy defaults. Current-head live CI must pass before promotion.

Fixes #1154

Part of #725. Production rollout, direct/required activation, and flag removal remain tracked in #1155, with review due 2026-09-12.

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

MegaLinter analysis: Success

Descriptor Linter Files Fixed Errors Max errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 0.74s
✅ GO revive 2 0 0 10.16s
✅ REPOSITORY betterleaks yes no no 0.77s
✅ REPOSITORY checkov yes no no 19.89s
✅ REPOSITORY git_diff yes no no 0.04s
✅ REPOSITORY osv-scanner yes no no 0.95s
✅ REPOSITORY secretlint yes no no 1.17s
✅ REPOSITORY syft yes no no 2.94s
✅ REPOSITORY trivy yes no no 13.24s
✅ REPOSITORY trivy-sbom yes no no 0.14s
✅ REPOSITORY trufflehog yes no no 5.87s

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@10.0.0 --custom-flavor-setup --custom-flavor-linters COPYPASTE_JSCPD,GO_REVIVE,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_BETTERLEAKS,REPOSITORY_OSV_SCANNER,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG

MegaLinter is provided by OX Security
Show us your support by starring ⭐ the repository

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation at 234e0e5fda47d3d0d5c5a81cece3749fa2729aa9: CI run 33958492585, attempt 1 accepted the workflow-level queue expression and both public default/enforced reusable calls. The three-slot fixture reproduced the critical queue state: slot 1 was running while slots 2 and 3 both remained pending.

Every slot then completed successfully, in order 1 → 3 → 2, and the exact-attempt observer passed. This verifies preservation and serialization of the burst, without assuming slot/event-dispatch order. No PR approval, revocation, branch write, or App credential was needed for that scheduler observation. The existing behavioral fixtures separately verify authorization/revocation logic; this run does not claim to have modified a real PR through those privileged paths.

The new observer is required by the aggregate CI check. A retry must rerun the full burst in one attempt; its failure diagnostic explains that recovery. Intentional actor-enforced lifecycle/evidence-removal cancellation and GitHub's 100-pending limit remain documented constraints.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

Please review this exact head. Pre-submission correctness, security, and simplification review is complete, including an independent review. Its one test-retry finding was fixed: an incomplete queue observation tells operators to rerun all jobs to recreate the same-attempt burst.

Validation: the regression guard failed on the original queues and now passes; deleting each of the three queue settings independently fails the guard. Existing author, revocation, lifecycle, review-gate, credential-boundary, merge-group isolation, harden-runner, OIDC, and required-check wiring tests pass. GitHub's official workflow parser 0.3.61 accepts both changed workflows, and its expression evaluator passed 1,260 flag/event/action combinations with cancellation unchanged. The observer predicate passed eight complete/incomplete/paginated/failed-slot probes. ShellCheck and YAML formatting pass; Zizmor reports only the same 67 existing low-severity self-repository suggestions. Local actionlint lacks the new queue key and existing job.workflow_* context fields, so schema validation used the official GitHub parser and the accepted live workflows instead; no lint configuration was weakened.

The live user evaluation records two simultaneous pending jobs followed by all three slots and the observer completing successfully. All 111 applicable checks now pass, with 74 skipped and nothing pending or failing. The fixture and observer have no repository write permissions or App credentials. Intentional actor-enforced workflow cancellation remains active, and the public documentation states the 100-pending limit and ordering constraint.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit's correctly formed request at 09:46:17Z has no reaction, acknowledgement, or substantive review after the bounded no-reaction window (rechecked at 09:50Z). Review objects and provider checks are empty; its 09:47:49Z status says Review skipped: automatic reviews are disabled. This is unserved review evidence, not approval. Advancing to the next provider under the ordered review procedure.

@codex review

Please review the current queue repair. CI is fully green and the preceding comments record independent pre-submission review, unchanged cancellation across 1,260 cases, and the successful live three-job burst. No production credentials or authorization gates were widened.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T09:55:36.204996Z 234e0e5 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

@devantler I will review pull request #1151 at commit 234e0e5fda47d3d0d5c5a81cece3749fa2729aa9.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 234e0e5fda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/enable-auto-merge.yaml Outdated
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Team

Run ID: 6cd081fd-bb85-40c0-b1ff-f3d7beaf9c8b

📥 Commits

Reviewing files that changed from the base of the PR and between b7835a7 and 234e0e5.

📒 Files selected for processing (4)
  • .github/tests/test-enable-auto-merge-author-gate.sh
  • .github/workflows/ci.yaml
  • .github/workflows/enable-auto-merge.yaml
  • README.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (1)
Pin third-party actions (non-`actions/*`, non-`github/*`, non-`devantler-tech/*`) to commit SHAs with a `# v` comment — enforced by `zizmor.yml`.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • .github/workflows/enable-auto-merge.yaml
  • .github/workflows/ci.yaml
🔇 Additional comments (4)
.github/workflows/enable-auto-merge.yaml (1)

160-162: LGTM!

Also applies to: 345-350, 413-413

README.md (1)

307-313: LGTM!

.github/workflows/ci.yaml (1)

2867-2927: LGTM!

Also applies to: 4137-4138, 4243-4244

.github/tests/test-enable-auto-merge-author-gate.sh (1)

213-230: LGTM!

Also applies to: 241-254


📝 Walkthrough

Walkthrough

The auto-merge workflow now uses conditional workflow-level queue settings and queue: max for both mutation jobs. CI adds a three-slot queue fixture and validates that all slots complete successfully. Required-check aggregation includes the new queue tests. The author-gate test checks production and fixture queue configuration. The README documents pending-queue behavior, cancellation conditions, and the 100-entry pending limit.

Merge Risk: ⚪ Minimal · up to 234e0

This change preserves queued auto-merge evaluations during event bursts while retaining intentional cancellation for lifecycle and evidence-removal events. Queue behavior and required CI coverage are in place, with no current merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #725 by adding queue preservation, retaining non-cancelling behavior, testing burst completion, preserving disarm behavior, and leaving cancelling workflows unchanged.
Out of Scope Changes check ✅ Passed The workflow changes, CI fixtures, regression tests, and documentation directly support the linked issue and stated objectives. No unrelated code changes are identified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Title check ✅ Passed The title clearly identifies the auto-merge fix and the retention of queued evaluations, which matches the main changes.
Description check ✅ Passed The description accurately covers queue behavior, preserved cancellation rules, tests, documentation, validation, and related issue tracking.

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.

@devantler devantler changed the title fix(auto-merge): preserve queued gate evaluations fix(auto-merge): add opt-in retention of queued evaluations Sep 5, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation at 5a3b1102ba8ea8984046494247cb0318f808f69a, based on current main c8e0575f3489bdc3890be9e4f0bc9bb202d2df1a: CI run 33960395519, attempt 1 is successful. All 114 applicable checks pass; 76 are skipped, with nothing pending or failing.

The final-head burst again reached one running job with two simultaneously pending jobs. Slots 1, 2, and 3 then completed successfully and without overlap (10:21:16–10:21:40Z, 10:21:46–10:22:07Z, and 10:22:10–10:22:33Z). The exact-attempt observer passed at 10:22:56Z. The fixture uses no repository write permissions or App credentials. Public reusable calls with the input omitted, explicitly false, and enabled all passed their eligibility checks; privileged mutation jobs correctly skipped for this human-authored PR. This is scheduler and public-call validation, not a claim of modifying real PRs through privileged paths.

Independent integration review at this exact head found no actionable issues: all 99 required jobs map uniquely to 99 result entries, the newly merged cooldown coverage remains wired, and the production queue workflow is byte-identical to the independently reviewed opt-in repair. Existing authorization and intentional cancellation remain unchanged. Caller rollout and later flag removal remain open under #725 and #1155.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

Please review this exact current-base head. The previous Codex finding is fixed and its thread resolved: queue-pending-evaluations is a boolean default-off input. Omitted, false, and direct-event inputs retain the existing single-pending behavior in all three concurrency groups. Only opted-in, non-cancelling evaluations use max; existing intentional cancellation, authorization, permissions, and mutation jobs are unchanged. Delivery issue #1154 and rollout/removal issue #1155 are children of #725; #1155 has a September 12 review date and is blocked by this delivery. This PR does not activate the capability for existing consumers or close the rollout parent.

Pre-submission correctness, security, and simplification review is complete. The official GitHub workflow parser 0.3.61 accepts both changed workflows. Its expression evaluator passed 3,780 flag/event cases and 144 direct-event cases. The default-off regression failed before the fix, and removing any of the three queue declarations independently fails the guard. Author/revocation behavior, required-check isolation and parity, merge-group isolation, harden-runner-first, OIDC, credential boundaries, ShellCheck, and changed-YAML formatting pass. Local actionlint lacks the new queue key and existing job.workflow_* context fields, so schema validation uses the official parser and accepted GitHub workflows without weakening lint configuration.

The branch integrates current main c8e0575f3489bdc3890be9e4f0bc9bb202d2df1a; CI wiring and the regression/ablation checks were rerun after that integration. The preceding user-evaluation record covers the exact final-head live queue run and all applicable CI checks.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== HEAD AND BASE ==='
git status --short
git rev-parse HEAD
git merge-base HEAD origin/main 2>/dev/null || true

echo '=== CHANGED FILES ==='
git diff --name-status "$(git merge-base HEAD origin/main)" HEAD

echo '=== DIFF ==='
git diff --find-renames --find-copies --unified=80 "$(git merge-base HEAD origin/main)" HEAD -- \
  .github/workflows/enable-auto-merge.yaml \
  .github/workflows/ci.yaml \
  .github/tests/test-enable-auto-merge-author-gate.sh \
  README.md

echo '=== OUTLINES ==='
ast-grep outline .github/workflows/enable-auto-merge.yaml --items all 2>/dev/null || true
ast-grep outline .github/workflows/ci.yaml --items all 2>/dev/null || true
ast-grep outline .github/tests/test-enable-auto-merge-author-gate.sh --items all 2>/dev/null || true

echo '=== INPUT, CONCURRENCY, AND CALLER REFERENCES ==='
rg -n -C 5 --glob '*.yaml' --glob '*.yml' --glob '*.sh' \
  'queue-pending-evaluations|^\s*concurrency:|^\s*queue:|enable-auto-merge\.ya?ml|uses:\s*\./\.github/workflows/enable-auto-merge' \
  .github README.md

Length of output: 117964


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== FOCUSED SOURCE WITH LINE NUMBERS ==='
sed -n '1,190p' .github/workflows/enable-auto-merge.yaml
sed -n '330,435p' .github/workflows/enable-auto-merge.yaml
sed -n '2800,2965p' .github/workflows/ci.yaml
sed -n '4080,4260p' .github/workflows/ci.yaml
sed -n '1,75p' .github/tests/test-enable-auto-merge-author-gate.sh
sed -n '205,285p' .github/tests/test-enable-auto-merge-author-gate.sh
tail -n 80 .github/tests/test-enable-auto-merge-author-gate.sh

echo '=== ALL REPOSITORY REFERENCES ==='
rg -n -C 3 --hidden -g '!/.git/**' \
  'queue-pending-evaluations|test-enable-auto-merge-queue-results|test-enable-auto-merge-queued|Enable Auto-Merge - Queue Slot|enable-auto-merge\.yaml' .

echo '=== REQUIRED CHECK WIRING PARITY ==='
python3 - <<'PY'
from pathlib import Path
import re
p = Path(".github/workflows/ci.yaml")
text = p.read_text()
start = text.index("  ci-required-checks:\n")
block = text[start:]
needs_block = re.search(r'(?ms)^    needs:\n(.*?)(?=^    runs-on:)', block).group(1)
env_block = re.search(r'(?ms)^          JOB_RESULTS: >-\n(.*?)(?=^         run:)', block).group(1)
needs = re.findall(r'^\s*-\s+([A-Za-z0-9_-]+)\s*$', needs_block, re.M)
results = re.findall(r'\$\{\{\s*needs\.([A-Za-z0-9_-]+)\.result\s*\}\}', env_block)
print("needs:", len(needs), "unique:", len(set(needs)))
print("results:", len(results), "unique:", len(set(results)))
print("missing_result_expressions:", sorted(set(needs) - set(results)))
print("orphan_result_expressions:", sorted(set(results) - set(needs)))
print("duplicate_needs:", sorted(x for x in set(needs) if needs.count(x) > 1))
print("duplicate_results:", sorted(x for x in set(results) if results.count(x) > 1))
PY

echo '=== YAML SHAPE CHECKS ==='
yq -o=json '{input: .on.workflow_call.inputs."queue-pending-evaluations", workflowConcurrency: .concurrency, disarmConcurrency: .jobs."disarm-untrusted-update".concurrency, autoMergeConcurrency: .jobs."auto-merge".concurrency}' .github/workflows/enable-auto-merge.yaml
yq -o=json '{queuedCall: .jobs."test-enable-auto-merge-queued", queueFixture: .jobs."test-enable-auto-merge-queue", queueObserver: .jobs."test-enable-auto-merge-queue-results"}' .github/workflows/ci.yaml

Length of output: 80161


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== AGGREGATE GATE PARITY ==='
python3 - <<'PY'
from pathlib import Path
import re
text = Path(".github/workflows/ci.yaml").read_text()
block = text[text.index("  ci-required-checks:\n"):]
needs = re.findall(r'^      - ([A-Za-z0-9_-]+)\s*$', block.split("    runs-on:", 1)[0], re.M)
job_results_start = block.index("          JOB_RESULTS: >-\n") + len("          JOB_RESULTS: >-\n")
job_results_end = block.index("        run: |", job_results_start)
results = re.findall(
    r'\$\{\{\s*needs\.([A-Za-z0-9_-]+)\.result\s*\}\}',
    block[job_results_start:job_results_end],
)
print(f"needs={len(needs)}, unique_needs={len(set(needs))}")
print(f"results={len(results)}, unique_results={len(set(results))}")
print("missing:", sorted(set(needs) - set(results)))
print("orphan:", sorted(set(results) - set(needs)))
print("duplicate_needs:", sorted(x for x in set(needs) if needs.count(x) > 1))
print("duplicate_results:", sorted(x for x in set(results) if results.count(x) > 1))
PY

echo '=== WORKFLOW AND FIXTURE YAML SHAPES ==='
yq -o=json '{input: .on.workflow_call.inputs."queue-pending-evaluations", workflowConcurrency: .concurrency, disarmConcurrency: .jobs."disarm-untrusted-update".concurrency, autoMergeConcurrency: .jobs."auto-merge".concurrency}' .github/workflows/enable-auto-merge.yaml
yq -o=json '{queuedCall: .jobs."test-enable-auto-merge-queued", queueFixture: .jobs."test-enable-auto-merge-queue", queueObserver: .jobs."test-enable-auto-merge-queue-results"}' .github/workflows/ci.yaml

echo '=== TEST EXIT PATH AND DOCUMENTED INPUTS ==='
tail -n 20 .github/tests/test-enable-auto-merge-author-gate.sh
python3 - <<'PY'
from pathlib import Path
import re
workflow = Path(".github/workflows/enable-auto-merge.yaml").read_text()
readme = Path("README.md").read_text()
# Confine the README extraction to the Enable Auto-Merge section.
section = readme[readme.index("### 🔀 Enable Auto-Merge"):readme.index("### 🧹 Lint")]
workflow_inputs = set(re.findall(r'^      ([a-z][a-z0-9-]+):\n        type:', workflow, re.M))
documented = set(re.findall(r'^\|\s*`([^`]+)`\s*\|\s*(?:Input|Secret)', section, re.M))
print("workflow_inputs:", sorted(workflow_inputs))
print("documented_inputs:", sorted(documented & workflow_inputs))
print("undocumented_workflow_inputs:", sorted(workflow_inputs - documented))
PY

echo '=== EXACT CHANGED-LINE LOCATIONS ==='
git diff --unified=0 c8e0575f3489bdc3890be9e4f0bc9bb202d2df1a HEAD -- .github/workflows/enable-auto-merge.yaml .github/workflows/ci.yaml .github/tests/test-enable-auto-merge-author-gate.sh README.md

Length of output: 3131


@devantler I reviewed commit 5a3b1102ba8ea8984046494247cb0318f808f69a.

I found no actionable issues.

The default-false input preserves the existing queue behavior. Opted-in non-cancelling workflow runs and both mutation jobs use queue: max. Actor-enforced cancellation paths retain queue: single.

The queue fixture has no write permissions. The observer is scoped to the current run attempt and requires all three queue slots to succeed. The required-check gate has complete parity: 99 unique needs entries map to 99 unique result expressions.

The sandbox did not provide yq, so the final structured YAML-shape query could not run. Direct source inspection and the supplied live parser and scheduler validation provide sufficient evidence for this review.

You are interacting with an AI system.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Readiness at 5a3b1102ba8ea8984046494247cb0318f808f69a, based on current main c8e0575f3489bdc3890be9e4f0bc9bb202d2df1a:

  • Programmatically tested: all 114 applicable checks pass, 76 skipped, none pending or failing; local regression, ablation, official-parser and expression-matrix evidence is recorded in the review request.
  • Reviewed: CodeRabbit's authenticated current-head verdict postdates request 5551174677, names the full head, reports no actionable issues, and analyzes the actual default-off, cancellation, permissions, queue observer, and 99-job aggregation behavior. Its missing local yq did not prevent source review; our parser and live CI validation cover that check. This is the substantive verdict-bearing reply, not the stale summary or the uninformative automatic-review-disabled status.
  • Tried and evaluated as a user: final-head live evaluation observed both pending jobs retained, all three serialized slots completed, and the exact-attempt observer succeeded. Omitted/off/on reusable calls passed with privileged mutation correctly skipped for this human PR.

Complete paginated comments, reviews, inline comments, and review threads contain no unresolved actionable findings; the earlier default-on finding is fixed, replied to, and resolved. Head/base, ownership, and activity are unchanged; the draft is clean and no auto-merge request is armed. The capability remains default-off, with caller rollout and flag removal owned by #1155. Promoting this delivery and proceeding through the normal head-pinned squash merge.

@devantler
devantler marked this pull request as ready for review September 5, 2026 10:32
@devantler
devantler merged commit 81ada4a into main Sep 5, 2026
190 checks passed
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Sep 5, 2026
@devantler
devantler deleted the codex/actions-queue-725 branch September 5, 2026 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Deliver opt-in retention of queued auto-merge evaluations

1 participant