Skip to content

Commit e7e38bb

Browse files
authored
[update] simplify premerge-ci (#750)
1 parent 84d2a1d commit e7e38bb

1 file changed

Lines changed: 20 additions & 320 deletions

File tree

.github/workflows/premerge-ci.yml

Lines changed: 20 additions & 320 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ on:
1010
branches:
1111
- main
1212
- develop
13-
push:
14-
branches:
15-
- ci/pr-**
1613

1714
env:
1815
REGION: us-west-2
@@ -26,158 +23,17 @@ env:
2623
ECR_REPOSITORY: "roboverse-dev"
2724

2825
jobs:
29-
prepare-or-promote:
30-
name: prepare-or-promote
31-
runs-on: ubuntu-latest
32-
permissions:
33-
contents: write
34-
pull-requests: write
35-
issues: write
36-
env:
37-
PRIV_CI_PUSH_TOKEN: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
38-
outputs:
39-
run_direct: ${{ steps.decide.outputs.run_direct }}
40-
pr_number: ${{ steps.decide.outputs.pr_number }}
41-
reason: ${{ steps.decide.outputs.reason }}
42-
steps:
43-
- name: Route CI flow
44-
id: decide
45-
env:
46-
GITHUB_EVENT_NAME: ${{ github.event_name }}
47-
GITHUB_REF: ${{ github.ref }}
48-
PR_NUMBER: ${{ github.event.pull_request.number || '' }}
49-
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name || '' }}
50-
BASE_REPO: ${{ github.repository }}
51-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52-
GITHUB_EVENT_PATH: ${{ github.event_path }}
53-
run: |
54-
RUN_DIRECT="false"
55-
PR_NUM="${PR_NUMBER}"
56-
REASON=""
57-
58-
case "$GITHUB_EVENT_NAME" in
59-
merge_group)
60-
BASE_REPO_NAME="${BASE_REPO}"
61-
HAS_FORK="false"
62-
PRS=$(jq -r '.merge_group.pull_requests[].number // empty' "$GITHUB_EVENT_PATH" 2>/dev/null || true)
63-
64-
if [ -z "$PRS" ]; then
65-
echo "No pull requests listed in merge_group payload; defaulting to same-repo."
66-
fi
67-
68-
for PR in $PRS; do
69-
HEAD_REPO_NAME=$(gh api "repos/${BASE_REPO_NAME}/pulls/${PR}" --jq '.head.repo.full_name' 2>/dev/null || echo "")
70-
BASE_REPO_FROM_PR=$(gh api "repos/${BASE_REPO_NAME}/pulls/${PR}" --jq '.base.repo.full_name' 2>/dev/null || echo "$BASE_REPO_NAME")
71-
72-
if [ -z "$HEAD_REPO_NAME" ]; then
73-
echo "Warning: could not determine head repo for PR #$PR; assuming same-repo."
74-
continue
75-
fi
76-
77-
if [ "$HEAD_REPO_NAME" != "$BASE_REPO_FROM_PR" ]; then
78-
HAS_FORK="true"
79-
echo "Detected fork PR #$PR (head repo: $HEAD_REPO_NAME, base repo: $BASE_REPO_FROM_PR)"
80-
else
81-
echo "PR #$PR is same-repo (head repo: $HEAD_REPO_NAME)"
82-
fi
83-
done
84-
85-
if [ "$HAS_FORK" = "true" ]; then
86-
RUN_DIRECT="false"
87-
REASON="merge_group_contains_fork"
88-
else
89-
RUN_DIRECT="true"
90-
REASON="merge_group_same_repo_only"
91-
fi
92-
;;
93-
push)
94-
if [[ "$GITHUB_REF" =~ ^refs/heads/ci/pr- ]]; then
95-
RUN_DIRECT="true"
96-
REASON="ci/pr-* push"
97-
PR_NUM="${GITHUB_REF#refs/heads/ci/pr-}"
98-
else
99-
REASON="unsupported push ref"
100-
fi
101-
;;
102-
workflow_dispatch)
103-
RUN_DIRECT="true"
104-
REASON="manual dispatch"
105-
;;
106-
pull_request_target)
107-
if [ "$HEAD_REPO" = "$BASE_REPO" ]; then
108-
REASON="same-repo PR, no promotion needed"
109-
else
110-
REASON="fork PR requires promotion"
111-
fi
112-
;;
113-
*)
114-
REASON="unsupported event"
115-
;;
116-
esac
117-
118-
echo "run_direct=${RUN_DIRECT}" >> "$GITHUB_OUTPUT"
119-
echo "pr_number=${PR_NUM}" >> "$GITHUB_OUTPUT"
120-
echo "reason=${REASON}" >> "$GITHUB_OUTPUT"
121-
122-
- name: Check actor permission
123-
id: perm
124-
if: >
125-
github.event_name == 'pull_request_target' &&
126-
steps.decide.outputs.reason == 'fork PR requires promotion' &&
127-
env.PRIV_CI_PUSH_TOKEN != '' &&
128-
env.PRIV_CI_PUSH_TOKEN != null
129-
env:
130-
ACTOR: ${{ github.actor }}
131-
REPO: ${{ github.repository }}
132-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133-
run: |
134-
perm=$(gh api "repos/$REPO/collaborators/$ACTOR/permission" --jq .permission 2>/dev/null || echo "none")
135-
echo "permission=$perm" >> "$GITHUB_OUTPUT"
136-
echo "Actor: $ACTOR, permission: $perm"
137-
138-
- name: Checkout repository for promotion
139-
if: >
140-
github.event_name == 'pull_request_target' &&
141-
steps.decide.outputs.reason == 'fork PR requires promotion' &&
142-
(steps.perm.outputs.permission == 'write' || steps.perm.outputs.permission == 'maintain' || steps.perm.outputs.permission == 'admin')
143-
uses: actions/checkout@v4
144-
with:
145-
fetch-depth: 0
146-
token: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
147-
148-
- name: Promote fork PR to ci/pr-* branch
149-
if: >
150-
github.event_name == 'pull_request_target' &&
151-
steps.decide.outputs.reason == 'fork PR requires promotion' &&
152-
(steps.perm.outputs.permission == 'write' || steps.perm.outputs.permission == 'maintain' || steps.perm.outputs.permission == 'admin')
153-
env:
154-
PR_NUMBER: ${{ steps.decide.outputs.pr_number }}
155-
REPO: ${{ github.repository }}
156-
GH_TOKEN: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
157-
run: |
158-
set -euo pipefail
159-
BRANCH="ci/pr-${PR_NUMBER}"
160-
git config --global user.name "github-actions[bot]"
161-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
162-
gh pr checkout "$PR_NUMBER"
163-
git push origin HEAD:"$BRANCH"
164-
165-
16626
pre-merge-tests:
167-
needs: prepare-or-promote
168-
if: needs.prepare-or-promote.outputs.run_direct == 'true'
27+
if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch'
16928
permissions:
170-
contents: write # Need write access to delete ci/pr-* branches
29+
contents: read
17130
pull-requests: write
172-
issues: write # Post status comment back to PR
31+
issues: write
17332
runs-on: codebuild-EC2_Launcher2-${{ github.run_id }}-${{ github.run_attempt }}
17433
timeout-minutes: 720
17534
steps:
176-
# change to the source code directory
17735
- name: Checkout code
17836
uses: actions/checkout@v4
179-
with:
180-
token: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
18137
- run: aws --version
18238
############# Prebuild ############
18339
- name: pre_build
@@ -540,182 +396,26 @@ jobs:
540396
if-no-files-found: warn
541397
retention-days: 7
542398

