Skip to content
Merged
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
91 changes: 42 additions & 49 deletions .github/workflows/docs-generate-html.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,62 @@

name: "Generate HTML"
run-name: "Generate ${{ inputs.publish-env != '' && inputs.publish-env || (inputs.build-ref == vars.DOCS_PROD_BRANCH && 'prod' || 'dev') }} HTML from ${{ inputs.build-ref }}"

permissions:
contents: read

# edit the list of branches according to your repository
# the list of branches should contain all the branches in your Antora publish playbooks
# Builds, verifies, and publishes docs for ONE environment, as a run entirely independent
# of any other environment's run. Triggered (via the API, not a workflow_call) by
# docs-trigger-builds.yml, once per environment that applies to a given push (dev, prod, or both) -
# so if dev's run fails, prod's run is completely unaffected, and vice versa.
on:
push:
branches:
- "main"
- "dev"
- "5.x"
- "4.4"
workflow_dispatch:

# change `dev` and `main` according to your repository's branch names
# `dev` is the branch you use to build and publish to staging
# `main` is the branch you use to build and publish to neo4j.com/docs
# in some cases, PROD_BRANCH and DEV_BRANCH may be the same branch
env:
DEV_BRANCH: 'dev'
PROD_BRANCH: 'main'
inputs:
build-ref:
description: 'The git ref to build from'
type: string
required: true
publish-env:
description: 'Override for dev/prod. Leave blank to derive it from build-ref against vars.DOCS_PROD_BRANCH - only needs setting explicitly when DOCS_DEV_BRANCH == DOCS_PROD_BRANCH, where build-ref alone cannot tell the two builds apart.'
type: string
required: false
default: ''

jobs:

prepare-ref-env:
name: Set build branch and environments
# Resolves publish-env (dev/prod) once, so neither docs-build nor publish-html
# duplicates the override-or-derive logic.
resolve-env:
name: Resolve environment
runs-on: ubuntu-latest
outputs:
build-ref: ${{ steps.set-ref-env.outputs.build-ref }}
environments: ${{ steps.set-ref-env.outputs.environments }}
publish-env: ${{ steps.resolve.outputs.publish-env }}
steps:
- name: Set Build Ref
id: set-ref-env
- name: Resolve publish-env
id: resolve
env:
PUBLISH_ENV_OVERRIDE: ${{ inputs.publish-env }}
BUILD_REF: ${{ inputs.build-ref }}
PROD_BRANCH: ${{ vars.DOCS_PROD_BRANCH }}
run: |
if [[ "${GITHUB_REF}" == "refs/heads/${{ env.DEV_BRANCH }}" ]]; then
build_from=${{ env.DEV_BRANCH }}
environments='["dev"]'
if [[ -n "${PUBLISH_ENV_OVERRIDE}" ]]; then
publish_env="${PUBLISH_ENV_OVERRIDE}"
elif [[ "${BUILD_REF}" == "${PROD_BRANCH}" ]]; then
publish_env="prod"
else
build_from=${{ env.PROD_BRANCH }}
environments='["prod"]'
publish_env="dev"
fi
# if dev branch = prod branch publish to both
if [[ "${{ env.DEV_BRANCH }}" == "${{ env.PROD_BRANCH }}" ]]; then
environments='["dev","prod"]'
fi
echo "build-ref=${build_from}" >> $GITHUB_OUTPUT
echo "environments=${environments[@]}" >> $GITHUB_OUTPUT

echo "publish-env=${publish_env}" >> $GITHUB_OUTPUT

docs-build:
name: Generate HTML
needs: prepare-ref-env
needs: resolve-env
uses: neo4j/docs-tools/.github/workflows/reusable-docs-build.yml@v2
with:
package-script: 'verify:publish'
build-ref: ${{needs.prepare-ref-env.outputs.build-ref}}
build-ref: ${{ inputs.build-ref }}
fetch-depth: 0
publish-env: ${{ needs.resolve-env.outputs.publish-env }}

docs-verify:
name: Verify HTML
Expand All @@ -64,15 +67,10 @@ jobs:

publish-html:
name: Publish HTML
needs: [docs-verify, prepare-ref-env]
needs: [docs-verify, resolve-env]
runs-on: ubuntu-latest

strategy:
matrix:
environments: ${{ fromJson(needs.prepare-ref-env.outputs.environments) }}

