Skip to content

Ensure we assign record with with syntax to ensure we do not update shared instances of repository #3260

Ensure we assign record with with syntax to ensure we do not update shared instances of repository

Ensure we assign record with with syntax to ensure we do not update shared instances of repository #3260

Workflow file for this run

name: preview-build
on:
pull_request:
types:
- opened
- synchronize
- reopened
push:
branches:
- main
- master
# TODO remove these need to be added to individual repositories
- '\d+.\d+.\d+'
- '\d+.\d+'
- '\d+.x'
tags:
- 'v?\d+.\d+.\d+'
- 'v?\d+.\d+'
workflow_call:
inputs:
strict:
description: 'Treat warnings as errors'
type: string
default: 'true'
metadata-only:
description: 'Only generate documentation metadata files'
type: string
required: false
default: 'false'
continue-on-error:
description: 'Do not fail to publish if build fails'
type: string
required: false
default: 'false'
path-pattern:
description: 'Path pattern to filter files. Only if changed files match the pattern, the workflow will continue.'
type: string
default: '**'
required: false
path-pattern-ignore:
description: 'Path pattern to ignore files.'
type: string
default: ''
required: false
free-disk-space:
description: 'Free disk space before running the build'
type: string
default: 'false'
required: false
disable-comments:
description: 'Disable comments'
type: boolean
default: false
required: false
permissions:
contents: read
deployments: write
id-token: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.head.ref || github.ref }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull_request') }}
jobs:
match:
if: github.event.repository.fork == false # Skip running the job on the fork itself (It still runs on PRs on the upstream from forks)
runs-on: ubuntu-latest
permissions:
contents: none
deployments: none
pull-requests: none
id-token: none
outputs:
content-source-match: ${{ steps.event-check.outputs.content-source-match != '' && steps.event-check.outputs.content-source-match || steps.match.outputs.content-source-match }}
content-source-next: ${{ steps.event-check.outputs.content-source-next != '' && steps.event-check.outputs.content-source-next || steps.match.outputs.content-source-next }}
content-source-current: ${{ steps.event-check.outputs.content-source-current != '' && steps.event-check.outputs.content-source-current || steps.match.outputs.content-source-current }}
content-source-speculative: ${{ steps.event-check.outputs.content-source-speculative != '' && steps.event-check.outputs.content-source-speculative || steps.match.outputs.content-source-speculative }}
steps:
- name: Not a push event
id: event-check
if: contains(fromJSON('["merge_group", "pull_request", "pull_request_target"]'), github.event_name)
# we always want to run for pull requests, but we do not want to indicate its either content source
run: |
echo "content-source-match=true" >> $GITHUB_OUTPUT
echo "content-source-next=false" >> $GITHUB_OUTPUT
echo "content-source-current=false" >> $GITHUB_OUTPUT
echo "content-source-speculative=false" >> $GITHUB_OUTPUT
- name: Match for push events
id: match
if: contains(fromJSON('["push"]'), github.event_name)
uses: elastic/docs-builder/actions/assembler-match@main
with:
ref_name: ${{ github.ref_name }}
repository: ${{ github.repository }}
- name: Debug
run: |
echo "Non sensitive data, echo'ing here temporarily to validate this job before connecting it further into the build job"
echo "content-source-match=${{ steps.event-check.outputs.content-source-match != '' && steps.event-check.outputs.content-source-match || steps.match.outputs.content-source-match }}"
echo "content-source-next=${{ steps.event-check.outputs.content-source-next != '' && steps.event-check.outputs.content-source-next || steps.match.outputs.content-source-next }}"
echo "content-source-current=${{ steps.event-check.outputs.content-source-current != '' && steps.event-check.outputs.content-source-current || steps.match.outputs.content-source-current }}"
echo "content-source-speculative=${{ steps.event-check.outputs.content-source-speculative != '' && steps.event-check.outputs.content-source-speculative || steps.match.outputs.content-source-speculative }}"
echo "ref=${{ github.ref_name }}"
echo "repo=${{ github.repository }}"
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 }}
steps:
- name: Checkout
if: contains(fromJSON('["push", "merge_group", "workflow_dispatch"]'), github.event_name)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Get changed files
if: contains(fromJSON('["merge_group", "pull_request", "pull_request_target"]'), github.event_name)
id: check-files
uses: tj-actions/changed-files@2f7c5bfce28377bc069a65ba478de0a74aa0ca32 # v46.0.1
with:
files: ${{ inputs.path-pattern != '' && inputs.path-pattern || '**' }}
files_ignore: |
${{ inputs.path-pattern-ignore != '' && inputs.path-pattern-ignore || '' }}
.github/**
README.md
build:
if: github.event.repository.fork == false # Skip running the job on the fork itself (It still runs on PRs on the upstream from forks)
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
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 }}
needs:
- check
- match
steps:
- name: Checkout
if: >
env.MATCH == 'true'
&& (
needs.check.outputs.any_modified == 'true'
|| contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name)
)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
persist-credentials: false
- name: Create Deployment
if: >
env.MATCH == 'true'
&& (
contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name)
|| (needs.check.outputs.any_modified == 'true' && startsWith(github.event_name, 'pull_request'))
)
uses: actions/github-script@v7
id: deployment
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
REF: ${{ startsWith(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'
&& steps.deployment.outputs.result
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_REF_NAME: ${{ github.ref_name }}
run: |
case "${GITHUB_EVENT_NAME}" in
"merge_group" | "pull_request" | "pull_request_target")
path_prefix="/${GITHUB_REPOSITORY}/pull/${PR_NUMBER}"
;;
"push" | "workflow_dispatch")
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'
&& github.repository == 'elastic/docs-builder'
&& steps.deployment.outputs.result
uses: elastic/docs-builder/.github/actions/bootstrap@main
# we run our artifact directly, please use the prebuild
# elastic/docs-builder@main GitHub Action for all other repositories!
- name: Build documentation
if: >
env.MATCH == 'true'
&& github.repository == 'elastic/docs-builder'
&& steps.deployment.outputs.result
run: |
dotnet run --project src/tooling/docs-builder -- --strict --path-prefix "${PATH_PREFIX}"
- name: Build documentation
if: >
env.MATCH == 'true'
&& (
github.repository != 'elastic/docs-builder'
&& (
steps.deployment.outputs.result
|| (
needs.check.outputs.any_modified == 'true'
&& github.event_name == 'merge_group'
)
)
)
uses: elastic/docs-builder@main
id: docs-build
continue-on-error: ${{ fromJSON(inputs.continue-on-error != '' && inputs.continue-on-error || 'false') }}
with:
prefix: ${{ env.PATH_PREFIX }}
strict: ${{ fromJSON(inputs.strict != '' && inputs.strict || 'true') }}
metadata-only: ${{ fromJSON(inputs.metadata-only != '' && inputs.metadata-only || 'false') }}
- name: 'Validate inbound links'
if: >
env.MATCH == 'true'
&& (
!cancelled()
&& steps.docs-build.outputs.skip != 'true'
&& (
steps.deployment.outputs.result
|| (
needs.check.outputs.any_modified == 'true'
&& github.event_name == 'merge_group'
)
)
)
uses: elastic/docs-builder/actions/validate-inbound-local@main
- name: 'Validate local path prefixes against those claimed by global navigation.yml'
if: >
env.MATCH == 'true'
&& (
!cancelled()
&& steps.docs-build.outputs.skip != 'true'
&& (
steps.deployment.outputs.result
|| (
needs.check.outputs.any_modified == 'true'
&& github.event_name == 'merge_group'
)
)
)
uses: elastic/docs-builder/actions/validate-path-prefixes-local@main
- uses: elastic/docs-builder/.github/actions/aws-auth@main
if: >
!cancelled()
&& steps.docs-build.outputs.skip != 'true'
&& steps.deployment.outputs.result
- name: Upload to S3
id: s3-upload
if: >
env.MATCH == 'true'
&& !cancelled()
&& steps.docs-build.outputs.skip != 'true'
&& steps.deployment.outputs.result
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'
&& (
contains(fromJSON('["push", "workflow_dispatch"]'), github.event_name)
&& (
needs.match.outputs.content-source-current == 'true'
|| needs.match.outputs.content-source-next == 'true'
|| needs.match.outputs.content-source-speculative == 'true'
)
&& steps.s3-upload.outcome == 'success'
)
uses: elastic/docs-builder/actions/update-link-index@main
- name: Update deployment status
uses: actions/github-script@v7
if: >
env.MATCH == 'true'
&& always()
&& steps.deployment.outputs.result
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
LANDING_PAGE_PATH: ${{ steps.docs-build.outputs.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.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}`,
})
comment:
if: >
startsWith(github.event_name, 'pull_request')
&& inputs.disable-comments != 'true'
&& needs.build.outputs.deployment_result
&& needs.check.outputs.any_modified
runs-on: ubuntu-latest
needs:
- check
- build
permissions:
contents: none
deployments: none
id-token: none
pull-requests: write
steps:
- name: Comment on PR
continue-on-error: true
uses: actions/github-script@v7
env:
ALL_CHANGED_FILES: ${{ needs.check.outputs.all_changed_files }}
PATH_PREFIX: ${{ needs.build.outputs.path_prefix }}
with:
script: |
const title = '## 🔍 Preview links for changed docs'
const changedMdFiles = process.env.ALL_CHANGED_FILES
.split(/\s+/)
.filter(i => i.endsWith('.md'))
.filter(i => !i.includes('/_snippets/'));
if (changedMdFiles.length === 0) {
return;
}
const toLink = (file) => {
const path = file
.replace('docs/', '')
.replace('/index.md', '')
.replace('.md', '');
return `[${file}](https://docs-v3-preview.elastic.dev${process.env.PATH_PREFIX}/${path})`;
}
const links = changedMdFiles.map(toLink)
const body = [
title,
...links.slice(0, 10).map(i => `- ${i}`),
]
if (links.length > 10) {
body.push('<details>');
body.push('<summary>More links …</summary>');
body.push('');
for (const link of links.slice(10, 100)) {
body.push(`- ${link}`);
}
body.push('');
body.push('</details>');
}
if (links.length > 100) {
body.push('');
body.push(`<sub>In total, ${links.length} files changed.</sub>`);
}
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = context.payload.pull_request.number;
// Post or update a single bot comment
const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number
});
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,
body:body.join('\n'),
});
}