name: Require Documentation Update on: pull_request: types: [opened, edited, synchronize] branches: - main jobs: check-docs: name: Check Documentation Update runs-on: ubuntu-latest steps: - name: Check if Documentation is Required id: check_docs run: | # Read PR body from the event JSON file — never from shell interpolation. # jq handles all escaping; the shell never sees the user-controlled string. if jq -r '.pull_request.body // ""' "$GITHUB_EVENT_PATH" | \ grep -qi '\[x\].*documentation needed'; then echo "Documentation required detected." echo "docs_required=true" >> "$GITHUB_OUTPUT" else echo "Documentation not required." echo "docs_required=false" >> "$GITHUB_OUTPUT" fi - name: Enforce Documentation Update (if required) if: steps.check_docs.outputs.docs_required == 'true' uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const featureBranch = context.payload.pull_request.head.ref; const repoOwner = context.repo.owner; const websiteRepo = 'website'; core.info(`Searching for a merged documentation PR for feature branch: ${featureBranch} in ${repoOwner}/${websiteRepo}...`); const { data: pulls } = await github.rest.pulls.list({ owner: repoOwner, repo: websiteRepo, state: 'closed', per_page: 100, }); const mergedPr = pulls.find( (pr) => pr.merged_at && pr.title.includes(featureBranch) ); if (!mergedPr) { core.setFailed( `❌ Documentation PR for branch '${featureBranch}' is required and has not been merged.` ); } else { core.info(`✅ Found merged documentation PR: ${mergedPr.html_url}`); }