diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 5e22c859a5..b415cb117f 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -47,6 +47,7 @@ jobs: build-type: ['RelWithDebInfo'] runs-on: ${{ matrix.runner }}${{ github.ref == 'refs/heads/amd-npi' && '-npi' || '' }}-emu-runner-set + if: github.event.pull_request.head.repo.full_name == 'AMD-ROCm-Internal/aqlprofile' permissions: contents: read @@ -94,7 +95,7 @@ jobs: -S ./dashboard.cmake core-rpm: - if: github.ref != 'refs/heads/amd-npi' + if: github.ref != 'refs/heads/amd-npi' && github.event.pull_request.head.repo.full_name == 'AMD-ROCm-Internal/aqlprofile' # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix strategy: fail-fast: false diff --git a/.github/workflows/external-pr-close.yml b/.github/workflows/external-pr-close.yml new file mode 100644 index 0000000000..fc5045d95d --- /dev/null +++ b/.github/workflows/external-pr-close.yml @@ -0,0 +1,102 @@ +name: Close external PR + +on: + pull_request_target: + types: [closed] + branches: + - amd-staging + +jobs: + git-mirror: + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name == 'AMD-ROCm-Internal/aqlprofile' && contains(github.event.pull_request.head.ref, 'external-pr') + steps: + - name: Get Current PR Body + id: current_pr + run: | + # Use the PR body directly from the event payload + # This is the body as it was when the 'opened' or 'edited' event was triggered. + RAW_PR_BODY="${{ github.event.pull_request.body }}" + + # Handle cases where the body might be null (e.g., an empty PR description) + # In bash, an unset or null variable in quotes becomes an empty string, + # but it's good practice to be explicit or test. + # If RAW_PR_BODY is null from the JSON payload, it will be treated as an empty string here by bash. + # For more robust null handling if needed elsewhere: PR_BODY_FOR_SCRIPT="${RAW_PR_BODY:-}" + PR_BODY_FOR_SCRIPT="$RAW_PR_BODY" + + echo "PR Body from event payload (first 500 chars):" + echo "${PR_BODY_FOR_SCRIPT:0:500}" # Print a snippet for logging + echo "-------------------" + + # If you need to pass this body to subsequent steps via GITHUB_OUTPUT, + # the multiline escaping is still crucial. + ESCAPED_PR_BODY="${RAW_PR_BODY//'%'/'%25'}" + ESCAPED_PR_BODY="${ESCAPED_PR_BODY//$'\n'/'%0A'}" + ESCAPED_PR_BODY="${ESCAPED_PR_BODY//$'\r'/'%0D'}" + + echo "PR_BODY_CONTENT<> $GITHUB_OUTPUT + echo "$ESCAPED_PR_BODY" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Extract Remote PR URL and Info + id: remote_pr_info + run: | + PR_BODY="${{ steps.current_pr.outputs.PR_BODY_CONTENT }}" + echo "Current PR Body:" + echo "${PR_BODY}" + echo "-------------------" + + # Regex to find GitHub PR URLs. This is a common pattern. + # It captures owner, repo, and pr_number. + REMOTE_PR_URL_REGEX="https://github.com/([^/]+)/([^/]+)/pull/([0-9]+)" + + if [[ "$PR_BODY" =~ $REMOTE_PR_URL_REGEX ]]; then + REMOTE_PR_URL="${BASH_REMATCH[0]}" + REMOTE_OWNER="${BASH_REMATCH[1]}" + REMOTE_REPO="${BASH_REMATCH[2]}" + REMOTE_PR_NUMBER="${BASH_REMATCH[3]}" + + echo "Found Remote PR URL: $REMOTE_PR_URL" + echo "Remote Owner: $REMOTE_OWNER" + echo "Remote Repo: $REMOTE_REPO" + echo "Remote PR Number: $REMOTE_PR_NUMBER" + + echo "REMOTE_PR_URL=$REMOTE_PR_URL" >> $GITHUB_OUTPUT + echo "REMOTE_OWNER=$REMOTE_OWNER" >> $GITHUB_OUTPUT + echo "REMOTE_REPO=$REMOTE_REPO" >> $GITHUB_OUTPUT + echo "REMOTE_PR_NUMBER=$REMOTE_PR_NUMBER" >> $GITHUB_OUTPUT + echo "FOUND_URL=true" >> $GITHUB_OUTPUT + else + echo "::warning::No GitHub PR URL found in the current PR body." + echo "FOUND_URL=false" >> $GITHUB_OUTPUT + fi + + - name: Output Results + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' + run: | + echo "Successfully retrieved branch info from remote PR." + echo "Remote PR URL: ${{ steps.remote_pr_info.outputs.REMOTE_PR_URL }}" + + - name: Handle No URL Found + if: steps.remote_pr_info.outputs.FOUND_URL == 'false' + run: | + echo "No remote PR URL was found in the body of PR #${{ github.event.pull_request.number }}." + + - name: Comment on and Close External PR + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' + env: + GH_TOKEN: ${{ secrets.EXT_TOKEN }} + EXTERNAL_PR_NUMBER: ${{ steps.remote_pr_info.outputs.REMOTE_PR_NUMBER }} + EXTERNAL_REPO: "ROCm/aqlprofile" + run: | + COMMENT_BODY="This pull request has been closed in the internal repository. Thank you for your contribution!" + + gh pr comment "$EXTERNAL_PR_NUMBER" \ + --repo "$EXTERNAL_REPO" \ + --body "$COMMENT_BODY" + + gh pr close "$EXTERNAL_PR_NUMBER" \ + --repo "$EXTERNAL_REPO" + + echo "Commented on and Closed external PR #${EXTERNAL_PR_NUMBER}" diff --git a/.github/workflows/external-pr-sync.yml b/.github/workflows/external-pr-sync.yml new file mode 100644 index 0000000000..5618fc8cc6 --- /dev/null +++ b/.github/workflows/external-pr-sync.yml @@ -0,0 +1,132 @@ +name: Sync external PR branch to public repository + +on: + pull_request_target: + branches: + - amd-staging + +jobs: + git-mirror: + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name == 'AMD-ROCm-Internal/aqlprofile' && contains(github.event.pull_request.head.ref, 'external-pr') + steps: + - name: Get Current PR Body + id: current_pr + run: | + # Use the PR body directly from the event payload + # This is the body as it was when the 'opened' or 'edited' event was triggered. + RAW_PR_BODY="${{ github.event.pull_request.body }}" + + # Handle cases where the body might be null (e.g., an empty PR description) + # In bash, an unset or null variable in quotes becomes an empty string, + # but it's good practice to be explicit or test. + # If RAW_PR_BODY is null from the JSON payload, it will be treated as an empty string here by bash. + # For more robust null handling if needed elsewhere: PR_BODY_FOR_SCRIPT="${RAW_PR_BODY:-}" + PR_BODY_FOR_SCRIPT="$RAW_PR_BODY" + + echo "PR Body from event payload (first 500 chars):" + echo "${PR_BODY_FOR_SCRIPT:0:500}" # Print a snippet for logging + echo "-------------------" + + # If you need to pass this body to subsequent steps via GITHUB_OUTPUT, + # the multiline escaping is still crucial. + ESCAPED_PR_BODY="${RAW_PR_BODY//'%'/'%25'}" + ESCAPED_PR_BODY="${ESCAPED_PR_BODY//$'\n'/'%0A'}" + ESCAPED_PR_BODY="${ESCAPED_PR_BODY//$'\r'/'%0D'}" + + echo "PR_BODY_CONTENT<> $GITHUB_OUTPUT + echo "$ESCAPED_PR_BODY" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Extract Remote PR URL and Info + id: remote_pr_info + run: | + PR_BODY="${{ steps.current_pr.outputs.PR_BODY_CONTENT }}" + echo "Current PR Body:" + echo "${PR_BODY}" + echo "-------------------" + + # Regex to find GitHub PR URLs. This is a common pattern. + # It captures owner, repo, and pr_number. + REMOTE_PR_URL_REGEX="https://github.com/([^/]+)/([^/]+)/pull/([0-9]+)" + + if [[ "$PR_BODY" =~ $REMOTE_PR_URL_REGEX ]]; then + REMOTE_PR_URL="${BASH_REMATCH[0]}" + REMOTE_OWNER="${BASH_REMATCH[1]}" + REMOTE_REPO="${BASH_REMATCH[2]}" + REMOTE_PR_NUMBER="${BASH_REMATCH[3]}" + + echo "Found Remote PR URL: $REMOTE_PR_URL" + echo "Remote Owner: $REMOTE_OWNER" + echo "Remote Repo: $REMOTE_REPO" + echo "Remote PR Number: $REMOTE_PR_NUMBER" + + echo "REMOTE_PR_URL=$REMOTE_PR_URL" >> $GITHUB_OUTPUT + echo "REMOTE_OWNER=$REMOTE_OWNER" >> $GITHUB_OUTPUT + echo "REMOTE_REPO=$REMOTE_REPO" >> $GITHUB_OUTPUT + echo "REMOTE_PR_NUMBER=$REMOTE_PR_NUMBER" >> $GITHUB_OUTPUT + echo "FOUND_URL=true" >> $GITHUB_OUTPUT + else + echo "::warning::No GitHub PR URL found in the current PR body." + echo "FOUND_URL=false" >> $GITHUB_OUTPUT + fi + + - name: Fetch Remote PR Branch Name + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' + id: remote_pr_branch + env: + GH_TOKEN: ${{ secrets.EXT_TOKEN }} + REMOTE_OWNER: ${{ steps.remote_pr_info.outputs.REMOTE_OWNER }} + REMOTE_REPO: ${{ steps.remote_pr_info.outputs.REMOTE_REPO }} + REMOTE_PR_NUMBER: ${{ steps.remote_pr_info.outputs.REMOTE_PR_NUMBER }} + run: | + if [ -n "$GH_TOKEN" ]; then + echo "Using provided TOKEN." + ACTUAL_GH_TOKEN="$GH_TOKEN" + else + echo "::error::No token available." + exit 1 + fi + + echo "Fetching branch name for $REMOTE_OWNER/$REMOTE_REPO/pull/$REMOTE_PR_NUMBER" + REMOTE_BRANCH_NAME=$(GH_TOKEN="$ACTUAL_GH_TOKEN" gh pr view "$REMOTE_PR_NUMBER" \ + --repo "$REMOTE_OWNER/$REMOTE_REPO" \ + --json headRefName --jq .headRefName) + + if [ -n "$REMOTE_BRANCH_NAME" ]; then + echo "Remote PR Branch Name: $REMOTE_BRANCH_NAME" + echo "REMOTE_BRANCH_NAME=$REMOTE_BRANCH_NAME" >> $GITHUB_OUTPUT + else + echo "::error::Could not retrieve branch name for remote PR $REMOTE_OWNER/$REMOTE_REPO/pull/$REMOTE_PR_NUMBER. Check PAT permissions or PR validity." + # Optionally exit 1 if this is critical + # exit 1 + fi + + - name: Output Results + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' && steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME + run: | + echo "Successfully retrieved branch name from remote PR." + echo "Remote PR URL: ${{ steps.remote_pr_info.outputs.REMOTE_PR_URL }}" + echo "Remote PR Branch Name: ${{ steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME }}" + # You can now use ${{ steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME }} in subsequent steps + # For example, create an artifact, comment on PR A, trigger another workflow, etc. + + - name: Handle No URL Found + if: steps.remote_pr_info.outputs.FOUND_URL == 'false' + run: | + echo "No remote PR URL was found in the body of PR #${{ github.event.pull_request.number }}." + + - name: Handle Branch Not Found + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' && !steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME + run: | + echo "A remote PR URL was found, but its branch name could not be retrieved." + echo "URL: ${{ steps.remote_pr_info.outputs.REMOTE_PR_URL }}" + + - name: Sync + if: steps.remote_pr_info.outputs.FOUND_URL == 'true' && steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME + uses: AMD-ROCm-Internal/rocprofiler-github-actions@git-sync-v3 + with: + source_repo: "https://${{ secrets.TOKEN }}@github.com/AMD-ROCm-Internal/aqlprofile.git" + source_branch: "${{ github.event.pull_request.head.ref }}" + destination_repo: "https://${{ secrets.EXT_TOKEN }}@github.com/ROCm/aqlprofile.git" + destination_branch: "${{ steps.remote_pr_branch.outputs.REMOTE_BRANCH_NAME }}" diff --git a/.github/workflows/external-pr.yml b/.github/workflows/external-pr.yml new file mode 100644 index 0000000000..85b813c0eb --- /dev/null +++ b/.github/workflows/external-pr.yml @@ -0,0 +1,82 @@ +name: Mirror External PR to Internal Repo + +on: + pull_request_target: + types: [opened, synchronize] + branches: + - amd-staging + +jobs: + mirror_pr: + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name != 'AMD-ROCm-Internal/aqlprofile' + + steps: + - name: Checkout PR base + uses: actions/checkout@v4 + + - name: Setup Git User + run: | + git config --global user.name 'External PR Mirror Bot' + git config --global user.email 'bot@users.noreply.github.com' + + - uses: wei/git-sync@v3 + name: Push branch to Internal Repository + with: + source_repo: "https://${{ secrets.EXTERNAL_REPO_TOKEN }}@github.com/ROCm/aqlprofile.git" + source_branch: "${{ github.event.pull_request.head.ref }}" + destination_repo: "https://${{ secrets.INTERNAL_REPO_TOKEN }}@github.com/AMD-ROCm-Internal/aqlprofile.git" + destination_branch: "external-pr/${{ github.event.pull_request.number }}" + + - name: Create Pull Request in Internal Repository + if: ${{ github.event.action == 'opened' }} + id: create_internal_pr + env: + GH_TOKEN: ${{ secrets.INTERNAL_REPO_TOKEN }} + INTERNAL_REPO: "AMD-ROCm-Internal/aqlprofile" + INTERNAL_BASE_BRANCH: "amd-staging" + HEAD_BRANCH: "external-pr/${{ github.event.pull_request.number }}" + PR_TITLE: "Mirror: ${{ github.event.pull_request.title }} (Ext PR #${{ github.event.pull_request.number }})" + PR_BODY: | + This PR mirrors changes from external pull request: ${{ github.event.pull_request.html_url }} + + Original PR Body: + ------------------- + ${{ github.event.pull_request.body }} + run: | + # Create PR and capture its URL + INTERNAL_PR_URL=$(gh pr create \ + --repo "$INTERNAL_REPO" \ + --base "$INTERNAL_BASE_BRANCH" \ + --head "$HEAD_BRANCH" \ + --title "$PR_TITLE" \ + --body "$PR_BODY") + + if [ -z "$INTERNAL_PR_URL" ]; then + echo "Failed to create internal PR. URL is empty." + # Check if PR already exists (gh pr create might not fail if branch has open PR) + EXISTING_PR_URL=$(gh pr list --repo "$INTERNAL_REPO" --head "$HEAD_BRANCH" --json url -q '.[0].url') + if [ -n "$EXISTING_PR_URL" ]; then + echo "Internal PR already exists: $EXISTING_PR_URL" + echo "INTERNAL_PR_URL=$EXISTING_PR_URL" >> $GITHUB_OUTPUT + else + echo "::error::Failed to create or find existing internal PR." + exit 1 + fi + fi + + + - name: Comment on and Close External PR + if: steps.create_internal_pr.outputs.INTERNAL_PR_URL != '' + env: + GH_TOKEN: ${{ secrets.EXTERNAL_REPO_TOKEN }} + EXTERNAL_PR_NUMBER: ${{ github.event.pull_request.number }} + EXTERNAL_REPO: ${{ github.repository }} + run: | + COMMENT_BODY="This pull request has been mirrored to our internal repository for review and integration. Thank you for your contribution!" + + gh pr comment "$EXTERNAL_PR_NUMBER" \ + --repo "$EXTERNAL_REPO" \ + --body "$COMMENT_BODY" + + echo "Commented on external PR #${EXTERNAL_PR_NUMBER}"