Post content validation comment #49
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: Post content validation comment | |
| # Runs after "Validate content" completes and posts the result as a PR comment. | |
| # | |
| # The pull_request trigger gives a read-only GITHUB_TOKEN for fork PRs — no | |
| # permissions block can override that. workflow_run always runs in the base | |
| # repo's context with a writable token, so it can post comments even when the | |
| # originating PR came from a fork. The validation result is passed via artifact. | |
| on: | |
| workflow_run: | |
| workflows: ["Validate content"] | |
| types: [completed] | |
| jobs: | |
| comment: | |
| runs-on: ubuntu-latest | |
| # Only post comments for PR-triggered runs, not manual workflow_dispatch runs | |
| if: github.event.workflow_run.event == 'pull_request' | |
| permissions: | |
| pull-requests: write | |
| issues: write | |
| actions: read # required to download artifacts from another workflow run | |
| steps: | |
| - name: Download PR info artifact | |
| id: download | |
| uses: actions/download-artifact@v4 | |
| continue-on-error: true # gracefully skip if artifact is missing (e.g. cancelled run) | |
| with: | |
| name: pr-info | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| run-id: ${{ github.event.workflow_run.id }} | |
| - name: Post or update PR comment | |
| if: steps.download.outcome == 'success' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const marker = '<!-- validate-content-bot -->'; | |
| const fs = require('fs'); | |
| const prNumber = parseInt(fs.readFileSync('pr-number.txt', 'utf8').trim(), 10); | |
| const branch = fs.readFileSync('branch.txt', 'utf8').trim(); | |
| const outcome = fs.readFileSync('outcome.txt', 'utf8').trim(); | |
| // No content files changed in this PR — nothing to comment on | |
| if (outcome === 'skip') return; | |
| let output = ''; | |
| try { output = fs.readFileSync('output.txt', 'utf8').trim(); } catch {} | |
| // Detect if this PR was auto-generated from an issue | |
| const issueMatch = branch.match(/^publish\/issue-(\d+)$/); | |
| const linkedIssue = issueMatch ? issueMatch[1] : null; | |
| const fixNote = linkedIssue | |
| ? `\n\nThis PR was auto-generated from issue #${linkedIssue}. [Edit the issue](https://github.com/${context.repo.owner}/${context.repo.repo}/issues/${linkedIssue}) to fix the errors above — removing and re-adding the \`approved\` label will regenerate the PR automatically.` | |
| : `\n\nFix the errors above and push again — validation will re-run automatically.`; | |
| const successBody = `${marker}\n✅ **Content validation passed!**`; | |
| const failureBody = `${marker}\n## ❌ Content Validation Failed\n\n\`\`\`\n${output}\n\`\`\`${fixNote}`; | |
| const body = outcome === 'failure' ? failureBody : successBody; | |
| const { data: issueComments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const existing = issueComments.find(c => c.body?.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.deleteComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| }); | |
| } | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body, | |
| }); |