BAU: guardrail duplicate job names for required status checks #6
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: Guardrail unique GHA workflow job names | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - whi-tw/guardrail_unique_workflow_names_for_status_checks # TODO: remove this branch before merging | |
| paths: | |
| - ".github/workflows/*.yml" | |
| - ".github/workflows/*.yaml" | |
| jobs: | |
| guardrail_unique_job_names: | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v5.0.0 | |
| - name: Ensure unique job names | |
| env: | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| TARGET_BRANCH: main | |
| GHA_INTEGRATION_ID: 15368 # GitHub Actions integration ID for status checks (this is derived, not published) | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # fetch legacy branch protection required checks | |
| branch_protection_checks=$(gh api "repos/${GITHUB_REPOSITORY}/branches/${TARGET_BRANCH}/protection/required_status_checks" 2>/dev/null | \ | |
| jq --argjson INTEGRATION_ID "$GHA_INTEGRATION_ID" '[.checks[] | select(.integration_id==$INTEGRATION_ID)]? // []') | |
| # fetch ruleset required checks | |
| ruleset_checks=$(gh api "repos/${GITHUB_REPOSITORY}/rules/branches/${TARGET_BRANCH}" | \ | |
| jq --argjson INTEGRATION_ID "$GHA_INTEGRATION_ID" '[.[] | select(.type=="required_status_checks") | .parameters.required_status_checks[] | select(.integration_id==$INTEGRATION_ID)]? // []') | |
| # Combine and deduplicate both sources of required checks | |
| required_checks="$(jq -n --argjson bp "$branch_protection_checks" --argjson rs "$ruleset_checks" \ | |
| '$bp + $rs | map(.context) | unique')" | |
| # Ensure that at least one required check exists | |
| if [ "$(echo "$required_checks" | jq 'length')" -eq 0 ]; then | |
| echo "⚠️ Warning: No required status checks found for branch '${TARGET_BRANCH}'. This is incorrect." | |
| echo "Please ensure at least one workflow job is marked as a required status check in branch protection rules or rulesets." | |
| echo "It's possible that the integration ID for GitHub Actions status checks has changed from ${GHA_INTEGRATION_ID}." | |
| echo "Legacy branch protection checks:" | |
| gh api "repos/${GITHUB_REPOSITORY}/branches/${TARGET_BRANCH}/protection/required_status_checks" | jq '.checks[]? // []' | |
| echo "" | |
| echo "Ruleset checks:" | |
| gh api "repos/${GITHUB_REPOSITORY}/rules/branches/${TARGET_BRANCH}" | jq '[.[] | select(.type=="required_status_checks") | .parameters.required_status_checks[]]? // []' | |
| echo "" | |
| echo "If you see checks above but they are not being picked up, please update the GHA_INTEGRATION_ID in this workflow file." | |
| exit 2 | |
| fi | |
| # Build a map of job names to their source files | |
| job_files="$(find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) -print0 | while IFS= read -r -d '' file; do | |
| filename="$(basename "$file")" | |
| yq eval --output-format=json '.jobs | to_entries | .[] | select(.value.name != null) | .value.name' "$file" | \ | |
| jq --arg file "$filename" '{name: ., file: $file}' | |
| done | jq -s '.')" | |
| # Group by job name and find duplicates (with their files) | |
| duplicates="$(echo "$job_files" | \ | |
| jq 'group_by(.name) | map(select(length > 1)) | map({name: .[0].name, files: [.[].file] | unique})')" | |
| # Find conflicts - required checks that are duplicated | |
| conflicts="$(jq -n \ | |
| --argjson required "$required_checks" \ | |
| --argjson duplicates "$duplicates" \ | |
| '$duplicates | map(select(.name as $name | $required | index($name)))')" | |
| # Check if any conflicts exist | |
| if [ "$(echo "$conflicts" | jq 'length')" -gt 0 ]; then | |
| echo "❌ Error: The following required status check names are duplicated in workflow files:" | |
| echo "$conflicts" | jq -r '.[] | " - \"\(.name)\" (found in: \(.files | join(", ")))"' | |
| exit 1 | |
| fi | |
| echo "✅ All required status checks have unique names" |