Skip to content
Merged
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
88 changes: 25 additions & 63 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
@@ -1,82 +1,44 @@
name: Documentation

# Publishes the docs site to the Cloudflare Worker that serves it.
#
# TRIGGERS ON `development`, NOT ON A `documentation` BRANCH. This file used to
# listen on a branch called `documentation`; nobody has pushed to one since
# 2026-05-25, so the site simply stopped being rebuilt while every docs change
# merged to development satisfied its review and published nothing.
on:
# `development` is where the work lands. This used to trigger on a
# `documentation` branch that exists but nobody updates — so the workflow
# was green and idle while the live site aged. Measured today:
# softwarecatalog.conduction.nl and stackiq.conduction.nl both still serve
# the pre-rename "SoftwareCatalog" title while docs/docusaurus.config.js
# says 'Stackiq'.
push:
branches: [development]
pull_request:
branches: [development]

jobs:
deploy:
# Permission CEILING for the called documentation workflow, not a grant.
# The callee has three jobs and this block is their UNION, which is what the
# token already resolves to today:
# build contents: read
# deploy contents: write (peaceiris/actions-gh-pages pushes to gh-pages)
# image contents: read, packages: write (buildx push to GHCR)
#
# ⚠️ `packages: write` is load-bearing at RUNTIME, not merely statically:
# the callee's `build-image` input DEFAULTS TO TRUE, so the `image` job
# really does run on a push to `development` and really does push to
# GHCR. Dropping it 403s that push.
#
# It would be required even if that job were disabled, because GitHub
# validates the callee's DECLARED job permissions against this ceiling
# before dispatch — including for jobs an `if:` will skip — so a too-low
# ceiling makes the whole call fail to start rather than run with less.
permissions:
contents: write
packages: write
uses: ConductionNL/.github/.github/workflows/documentation.yml@main
# A reusable workflow receives NO secrets by default, and the
# `permissions:` block above governs the TOKEN, not the secrets. Without
# this block `secrets.CF_API_TOKEN` is empty inside the callee, its
# "Publish to the Cloudflare Worker" step skips itself on its own guard,
# and the run finishes GREEN having written only gh-pages — which nothing
# serves. The live site never changes and no check goes red to say so.
#
# Mapped explicitly rather than `secrets: inherit`, because `inherit`
# hands the callee EVERY secret this repo holds — signing cert and key,
# appstore token, deploy keys — for the sake of two Cloudflare values.
# This way only those two cross the boundary.
#
# The exposure above is the ONLY reason for the explicit mapping. The
# names are the same on both sides: the org secrets really are
# `CF_API_TOKEN` / `CF_ACCOUNT_ID` — the names ConductionNL/.github's own
# deploy-docs.yml reads directly, and the names the callee declares under
# `workflow_call.secrets`.
#
# This block first read `secrets.CLOUDFLARE_API_TOKEN` /
# `secrets.CLOUDFLARE_ACCOUNT_ID`, which are not secrets anywhere in this
# org. Mapping from a name that does not exist is NOT an error — it
# yields an empty string — so the callee's publish step would have skipped
# itself on its own guard and the run would still have finished green.
# Measured on planninq run 32760529026, where that spelling did merge:
# "Publish to the Cloudflare Worker" SKIPPED, the log showing
# `CF_API_TOKEN:` with no value.
# A reusable workflow receives NO secrets by default. Without this block the
# callee's publish step finds CF_API_TOKEN empty, skips itself on its own
# `if:` guard, and the run finishes GREEN having changed nothing -- the
# failure that left the fleet's docs sites on May builds. The names are the
# same on both sides; the org secrets really are CF_API_TOKEN/CF_ACCOUNT_ID.
secrets:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
with:
# `stackiq.conduction.nl` resolves as of 2026-08-23 — attached as a
# second custom domain on the SAME `softwarecatalog-docs` worker that
# serves `softwarecatalog.conduction.nl`. Both hosts answer 200.
# (The comment that used to sit here said the new host answered 000;
# that was true when it was written and is not any more.)
cname: stackiq.conduction.nl

# softwarecatalog.conduction.nl is the retired hostname. It stays in docs-hosts so
# existing links keep resolving, and canonical-host below turns it into a
# 301 rather than a second live copy of every page.
# EVERY host this worker answers on, in FULL: wrangler reconciles the
# worker's triggers against this list, so a host left out is REMOVED and
# goes dark.
docs-hosts: softwarecatalog.conduction.nl,stackiq.conduction.nl

# The worker that ALREADY holds both custom domains. Without this the
# callee derives the name from `cname` — `stackiq-docs` — which does not
# exist. Deploying that would create a SECOND worker while both custom
# domains keep routing to `softwarecatalog-docs`: every deploy green,
# reaching nobody. Renaming the worker is a Cloudflare-side move, not
# something this file can perform.
# The ONE hostname this site is reached on. Every other host in
# docs-hosts answers 301 to the same path here. Before this, both hostnames
# served identical content and the retired name stayed as discoverable
# as the current one.
canonical-host: stackiq.conduction.nl
# PINNED. Deriving the name is how a deploy goes green and reaches
# nobody: wrangler creates the derived worker and publishes there while
# the custom domains keep routing to the real one.
worker-name: softwarecatalog-docs
Loading