|
| 1 | +name: Mirror External PR to Internal Repo |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request_target: # IMPORTANT: Use pull_request_target for security |
| 5 | + types: [opened, synchronize] |
| 6 | + branches: |
| 7 | + - amd-staging |
| 8 | + |
| 9 | +permissions: |
| 10 | + pull-requests: write # To close and comment on the PR in the public repo |
| 11 | + contents: read # To checkout code |
| 12 | + |
| 13 | +jobs: |
| 14 | + mirror_pr: |
| 15 | + runs-on: ubuntu-latest |
| 16 | + if: github.event.pull_request.head.repo.full_name != 'AMD-ROCm-Internal/aqlprofile' # Avoid loops if internal creates a PR back |
| 17 | + |
| 18 | + steps: |
| 19 | + - name: Harden Runner |
| 20 | + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 |
| 21 | + with: |
| 22 | + egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs |
| 23 | + |
| 24 | + - name: Checkout PR base |
| 25 | + uses: actions/checkout@v4 |
| 26 | + # This checks out the base of the PR, not the PR head itself initially |
| 27 | + |
| 28 | + - name: Setup Git User |
| 29 | + run: | |
| 30 | + git config --global user.name 'External PR Mirror Bot' |
| 31 | + git config --global user.email 'bot@users.noreply.github.com' |
| 32 | +
|
| 33 | + - name: Fetch PR branch from fork/external |
| 34 | + env: |
| 35 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use built-in token to fetch from public fork |
| 36 | + run: | |
| 37 | + # The PR branch is available at 'refs/pull/PULL_REQUEST_NUMBER/head' |
| 38 | + # We fetch it into a local branch with a unique name |
| 39 | + # Using github.event.pull_request.head.sha ensures we get the exact commit |
| 40 | + git fetch origin pull/${{ github.event.pull_request.number }}/head:external-pr-${{ github.event.pull_request.number }} |
| 41 | + git checkout external-pr-${{ github.event.pull_request.number }} |
| 42 | + echo "Checked out PR branch: external-pr-${{ github.event.pull_request.number }}" |
| 43 | + git show --summary # Show commit details |
| 44 | +
|
| 45 | + - name: Push branch to Internal Repository |
| 46 | + env: |
| 47 | + INTERNAL_REPO_PAT: ${{ secrets.INTERNAL_REPO_PAT }} |
| 48 | + INTERNAL_REPO_URL: "https://x-access-token:${{ secrets.INTERNAL_REPO_PAT }}@github.com/AMD-ROCm-Internal/aqlprofile.git" |
| 49 | + INTERNAL_BRANCH_NAME: "external-pr-${{ github.event.pull_request.number }}" |
| 50 | + run: | |
| 51 | + git remote add internal_mirror "${INTERNAL_REPO_URL}" |
| 52 | + git push internal_mirror "refs/heads/${INTERNAL_BRANCH_NAME}:refs/heads/${INTERNAL_BRANCH_NAME}" --force |
| 53 | + echo "Pushed to internal repository as branch ${INTERNAL_BRANCH_NAME}" |
| 54 | +
|
| 55 | + - name: Create Pull Request in Internal Repository |
| 56 | + id: create_internal_pr |
| 57 | + env: |
| 58 | + GH_TOKEN: ${{ secrets.INTERNAL_REPO_PAT }} # PAT for internal repo actions |
| 59 | + INTERNAL_REPO: "AMD-ROCm-Internal/aqlprofile" |
| 60 | + INTERNAL_BASE_BRANCH: "amd-staging" # Change if your internal default branch is different |
| 61 | + HEAD_BRANCH: "external-pr-${{ github.event.pull_request.number }}" |
| 62 | + PR_TITLE: "Mirror: ${{ github.event.pull_request.title }} (Ext PR #${{ github.event.pull_request.number }})" |
| 63 | + PR_BODY: | |
| 64 | + This PR mirrors changes from external pull request: ${{ github.event.pull_request.html_url }} |
| 65 | +
|
| 66 | + Original PR Body: |
| 67 | + ------------------- |
| 68 | + ${{ github.event.pull_request.body }} |
| 69 | + run: | |
| 70 | + # Create PR and capture its URL |
| 71 | + INTERNAL_PR_URL=$(gh pr create \ |
| 72 | + --repo "$INTERNAL_REPO" \ |
| 73 | + --base "$INTERNAL_BASE_BRANCH" \ |
| 74 | + --head "$HEAD_BRANCH" \ |
| 75 | + --title "$PR_TITLE" \ |
| 76 | + --body "$PR_BODY") |
| 77 | +
|
| 78 | + if [ -z "$INTERNAL_PR_URL" ]; then |
| 79 | + echo "Failed to create internal PR. URL is empty." |
| 80 | + # Check if PR already exists (gh pr create might not fail if branch has open PR) |
| 81 | + EXISTING_PR_URL=$(gh pr list --repo "$INTERNAL_REPO" --head "$HEAD_BRANCH" --json url -q '.[0].url') |
| 82 | + if [ -n "$EXISTING_PR_URL" ]; then |
| 83 | + echo "Internal PR already exists: $EXISTING_PR_URL" |
| 84 | + echo "INTERNAL_PR_URL=$EXISTING_PR_URL" >> $GITHUB_OUTPUT |
| 85 | + else |
| 86 | + echo "::error::Failed to create or find existing internal PR." |
| 87 | + exit 1 |
| 88 | + fi |
| 89 | + else |
| 90 | + echo "Internal PR created: $INTERNAL_PR_URL" |
| 91 | + echo "INTERNAL_PR_URL=$INTERNAL_PR_URL" >> $GITHUB_OUTPUT |
| 92 | + fi |
| 93 | +
|
| 94 | +
|
| 95 | + - name: Comment on and Close External PR |
| 96 | + if: steps.create_internal_pr.outputs.INTERNAL_PR_URL != '' # Only if internal PR was created/found |
| 97 | + env: |
| 98 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Built-in token for actions on ROCm/aqlprofile |
| 99 | + EXTERNAL_PR_NUMBER: ${{ github.event.pull_request.number }} |
| 100 | + EXTERNAL_REPO: ${{ github.repository }} # e.g., ROCm/aqlprofile |
| 101 | + INTERNAL_PR_URL: ${{ steps.create_internal_pr.outputs.INTERNAL_PR_URL }} |
| 102 | + run: | |
| 103 | + COMMENT_BODY="This pull request has been mirrored to our internal repository for review and integration: ${INTERNAL_PR_URL} . This external PR will now be closed. Thank you for your contribution!" |
| 104 | +
|
| 105 | + gh pr comment "$EXTERNAL_PR_NUMBER" \ |
| 106 | + --repo "$EXTERNAL_REPO" \ |
| 107 | + --body "$COMMENT_BODY" |
| 108 | +
|
| 109 | + echo "Commented on external PR #${EXTERNAL_PR_NUMBER}" |
0 commit comments