steps:
- name: Publish to ${{ matrix.environments }}
- name: Publish to ${{ needs.resolve-env.outputs.publish-env }}
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 #v4
with:
token: ${{ secrets.DOCS_DISPATCH_TOKEN }}
Expand All @@ -83,10 +81,5 @@ jobs:
"org": "${{ github.repository_owner }}",
"repo": "${{ github.event.repository.name }}",
"run_id": "${{ github.run_id }}",
"publish_env": "${{ matrix.environments }}"
"publish_env": "${{ needs.resolve-env.outputs.publish-env }}"
}

- name: Echo
if: ${{ matrix.environments == 'prod' }}
run: |
echo "If this step runs then approval has been granted" >> $GITHUB_STEP_SUMMARY
85 changes: 85 additions & 0 deletions .github/workflows/docs-generate-pdf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: "Generate PDF"
run-name: "Generate ${{ inputs.publish-env != '' && inputs.publish-env || (inputs.build-ref == vars.DOCS_PROD_BRANCH && 'prod' || 'dev') }} PDF from ${{ inputs.build-ref }}"

permissions:
contents: read

# Mirrors docs-generate-html.yml's shape (workflow_dispatch with build-ref and
# publish-env inputs, resolve-env -> build -> publish) and its own reusable-workflow
# reference convention (a pinned neo4j/docs-tools/...@v2 tag, not a relative path -
# this repo doesn't contain reusable-docs-pdf-build.yml itself). Still simpler than
# docs-generate-html.yml in one way: there's no docs-verify step (no equivalent check
# exists yet for a PDF), and build/publish are two plain jobs rather than a
# reusable-workflow call plus a verify call.
on:
workflow_dispatch:
inputs:
build-ref:
description: 'The git ref to build from'
type: string
required: true
publish-env:
description: 'Override for dev/prod. Leave blank to derive it from build-ref against vars.DOCS_PROD_BRANCH - only needs setting explicitly when DOCS_DEV_BRANCH == DOCS_PROD_BRANCH, where build-ref alone cannot tell the two builds apart.'
type: string
required: false
default: ''

jobs:

# Resolves publish-env (dev/prod) once, so publish-pdf doesn't duplicate the
# override-or-derive logic - same job as docs-generate-html.yml's own resolve-env.
resolve-env:
name: Resolve environment
runs-on: ubuntu-latest
outputs:
publish-env: ${{ steps.resolve.outputs.publish-env }}
steps:
- name: Resolve publish-env
id: resolve
env:
PUBLISH_ENV_OVERRIDE: ${{ inputs.publish-env }}
BUILD_REF: ${{ inputs.build-ref }}
PROD_BRANCH: ${{ vars.DOCS_PROD_BRANCH }}
run: |
if [[ -n "${PUBLISH_ENV_OVERRIDE}" ]]; then
publish_env="${PUBLISH_ENV_OVERRIDE}"
elif [[ "${BUILD_REF}" == "${PROD_BRANCH}" ]]; then
publish_env="prod"
else
publish_env="dev"
fi

echo "publish-env=${publish_env}" >> $GITHUB_OUTPUT

docs-build-pdf:
name: Generate PDF
uses: neo4j/docs-tools/.github/workflows/reusable-docs-pdf-build.yml@v2
with:
build-ref: ${{ inputs.build-ref }}
fetch-depth: 0

# Hand off to docs-publish (a separate repo) to actually publish this run's "pdf"
# artifact - same mechanism docs-generate-html.yml already uses for its "docs"
# artifact. docset/version come from docs-build-pdf itself (read back out of the
# PDF's own build path - see reusable-docs-pdf-build.yml), since there's no HTML
# directory tree here for docs-publish to infer them from the way it does for HTML.
publish-pdf:
name: Publish PDF
needs: [docs-build-pdf, resolve-env]
runs-on: ubuntu-latest
steps:
- name: Publish to ${{ needs.resolve-env.outputs.publish-env }}
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 #v4
with:
token: ${{ secrets.DOCS_DISPATCH_TOKEN }}
repository: neo4j/docs-publish
event-type: publish-pdf
client-payload: |-
{
"org": "${{ github.repository_owner }}",
"repo": "${{ github.event.repository.name }}",
"run_id": "${{ github.run_id }}",
"publish_env": "${{ needs.resolve-env.outputs.publish-env }}",
"docset": "${{ needs.docs-build-pdf.outputs.docset }}",
"version": "${{ needs.docs-build-pdf.outputs.version }}"
}
169 changes: 169 additions & 0 deletions .github/workflows/docs-trigger-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: "Trigger docs builds"

