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 + )"