diff --git a/.github/workflows/codex-preview.yml b/.github/workflows/codex-preview.yml
index 34c2706..9830eeb 100644
--- a/.github/workflows/codex-preview.yml
+++ b/.github/workflows/codex-preview.yml
@@ -51,7 +51,6 @@ 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
@@ -77,6 +76,8 @@ jobs:
contents: read
id-token: write
runs-on: ${{ needs.check.outputs.any_modified == 'true' && 'ubuntu-latest' || 'ubuntu-slim' }}
+ env:
+ DOCS_DIFF_BASE: ${{ github.event.pull_request.base.sha }}
steps:
- name: Checkout code
if: needs.check.outputs.any_modified == 'true'
@@ -86,6 +87,11 @@ jobs:
uses: actions/checkout@v6
with:
persist-credentials: false
+ - name: Fetch PR base for git diff
+ if: >
+ needs.check.outputs.any_modified == 'true'
+ && startsWith(github.event_name, 'pull_request')
+ run: git fetch --no-tags --depth=1 origin "${{ github.event.pull_request.base.sha }}"
- uses: elastic/docs-actions/codex/build@v1
if: needs.check.outputs.any_modified == 'true'
id: codex-build
@@ -208,39 +214,30 @@ jobs:
permissions:
pull-requests: write
steps:
+ - name: Download changed pages artifact
+ continue-on-error: true
+ uses: actions/download-artifact@v8
+ with:
+ name: changed-pages
+ path: changed-pages
- 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 }}
- DOCS_PATH: ${{ inputs.path }}
with:
# language=js
script: |
- const title = '## 🔍 Preview links for changed Codex pages'
+ const fs = require('fs');
+ const path = require('path');
+
+ const title = '## 🔍 Preview links for changed Codex pages';
+ const previewHost = 'https://codex.elastic.dev';
+ const previewUrl = `${previewHost}${process.env.PATH_PREFIX}`;
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 upsertComment = async (body) => {
const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number: prNumber
});
@@ -249,35 +246,53 @@ jobs:
c.body.startsWith(title)
);
if (existing) {
- await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
+ await github.rest.issues.updateComment({
+ owner, repo,
+ comment_id: existing.id,
+ body,
+ });
} else {
- await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body });
+ await github.rest.issues.createComment({
+ owner, repo,
+ issue_number: prNumber,
+ body,
+ });
}
+ };
+
+ const jsonPath = path.join(process.env.GITHUB_WORKSPACE, 'changed-pages', 'changed-pages.json');
+ if (!fs.existsSync(jsonPath)) {
+ await upsertComment([
+ title,
+ '',
+ `[Browse the full preview](${previewUrl})`,
+ ].join('\n'));
return;
}
- const docsRoot = (process.env.DOCS_PATH || 'docs')
- .replace(/^\.\//, '')
- .replace(/\/+$/, '');
- const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const rootPattern = new RegExp(`^${escapeRegExp(docsRoot)}/`);
-
- const escapeMarkdown = (s) => s.replace(/([[\]()\\])/g, '\\$1');
- const toMarkdownLink = (file) => {
- const path = file
- .replace(rootPattern, '')
- .replace(/\/index.md$/, '')
- .replace(/\.md$/, '');
- return `[${escapeMarkdown(file)}](https://codex.elastic.dev${process.env.PATH_PREFIX}/${path})`;
+ const changedPages = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ const pages = changedPages.pages || [];
+ if (changedPages.config_changed || pages.length === 0) {
+ await upsertComment([
+ title,
+ '',
+ changedPages.config_changed
+ ? 'This PR changes navigation or configuration. Browse the full preview for accurate links.'
+ : 'This PR only changes snippets or data files. No direct page links are available.',
+ `[Browse the full preview](${previewUrl})`,
+ ].join('\n'));
+ return;
}
- const links = changedMdFiles.map(toMarkdownLink)
+ const escapeMarkdown = (s) => s.replace(/([[\]()\\])/g, '\\$1');
+ const links = pages.map(page =>
+ `[${escapeMarkdown(page.source_path)}](${previewHost}${page.url})`
+ );
const body = [
title,
...links.slice(0, 10).map(i => `- ${i}`),
- ]
-
+ ];
if (links.length > 10) {
body.push('');
body.push(' More links …
');
@@ -288,32 +303,11 @@ jobs:
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'),
- });
- }
+ await upsertComment(body.join('\n'));
update-link-index:
needs:
diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml
index 2eae288..01cdcbf 100644
--- a/.github/workflows/docs-deploy.yml
+++ b/.github/workflows/docs-deploy.yml
@@ -404,6 +404,7 @@ jobs:
HEAD_SHA: ${{ needs.preflight.outputs.head-sha }}
HEAD_BRANCH: ${{ needs.preflight.outputs.head-branch }}
HEAD_REPO: ${{ needs.preflight.outputs.head-repo }}
+ BASE_REF: ${{ needs.preflight.outputs.base-ref }}
steps:
- name: Reject fork checkout
if: >
@@ -422,6 +423,10 @@ jobs:
persist-credentials: false
allow-unsafe-pr-checkout: true
+ - name: Fetch PR base for git diff
+ if: needs.preflight.outputs.event == 'pull_request'
+ run: git fetch --no-tags --depth=1 origin "${{ needs.preflight.outputs.base-ref }}"
+
- name: Validate checkout SHA
# language=bash
run: |
@@ -497,6 +502,8 @@ jobs:
-e GITHUB_REPOSITORY="${HEAD_REPO}" \
-e GITHUB_REF_NAME="${HEAD_BRANCH}" \
-e GITHUB_REF="refs/heads/${HEAD_BRANCH}" \
+ -e GITHUB_BASE_REF="${BASE_REF}" \
+ -e DOCS_DIFF_BASE="origin/${BASE_REF}" \
-e INPUT_PREFIX="${PATH_PREFIX}" \
-e INPUT_STRICT="${STRICT_FLAG}" \
"${IMAGE_DIGEST}" || EXIT_CODE=$?
@@ -524,6 +531,19 @@ jobs:
retention-days: 1
if-no-files-found: error
+ - name: Upload changed pages artifact
+ id: upload-changed-pages
+ if: >
+ steps.docs-build.outcome == 'success'
+ && steps.docs-build.outputs.skip != 'true'
+ uses: actions/upload-artifact@v7
+ with:
+ name: changed-pages
+ path: .artifacts/docs/html/changed-pages.json
+ compression-level: 1
+ retention-days: 1
+ if-no-files-found: warn
+
- name: Upload docs artifact
id: upload-docs
if: >
@@ -663,44 +683,31 @@ jobs:
id-token: none
pull-requests: write
steps:
+ - name: Download changed pages artifact
+ continue-on-error: true
+ uses: actions/download-artifact@v8
+ with:
+ name: changed-pages
+ path: changed-pages
- name: Comment on PR
continue-on-error: true
uses: actions/github-script@v9
env:
PR_NUMBER: ${{ needs.preflight.outputs.pr-number }}
PATH_PREFIX: ${{ needs.build.outputs.path_prefix }}
- DOCS_PATH: ${{ inputs.path }}
- PATH_PATTERN: ${{ inputs.path-pattern }}
with:
# language=js
script: |
- const title = '## 🔍 Preview links for changed docs'
+ const fs = require('fs');
+ const path = require('path');
+
+ const title = '## 🔍 Preview links for changed docs';
+ const previewHost = 'https://docs-v3-preview.elastic.dev';
+ const previewUrl = `${previewHost}${process.env.PATH_PREFIX}`;
const { owner, repo } = context.repo;
const prNumber = parseInt(process.env.PR_NUMBER);
- const files = await github.paginate(github.rest.pulls.listFiles, {
- owner, repo, pull_number: prNumber
- });
-
- const changedMdFiles = files
- .map(f => f.filename)
- .filter(i => i.endsWith('.md'))
- .filter(i => !i.includes('/_snippets/'));
-
- if (changedMdFiles.length === 0) {
- const hasSnippetOrCsv = files
- .map(f => f.filename)
- .some(f => f.includes('/_snippets/') || f.endsWith('.csv'));
- if (!hasSnippetOrCsv) return;
-
- const previewUrl = `https://docs-v3-preview.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 upsertComment = async (body) => {
const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number: prNumber
});
@@ -721,34 +728,41 @@ jobs:
body,
});
}
+ };
+
+ const jsonPath = path.join(process.env.GITHUB_WORKSPACE, 'changed-pages', 'changed-pages.json');
+ if (!fs.existsSync(jsonPath)) {
+ await upsertComment([
+ title,
+ '',
+ `[Browse the full preview](${previewUrl})`,
+ ].join('\n'));
return;
}
- const rawDocsPath = process.env.DOCS_PATH
- || (process.env.PATH_PATTERN || '').replace(/\/\*+$/, '')
- || 'docs';
- const docsRoot = rawDocsPath
- .replace(/^\.\//, '')
- .replace(/\/+$/, '');
- const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const rootPattern = new RegExp(`^${escapeRegExp(docsRoot)}/`);
-
- const escapeMarkdown = (s) => s.replace(/([[\]()\\])/g, '\\$1');
- const toMarkdownLink = (file) => {
- const path = file
- .replace(rootPattern, '')
- .replace(/\/index\.md$/, '')
- .replace(/\.md$/, '');
- return `[${escapeMarkdown(file)}](https://docs-v3-preview.elastic.dev${process.env.PATH_PREFIX}/${path})`;
+ const changedPages = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
+ const pages = changedPages.pages || [];
+ if (changedPages.config_changed || pages.length === 0) {
+ await upsertComment([
+ title,
+ '',
+ changedPages.config_changed
+ ? 'This PR changes navigation or configuration. Browse the full preview for accurate links.'
+ : 'This PR only changes snippets or data files. No direct page links are available.',
+ `[Browse the full preview](${previewUrl})`,
+ ].join('\n'));
+ return;
}
- const links = changedMdFiles.map(toMarkdownLink)
+ const escapeMarkdown = (s) => s.replace(/([[\]()\\])/g, '\\$1');
+ const links = pages.map(page =>
+ `[${escapeMarkdown(page.source_path)}](${previewHost}${page.url})`
+ );
const body = [
title,
...links.slice(0, 10).map(i => `- ${i}`),
- ]
-
+ ];
if (links.length > 10) {
body.push('');
body.push(' More links …
');
@@ -759,32 +773,11 @@ jobs:
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'),
- });
- }
+ await upsertComment(body.join('\n'));
- name: Comment on docs changes about versioning requirements
if: inputs.enable-cumulative-comment == true
diff --git a/codex/build/action.yml b/codex/build/action.yml
index 35f5a5a..f0586cf 100644
--- a/codex/build/action.yml
+++ b/codex/build/action.yml
@@ -111,3 +111,12 @@ runs:
compression-level: 1
retention-days: 1
if-no-files-found: error
+
+ - name: Upload changed pages
+ uses: actions/upload-artifact@v7
+ with:
+ name: changed-pages
+ path: .artifacts/docs/html/changed-pages.json
+ compression-level: 1
+ retention-days: 1
+ if-no-files-found: warn