Skip to content

feat(ci): add a manual trigger for changelog site publish - #37141

Open
sfreudenthaler wants to merge 2 commits into
37138-autodetect-previous-tagfrom
37136-manual-changelog-publish
Open

feat(ci): add a manual trigger for changelog site publish#37141
sfreudenthaler wants to merge 2 commits into
37138-autodetect-previous-tagfrom
37136-manual-changelog-publish

Conversation

@sfreudenthaler

@sfreudenthaler sfreudenthaler commented Aug 20, 2026

Copy link
Copy Markdown
Member

Closes: #37136

Stack #37143, middle. Based on #37140.

What

Adds cicd_manual_changelog-site-publish.yml, a workflow_dispatch wrapper around the existing changelog site publish phase — the pattern cicd_ai-release-notes-backfill.yml already uses for the notes phase.

gh workflow run cicd_manual_changelog-site-publish.yml --repo dotCMS/core --ref main \
  -f release_tag=v26.08.19-04

Why

The phase is workflow_call: only and gated on success(), so any upstream failure or cancellation skips it with no CI path to recover. Today that means a local checkout plus three values that otherwise never leave GitHub — DOTCMS_DEVSITE_URL, DOTCMS_DEVSITE_RELEASENOTES_TOKEN, DOTCMS_DEVSITE_RELEASENOTES_ACCOUNT.

That is what 26.08.19 cost: four attempts, three shipping Docker images with no changelog, the fourth publishing a changelog covering 1 of 19 commits. Recovery needed Keeper and a local shell.

The phase's comments also describe --force as "a manual operator re-run only", but no manual re-run path existed — the flag was unreachable from CI.

How

The wrapper derives what the pipeline would have passed:

Input Derived from
release_version the tag, minus the v
docker_tags Docker Hub public API, preferring the version_sha tag so a manual entry matches a pipeline-written one
released_date the release's own publishedAt, so backfilling an older release does not stamp today's date

The phase gains force and released_date, both defaulting to current behavior. The release pipeline path is unchangedcicd_6-release.yml sets neither input.

Access control

workflow_dispatch is limited to accounts with write access — never forks, never anonymous — but that is 45 accounts today, and this writes to the public docs site with a service-account token. So the publish job sits behind a no-op approval gate on the changelog-site-publish environment (required_reviewers: dotDevelopers), matching cicd_evergreen-tracks-promote.yml's apply gate.

The environment has been created with that rule. It must keep it: GitHub auto-creates a missing environment unprotected on first use, which would silently remove the gate — it fails open, not closed.

Verification

Both workflows parse as valid YAML. The resolve logic was run against a real tag and reproduces the manual publish exactly: docker tag → 26.08.19-04_a0181f9, released date → 2026-08-20, both matching the entry now live on the site.

Not exercised end-to-end against the live site: the only release currently needing a publish was already published by hand, and re-running would trip human-edit protection. A run on the next release that needs it is the real test.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EbgDBJuoBrpJxh5qLMPorL

@claude

claude Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sfreudenthaler's task in 1m 59s —— View job


Code Review

Reviewed against origin/37138-autodetect-previous-tag. The design is sound: force/released_date are optional with defaults, the pipeline path in cicd_6-release.yml:513 sets neither, so existing behavior is unchanged. Secrets passed by the wrapper match the phase's declared secrets: block, and the phase's job-level concurrency group (...-${release_version}) correctly serializes a manual publish against a pipeline publish for the same version.

