diff --git a/.github/workflows/docs-generate-html.yml b/.github/workflows/docs-generate-html.yml
index d3f2947..c77aee2 100644
--- a/.github/workflows/docs-generate-html.yml
+++ b/.github/workflows/docs-generate-html.yml
@@ -1,5 +1,5 @@
name: "Generate HTML"
-run-name: "Generate HTML for ${{ inputs.dispatch-env }}"
+run-name: "Generate HTML from ${{ inputs.build-ref }}"
permissions:
contents: read
@@ -16,25 +16,48 @@ on:
type: string
required: true
publish-env:
- description: 'staging or prod - passed through to reusable-docs-build.yml, which uses it to resolve DOCS_PUBLISH_URL'
+ 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: true
- dispatch-env:
- description: 'dev or prod - the environment label used for the docs-publish dispatch payload'
- type: string
- required: true
+ required: false
+ default: ''
jobs:
+ # 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:
+ 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:
name: Generate HTML
+ needs: resolve-env
uses: ./.github/workflows/reusable-docs-build.yml
with:
docs-dir: 'docs'
package-script: 'verify:publish'
build-ref: ${{ inputs.build-ref }}
fetch-depth: 0
- publish-env: ${{ inputs.publish-env }}
+ publish-env: ${{ needs.resolve-env.outputs.publish-env }}
docs-verify:
name: Verify HTML
@@ -42,4 +65,24 @@ jobs:
uses: ./.github/workflows/reusable-docs-verify.yml
with:
failOnWarnings: true
-
\ No newline at end of file
+
+ # Hand off to docs-publish (a separate repo) to actually publish this run's "docs"
+ # artifact.
+ publish-html:
+ name: Publish HTML
+ needs: [docs-verify, 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-html
+ client-payload: |-
+ {
+ "org": "${{ github.repository_owner }}",
+ "repo": "${{ github.event.repository.name }}",
+ "run_id": "${{ github.run_id }}",
+ "publish_env": "${{ needs.resolve-env.outputs.publish-env }}"
+ }
diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml
index 812f17c..5a282c8 100644
--- a/.github/workflows/docs-publish.yml
+++ b/.github/workflows/docs-publish.yml
@@ -1,11 +1,32 @@
name: "Publish docs"
+# This workflow's job is dispatching docs-generate-html.yml with the right build-ref(s)
+# for whatever just happened - it is NOT the only valid way to wire this up, and isn't
+# always the right choice.
+#
+# Use this (docs-publish.yml -> docs-generate-html.yml) when a single trigger might
+# legitimately need to build more than one environment - e.g. a manual "rebuild
+# everything" workflow_dispatch, or 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 (e.g. dev and main), you
+# almost certainly do NOT want this: a commit to dev should only ever build staging, and
+# a commit to main should only ever build prod - never both from one commit, since
+# they're different content on different branches. For that shape, skip this file
+# entirely and give docs-generate-html.yml its own direct `on: push: branches: [...]`
+# trigger per environment instead (see docs-aura's docs-generate-html.yml for that
+# pattern) - simpler, and structurally can't build the wrong branch's content into the
+# wrong environment.
+
permissions:
contents: read
actions: write
-# edit the list of branches according to your repository
-# the list of branches should contain all the branches in your Antora publish playbooks
+# Edit the branches list below to match your repository: it must be the union of every
+# branch listed in BOTH your staging and prod Antora publish.yml playbooks (content
+# sources' `branches`). prepare-ref-env's logic below assumes this - it doesn't inspect
+# the playbooks itself, it just trusts that if this workflow ran at all, the branch that
+# triggered it is a real content branch for at least one of the two environments.
on:
push:
branches:
@@ -21,65 +42,81 @@ env:
jobs:
prepare-ref-env:
- name: Set build branch and environments
+ name: Set builds to trigger
runs-on: ubuntu-latest
outputs:
- build-ref: ${{ steps.set-ref-env.outputs.build-ref }}
- environments: ${{ steps.set-ref-env.outputs.environments }}
+ # JSON array of {buildRef, publishEnv} - one entry per independent
+ # docs-generate-html.yml run to trigger. publishEnv is left '' except in the one
+ # case where it's genuinely ambiguous (see below) - docs-generate-html.yml derives
+ # it itself from build-ref against its own vars.DOCS_PROD_BRANCH whenever
+ # publishEnv is blank.
+ builds: ${{ steps.set-ref-env.outputs.builds }}
steps:
- - name: Set Build Ref
+ - name: Set builds
id: set-ref-env
run: |
dev_branch="${{ env.DEV_BRANCH }}"
prod_branch="${{ env.PROD_BRANCH }}"
+ # Rules:
+ # - No separate prod branch configured -> staging only, always (nothing to
+ # double up).
+ # - 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 -> staging 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 [[ -z "${prod_branch}" ]]; then
- build_from="${dev_branch}"
- environments='["dev"]'
+ builds=$(jq -nc --arg dev "$dev_branch" \
+ '[{buildRef:$dev,publishEnv:""}]')
+ elif [[ "${dev_branch}" == "${prod_branch}" ]]; then
+ # build-ref alone can't distinguish these two - same branch - so publishEnv
+ # has to be passed explicitly here, or docs-generate-html.yml's derivation
+ # would resolve both to the same environment.
+ builds=$(jq -nc --arg b "$dev_branch" \
+ '[{buildRef:$b,publishEnv:"dev"},{buildRef:$b,publishEnv:"prod"}]')
elif [[ "${GITHUB_REF}" == "refs/heads/${dev_branch}" ]]; then
- build_from="${dev_branch}"
- environments='["dev"]'
+ builds=$(jq -nc --arg dev "$dev_branch" \
+ '[{buildRef:$dev,publishEnv:""}]')
else
- build_from="${prod_branch}"
- environments='["prod"]'
- fi
-
- if [[ -n "${prod_branch}" && "${dev_branch}" == "${prod_branch}" ]]; then
- environments='["dev","prod"]'
+ builds=$(jq -nc --arg dev "$dev_branch" --arg prod "$prod_branch" \
+ '[{buildRef:$dev,publishEnv:""},{buildRef:$prod,publishEnv:""}]')
fi
- echo "build-ref=${build_from}" >> $GITHUB_OUTPUT
- echo "environments=${environments}" >> $GITHUB_OUTPUT
+ echo "builds=${builds}" >> $GITHUB_OUTPUT
- # Trigger docs-generate-html.yml as its own separate run, once per environment that
- # applies - not a workflow_call (which would keep both in this one run) - so dev and
- # prod are fully independent runs: if dev's run fails, prod's run is unaffected, and
- # each ends up with a plain "docs" artifact exactly like a run does today.
+ # Trigger docs-generate-html.yml as its own separate run, once per build - not a
+ # workflow_call (which would keep them all in this one run) - so each is fully
+ # independent: if one run fails, the others are unaffected, and each ends up with a
+ # plain "docs" artifact exactly like a run does today (no name collisions, since
+ # they're separate runs, not jobs sharing one run).
trigger-generate-html:
- name: Trigger per-environment builds
+ name: Trigger builds
needs: prepare-ref-env
runs-on: ubuntu-latest
steps:
- - name: Dispatch docs-generate-html.yml for each environment
+ - name: Dispatch docs-generate-html.yml for each build
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
- BUILD_REF: ${{ needs.prepare-ref-env.outputs.build-ref }}
- ENVIRONMENTS: ${{ needs.prepare-ref-env.outputs.environments }}
+ BUILDS: ${{ needs.prepare-ref-env.outputs.builds }}
DISPATCH_REF: ${{ github.ref_name }}
with:
script: |
- const environments = JSON.parse(process.env.ENVIRONMENTS)
- const publishEnvFor = { dev: 'staging', prod: 'prod' }
- for (const dispatchEnv of environments) {
+ const builds = JSON.parse(process.env.BUILDS)
+ for (const build of builds) {
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'docs-generate-html.yml',
ref: process.env.DISPATCH_REF,
inputs: {
- 'build-ref': process.env.BUILD_REF,
- 'publish-env': publishEnvFor[dispatchEnv],
- 'dispatch-env': dispatchEnv,
+ 'build-ref': build.buildRef,
+ 'publish-env': build.publishEnv,
},
})
}
diff --git a/.github/workflows/reusable-docs-build.yml b/.github/workflows/reusable-docs-build.yml
index a19e05c..077a766 100644
--- a/.github/workflows/reusable-docs-build.yml
+++ b/.github/workflows/reusable-docs-build.yml
@@ -37,10 +37,10 @@ on:
type: string
default: 'verify:preview'
publish-env:
- description: "The publish environment to build docs for: staging or prod"
+ description: "The publish environment to build docs for: dev or prod"
required: false
type: string
- default: 'staging'
+ default: 'dev'
antora-attributes:
description: 'Antora attributes to pass to the build script'
required: false
@@ -157,15 +157,15 @@ jobs:
# sandbox right now.
#
# Resolved once here, not duplicated at each use: ANTORA_CLI_OPTIONS and
- # DOCS_NAV_URL both need the staging-vs-prod split, but they read it via
+ # DOCS_NAV_URL both need the dev-vs-prod split, but they read it via
# env.DOCS_PUBLISH_URL from the "Run package script" step's own env: block
# below rather than from here directly - a step's env CAN reference an
# already-resolved job-level env var, but two entries in this same job-level
# env: block can't reference each other (this one included), so they can't be
# defined here alongside it.
- DOCS_PUBLISH_URL: "${{ inputs.publish-env == 'staging' && 'https://development.neo4j.dev/docs/sandbox/restructure/docs' || 'https://neo4j.com/docs' }}"
+ DOCS_PUBLISH_URL: "${{ inputs.publish-env == 'dev' && 'https://development.neo4j.dev/docs/sandbox/restructure/docs' || 'https://neo4j.com/docs' }}"
ANTORA_UI_BUNDLE_URL: "${{ inputs.package-script == 'verify:publish' && 'https://static-content.neo4j.com/build/ui-bundle-docs-restructure.zip'|| inputs.antora-ui-bundle-url }}"
- # page-no-local-manifest: staging/prod never serve local-manifest.json (that's a
+ # page-no-local-manifest: dev/prod never serve local-manifest.json (that's a
# local-dev-only file - see the tabbed-nav extension's emitLocalManifest option and
# its middleware). Stamped so the UI bundle can skip fetching it there entirely,
# rather than issuing a request that's guaranteed to 404.
@@ -346,7 +346,7 @@ jobs:
# extra place to look, so those extensions can still find hoisted deps (e.g. vinyl) that are
# only installed under docs/node_modules.
NODE_PATH: ${{ github.workspace }}/${{ env.DOCS_DIR }}/node_modules
- # Both derive the staging/prod split from the single env.DOCS_PUBLISH_URL set
+ # Both derive the dev/prod split from the single env.DOCS_PUBLISH_URL set
# at job level above - defined here, not there, because that's a job-level
# env: block and this one can read it; two entries in the SAME block can't
# read each other. Everything else - including PR previews - derives the