# This workflow's job is dispatching docs-generate-html.yml and docs-generate-pdf.yml
# with the right build-ref(s) for whatever just happened - it is NOT the only valid way
# to wire this up. It doesn't publish anything itself - the dispatched workflows hand
# off to the (separate) docs-publish repo for that.
#
# Use this (docs-trigger-builds.yml -> docs-generate-*.yml) when a single trigger might
# legitimately need to build more than one environment - e.g. a repo where
# DOCS_DEV_BRANCH == DOCS_PROD_BRANCH (one branch serving both, so every push to it
# always means both).
#
# If your repo instead has clean, separate dev/prod branches, you may not need this at
# all: docs-generate-html.yml can be given its own direct `on: push: branches: [...]`
# trigger per environment instead - simpler, and structurally can't build the wrong
# branch's content into the wrong environment. This template still works fine for that
# shape too (it will just always resolve to a single build), so which to use is a
# judgment call, not a hard requirement.

permissions:
contents: read
actions: write

# edit the list of branches according to your repository - every branch that should
# trigger a rebuild, including older versioned content branches (a push there still
# needs to refresh dev/prod's current HTML and this push's own PDF).
on:
push:
branches:
- 'dev'
- 'main'
- '5.x'
- '4.4'
workflow_dispatch:

jobs:

prepare-builds:
name: Set builds to trigger
runs-on: ubuntu-latest
outputs:
# JSON array of {workflow, buildRef, publishEnv} - one entry per independent
# dispatch to make. publishEnv is left '' for docs-generate-html.yml except in
# the one case where it's genuinely ambiguous (see below) - that workflow
# derives it itself from build-ref against its own vars.DOCS_PROD_BRANCH
# whenever publishEnv is blank. docs-generate-pdf.yml's publishEnv is always
# resolved explicitly here instead, using the same conservative default as the
# HTML rules below: the dev branch is the only case treated as dev, every other
# branch defaults to prod.
builds: ${{ steps.set-builds.outputs.builds }}
steps:
# DOCS_DEV_BRANCH and DOCS_PROD_BRANCH are required repository variables
# (Settings -> Secrets and variables -> Actions -> Variables), not values to edit
# here. docs-generate-html.yml, docs-generate-pdf.yml, and docs-publish (a
# separate repo) all independently read the same variables, so they can't be set
# by editing this file on a branch/PR.
# `dev` is the branch you use to build and publish to staging.
# `main` is the branch you use to build and publish to neo4j.com/docs.
# If your repo has no separate prod environment, set DOCS_PROD_BRANCH equal to
# DOCS_DEV_BRANCH - every push will then resolve to both (see the rules below).
- name: Set builds
id: set-builds
env:
DEV_BRANCH: ${{ vars.DOCS_DEV_BRANCH }}
PROD_BRANCH: ${{ vars.DOCS_PROD_BRANCH }}
run: |
dev_branch="${DEV_BRANCH}"
prod_branch="${PROD_BRANCH}"

if [[ -z "${dev_branch}" ]]; then
echo "::error::vars.DOCS_DEV_BRANCH is not set for this repository. Set it in Settings -> Secrets and variables -> Actions -> Variables."
exit 1
fi
if [[ -z "${prod_branch}" ]]; then
echo "::error::vars.DOCS_PROD_BRANCH is not set for this repository. Set it in Settings -> Secrets and variables -> Actions -> Variables."
exit 1
fi

