fix(api): sign S3 report download URLs with Signature Version 4 #15037
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 'Tools: PR Conflict Checker' | |
| on: | |
| # zizmor: ignore[dangerous-triggers] - intentional: needs write access for conflict labels/comments, checkout uses PR head SHA for read-only grep | |
| pull_request_target: | |
| types: | |
| - 'opened' | |
| - 'synchronize' | |
| - 'reopened' | |
| branches: | |
| - 'master' | |
| - 'v5.*' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: {} | |
| jobs: | |
| check-conflicts: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout PR head | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| fetch-depth: 1 | |
| persist-credentials: false # No write token in the untrusted PR-head tree; public repo so base fetch/changed-files work unauthenticated | |
| - name: Fetch PR base ref for tj-actions/changed-files | |
| env: | |
| BASE_REF: ${{ github.event.pull_request.base.ref }} | |
| run: git fetch --depth=1 origin "${BASE_REF}" | |
| - name: Get changed files | |
| id: changed-files | |
| uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6 | |
| with: | |
| files: '**' | |
| safe_output: false # Raw paths (list read via env var, injection-safe); default escaping backslash-quotes chars like () and breaks the -f test | |
| separator: "\n" # Newline-delimited so the reader tolerates spaces and glob chars in paths | |
| - name: Check for conflict markers | |
| id: conflict-check | |
| run: | | |
| echo "Checking for conflict markers in changed files..." | |
| CONFLICT_FILES="" | |
| HAS_CONFLICTS=false | |
| # Read newline-delimited paths so spaces/globs neither word-split nor glob-expand | |
| while IFS= read -r file; do | |
| [ -n "$file" ] || continue | |
| [ -f "$file" ] || continue | |
| echo "Checking file: $file" | |
| if grep -qE '^(<<<<<<<|=======|>>>>>>>)' "$file" 2>/dev/null; then | |
| echo "Conflict markers found in: $file" | |
| CONFLICT_FILES="${CONFLICT_FILES}- \`${file}\`"$'\n' | |
| HAS_CONFLICTS=true | |
| fi | |
| done <<< "$STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES" | |
| if [ "$HAS_CONFLICTS" = true ]; then | |
| echo "has_conflicts=true" >> "$GITHUB_OUTPUT" | |
| { | |
| echo "conflict_files<<EOF" | |
| echo "$CONFLICT_FILES" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "Conflict markers detected" | |
| else | |
| echo "has_conflicts=false" >> "$GITHUB_OUTPUT" | |
| echo "No conflict markers found in changed files" | |
| fi | |
| env: | |
| STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} | |
| - name: Check base-branch mergeability | |
| id: merge-check | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| MERGEABLE=null | |
| # GitHub computes mergeability async, so .mergeable is null until ready; poll until resolved | |
| for attempt in 1 2 3 4 5; do | |
| MERGEABLE=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.mergeable') | |
| if [ "$MERGEABLE" != "null" ]; then | |
| break | |
| fi | |
| echo "Attempt ${attempt}: mergeability not computed yet, retrying..." | |
| sleep 3 | |
| done | |
| # Keep 'unknown' distinct from 'clean' so we never assert a clean merge we could not confirm | |
| case "$MERGEABLE" in | |
| false) STATUS=conflict; echo "PR branch cannot be merged cleanly into its base branch" ;; | |
| true) STATUS=clean; echo "PR branch merges cleanly into its base branch" ;; | |
| *) STATUS=unknown; echo "::warning::Mergeability did not resolve after retries; leaving it undetermined" ;; | |
| esac | |
| echo "merge_status=${STATUS}" >> "$GITHUB_OUTPUT" | |
| - name: Manage conflict label | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| HAS_CONFLICTS: ${{ steps.conflict-check.outputs.has_conflicts }} | |
| MERGE_STATUS: ${{ steps.merge-check.outputs.merge_status }} | |
| run: | | |
| LABEL_NAME="has-conflicts" | |
| if [ "$HAS_CONFLICTS" = "true" ] || [ "$MERGE_STATUS" = "conflict" ]; then | |
| echo "Adding conflict label to PR #${PR_NUMBER}..." | |
| gh pr edit "$PR_NUMBER" --add-label "$LABEL_NAME" --repo ${{ github.repository }} || true | |
| elif [ "$MERGE_STATUS" = "unknown" ]; then | |
| # Don't drop the label on an undetermined merge state; a later run will settle it | |
| echo "Mergeability undetermined; leaving label unchanged" | |
| else | |
| echo "Removing conflict label from PR #${PR_NUMBER}..." | |
| gh pr edit "$PR_NUMBER" --remove-label "$LABEL_NAME" --repo ${{ github.repository }} || true | |
| fi | |
| - name: Find existing comment | |
| uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0 | |
| id: find-comment | |
| with: | |
| issue-number: ${{ github.event.pull_request.number }} | |
| comment-author: 'github-actions[bot]' | |
| body-includes: '<!-- conflict-checker-comment -->' | |
| - name: Create or update comment | |
| uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 | |
| with: | |
| comment-id: ${{ steps.find-comment.outputs.comment-id }} | |
| issue-number: ${{ github.event.pull_request.number }} | |
| edit-mode: replace | |
| body: | | |
| <!-- conflict-checker-comment --> | |
| ${{ (steps.conflict-check.outputs.has_conflicts == 'true' || steps.merge-check.outputs.merge_status == 'conflict') && '⚠️ **Conflicts Detected**' || (steps.merge-check.outputs.merge_status == 'unknown' && 'ℹ️ **Conflict Check Incomplete**' || '✅ **No Conflicts**') }} | |
| ${{ steps.conflict-check.outputs.has_conflicts == 'true' && format(' | |
| **Conflict markers** are present in the following files: | |
| {0} | |
| Resolve them by removing every `<<<<<<<`, `=======`, and `>>>>>>>` marker, then commit and push.', steps.conflict-check.outputs.conflict_files) || '' }} | |
| ${{ steps.merge-check.outputs.merge_status == 'conflict' && ' | |
| **Merge conflict with the base branch.** This PR cannot be merged cleanly. Update your branch with the latest base (rebase or merge) and resolve the conflicts.' || '' }} | |
| ${{ steps.merge-check.outputs.merge_status == 'unknown' && ' | |
| GitHub had not finished computing mergeability, so base-branch conflict status could not be verified on this run.' || '' }} | |
| ${{ (steps.conflict-check.outputs.has_conflicts != 'true' && steps.merge-check.outputs.merge_status == 'clean') && ' | |
| No conflict markers, and the branch merges cleanly into its base.' || '' }} | |
| - name: Fail workflow if conflicts detected | |
| if: steps.conflict-check.outputs.has_conflicts == 'true' || steps.merge-check.outputs.merge_status == 'conflict' | |
| env: | |
| HAS_CONFLICTS: ${{ steps.conflict-check.outputs.has_conflicts }} | |
| MERGE_STATUS: ${{ steps.merge-check.outputs.merge_status }} | |
| run: | | |
| [ "$HAS_CONFLICTS" = "true" ] && echo "::error::Conflict markers detected in changed files" | |
| [ "$MERGE_STATUS" = "conflict" ] && echo "::error::PR branch has merge conflicts with the base branch" | |
| exit 1 |