Repository navigation
vercel.deployment.success #41
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: Preview links for changed pages | |
| # Vercel sends this event when a deployment finishes. We use it to comment on the | |
| # PR with direct links to the docs pages that PR changed, since the Vercel bot's | |
| # own comment only links to the root of the preview deployment. | |
| # | |
| # GitHub only delivers repository_dispatch to the workflow file on the default | |
| # branch, so workflow_dispatch takes the same two payload fields as inputs for | |
| # testing before merge and for re-running on a PR by hand: | |
| # gh workflow run preview-links.yml --ref <branch> -f url=<preview url> -f sha=<pr head sha> | |
| on: | |
| repository_dispatch: | |
| types: [vercel.deployment.success] | |
| workflow_dispatch: | |
| inputs: | |
| url: | |
| description: Preview deployment URL (client_payload.url) | |
| required: true | |
| sha: | |
| description: Full commit SHA of the PR head (client_payload.git.sha) | |
| required: true | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| comment: | |
| if: github.event.client_payload.environment != 'production' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/github-script@v7 | |
| env: | |
| PREVIEW_URL: ${{ github.event.client_payload.url || inputs.url }} | |
| COMMIT_SHA: ${{ github.event.client_payload.git.sha || inputs.sha }} | |
| with: | |
| script: | | |
| const {PREVIEW_URL, COMMIT_SHA} = process.env; | |
| if (!PREVIEW_URL || !/^[0-9a-f]{40}$/i.test(COMMIT_SHA ?? '')) { | |
| core.setFailed(`Need a preview URL and a full commit SHA; got url=${JSON.stringify(PREVIEW_URL)} sha=${JSON.stringify(COMMIT_SHA)}. ` | |
| + `Vercel sends these as client_payload.url and client_payload.git.sha; workflow_dispatch takes them as the url and sha inputs.`); | |
| return; | |
| } | |
| const previewUrl = PREVIEW_URL.replace(/\/$/, ''); | |
| const sha = COMMIT_SHA; | |
| const {owner, repo} = context.repo; | |
| // The dispatch payload has no PR number; look it up from the commit. | |
| const {data: prs} = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | |
| owner, repo, commit_sha: sha | |
| }); | |
| const pr = prs.find(p => p.state === 'open' && p.head.sha === sha); | |
| if (!pr) { | |
| core.info(`No open PR with head ${sha}; nothing to do.`); | |
| return; | |
| } | |
| const files = await github.paginate(github.rest.pulls.listFiles, { | |
| owner, repo, pull_number: pr.number, per_page: 100 | |
| }); | |
| // Mirror contentlayer's flattenedPath: docs/<path>.mdx -> /<path>, | |
| // with a trailing /index dropped. Preview deployments have no basePath. | |
| const pages = files | |
| .filter(f => f.filename.startsWith('docs/') && f.filename.endsWith('.mdx') && f.status !== 'removed') | |
| .map(f => f.filename.slice('docs/'.length, -'.mdx'.length).replace(/^index$/, '').replace(/\/index$/, '')) | |
| .map(path => ({path, url: `${previewUrl}/${path}`})); | |
| if (pages.length === 0) { | |
| core.info(`PR #${pr.number} changes no docs pages; not commenting.`); | |
| return; | |
| } | |
| const marker = '<!-- preview-links-for-changed-pages -->'; | |
| const max = 40; | |
| const lines = pages.slice(0, max).map(p => `- [/${p.path}](${p.url})`); | |
| if (pages.length > max) lines.push(`- …and ${pages.length - max} more`); | |
| const body = [ | |
| marker, | |
| `Direct preview links to pages changed in this PR:`, | |
| ...lines | |
| ].join('\n'); | |
| // Update our previous comment instead of adding a new one per push. | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner, repo, issue_number: pr.number, per_page: 100 | |
| }); | |
| const existing = comments.find(c => c.body?.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({owner, repo, comment_id: existing.id, body}); | |
| } else { | |
| await github.rest.issues.createComment({owner, repo, issue_number: pr.number, body}); | |
| } |