Multi-Document Extraction Bleed Fix #446
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: Validate PR template | |
on: | |
pull_request_target: | |
types: [opened, edited, synchronize, reopened] | |
workflow_dispatch: | |
permissions: | |
contents: read | |
pull-requests: read | |
jobs: | |
check: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Check PR author permissions | |
id: check | |
if: github.event_name == 'pull_request_target' && github.event.pull_request.draft == false | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
script: | | |
const pr = context.payload.pull_request; | |
const {owner, repo} = context.repo; | |
const actor = pr.user.login; | |
const authorType = pr.user.type; | |
// Check if PR author is a bot (e.g., Dependabot) | |
if (authorType === 'Bot') { | |
core.setOutput('skip_validation', 'true'); | |
console.log(`Skipping validation for bot-authored PR: ${actor}`); | |
return; | |
} | |
// Check if this is a community provider PR (only modifies COMMUNITY_PROVIDERS.md) | |
const { data: files } = await github.rest.pulls.listFiles({ | |
owner, repo, | |
pull_number: pr.number | |
}); | |
const isCommunityProviderPR = files.length === 1 && | |
files[0].filename === 'COMMUNITY_PROVIDERS.md'; | |
if (isCommunityProviderPR) { | |
core.setOutput('is_community_provider', 'true'); | |
console.log('Community provider PR detected - relaxed validation will apply'); | |
} else { | |
core.setOutput('is_community_provider', 'false'); | |
} | |
// Get permission level | |
try { | |
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ | |
owner, repo, username: actor | |
}); | |
const permission = data.permission; // admin|maintain|write|triage|read|none | |
console.log(`Actor ${actor} has permission level: ${permission}`); | |
// Check if user has write+ permissions | |
if (['admin', 'maintain', 'write'].includes(permission)) { | |
core.setOutput('skip_validation', 'true'); | |
console.log(`Skipping validation for maintainer: ${actor} (${permission})`); | |
} else { | |
core.setOutput('skip_validation', 'false'); | |
console.log(`Validation required for: ${actor} (${permission})`); | |
} | |
} catch (e) { | |
// If we can't determine permissions, require validation | |
core.setOutput('skip_validation', 'false'); | |
core.warning(`Permission lookup failed: ${e.message}`); | |
} | |
- name: Validate PR template | |
if: | | |
github.event_name == 'pull_request_target' && | |
github.event.pull_request.draft == false && | |
steps.check.outputs.skip_validation != 'true' | |
env: | |
PR_BODY: ${{ github.event.pull_request.body }} | |
IS_COMMUNITY_PROVIDER: ${{ steps.check.outputs.is_community_provider }} | |
run: | | |
printf '%s\n' "$PR_BODY" | tr -d '\r' > body.txt | |
# Required sections from the template | |
required=( "# Description" "# How Has This Been Tested?" "# Checklist" ) | |
err=0 | |
# Check for required sections | |
for h in "${required[@]}"; do | |
grep -Fq "$h" body.txt || { echo "::error::$h missing"; err=1; } | |
done | |
# Check for issue reference - relaxed for community provider PRs | |
if [ "$IS_COMMUNITY_PROVIDER" = "true" ]; then | |
# For community provider PRs, accept either "Fixes #" or "Related to #" (case-insensitive) | |
if ! grep -Eiq '(Fixes #[0-9]+|Related to #[0-9]+)' body.txt; then | |
echo "::error::Issue reference missing (need 'Fixes #NNN' or 'Related to #NNN')" | |
err=1 | |
fi | |
else | |
# For other PRs, require "Fixes #" with a number | |
if ! grep -Eq 'Fixes #[0-9]+' body.txt; then | |
echo "::error::Missing 'Fixes #NNN' reference" | |
err=1 | |
fi | |
fi | |
# Check for placeholder text that should be replaced | |
grep -Eiq 'Replace this with|Choose one:' body.txt && { | |
echo "::error::Template placeholders still present"; err=1; | |
} | |
# Also check for the unmodified issue number placeholder | |
grep -Fq 'Fixes #[issue number]' body.txt && { | |
echo "::error::Issue number placeholder not updated"; err=1; | |
} | |
exit $err | |
- name: Log skip reason | |
if: | | |
github.event_name == 'pull_request_target' && | |
(github.event.pull_request.draft == true || | |
steps.check.outputs.skip_validation == 'true') | |
run: | | |
echo "Skipping PR template validation. Draft: ${{ github.event.pull_request.draft }}; skip_validation: ${{ steps.check.outputs.skip_validation || 'N/A' }}" |