Skip to content

ci(docs): fix publish jobs cascade-skipped by always() build gate#674

Merged
marc0olo merged 1 commit into
mainfrom
fix/docs-publish-cascade-skip
Jul 24, 2026
Merged

ci(docs): fix publish jobs cascade-skipped by always() build gate#674
marc0olo merged 1 commit into
mainfrom
fix/docs-publish-cascade-skip

Conversation

@marc0olo

@marc0olo marc0olo commented Jul 24, 2026

Copy link
Copy Markdown
Member

Problem

v1.2.0 was released and versions.json was bumped to 1.2, but the docs-deployment branch never received the v1.2 docs:

  • no /1.2/ folder was created,
  • versions.json on the branch still lists 1.1 as latest,
  • the root index.html still redirects to ./1.1/,

yet every workflow run reported success. The last real deploy to the branch was #669; #670 (release), #671, and #672 published nothing.

Root cause

#671 fixed a required-status-check deadlock by adding a PR-only changes gate and making build depend on it with always():

changes ──▶ build ──▶ publish-root-files / publish-main-docs / publish-versioned-docs ──▶ deploy-to-ic

changes has if: github.event_name == 'pull_request', so on push and tag events it is skipped. build survives that via always(). But the three publish jobs had plain if: conditions with no status-check function, so GitHub injected an implicit success() gate. That implicit gate evaluates the job's ancestry, and because a skipped job (changes) sits in the chain, it returns false — cascade-skipping the publish jobs even though build itself succeeded.

deploy-to-ic uses always() and only excluded failure/cancelled. Since skipped is neither, it still ran and re-pushed the unchanged docs-deployment branch to IC mainnet, reporting green — which is what masked the failure.

Why this change is required

Without it, no versioned docs will ever publish again on a release, and the root redirect/metadata will never advance past 1.1 — silently, with green runs. Every future release would ship with stale docs. The always() on build (needed for #671's PR gating) is permanent, so the publish jobs must be made resilient to a skipped ancestor.

Fix

Add !cancelled() (a status-check function — its presence suppresses the implicit success()) plus an explicit needs.build.result == 'success' gate to each publish job. needs.build.result alone is not sufficient: it's a context expression, not a status function, so the implicit success() would still be injected and still cascade-skip. The !cancelled() is load-bearing.

deploy-to-ic additionally requires contains(needs.*.result, 'success'), so a run where all three publish jobs skipped can no longer redeploy the stale branch and pass as success.

Correctness across every trigger

Event changes build root-files / main-docs versioned deploy-to-ic
Push to main (docs) skipped success run skip (not a tag) run (2 successes)
Tag v1.2.0 skipped success skip (not main) run → builds /1.2/ run (1 success)
docs/v1.2 branch skipped success skip run/1.2/ run
workflow_dispatch on main skipped success run skip (not push) run
PR, docs unchanged success (docs=false) skipped skip skip skip
PR, docs changed success (docs=true) success skip (not main/push) skip skip
build fails skipped failure skip skip skip → run is red
Run cancelled skip (!cancelled()) skip skip

Scope / relationship to #671

This touches only push/tag/workflow_dispatch behavior. The PR required-check gating introduced by #671 is unchanged: the changes and build (docs-build:required) jobs are not modified, so docs-build:required still reports on every PR and docs-less PRs still pass via a skipped build.

Recovery — republishing v1.2 (do this AFTER merge)

Publishing is not retroactive; merging this does not republish v1.2.

1. Publish the missing /1.2/ folder (only publish-versioned-docs creates it, on a tag or docs/v* push).

⚠️ A push event runs the workflow file as it exists on the pushed ref. A docs/v1.2 branch taken straight from tag v1.2.0 carries the pre-fix docs.yml, so publish-versioned-docs would cascade-skip again and the /1.2/ recovery would silently fail. The recovery branch must carry this fix. Branch from the tag (for the correct v1.2 docs sources), then overlay the fixed workflow from main before pushing:

git fetch origin --tags
git checkout -b docs/v1.2 v1.2.0                      # v1.2 docs sources from the release tag
git checkout origin/main -- .github/workflows/docs.yml # overlay the fixed workflow (this PR, merged)
git commit -m "ci(docs): apply publish-job fix for v1.2 recovery build"
git push origin docs/v1.2

docs.yml at v1.2.0 is byte-identical to this PR's merge base, so the overlay is a clean, docs-only-workflow change and leaves all v1.2 content sources untouched.

2. Update the root redirect + metadata (publish-root-files, main/dispatch only). versions.json on main already marks 1.2 as latest, so re-run the workflow:

gh workflow run docs.yml --ref main

Verify:

git fetch origin docs-deployment
git ls-tree origin/docs-deployment --name-only | grep 1.2          # 1.2/ exists
git show origin/docs-deployment:versions.json | jq '.versions[0]'  # {"version":"1.2","latest":true}
git show origin/docs-deployment:index.html | grep refresh          # → ./1.2/

The docs publish jobs (publish-root-files, publish-main-docs,
publish-versioned-docs) were silently skipped on every push/tag event
since #671, so v1.2.0 published no /1.2/ folder and the root redirect
still points at 1.1 — while the run stayed green.

Root cause: #671 introduced a PR-only `changes` gate and made `build`
depend on it with `always()`. `changes` is skipped on push/tag events;
`build` survives via always(), but the publish jobs had plain `if:`
conditions with no status-check function, so GitHub injected an implicit
success() that evaluates the ancestry — including the skipped `changes`
job — and cascade-skipped them despite `build` succeeding.

Fix: add `!cancelled()` (a status-check function, which suppresses the
implicit success()) plus an explicit `needs.build.result == 'success'`
gate to each publish job. Also require `contains(needs.*.result,
'success')` on deploy-to-ic so an all-skipped publish set no longer
re-deploys the stale branch to IC mainnet and reports green.

This touches only push/tag/dispatch behavior; the PR required-check
gating from #671 (changes + build jobs) is unchanged.
@marc0olo
marc0olo requested a review from a team as a code owner July 24, 2026 09:24
Copilot AI review requested due to automatic review settings July 24, 2026 09:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes skipped documentation publishing jobs caused by the PR-only build gate.

Changes:

  • Adds explicit successful-build gates to all publishing jobs.
  • Prevents deployment when no publishing job succeeds.
  • Documents the workflow status-check behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/docs.yml
@marc0olo
marc0olo merged commit f2fb756 into main Jul 24, 2026
102 checks passed
@marc0olo
marc0olo deleted the fix/docs-publish-cascade-skip branch July 24, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants