diff --git a/.github/workflows/docs-generate-html.yml b/.github/workflows/docs-generate-html.yml
index 546fc2e..c8960d0 100644
--- a/.github/workflows/docs-generate-html.yml
+++ b/.github/workflows/docs-generate-html.yml
@@ -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
@@ -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 }}
@@ -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
diff --git a/.github/workflows/docs-generate-pdf.yml b/.github/workflows/docs-generate-pdf.yml
new file mode 100644
index 0000000..8b167bb
--- /dev/null
+++ b/.github/workflows/docs-generate-pdf.yml
@@ -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 }}"
+ }
diff --git a/.github/workflows/docs-trigger-builds.yml b/.github/workflows/docs-trigger-builds.yml
new file mode 100644
index 0000000..049f6ce
--- /dev/null
+++ b/.github/workflows/docs-trigger-builds.yml
@@ -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()