Skip to content

Auto Merge Optimization PR #46

Auto Merge Optimization PR

Auto Merge Optimization PR #46

name: Auto Merge Optimization PR
"on":
workflow_run:
workflows: ["CI"]
types: [completed]
jobs:
auto-merge:
if: github.event.workflow_run.conclusion == 'success' && (startsWith(github.event.workflow_run.head_branch, 'automation/monthly-optimization-issue-') || startsWith(github.event.workflow_run.head_branch, 'codex/monthly-optimization-issue-'))
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Resolve automation PR
id: pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p data/output/auto_merge
BRANCH_NAME="${{ github.event.workflow_run.head_branch }}"
PR_NUMBER=$(gh pr list --state open --head "${BRANCH_NAME}" --json number --jq '.[0].number // empty')
if [ -z "${PR_NUMBER}" ]; then
echo "No open automation PR found for ${BRANCH_NAME}." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
- name: Evaluate merge eligibility
id: merge_guard
if: steps.pr.outputs.pr_number != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_NAME: ${{ github.event.workflow_run.head_branch }}
run: |
gh pr view "${{ steps.pr.outputs.pr_number }}" --json number,isDraft,body,url,files,labels > data/output/auto_merge/pr.json
python3 - <<'PY'
import json
import os
from pathlib import Path
from scripts.prepare_auto_optimization_pr import evaluate_changed_files
pr = json.loads(Path("data/output/auto_merge/pr.json").read_text(encoding="utf-8"))
body = pr.get("body") or ""
changed_files = [item.get("path", "") for item in pr.get("files", [])]
labels = {item.get("name", "") for item in pr.get("labels", [])}
branch_name = os.environ["BRANCH_NAME"]
codex_branch = branch_name.startswith("codex/monthly-optimization-issue-")
guard = evaluate_changed_files(changed_files)
has_marker = "<!-- auto-optimization-pr:issue-" in body
task_level_allowed = "Task-level auto-merge eligible: `yes`" in body
has_auto_merge_label = "auto-merge-ok" in labels
should_merge = (
has_marker
and task_level_allowed
and not pr.get("isDraft")
and guard["allowed"]
and (not codex_branch or has_auto_merge_label)
)
if not has_marker:
reason = "missing_marker"
elif not task_level_allowed:
reason = "task_level_guard"
elif pr.get("isDraft"):
reason = "draft_pr"
elif not guard["allowed"]:
reason = "sensitive_changed_files"
elif codex_branch and not has_auto_merge_label:
reason = "missing_auto_merge_label"
else:
reason = "ready"
summary_lines = [
"## Auto-Merge Gate",
f"- PR: {pr['url']}",
f"- Branch: `{branch_name}`",
f"- Codex branch: `{ 'yes' if codex_branch else 'no' }`",
f"- Draft: `{ 'yes' if pr.get('isDraft') else 'no' }`",
f"- Task-level auto-merge eligible: `{ 'yes' if task_level_allowed else 'no' }`",
f"- Auto-merge label: `{ 'yes' if has_auto_merge_label else 'no' }`",
f"- Sensitive files touched: `{len(guard['blocked_files'])}`",
f"- Final merge decision: `{ 'merge' if should_merge else 'skip' }`",
f"- Reason: `{reason}`",
]
if guard["blocked_files"]:
summary_lines.append("")
summary_lines.append("### Sensitive changed files")
summary_lines.extend(f"- `{path}`" for path in guard["blocked_files"])
Path("data/output/auto_merge/summary.md").write_text("\n".join(summary_lines).strip() + "\n", encoding="utf-8")
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output:
print(f"should_merge={'true' if should_merge else 'false'}", file=output)
print(f"reason={reason}", file=output)
print(f"pr_url={pr['url']}", file=output)
PY
- name: Append merge summary
if: steps.pr.outputs.pr_number != ''
run: cat data/output/auto_merge/summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Merge automation PR
if: steps.merge_guard.outputs.should_merge == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr merge "${{ steps.pr.outputs.pr_number }}" --rebase --delete-branch