Skip to content

feat(evergreen-tracks): add a tracks input so latest can be moved without cutting a release - #37037

Open
sfreudenthaler wants to merge 1 commit into
mainfrom
issue-37036-tracks-input
Open

feat(evergreen-tracks): add a tracks input so latest can be moved without cutting a release#37037
sfreudenthaler wants to merge 1 commit into
mainfrom
issue-37036-tracks-input

Conversation

@sfreudenthaler

Copy link
Copy Markdown
Member

Adds a tracks input to the promote workflow so latest can be repointed without cutting a release.

Why

When the 2026-08-12 release cut failed to move latest (#37025 — Hub started refusing anonymous tag pagination), there was no supported way to fix it. The promote workflow hardcoded --tracks standard,trailing, the admin workflow only does taint/hold, and re-running the failed release job replays the pre-fix commit. We ended up cutting 26.08.12-02 — code-identical to -01 apart from the CI fix — to move one floating tag. That works (verified below), but it rebuilds artifacts, redeploys to Artifactory, regenerates release notes and publishes a changelog entry to dev.dotcms.com, and leaves a phantom release in front of customers.

What changes

before after
daily cron standard,trailing standard,trailing (unchanged)
dispatch, no input standard,trailing standard,trailing (unchanged)
dispatch tracks=latest not possible moves latest, behind the approval gate

A schedule event carries no inputs at all, so the || 'standard,trailing' fallback is what keeps the cron on its current behaviour — same pattern the existing repo / *_days inputs already use.

latest stays owned by the release pipeline; this is explicitly the break-glass path, and the header comment says so. The apply job still holds the evergreen-tracks-registry lock, so it cannot race the release pipeline's latest-promote — and if a GA cut repoints latest while an approval sits, the existing drift check makes apply refuse rather than fight it, which is the outcome we want.

Latent bug fixed along the way

The moved-summary grep matched only ^(standard|trailing), so a latest move would have applied correctly but reported moved=false and posted no Slack notice. Silent success is the one outcome this workflow exists to prevent. Now ^(latest|standard|trailing).

Worth flagging for review: this bug was invisible until the input existed, and it would have shown up as "we moved latest and nobody heard about it" — the same shape as the original incident.

Verification

  • YAML parses; plan and apply resolve TRACKS to the identical expression, which they must — apply diffs its re-derived plan against the approved one, so any divergence would fail every run.
  • All three --tracks call sites now read $TRACKS (plan, apply's re-plan, apply's mutation).
  • Empty/cron path resolves to standard,trailing.
  • The engine plans a latest-only scope correctly against the live registry in 2 calls.
  • End-to-end evidence that the underlying path is sound: release 26.08.12-02 (run 31628506475) moved latest on both repos in 2 filtered calls each — dotcms/dotcms07e6e29f…, dotcms/dotcms-dev982dc0fd…, both matching 26.08.12-02.

Closes: #37036

🤖 Generated with Claude Code

https://claude.ai/code/session_01PqQqV1iv96Db8AzBSWTXV4

…-of-band

When the 2026-08-12 release cut failed to move `latest` (#37025, Hub 403 on the
unauthenticated tag walk), there was no supported way to repoint it: this
workflow hardcoded `--tracks standard,trailing`, the admin workflow only does
taint/hold, and re-running the failed release job replays the pre-fix commit.
The only route left was cutting a throwaway release to move a tag.

The new `tracks` input defaults to `standard,trailing`, so the daily cron and
every existing dispatch behave exactly as before — a `schedule` event carries no
inputs at all, which the `||` fallback covers. Dispatching with `tracks=latest`
lands behind the same required-reviewer gate as any other manual move, and the
apply job still holds the registry lock, so it cannot race the release
pipeline's latest-promote.

Also widens the moved-summary grep to include `latest`. It matched only
`^(standard|trailing)`, so a latest move would have applied correctly but
reported moved=false and posted no Slack notice — silent success is the one
outcome this workflow is built to avoid.

Verified: YAML parses, both steps resolve TRACKS identically (they must — apply
diffs its re-derived plan against the approved one), the empty/cron path still
yields standard,trailing, and the engine plans a latest-only scope correctly
against the live registry in 2 calls.

Closes: #37036

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqQqV1iv96Db8AzBSWTXV4
@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

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


Review: evergreen-tracks tracks input

I read the full workflow, the diff against origin/main, and the evergreen-tracks CLI to check the assumptions the workflow relies on.

Verified sound:

  • All three --tracks sites now read $TRACKS (plan :111, apply re-plan :207, apply mutation :230); no hardcoded standard,trailing remains in any command.
  • plan and apply derive TRACKS from the identical expression (:94, :197), which the drift check requires.
  • Cron/empty path: schedule carries no inputs, so github.event.inputs.tracks || 'standard,trailing' yields the prior behavior — same pattern as repo/*_days.
  • Track validation isn't missing: cli.py:122-125 rejects unknown tracks with exit code 2, so a typo (tracks=lastest) fails the plan job → Slack failure notice rather than a silent no-op. Good.
  • Widened grep ^(latest|standard|trailing) (:241) correctly fixes the silent-success gap for a latest move.

New Issues

  • 🟡 Medium: .github/workflows/cicd_evergreen-tracks-promote.yml:155-156 — the apply job header comment still states unconditionally that "The plan is scoped to standard,trailing, so an unattended latest move by the release pipeline does NOT trip it." Once tracks=latest is dispatched that is no longer true — an unattended latest move by the release pipeline will trip the drift check (which the PR intends: "deliberately opts INTO that check"). The plan-job comment at :101-105 was updated for exactly this case; the apply-job comment was not, leaving the two halves of the safety model describing different behavior. Non-blocking, but this file's safety guarantees are carried almost entirely in its comments, so the drift matters. Suggest scoping the claim to the default path (e.g. "On the default standard,trailing scope, an unattended latest move does NOT trip it; a break-glass tracks=latest dispatch deliberately opts in."). Fix this →

No functional bugs found in the diff. The change is minimal, the fallback pattern is consistent with the existing inputs, and the lock/gate/drift interactions for the break-glass latest path behave as the PR body describes.
· issue-37036-tracks-input

@dcolina dcolina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. 👍🏽

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : CI/CD PR changes GitHub Actions/workflows

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

evergreen-tracks: no supported way to move latest outside a release cut

2 participants