name: PR Trigger Reality Sync on: issue_comment: types: [created] pull_request_target: types: [synchronize] jobs: # Post a helpful message when unauthorized users try to trigger sync unauthorized-message: if: | github.event_name == 'issue_comment' && github.event.issue.pull_request && ( contains(github.event.comment.body, '@rerun-bot reality-sync') || contains(github.event.comment.body, '@rerun-bot sync-reality') ) && github.event.comment.user.type != 'Bot' && github.event.comment.author_association != 'OWNER' && github.event.comment.author_association != 'MEMBER' runs-on: ubuntu-latest steps: - name: Create GitHub App token id: app-token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.SYNC_APP_ID }} private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }} owner: rerun-io repositories: rerun - name: Post unauthorized message env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | gh pr comment ${{ github.event.issue.number }} \ --repo ${{ github.repository }} \ --body "Sorry, only organization members can trigger reality-sync." trigger-import: # For issue_comment: org members (OWNER/MEMBER) can trigger with '@rerun-bot reality-sync' or '@rerun-bot sync-reality' # For pull_request_target: only auto-sync non-fork PRs (fork PRs require explicit comment trigger) if: | ( github.event_name == 'issue_comment' && github.event.issue.pull_request && ( contains(github.event.comment.body, '@rerun-bot reality-sync') || contains(github.event.comment.body, '@rerun-bot sync-reality') ) && github.event.comment.user.type != 'Bot' && ( github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' ) ) || ( github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name == github.repository ) runs-on: ubuntu-latest defaults: run: shell: bash --noprofile --norc -euo pipefail {0} steps: - name: Create GitHub App token id: app-token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.SYNC_APP_ID }} private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }} owner: rerun-io repositories: | reality rerun - name: Acknowledge command (eyes reaction) if: github.event_name == 'issue_comment' env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | gh api -X POST \ /repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions \ -f content=eyes - name: Determine PR number id: pr-info run: | if [ "${{ github.event_name }}" = "issue_comment" ]; then echo "pr_number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT echo "triggered_by=${{ github.event.comment.user.login }}" >> $GITHUB_OUTPUT echo "trigger_type=comment" >> $GITHUB_OUTPUT else echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT echo "triggered_by=${{ github.event.sender.login }}" >> $GITHUB_OUTPUT echo "trigger_type=push" >> $GITHUB_OUTPUT fi - name: Check for existing sync comment (push events only) if: github.event_name == 'pull_request_target' id: check-sync-comment env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}" echo "Checking PR #${PR_NUMBER} for existing sync comment…" # Look for "Sync complete" comment from the sync bot (GitHub App) # Check performed_via_github_app.id matches our app to prevent spoofing SYNC_APP_ID="${{ vars.SYNC_APP_ID }}" SYNC_COMMENT=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ | jq -r --arg app_id "$SYNC_APP_ID" '.[] | select((.performed_via_github_app.id | tostring == $app_id) and (.body | contains("Sync complete. Mirror PR in reality:"))) | .id' \ | head -1) if [ -n "$SYNC_COMMENT" ]; then echo "has_sync=true" >> $GITHUB_OUTPUT echo "✓ Found existing sync comment, will re-sync on push" else echo "has_sync=false" >> $GITHUB_OUTPUT echo "No existing sync comment found, skipping auto-sync" fi - name: Get PR details if: | github.event_name == 'issue_comment' || steps.check-sync-comment.outputs.has_sync == 'true' env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}" echo "Fetching PR details for PR #${PR_NUMBER}…" gh pr view "$PR_NUMBER" \ --repo ${{ github.repository }} \ --json headRefName,headRepositoryOwner,headRepository,number,title,body,labels \ > /tmp/pr_data.json echo "PR data:" jq '.' /tmp/pr_data.json - name: Trigger reality sync workflow if: | github.event_name == 'issue_comment' || steps.check-sync-comment.outputs.has_sync == 'true' env: GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | echo "================================================" echo "Triggering repository_dispatch to reality repo" echo "Trigger type: ${{ steps.pr-info.outputs.trigger_type }}" echo "================================================" # Construct the entire payload using jq to avoid shell substitution # This ensures backticks and other special characters in title/body are handled safely jq -n \ --arg repo "${{ github.event.repository.name }}" \ --arg current_repo "${{ github.repository }}" \ --arg triggered_by "${{ steps.pr-info.outputs.triggered_by }}" \ --slurpfile pr_data /tmp/pr_data.json \ '{ event_type: "sync-import-pr", client_payload: { repo: $repo, pr_number: $pr_data[0].number, head_ref: $pr_data[0].headRefName, head_owner: $pr_data[0].headRepositoryOwner.login, head_repo: $pr_data[0].headRepository.name, title: $pr_data[0].title, body: ($pr_data[0].body // ""), labels: $pr_data[0].labels, is_fork: (("\($pr_data[0].headRepositoryOwner.login)/\($pr_data[0].headRepository.name)") != $current_repo), triggered_by: $triggered_by } }' > /tmp/dispatch_payload.json echo "Dispatch payload:" jq '.' /tmp/dispatch_payload.json # Make the API call with the JSON payload if gh api repos/rerun-io/reality/dispatches --input /tmp/dispatch_payload.json 2>&1; then echo "✓ Successfully dispatched sync-import-pr event to reality repo" echo "Note: repository_dispatch returns 204 No Content on success" echo "The reality repo should now be processing the import workflow" else echo "::error::Failed to dispatch repository_dispatch event to reality repo" echo "::error::This could be due to:" echo "::error:: 1. Insufficient permissions on the GitHub App token" echo "::error:: 2. Reality repo not found or not accessible" echo "::error:: 3. Network issues" exit 1 fi