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