Skip to content

ci: declare contents:read on smoke-test workflow #553

ci: declare contents:read on smoke-test workflow

ci: declare contents:read on smoke-test workflow #553

name: Docs preview (local)
# In-repo docs build using dotnet run (elastic/docs-builder only). Replaces the former
# Previously lived in preview-build.yml (removed); this repo builds docs from source here.
# Triggers are only pull_request and push — conditions below match those events only.
on:
pull_request:
types:
- opened
- synchronize
- reopened
push:
branches:
- main
permissions:
contents: read
id-token: write
pull-requests: read
# PR number avoids grouping disparate PRs that share the same head.ref (e.g. forks).
concurrency:
group: docs-preview-local-${{ github.event_name == 'pull_request' && format('pr{0}-{1}', github.event.pull_request.number, github.event.pull_request.head.ref) || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
match:
if: github.event.repository.fork == false
runs-on: ubuntu-latest
permissions:
contents: none
deployments: none
pull-requests: none
id-token: none
outputs:
content-source-match: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-match, steps.push-check.outputs.content-source-match) }}
content-source-next: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-next, steps.push-check.outputs.content-source-next) }}
content-source-current: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-current, steps.push-check.outputs.content-source-current) }}
content-source-edge: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-edge, steps.push-check.outputs.content-source-edge) }}
content-source-speculative: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-speculative, steps.push-check.outputs.content-source-speculative) }}
steps:
- name: Match for PR events
id: pr-check
if: github.event_name == 'pull_request'
uses: elastic/docs-builder/actions/assembler-match@main
with:
ref_name: ${{ github.base_ref }}
repository: ${{ github.repository }}
- name: Match for PR events debug
if: github.event_name == 'pull_request'
run: |
echo "ref=${{ github.base_ref }}"
echo "repo=${{ github.repository }}"
- name: Match for push events
id: push-check
if: github.event_name == 'push'
uses: elastic/docs-builder/actions/assembler-match@main
with:
ref_name: ${{ github.ref_name }}
repository: ${{ github.repository }}
- name: Match for push events debug
if: github.event_name == 'push'
run: |
echo "ref=${{ github.ref_name }}"
echo "repo=${{ github.repository }}"
- name: Debug outputs
run: |
echo "content-source-match: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-match, steps.push-check.outputs.content-source-match) }}"
echo "content-source-next: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-next, steps.push-check.outputs.content-source-next) }}"
echo "content-source-current: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-current, steps.push-check.outputs.content-source-current) }}"
echo "content-source-edge: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-edge, steps.push-check.outputs.content-source-edge) }}"
echo "content-source-speculative: ${{ format('{0}{1}', steps.pr-check.outputs.content-source-speculative, steps.push-check.outputs.content-source-speculative) }}"
check:
runs-on: ubuntu-latest
needs:
- match
permissions:
contents: read
deployments: none
id-token: none
pull-requests: read
outputs:
any_modified: ${{ steps.check-files.outputs.any_modified }}
all_changed_files: ${{ steps.check-files.outputs.all_changed_files }}
added_files: ${{ steps.check-modified-file-detail.outputs.added_files }}
modified_files: ${{ steps.check-modified-file-detail.outputs.modified_files }}
deleted_files: ${{ steps.check-modified-file-detail.outputs.deleted_files }}
renamed_files: ${{ steps.check-modified-file-detail.outputs.renamed_files }}
steps:
- name: Checkout
if: github.event_name == 'push'
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Get changed files
if: contains(fromJSON('["push", "pull_request"]'), github.event_name)
id: check-files
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
with:
files: '**'
files_ignore: |
.github/**
README.md
- name: Get modified file detail
if: github.event_name == 'pull_request'
id: check-modified-file-detail
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
IGNORE_PATTERNS: |
.github/**
README.md
with:
script: |
const ignorePatterns = process.env.IGNORE_PATTERNS;
const ignoreLines = ignorePatterns
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean);
const pathMatchesIgnorePattern = (path, pattern) => {
if (pattern.endsWith('/**')) {
const prefix = pattern.slice(0, -2);
const dir = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
return path === dir || path.startsWith(`${dir}/`);
}
if (pattern.includes('*')) {
const re = new RegExp(
'^' +
pattern
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
.replace(/\*\*/g, '.*')
.replace(/\*/g, '[^/]*') +
'$'
);
return re.test(path);
}
return path === pattern;
};
const pathMatchesAnyIgnore = (path) =>
ignoreLines.some((p) => pathMatchesIgnorePattern(path, p));
const { owner, repo } = context.repo;
const pull_number = context.payload.pull_request.number;
const allFiles = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number,
});
const filteredFiles = allFiles.filter((file) => !pathMatchesAnyIgnore(file.filename));
const added = [];
const modified = [];
const deleted = [];
const renamed = [];
for (const file of filteredFiles) {
switch (file.status) {
case 'added':
added.push(file.filename);
break;
case 'modified':
modified.push(file.filename);
break;
case 'removed':
deleted.push(file.filename);
break;
case 'renamed':
renamed.push(`${file.previous_filename}:${file.filename}`);
break;
}
}
core.setOutput('added_files', added.join(' '));
core.setOutput('modified_files', modified.join(' '));
core.setOutput('deleted_files', deleted.join(' '));
core.setOutput('renamed_files', renamed.join(' '));
build:
if: github.event.repository.fork == false
runs-on: ubuntu-latest
permissions:
contents: read
deployments: none
id-token: write
pull-requests: none
outputs:
deployment_result: ${{ steps.deployment.outputs.result }}
path_prefix: ${{ steps.generate-path-prefix.outputs.result }}
env:
GITHUB_PR_REF_NAME: ${{ github.event.pull_request.head.ref }}
MATCH: ${{ needs.match.outputs.content-source-match }}
ADDED_FILES: ${{ needs.check.outputs.added_files }}
MODIFIED_FILES: ${{ needs.check.outputs.modified_files }}
DELETED_FILES: ${{ needs.check.outputs.deleted_files }}
RENAMED_FILES: ${{ needs.check.outputs.renamed_files }}
needs:
- check
- match
steps:
- name: Checkout
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
persist-credentials: false
- name: Create Deployment
# disabled: deployments are not enabled on this branch
if: >
false
&& env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
&& (
github.event_name == 'push'
|| github.event_name == 'pull_request'
)
uses: actions/github-script@v8
id: deployment
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref_name }}
with:
result-encoding: string
script: |
const { owner, repo } = context.repo;
const prNumber = process.env.PR_NUMBER;
const environment = 'docs-preview';
const task = prNumber ? `docs-preview-${prNumber}` : undefined;
const deployment = await github.rest.repos.createDeployment({
owner,
repo,
environment,
task,
ref: process.env.REF,
auto_merge: false,
transient_environment: true,
required_contexts: [],
})
await github.rest.repos.createDeploymentStatus({
deployment_id: deployment.data.id,
owner,
repo,
state: "in_progress",
log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
})
return deployment.data.id
- name: Generate env.PATH_PREFIX
id: generate-path-prefix
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_REF_NAME: ${{ github.ref_name }}
run: |
case "${GITHUB_EVENT_NAME}" in
pull_request)
path_prefix="/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}"
;;
push)
path_prefix="/${GITHUB_REPOSITORY}/tree/${GITHUB_REF_NAME}"
;;
*)
echo "Unsupported event: '${GITHUB_EVENT_NAME}'";
exit 1;
;;
esac
echo "PATH_PREFIX=${path_prefix}" >> $GITHUB_ENV
echo "result=${path_prefix}" >> $GITHUB_OUTPUT
- name: Bootstrap Action Workspace
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
uses: elastic/docs-builder/.github/actions/bootstrap@main
- name: 'Validate redirect rules'
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
run: |
dotnet run --project src/tooling/docs-builder -- diff validate
- name: Build documentation
id: internal-docs-build
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
run: |
dotnet run --project src/tooling/docs-builder -- --strict --path-prefix "${PATH_PREFIX}"
- name: 'Validate inbound links'
if: >
env.MATCH == 'true'
&& !cancelled()
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
&& steps.internal-docs-build.outputs.skip != 'true'
&& needs.check.outputs.any_modified != 'false'
run: |
dotnet run --project src/tooling/docs-builder -- inbound-links validate-link-reference
- name: 'Validate local path prefixes against those claimed by global navigation.yml'
id: internal-validate-path-prefixes
if: >
env.MATCH == 'true'
&& !cancelled()
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
&& steps.internal-docs-build.outputs.skip != 'true'
&& steps.internal-docs-build.outcome != 'skipped'
&& needs.check.outputs.any_modified != 'false'
run: |
dotnet run --project src/tooling/docs-builder -- assembler navigation validate-link-reference
- uses: elastic/docs-builder/.github/actions/aws-auth@main
if: >
env.MATCH == 'true'
&& !cancelled()
&& needs.check.outputs.any_modified != 'false'
&& steps.internal-docs-build.outputs.skip != 'true'
&& steps.internal-docs-build.outcome == 'success'
&& steps.internal-validate-path-prefixes.outcome == 'success'
- name: Upload to S3
id: s3-upload
if: >
env.MATCH == 'true'
&& !cancelled()
&& steps.internal-docs-build.outputs.skip != 'true'
&& steps.internal-docs-build.outcome == 'success'
env:
AWS_RETRY_MODE: standard
AWS_MAX_ATTEMPTS: 6
run: |
aws s3 sync .artifacts/docs/html "s3://elastic-docs-v3-website-preview${PATH_PREFIX}" --delete --no-follow-symlinks
aws cloudfront create-invalidation \
--distribution-id EKT7LT5PM8RKS \
--paths "${PATH_PREFIX}" "${PATH_PREFIX}/*"
- name: Update Link Index
if: >
env.MATCH == 'true'
&& needs.check.outputs.any_modified != 'false'
&& (
github.event_name == 'push'
&& steps.internal-validate-path-prefixes.outcome == 'success'
)
uses: elastic/docs-builder/actions/update-link-index@main
- name: Update deployment status
uses: actions/github-script@v8
# disabled: deployments are not enabled on this branch
if: >
false
&& env.MATCH == 'true'
&& always()
&& steps.deployment.outputs.result
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
LANDING_PAGE_PATH: ${{ env.PATH_PREFIX }}
with:
script: |
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: ${{ steps.deployment.outputs.result }},
state: "${{ steps.internal-docs-build.outputs.skip == 'true' && 'inactive' || (steps.s3-upload.outcome == 'success' && 'success' || 'failure') }}",
environment_url: `https://docs-v3-preview.elastic.dev${process.env.LANDING_PAGE_PATH}`,
log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
})