543-
544-
- name: Report commit status to PR
545-
if: always()
546-
uses: actions/github-script@v7
547-
env:
548-
JOB_STATUS: ${{ job.status }}
549-
PRIV_CI_PUSH_TOKEN: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
550-
with:
551-
github-token: ${{ secrets.PRIV_CI_PUSH_TOKEN }}
552-
script: |
553-
const status = process.env.JOB_STATUS;
554-
const ref = context.ref;
555-
556-
// Only report status for ci/pr-* branches
557-
const match = ref.match(/^refs\/heads\/ci\/pr-(\d+)$/);
558-
if (!match) {
559-
core.info(`Ref ${ref} is not a ci/pr-* branch, skip status reporting.`);
560-
return;
561-
}
562-
563-
const prNumber = Number(match[1]);
564-
565-
// Get the PR's HEAD SHA
566-
const { data: pr } = await github.rest.pulls.get({
567-
owner: context.repo.owner,
568-
repo: context.repo.repo,
569-
pull_number: prNumber
570-
});
571-
572-
const sha = pr.head.sha;
573-
core.info(`Reporting status to PR #${prNumber} commit ${sha}`);
574-
575-
// Map job status to commit status state
576-
let state, description;
577-
if (status === 'success') {
578-
state = 'success';
579-
description = 'Privileged CI tests passed';
580-
} else if (status === 'cancelled') {
581-
state = 'error';
582-
description = 'Privileged CI tests were cancelled';
583-
} else {
584-
state = 'failure';
585-
description = 'Privileged CI tests failed';
586-
}
587-
588-
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
589-
590-
// Create commit status
591-
await github.rest.repos.createCommitStatus({
592-
owner: context.repo.owner,
593-
repo: context.repo.repo,
594-
sha: sha,
595-
state: state,
596-
context: 'pre-merge-tests',
597-
description: description,
598-
target_url: runUrl
599-
});
600-
601-
core.info(`✅ Reported status '${state}' to commit ${sha}`);
602-
603-
- name: Clean up ci/pr-* branch
604-
if: always()
605-
run: |
606-
REF="${GITHUB_REF}"
607-
# Only delete if we're running on a ci/pr-* branch
608-
if [[ "$REF" =~ ^refs/heads/ci/pr-[0-9]+$ ]]; then
609-
BRANCH="${REF#refs/heads/}"
610-
echo "Cleaning up temporary branch: $BRANCH"
611-
# Delete the branch from remote (ignore errors if already deleted)
612-
git push origin --delete "$BRANCH" 2>/dev/null || echo "Branch $BRANCH already deleted or not found"
613-
echo "✓ Cleanup complete"
614-
else
615-
echo "Not a ci/pr-* branch (ref: $REF), skipping cleanup"
616-
fi
617-
618-
fork-merge-group-check:
619-
needs: prepare-or-promote
620-
if: needs.prepare-or-promote.outputs.reason == 'merge_group_contains_fork'
399+
workflow-integrity-check:
621400
runs-on: ubuntu-latest
401+
if: github.event_name == 'pull_request_target'
622402
permissions:
623-
statuses: write
403+
pull-requests: read
624404
steps:
625-
- name: Check pre-merge-tests status for fork PRs
405+
- name: Check for workflow changes
626406
env:
627407
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
628-
GITHUB_REPOSITORY: ${{ github.repository }}
629-
GITHUB_EVENT_PATH: ${{ github.event_path }}
408+
PR_NUMBER: ${{ github.event.pull_request.number }}
630409
run: |
631-
set -euo pipefail
632-
633-
echo "merge_group contains fork PR(s). Checking pre-merge-tests commit statuses..."
634-
635-
# Extract PR numbers from merge_group payload
636-
PRS=$(jq -r '.merge_group.pull_requests[].number // empty' "$GITHUB_EVENT_PATH" 2>/dev/null || true)
637-
638-
if [ -z "$PRS" ]; then
639-
echo "⚠️ Warning: No pull requests listed in merge_group payload."
640-
echo "This is unexpected. Proceeding with caution (passing)."
641-
exit 0
642-
fi
643-
644-
ALL_PASSED=true
645-
for PR in $PRS; do
646-
# Check if this is a fork PR
647-
PR_DATA=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR}" 2>/dev/null || echo "{}")
648-
HEAD_REPO=$(echo "$PR_DATA" | jq -r '.head.repo.full_name // ""')
649-
BASE_REPO=$(echo "$PR_DATA" | jq -r '.base.repo.full_name // ""')
650-
HEAD_SHA=$(echo "$PR_DATA" | jq -r '.head.sha // ""')
651-
652-
if [ "$HEAD_REPO" = "$BASE_REPO" ]; then
653-
echo "PR #$PR is same-repo, skipping status check."
654-
continue
655-
fi
656-
657-
if [ -z "$HEAD_SHA" ]; then
658-
echo "❌ Could not get HEAD SHA for PR #$PR."
659-
ALL_PASSED=false
660-
continue
661-
fi
662-
663-
echo "PR #$PR is from fork ($HEAD_REPO). Checking commit status for $HEAD_SHA..."
664-
665-
# Get the combined status for the commit
666-
STATUS_DATA=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${HEAD_SHA}/status" 2>/dev/null || echo "{}")
667-
668-
# Find the pre-merge-tests status
669-
PRIV_STATUS=$(echo "$STATUS_DATA" | jq -r '.statuses[] | select(.context == "pre-merge-tests") | .state' | head -1)
670-
671-
echo " Commit: $HEAD_SHA"
672-
echo " pre-merge-tests status: ${PRIV_STATUS:-not found}"
673-
674-
if [ -z "$PRIV_STATUS" ]; then
675-
echo "❌ No pre-merge-tests status found for PR #$PR. Please ensure the ci/pr-* run completed."
676-
ALL_PASSED=false
677-
elif [ "$PRIV_STATUS" = "pending" ]; then
678-
echo "⏳ pre-merge-tests is still pending for PR #$PR. Please wait for completion."
679-
ALL_PASSED=false
680-
elif [ "$PRIV_STATUS" != "success" ]; then
681-
echo "❌ pre-merge-tests status is '$PRIV_STATUS' for PR #$PR."
682-
ALL_PASSED=false
683-
else
684-
echo "✅ pre-merge-tests passed for PR #$PR."
685-
fi
686-
done
687-
688-
if [ "$ALL_PASSED" = "true" ]; then
689-
echo ""
690-
echo "All fork PR privileged tests have passed. Merge queue check succeeded."
691-
exit 0
692-
else
693-
echo ""
694-
echo "One or more fork PR privileged tests have not passed. Failing merge queue check."
695-
exit 1
696-
fi
697-
698-
- name: Report pre-merge-tests status to merge group commit
699-
if: always()
700-
env:
701-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
702-
MERGE_GROUP_SHA: ${{ github.event.merge_group.head_sha }}
703-
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
704-
JOB_STATUS: ${{ job.status }}
705-
run: |
706-
if [ "$JOB_STATUS" = "success" ]; then
707-
STATE="success"
708-
DESCRIPTION="Fork PR privileged tests verified"
709-
else
710-
STATE="failure"
711-
DESCRIPTION="Fork PR privileged tests failed"
712-
fi
713-
714-
echo "Reporting pre-merge-tests status ($STATE) to merge group commit ${MERGE_GROUP_SHA}..."
715-
gh api "repos/${{ github.repository }}/statuses/${MERGE_GROUP_SHA}" \
716-
-X POST \
717-
-f state=$STATE \
718-
-f context=pre-merge-tests \
719-
-f description="$DESCRIPTION" \
720-
-f target_url="${RUN_URL}"
721-
echo "✅ Successfully reported pre-merge-tests status."
410+
set -euo pipefail
411+
echo "Checking if .github/workflows/premerge-ci.yml is modified in PR #$PR_NUMBER..."
412+
CHANGES=$(gh pr diff "$PR_NUMBER" --name-only)
413+
414+
if echo "$CHANGES" | grep -q "^.github/workflows/premerge-ci.yml$"; then
415+
echo "❌ Critical workflow modification detected!"
416+
echo "For security reasons, this workflow file cannot be modified via Pull Request."
417+
echo "Please revert changes to .github/workflows/premerge-ci.yml to pass this check."
418+
exit 1
419+
fi
420+
421+
echo "✅ Workflow integrity verified (file not modified)."

0 commit comments

Comments
 (0)