diff --git a/.github/workflows/codex-preview.yml b/.github/workflows/codex-preview.yml index 8814310b..df65694a 100644 --- a/.github/workflows/codex-preview.yml +++ b/.github/workflows/codex-preview.yml @@ -41,6 +41,7 @@ jobs: runs-on: ubuntu-slim outputs: any_modified: ${{ steps.check-files.outputs.any_modified }} + all_changed_files: ${{ steps.check-files.outputs.all_changed_files }} steps: - name: Checkout # Checkout is needed to get changed files when the event is not a pull request @@ -185,6 +186,116 @@ jobs: log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, }) + comment: + if: needs.deploy.result == 'success' + needs: + - check + - build + - deploy + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Comment preview links on PR + continue-on-error: true + uses: actions/github-script@v9 + env: + PATH_PREFIX: ${{ needs.build.outputs.path_prefix }} + ALL_CHANGED_FILES: ${{ needs.check.outputs.all_changed_files }} + with: + # language=js + script: | + const title = '## 🔍 Preview links for changed Codex pages' + const { owner, repo } = context.repo; + const prNumber = context.payload.pull_request.number; + + const files = (process.env.ALL_CHANGED_FILES || '').split(' ').filter(Boolean); + + const changedMdFiles = files + .filter(i => i.endsWith('.md')) + .filter(i => !i.includes('/_snippets/')); + + if (changedMdFiles.length === 0) { + const hasSnippetOrCsv = files + .some(f => f.includes('/_snippets/') || f.endsWith('.csv')); + if (!hasSnippetOrCsv) return; + + const previewUrl = `https://codex.elastic.dev${process.env.PATH_PREFIX}`; + const body = [ + title, + '', + 'This PR only changes snippets or data files. No direct page links are available.', + `[Browse the full preview](${previewUrl})`, + ].join('\n'); + + const { data: comments } = await github.rest.issues.listComments({ + owner, repo, issue_number: prNumber + }); + const existing = comments.find(c => + c.user.type === 'Bot' && + c.body.startsWith(title) + ); + if (existing) { + await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body }); + } else { + await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body }); + } + return; + } + + const escapeMarkdown = (s) => s.replace(/([[\]()\\])/g, '\\$1'); + const toMarkdownLink = (file) => { + const path = file + .replace(/^docs\//, '') + .replace(/\/index.md$/, '') + .replace(/\.md$/, ''); + return `[${escapeMarkdown(file)}](https://codex.elastic.dev${process.env.PATH_PREFIX}/${path})`; + } + + const links = changedMdFiles.map(toMarkdownLink) + + const body = [ + title, + ...links.slice(0, 10).map(i => `- ${i}`), + ] + + if (links.length > 10) { + body.push('
'); + body.push(' More links … '); + body.push(''); + for (const link of links.slice(10, 100)) { + body.push(`- ${link}`); + } + body.push(''); + body.push('
'); + } + + if (links.length > 100) { + body.push(''); + body.push(` In total, ${links.length} files changed. `); + } + + const { data: comments } = await github.rest.issues.listComments({ + owner, repo, issue_number: prNumber + }); + const existing = comments.find(c => + c.user.type === 'Bot' && + c.body.startsWith(title) + ); + if (existing) { + await github.rest.issues.updateComment({ + owner, repo, + comment_id: existing.id, + body: body.join('\n'), + }); + } else { + await github.rest.issues.createComment({ + owner, repo, + issue_number: prNumber, + body: body.join('\n'), + }); + } + update-link-index: needs: - build