# HTML rules:
# - DEV_BRANCH == PROD_BRANCH -> both, always (one branch serves both, so
# there's no "the other one didn't change" case to worry about).
# - The triggering branch IS the dev branch -> dev only (a change on dev has
# no bearing on prod's already-published content).
# - Anything else (including a push to the prod branch, or any other branch)
# -> both. We deliberately don't try to be clever about only rebuilding the
# one that "actually changed" - e.g. a branch that's fallen out of the dev
# set but is still in the prod set would be misdetected either way, so we
# just always rebuild everything except the one case (dev branch) we know
# for certain doesn't affect prod.
if [[ "${dev_branch}" == "${prod_branch}" ]]; then
html_builds=$(jq -nc --arg b "$dev_branch" \
'[{workflow:"docs-generate-html.yml",buildRef:$b,publishEnv:"dev"},{workflow:"docs-generate-html.yml",buildRef:$b,publishEnv:"prod"}]')
elif [[ "${GITHUB_REF}" == "refs/heads/${dev_branch}" ]]; then
html_builds=$(jq -nc --arg dev "$dev_branch" \
'[{workflow:"docs-generate-html.yml",buildRef:$dev,publishEnv:""}]')
else
html_builds=$(jq -nc --arg dev "$dev_branch" --arg prod "$prod_branch" \
'[{workflow:"docs-generate-html.yml",buildRef:$dev,publishEnv:""},{workflow:"docs-generate-html.yml",buildRef:$prod,publishEnv:""}]')
fi

# PDF always builds from the branch that triggered this run - no dev/prod
# pairing to work out the way HTML has to (there's only ever one PDF build
# per trigger). Its publish-env is still dev or prod, though, resolved with
# the same conservative default the HTML rules above use: the dev branch is
# the one case known for certain not to affect prod, so it's the only one
# that resolves to dev - every other branch (the real prod branch, a third
# long-lived branch, a typo, ...) resolves to prod.
if [[ "${GITHUB_REF}" == "refs/heads/${dev_branch}" ]]; then
pdf_publish_env="dev"
else
pdf_publish_env="prod"
fi
pdf_build=$(jq -nc --arg ref "${GITHUB_REF_NAME}" --arg env "$pdf_publish_env" \
'[{workflow:"docs-generate-pdf.yml",buildRef:$ref,publishEnv:$env}]')

builds=$(jq -nc --argjson html "$html_builds" --argjson pdf "$pdf_build" '$html + $pdf')
echo "builds=${builds}" >> $GITHUB_OUTPUT

# One matrix job instance per build prepare-builds resolved, each dispatching its
# target workflow as its own separate run - not a workflow_call (which would keep
# them all in this one run), so each is fully independent: fail-fast: false means
# one matrix instance failing to dispatch doesn't cancel the others, and each
# dispatched run ends up with its own normally-named artifacts (no collisions, since
# they're separate runs, not jobs sharing one run).
trigger-builds:
name: Trigger ${{ matrix.build.workflow }} (${{ matrix.build.buildRef }})
needs: prepare-builds
strategy:
fail-fast: false
matrix:
build: ${{ fromJson(needs.prepare-builds.outputs.builds) }}
runs-on: ubuntu-latest
steps:
- name: Dispatch
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
BUILD: ${{ toJson(matrix.build) }}
PROD_BRANCH: ${{ vars.DOCS_PROD_BRANCH }}
with:
script: |
const build = JSON.parse(process.env.BUILD)
const prodBranch = process.env.PROD_BRANCH
// Both docs-generate-html.yml and docs-generate-pdf.yml accept publish-env.
const inputs = { 'build-ref': build.buildRef, 'publish-env': build.publishEnv }
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: build.workflow,
// Dispatch from build.buildRef itself, NOT the branch that triggered
// this workflow - a dispatched run's ref becomes its real head_branch,
// which is exactly what docs-publish's check-build-branch inspects.
// Using a single fixed ref for every build here would make every
// dispatched run's head_branch equal whatever branch triggered THIS
// workflow, regardless of which environment it's actually building for
// - so a trigger from any branch other than build.buildRef (e.g. a
// versioned content branch, or the "other" HTML build when both are
// triggered) would always fail that check downstream, even for an
// otherwise-legitimate build.
ref: build.buildRef,
inputs,
})
// Mirrors docs-generate-html.yml's own publish-env derivation for
// display purposes only - the real derivation happens inside the
// dispatched run, this is just to show what it will resolve to when no
// explicit override was passed (the empty-string case, only possible for
// an HTML build - see prepare-builds above).
const env = build.publishEnv || (build.buildRef === prodBranch ? 'prod' : 'dev')
core.summary.addRaw(`Triggered \`${build.workflow}\` on branch \`${build.buildRef}\` for \`${env}\``, true)
await core.summary.write()
Loading