Skip to content

BAU: guardrail duplicate job names for required status checks #4

BAU: guardrail duplicate job names for required status checks

BAU: guardrail duplicate job names for required status checks #4

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')"
# 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"
report:
# Required, for 'required PR status checks' on GitHub.
name: "Run terraform tests"
runs-on: ubuntu-24.04-arm
steps:
- name: noop
run: echo "This is a placeholder job to satisfy required status checks."