New Issues

  • 🟡 Medium: .github/workflows/cicd_manual_changelog-site-publish.yml:59 — The resolve step guards the v prefix but not the dotcms-cli- / _lts_ exclusions that the phase's if: also enforces (cicd_comp_changelog-site-publish-phase.yml:86-89). A manual dispatch of a CLI or LTS tag (e.g. dotcms-cli-v1.2.3 or v26.08.19_lts_01) passes resolve, passes the approval gate, then the publish job is silently skipped by the phase if: — a green run that published nothing. This is the exact failure mode the v-prefix case check was added to prevent; the guard is just incomplete. Consider rejecting those two patterns in the same case/if block so the operator gets an error instead of a false-green. Fix this →

  • 🟡 Medium: .github/workflows/cicd_manual_changelog-site-publish.yml:73 — If gh release view returns a null publishedAt (e.g. a draft, or a release whose date is unset), .publishedAt[0:10] yields an empty string, so released_date is empty and the phase falls back to date -u +%F (today). Since the whole point of deriving released_date is to avoid stamping today's date on a backfill, this edge silently reintroduces the bug it was written to prevent.

    • Assumption: gh release view <tag> can resolve a release whose publishedAt is null.
    • What to verify: whether any release an operator would realistically backfill can have a null publishedAt; if so, fail fast (or warn) rather than silently defaulting to today.

Neither is blocking. The rest — Docker Hub tag resolution, sha-preference matching the pipeline, the fallback path, and the paging caveat already called out in the ponytail: comment — looks correct.

· 37136-manual-changelog-publish

sfreudenthaler and others added 2 commits August 20, 2026 14:23
The changelog site publish phase is workflow_call: only, so when the release
pipeline skips it -- any upstream failure or cancellation, since the job is
gated on success() -- the only recovery is running the publisher locally with
DOTCMS_DEVSITE_URL, _RELEASENOTES_TOKEN and _RELEASENOTES_ACCOUNT in hand.

Adds cicd_manual_changelog-site-publish.yml, a workflow_dispatch wrapper around
the existing phase, mirroring cicd_ai-release-notes-backfill.yml. Credentials
stay in repo vars/secrets; an operator supplies only the release tag. The
wrapper derives release_version from the tag, the sha-tagged docker image from
Docker Hub's public API, and released_date from the release's own publishedAt
so backfilling an older release does not stamp today's date.

The phase gains force and released_date inputs, both defaulting to current
behavior, so the release pipeline path is unchanged. force makes the --force
override the phase comments already describe reachable from CI.

The publish job sits behind a no-op approval gate on the changelog-site-publish
environment (required_reviewers: dotDevelopers): this writes to the public docs
site with a service-account token, and workflow_dispatch is open to every
account with write access on this repo.

Closes: #37136

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EbgDBJuoBrpJxh5qLMPorL
The phase gates its publish job on startsWith(release_tag, 'v'). A tag typed
without the prefix resolved fine, passed the approval gate, and was then
silently skipped -- the run reported success while nothing was published.

Fails fast in resolve instead, before anyone is asked to approve.

Found in review of #37141.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EbgDBJuoBrpJxh5qLMPorL
@sfreudenthaler
sfreudenthaler force-pushed the 37136-manual-changelog-publish branch from 513fe3b to 76cebb1 Compare August 20, 2026 18:24
@sfreudenthaler

Copy link
Copy Markdown
Member Author

Both findings addressed.

1. Silent no-op on a missing v prefix — fixed. resolve now fails fast:

case "$RELEASE_TAG" in
  v*) ;;
  *) echo "Error: release_tag must start with 'v' (got '$RELEASE_TAG')"; exit 1;;
esac

Good catch, and the failure mode was the bad kind: resolve succeeds, a human approves at the gate, publish is skipped by the phase's startsWith guard, and the run goes green having published nothing. It now dies before anyone is asked to approve. Verified both branches of the case statement.

2. Environment provisioning — the review assumed it is not yet provisioned; it is. changelog-site-publish was created before this PR was opened, and re-verified just now via gh api /repos/dotCMS/core/environments/changelog-site-publish:

required_reviewers -> dotDevelopers

Same for release-notes-backfill in #37142. This is in the PR description, but worth restating here since it cannot be checked from the diff.

The caveat in the code comment stands regardless: if either environment is ever deleted, GitHub recreates it unprotected on first use and the gate silently disappears. It fails open, and no code in this repo can defend against that.

@github-actions github-actions Bot added Area : CI/CD PR changes GitHub Actions/workflows and removed AI: Safe To Rollback labels Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : CI/CD PR changes GitHub Actions/workflows

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Changelog site publish has no manual trigger, so a missed release requires local credentials to fix

1 participant