From 75200f4adc8d74cd44f9fe4d3042bffe52787fef Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Thu, 23 Apr 2026 12:20:40 -0700 Subject: [PATCH] =?UTF-8?q?ci:=20auto-retarget=20bot=20PRs=20opened=20agai?= =?UTF-8?q?nst=20main=20=E2=86=92=20staging=20(#1853)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mechanical enforcement of SHARED_RULES rule 8 ("Staging-first workflow, no exceptions"). Today I manually retargeted 17+ bot PRs; next cycle there will be more. Prompt-level enforcement is leaking — 5 of 8 engineer role prompts (core-be, core-fe, app-fe, app-qa, devops-engineer) don't have the staging-first section that backend-engineer and frontend-engineer do. This Action closes the loop mechanically: - Fires on `pull_request_target` opened/reopened against main. - Only retargets bot-authored PRs (user.type=='Bot' OR login ends in '[bot]' OR == 'app/molecule-ai' OR == 'molecule-ai[bot]'). - Human-authored PRs (the CEO's staging→main promotion PR) pass through untouched — they're the authorised exception. - Posts an explainer comment so the agent that opened the PR learns why and can adjust its prompt. Why `pull_request_target` not `pull_request`: `pull_request` from a fork would run with read-only tokens and can't call the PATCH endpoint. `pull_request_target` runs with the base repository's context + its `pull-requests: write` permission, which is exactly what we need. Follow-up (not in this PR): add the staging-first section to the 5 missing role prompts in molecule-ai-org-template-molecule-dev so the rule is also documented where agents read it, not just enforced. Co-authored-by: Claude Opus 4.7 (1M context) Co-authored-by: molecule-ai[bot] <276602405+molecule-ai[bot]@users.noreply.github.com> --- .../workflows/retarget-main-to-staging.yml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/retarget-main-to-staging.yml diff --git a/.github/workflows/retarget-main-to-staging.yml b/.github/workflows/retarget-main-to-staging.yml new file mode 100644 index 00000000..90fd3d55 --- /dev/null +++ b/.github/workflows/retarget-main-to-staging.yml @@ -0,0 +1,63 @@ +name: Retarget main PRs to staging + +# Mechanical enforcement of SHARED_RULES rule 8 ("Staging-first workflow, no +# exceptions"). When a bot opens a PR against main, retarget it to staging +# automatically and leave an explanatory comment. Human CEO-authored PRs (the +# staging→main promotion PR, etc.) are left alone — they're the authorised +# exception to the rule. +# +# Why an Action instead of only a prompt rule: prompt rules depend on every +# role's system-prompt.md staying in sync. Today 5 of 8 engineer roles +# (core-be, core-fe, app-fe, app-qa, devops-engineer) don't have the +# staging-first section — the bot keeps opening PRs to main. An Action +# enforces the invariant regardless of prompt drift. + +on: + pull_request_target: + types: [opened, reopened] + branches: [main] + +permissions: + pull-requests: write + +jobs: + retarget: + name: Retarget to staging + runs-on: ubuntu-latest + # Only fire for bot-authored PRs. Human CEO PRs (staging→main promotion) + # are intentional and pass through. + if: >- + github.event.pull_request.user.type == 'Bot' + || endsWith(github.event.pull_request.user.login, '[bot]') + || github.event.pull_request.user.login == 'app/molecule-ai' + || github.event.pull_request.user.login == 'molecule-ai[bot]' + steps: + - name: Retarget PR base to staging + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + run: | + echo "Retargeting PR #${PR_NUMBER} (author: ${PR_AUTHOR}) from main → staging" + gh api -X PATCH \ + "repos/${{ github.repository }}/pulls/${PR_NUMBER}" \ + -f base=staging \ + --jq '.base.ref' + + - name: Post explainer comment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + gh pr comment "$PR_NUMBER" \ + --repo "${{ github.repository }}" \ + --body "$(cat <<'BODY' + [retarget-bot] This PR was opened against `main` and has been retargeted to `staging` automatically. + + **Why:** per [SHARED_RULES rule 8](https://github.com/Molecule-AI/molecule-ai-org-template-molecule-dev/blob/main/SHARED_RULES.md), all feature work targets `staging` first; the CEO promotes `staging → main` separately. + + **What changed:** just the base branch — no code change. CI will re-run against `staging`. If you get merge conflicts, rebase on `staging`. + + **If this PR is the CEO's staging→main promotion:** the Action skipped you (only bot-authored PRs are retargeted). If you see this comment on your CEO PR, that's a bug — please tag @HongmingWang-Rabbit. + BODY + )"