Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 57 additions & 63 deletions .github/workflows/codex-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'
Expand All @@ -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
Expand Down Expand Up @@ -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
});
Expand All @@ -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('<details>');
body.push('<summary> More links … </summary>');
Expand All @@ -288,32 +303,11 @@ jobs:
body.push('');
body.push('</details>');
}

if (links.length > 100) {
body.push('');
body.push(`<sub> In total, ${links.length} files changed. </sub>`);
}

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:
Expand Down
127 changes: 60 additions & 67 deletions .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@
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: >
Expand All @@ -422,6 +423,10 @@
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 }}"

Check notice on line 428 in .github/workflows/docs-deploy.yml

View workflow job for this annotation

GitHub Actions / Run zizmor

template-injection

docs-deploy.yml:428: code injection via template expansion: may expand into attacker-controllable code

- name: Validate checkout SHA
# language=bash
run: |
Expand Down Expand Up @@ -497,6 +502,8 @@
-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=$?
Expand Down Expand Up @@ -524,6 +531,19 @@
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: >
Expand Down Expand Up @@ -663,44 +683,31 @@
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
});
Expand All @@ -721,34 +728,41 @@
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('<details>');
body.push('<summary> More links … </summary>');
Expand All @@ -759,32 +773,11 @@
body.push('');
body.push('</details>');
}

if (links.length > 100) {
body.push('');
body.push(`<sub> In total, ${links.length} files changed. </sub>`);
}

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
Expand Down
Loading
Loading