feat(docs): trunk-based versioning with permanent next/ directory#495
feat(docs): trunk-based versioning with permanent next/ directory#495myasnikovdaniil merged 15 commits intomainfrom
Conversation
Hugo v0.153.0+ replaced the deprecated excludeFiles module-mount key with files (which supports negative patterns like `! docs/next/**`). The upcoming trunk-based versioning change uses this syntax to exclude the new next/ directory from production builds, so bump both netlify.toml and the GitHub Pages workflow to 0.160.1. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Add the permanent content/en/docs/next/ directory as a version-agnostic trunk for upcoming/unreleased docs. The content is a copy of v1.2/ with internal /docs/v1.2/ links rewritten to /docs/next/, and _index.md retitled "Cozystack Next (unreleased)" with a draft-banner shortcode. Subsequent commits wire up mount/switcher/makefile support so next/ is visible in local dev and Netlify deploy previews, excluded from the GitHub Pages production build, and can be promoted to a released vX.Y/ directory via hack/release_next.sh. Replaces the hardcoded v1.3 draft-directory approach from #493. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Adds the `next` version entry (hidden, order 999) so the version switcher and release tooling know about it, and migrates the content mount from the deprecated `excludeFiles` to the new `files` syntax (Hugo 0.160+). Production builds exclude docs/next/** via config/production/hugo.yaml, which duplicates the full module.mounts list (Hugo replaces arrays wholesale during config merge). Local dev and Netlify deploy previews render next/ — the preview context sets HUGO_ENV=preview to skip the production override. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Version entries with `hidden: true` (like `next`) are now skipped in the dropdown but remain known to tooling and build configuration. navbar-version-selector.html duplicated the same logic and is removed; the dropdown in version-switcher.html is the single source of truth. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Introduces layouts/docs/docs-landing.html, a landing template that iterates Site.Params.versions at build time. It filters out hidden entries (next), labels latest_version_id as "Latest (stable)", and links each version's docs root. Removes the hardcoded version references from the body. With this, releasing a new version (via release-next/register_version.sh) requires no edits to the landing page. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Orders version landing pages so newer versions sort above older ones in Hugo's sidebar/navigation: next → 5, v1.2 → 10 (unchanged), v1.1 → 30, v1.0 → 40, v0 → 50 v1.2 stays at weight 10 as the current latest. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Script used by hack/release_next.sh to register a new version (or unhide an existing hidden one) in hugo.yaml and set it as latest_version_id. Order is auto-computed from non-hidden entries so new versions slot in above older ones. The 'next' entry is never touched. Requires yq v4+. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Given a RELEASE_TAG (e.g., v1.3.0), derives the target minor version (v1.3), copies content/en/docs/next/ to content/en/docs/v1.3/, rewrites /docs/next/ links to /docs/v1.3/, strips the draft-banner shortcode from _index.md, and calls register_version.sh to register v1.3 as the new latest in hugo.yaml. Validates preconditions (next/ non-empty, target dir doesn't exist) and fails hard — there is no silent no-op. next/ itself is never modified, so the trunk stays in place for the next release cycle. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
When --version=next, the script now rewrites the title/linkTitle to the unreleased form, sets weight=5, prepends the draft-banner warning shortcode (idempotently), and skips the usual "Cozystack vX.Y → vX.Y" rename (no source version appears in next/'s content). This is what `make init-next` calls to (re)initialize the trunk from the latest released version. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
RELEASE_TAG drives the routing: - no tag → next/ (trunk), BRANCH=main - tag for released minor (v1.2/) → v1.2/ in place, BRANCH=tag - tag for unreleased minor → next/ (still accumulating), BRANCH=tag Detection checks both that the target directory exists AND that its entry in hugo.yaml is non-hidden (via yq). Falls back to directory-only when yq is absent; `next` is excluded by design as it's always hidden. Adds new targets: - init-next — rm -rf + reinit next/ from latest released version - release-next — promote next/ to vX.Y/ (requires RELEASE_TAG) - show-target — debug: prints resolved DOC_VERSION/BRANCH Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Replaces the "Creating a new version" section with the trunk-based workflow (init-next / release-next), documents the RELEASE_TAG routing table, and notes Hugo 0.160.1 / yq v4+ as new tool requirements. Also notes next/ behavior in dev and deploy previews (visible) vs production (excluded via config/production/hugo.yaml) and updates the upstream release-workflow contract to include release-next for new minors. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, reopen this pull request to trigger a review.
✅ Deploy Preview for cozystack ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Important Review skippedToo many files! This PR contains 203 files, which is 53 over the limit of 150. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (13)
📒 Files selected for processing (203)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a permanent next/ documentation trunk for Cozystack, providing a version-agnostic space for upcoming release documentation. The changes include a comprehensive suite of new guides covering architecture, multi-location clusters, cloud-specific installations, and advanced operations like OIDC and scheduling classes. The feedback identifies a broken link to a missing file, a typo in a CLI flag, and the use of a deprecated Kubernetes API version. Additionally, there are several instances of inconsistent Talos version numbers across the new documentation examples that should be unified.
| own etcd (only applicable when the tenant was created with | ||
| `etcd: true`). | ||
|
|
||
| See [Tenant `isolated` flag removed]({{% ref "/docs/next/operations/upgrades#tenant-isolated-flag-removed" %}}) |
There was a problem hiding this comment.
The link points to /docs/next/operations/upgrades#tenant-isolated-flag-removed, but the file operations/upgrades.md appears to be missing from the next/ directory in this pull request. This will result in a broken link. Please ensure the file is included or update the link to the correct destination.
There was a problem hiding this comment.
The link is valid. content/en/docs/next/operations/upgrades/_index.md exists and contains the heading "Tenant isolated flag removed" at line 137. With autoHeadingIDType: github in hugo.yaml, Hugo auto-generates the anchor #tenant-isolated-flag-removed, and the ref shortcode resolves the directory index correctly. No change needed.
|
|
||
| ```bash | ||
| talm template -f nodes/node1.yaml -I | ||
| talm apply -f nodes/node1.yaml |
There was a problem hiding this comment.
-I is the intended flag — it is --in-place (re-template and overwrite generated files), not a typo for -i (--insecure). talm template --help lists both: -I, --in-place and -i, --insecure. The doc describes re-rendering generated files after editing _helpers.tpl, which is exactly what --in-place does.
| cluster: | ||
| ... | ||
| scheduler: | ||
| config: |
There was a problem hiding this comment.
There was a problem hiding this comment.
Valid tech-debt point — v1beta3 graduated to v1 in Kubernetes 1.25. However, this file is a verbatim copy from content/en/docs/v1.2/ (introduced by cp -a when seeding the next/ trunk); this PR does not touch its content. I'd rather land this as a separate content PR that updates both v1.2/ and next/, so the API version stays consistent across published versions.
| ```console | ||
| $ boot-to-talos | ||
| Target disk [/dev/sda]: | ||
| Talos installer image [ghcr.io/cozystack/cozystack/talos:v1.10.5]: |
There was a problem hiding this comment.
Noted. The Talos version here is byte-identical to content/en/docs/v1.2/getting-started/install-talos.md (diff shows only path rewrites in links/aliases). The wider inconsistency already exists in v1.2/ across multiple files (v1.9.5, v1.10.3, v1.10.5, v1.11.6, v1.12.6). A consistency sweep should pick a canonical version and update both v1.2/ and next/ in a dedicated content PR — out of scope for this trunk-mechanism change.
| - name: vfio_pci | ||
| - name: vfio_iommu_type1 | ||
| install: | ||
| image: ghcr.io/cozystack/cozystack/talos:v1.10.3 |
There was a problem hiding this comment.
The Talos version in this configuration snippet (v1.10.3) is inconsistent with other examples in the documentation. Please use a consistent version (e.g., v1.12.6) throughout the next/ trunk.
| image: ghcr.io/cozystack/cozystack/talos:v1.10.3 | |
| image: ghcr.io/cozystack/cozystack/talos:v1.12.6 |
There was a problem hiding this comment.
Same as the thread on install-talos.md: this is a verbatim copy from v1.2/. A consistency sweep picking a canonical Talos version should land as a separate content PR touching both v1.2/ and next/. Not introducing content edits in this infrastructure PR.
| - name: vfio_pci | ||
| - name: vfio_iommu_type1 | ||
| install: | ||
| image: ghcr.io/cozystack/cozystack/talos:v1.10.3 |
There was a problem hiding this comment.
The Talos version in this configuration snippet (v1.10.3) is inconsistent with other examples in the documentation. Please use a consistent version (e.g., v1.12.6) throughout the next/ trunk.
| image: ghcr.io/cozystack/cozystack/talos:v1.10.3 | |
| image: ghcr.io/cozystack/cozystack/talos:v1.12.6 |
There was a problem hiding this comment.
Same reasoning as the other Talos-version threads — this file is byte-identical to v1.2/install/kubernetes/talos-bootstrap.md. Deferring to a follow-up content PR so the canonical version is aligned across all published docs versions at once.
release_next.sh set the new version's _index.md weight to 10 but left older versions untouched — so the outgoing latest (also weight 10) would collide with the incoming one, making sidebar ordering undefined. register_version.sh now owns weight normalization: after every release registration it walks all non-hidden version entries sorted by `order` descending and rewrites each _index.md weight to 10, 20, 30, …. The permanent `next` trunk stays at weight 5 (set by init_version.sh) and is not touched. The redundant weight sed is removed from release_next.sh. Verified end-to-end with a simulated v1.3 release: next → 5, v1.3 → 10, v1.2 → 20, v1.1 → 30, v1.0 → 40, v0 → 50. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Explains the versioning model (independent per-minor directories, no auto-backport), why `next/` exists (writing upcoming-release docs without committing to a version number), where to make each kind of change, how autogenerated content sync works, and the full release lifecycle including `release-next` and `init-next`. Mirrors CLAUDE.md's reference material but in a narrative form aimed at human contributors — CLAUDE.md stays as the terse machine-readable reference. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
lexfrei
left a comment
There was a problem hiding this comment.
Reviewed the design and the routing/lifecycle scripts with a focus on completeness and release-time correctness. Overall the design is sound (permanent next/ trunk, production exclusion via a dedicated config, Makefile routing, version registration in hugo.yaml). Commits are atomic and CONTRIBUTING.md is excellent.
Two gaps in the end-to-end flow are worth closing before merge, plus one content-hygiene item and a few nits.
Blocking
1. aliases: - /docs/v1/ does not move between latest versions
v1.2/_index.md carries aliases: - /docs/v1/. Hugo aliases are server-side redirects, so after release-next promotes next/ to v1.3, /docs/v1/ still points at the now-stale v1.2. The JS fallback in layouts/404.html does not help — Hugo's alias wins with a 200 redirect before the 404 renders.
hack/release_next.sh should: (a) strip the /docs/v<major>/ alias from the previous latest_version_id _index.md, and (b) add it to the new one. Otherwise every new minor release quietly breaks the short path.
2. Upstream workflow contract is not linked
The design delegates "when to call release-next vs update-all" to cozystack/cozystack tags.yaml. There's no companion PR referenced in this one. Until that lands upstream, release-next is never invoked and the flow is not actually end-to-end. Please link the companion upstream PR (or explicitly mark it as a required follow-up in the PR description).
Content hygiene (not blocking, but should land before the next release)
3. release_next.sh rewrites URLs, not prose
The sed pass only rewrites /docs/next/ → /docs/vX.Y/. Version references in prose are promoted verbatim:
next/install/talos/boot-to-talos.md:27— "For Cozystack v1.2.x the pinned Talos version is v1.12.6"next/install/talos/boot-to-talos.md:36— "Cozystack v1.2.x … Talos v1.11"next/cozystack-api/go-types.md:16—go get …@v1.2.0next/operations/scheduling-classes.md:35— "Cozystack v1.2+"
These are inherited from v1.2, but at the release boundary they become factually wrong on the v1.3 pages. At minimum, add a release checklist item to CONTRIBUTING.md ("audit version-specific prose before release-next"). Ideally the script does a targeted sed pass for known patterns (Cozystack v<prev>, @v<prev>.0).
Nits
make init-nextis destructive and manual. It silentlyrm -rfscontent/en/docs/next/and re-initializes. Afterrelease-nextthe trunk still holds a stale copy, and the momentinit-nextruns is left to a human. Consider either chaininginit-nextat the end ofrelease-next, or guarding against a dirty tree insidenext/.release_next.sh:47accepts pre-release tags. The regex^v([0-9]+)\.([0-9]+)\.([0-9]+).*$happily matchesv1.3.0-rc1and would promotenext/from an RC. The PR description saysrelease-nextis "for new minor/major releases only" — the script should enforce that.register_version.shuses non-portablesed -i. Lines 67, 72, 78, 80 usesed -i "..."without an extension (GNU-only). The neighbouringrelease_next.shuses the portablesed -i.bakidiom. Fine on Linux CI, but inconsistent.label: "Next (unreleased)"inhugo.yaml:126is unused. Neitherversion-switcher.htmlnordocs-landing.htmlreads.label. On a/docs/next/preview page the switcher button showsnext(from.version). Either wirelabelinto the switcher for hidden entries, or drop the field.release_next.sh:98-99comment is misleading. The comment says "Collapse any double blank lines", but'/./,/^$/!d'actually strips leading/trailing blank lines. The effect is correct for this input shape, but the comment will mislead the next reader.
Strengths
- Clean separation: trunk vs production override vs Makefile routing.
release_next.shfail-fast preconditions (non-emptynext/, target directory absent) are the right shape.CONTRIBUTING.mdis thorough; decision table + command reference make contributor onboarding easy.[context.deploy-preview.environment] HUGO_ENV=previewis a tidy way to opt previews into the trunk.- Verified locally:
next/has the same 198 files asv1.2/, and no stray/docs/v1.2/link slipped intonext/.
- release_next.sh: reject pre-release RELEASE_TAGs (v1.3.0-rc1 etc.) so only final releases can promote next/ → vX.Y/ - release_next.sh: tighten the comment on the post-banner cleanup sed to describe what it actually does (trims leading/trailing blanks, collapses runs of blanks), instead of the inaccurate "collapse double blank lines" - v1.2/_index.md: drop stale "aliases: - /docs/v1/". The 404 JS fallback in layouts/404.html already redirects /docs/v<major>/... to the current latest dynamically via Site.Params.latest_version_id, so a Hugo alias is both unnecessary and actively harmful (it shadows the fallback and pins the short path at whichever version last held the alias) - register_version.sh: use portable "sed -i.bak" with a single trailing cleanup, matching the existing pattern in release_next.sh - hugo.yaml: drop unused "label: Next (unreleased)" from the next version entry — no layout reads .label - CONTRIBUTING.md: add a "Pre-release audit" subsection with grep patterns that catch version-specific prose inherited from the previous release (release_next.sh rewrites URL paths but not body text) - CONTRIBUTING.md: promote "make init-next" from "common practice" to a mandatory final step of every release, so the trunk never lingers with already-released content Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
Thanks for the thorough review — addressed all eight items; Blocking
Content hygiene
Nits
|
|
Added upstream PR |
lexfrei
left a comment
There was a problem hiding this comment.
All review points from the previous round are addressed in d7a0008.
Blockers resolved
aliases: - /docs/v1/was dropped fromv1.2/_index.md; the short path is now handled dynamically bylayouts/404.htmlviaSite.Params.latest_version_id, so no release-time alias shuffling is needed. The script header documents this decision.- Companion upstream PR cozystack/cozystack#2433 is linked in the PR body, so the end-to-end flow has a landing target.
Content hygiene
CONTRIBUTING.mdgained a "Pre-release audit" section with ready-to-run grep patterns (Cozystack v[0-9],@v[0-9],talos:v[0-9]) — good compromise short of automating prose rewrites in the script.
Nits cleaned up
release_next.shregex tightened to^v([0-9]+)\.([0-9]+)\.([0-9]+)$(no pre-release suffix), with a clear error.register_version.shstandardized onsed -i.bak+ cleanup, matchingrelease_next.sh.- Unused
label:field removed fromhugo.yaml. '/./,/^$/!d'comment rewritten to describe actual behavior.init-nextsection inCONTRIBUTING.mdpromoted to "Run this as the final step of every release" with rationale — documentation-only, but explicit enough.
One minor follow-up (not blocking): netlify.toml:26-29 still hardcodes /docs/v1/* → /docs/v1.2/:splat, which will go stale when latest_version_id moves to v1.3. Preview-only and pre-existing, so fine to pick up separately.
LGTM.
## What this PR does Updates the `update-website-docs` job in `.github/workflows/tags.yaml` to match the new docs-versioning contract introduced in cozystack/website#495. The website repo replaces the old "pre-create `vX.Y/` draft directory" scheme with a permanent `content/en/docs/next/` trunk. Released version directories are no longer implicitly pre-created — the upstream release workflow owns the explicit decision of when to promote `next/` → `vX.Y/`. ### Changes - **New step `Determine if this release promotes next/`** — parses the tag and only sets `promote=true` for final `vX.Y.Z` tags where `content/en/docs/vX.Y/` does not already exist. Prereleases (`vX.Y.Z-rc.N`, etc.) and patch releases skip promotion. - **New step `Promote next/ to released version`** — gated on `promote=true`; runs `make release-next RELEASE_TAG=<tag>`. - **Step order**: `release-next` runs **before** `update-all`. This way `update-all` routes into the freshly-created `vX.Y/` directory (per the website Makefile's routing logic), and `next/` stays untouched as the trunk for the following release. - **`git add content hugo.yaml`** — `release-next` registers the new version in `hugo.yaml` via `register_version.sh`, so the commit step must stage it. - Converted the existing `update-all` step to use `env:` vars for consistency with the new step and workflow-injection hardening. ### Behaviour by tag | Tag | `release-next`? | `update-all` targets | |-----|-----------------|----------------------| | `v1.3.0` (v1.3 does not exist) | yes — promotes next/ → v1.3/ | v1.3/ | | `v1.3.1` (v1.3 exists) | no — skipped | v1.3/ | | `v1.3.0-rc.1` | no — skipped (prerelease) | next/ | | `v2.0.0` (v2.0 does not exist) | yes — promotes next/ → v2.0/ | v2.0/ | ### Release note ```release-note Release tagging now promotes the website's `next/` docs trunk to `vX.Y/` when cutting a new minor or major release (requires cozystack/website#495 to be merged first). ``` ### Dependency Must not merge until cozystack/website#495 is merged on `main` of the website repo, otherwise `make release-next` won't exist there and new-minor release tags will fail. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated release automation to apply conditional logic for version promotion based on tag patterns and documentation availability. Modified documentation staging behavior in release workflows. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
The website repo is switching to a permanent `content/en/docs/next/` trunk (cozystack/website#495). Released version directories are no longer pre-created — the upstream release workflow is now responsible for explicitly promoting `next/` → `vX.Y/` on new minor/major releases via `make release-next`. Update the `update-website-docs` job to match that contract: - New `Determine if this release promotes next/` step parses the tag and only enables promotion for final `vX.Y.Z` tags where `content/en/docs/vX.Y/` does not already exist. Prereleases and patch releases keep the old behaviour (target routing is handled by the website Makefile on its own). - New `Promote next/ to released version` step runs `make release-next RELEASE_TAG=...` before `make update-all`, so the subsequent `update-all` routes into the freshly-created `vX.Y/` directory and `next/` stays untouched as the trunk for the following release. - `git add content hugo.yaml` to pick up the version registration that `release-next` writes via `register_version.sh`. - Convert the existing `update-all` step to use `env:` vars, matching the new step and addressing the workflow-injection hardening guidance. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Summary
Replaces the hardcoded
v1.3draft-directory approach from #493 with a permanentcontent/en/docs/next/trunk for upcoming/unreleased Cozystack docs. The next release version is no longer assumed at write-time —next/is promoted tovX.Y/when the upstream release workflow firesmake release-next RELEASE_TAG=vX.Y.Z.content/en/docs/next/trunk (198 files, seeded fromv1.2), excluded from production viaconfig/production/hugo.yaml, visible in local dev and Netlify deploy previews.RELEASE_TAG: patch releases of an existing registered version update in-place; everything else accumulates innext/.hack/release_next.sh(promotenext/→vX.Y/),hack/register_version.sh(managehugo.yamlentries).hidden: trueentries at build time — no manual edits to add a new version to the dropdown/table.Design
Problem
PR #493 introduced version lifecycle management by creating a draft
v1.3directory. This hardcodes an assumption about what the next release will be. The actual next version could be v1.5, v2.0, or anything else. Docs written ahead of a release should not be tied to a specific version number until the release actually happens.Core Concept
A permanent
content/en/docs/next/directory serves as a version-agnostic trunk. Docs for upcoming features accumulate here. When a cozystack release is cut,next/is copied out to the actual version directory and registered.Directory Structure
content/en/docs/next/is a full content tree — a copy of the latest released version plus manual edits for upcoming features./docs/next/paths (rewritten to the actual version at release time)_index.mdtitle: "Cozystack Next (unreleased)" with a draft bannerVersion Registration in
hugo.yamlhidden: true+ content mount exclusion (- '! docs/next/**') excludesnext/from production builds.Build Integration
Production (GitHub Pages):
next/excluded viaconfig/production/hugo.yaml, which duplicates the fullmoduleblock from basehugo.yaml(Hugo replaces arrays wholesale during config merge) with- '! docs/next/**'added to the content mount.download_openapi.shiteratesv*/— naturally skipsnext/.Deploy previews (Netlify) & local dev:
next/is visible at/docs/next/. Netlify's[context.deploy-preview]setsHUGO_ENV=previewso deploy previews skip the production override. Version switcher hides the entry (labelNext (unreleased)) from the dropdown but is aware of it for tooling.Makefile Routing Logic
When
RELEASE_TAGis set, deriveDOC_VERSION(e.g.,v1.3.0→v1.3). Then:content/en/docs/$DOC_VERSION/exists and is registered as non-hidden inhugo.yaml→ target$DOC_VERSION(patch release, update in place)nextWithout
RELEASE_TAG→ targetnext,BRANCH=main.make update-all(no tag)next/make update-all RELEASE_TAG=v1.1.8(v1.1 exists)v1.1/make update-all RELEASE_TAG=v1.3.0-rc1(v1.3 doesn't exist)next/make update-all RELEASE_TAG=v1.3.0(v1.3 doesn't exist)next/make release-next RELEASE_TAG=v1.3.0next/→v1.3/make update-all RELEASE_TAG=v1.3.1(v1.3 now exists)v1.3/Makefile Targets
make update-allmake release-next RELEASE_TAG=vX.Y.Znext/→vX.Y/, registers versionmake init-nextnext/from latest released versionmake show-targetDOC_VERSION/BRANCHrelease-nextFlow (hack/release_next.sh)next/exists and is non-empty;RELEASE_TAGis set; derivedDOC_VERSIONdoesn't already exist as a released directory. Fail hard on any validation error.cp -a content/en/docs/next/ content/en/docs/$DOC_VERSION/.mdfiles in$DOC_VERSION/—/docs/next/→/docs/$DOC_VERSION/,"docs/next/→"docs/$DOC_VERSION/_index.md: title →Cozystack $DOC_VERSION Documentation, remove the{{% warning %}}…{{% /warning %}}draft banner, setweight: 10register_version.sh --release $DOC_VERSION(unhides if already present, or inserts a new entry with auto-computedorder)next/is never modified during release.Upstream Workflow Contract
The upstream
cozystack/cozystacktags.yamlworkflow:make update-all RELEASE_TAG=vX.Y.Zmake release-next RELEASE_TAG=vX.Y.ZUpstream PR ci(docs): promote next/ trunk on new minor/major releases cozystack#2433
The upstream workflow owns the decision of when to call
release-next. No automatic detection — explicit conditional logic on the upstream side.release-nextvalidates and fails hard if preconditions aren't met (no silent no-ops).Changes vs PR #493
Keep:
hidden: truefield on version entries inhugo.yamlregister_version.sh(with modifications)init_version.sh(for edge cases)navbar-version-selector.html_index.mdfilesRemove / replace:
content/en/docs/v1.3/→ replaced bycontent/en/docs/next/make add-draft→ replaced bymake init-nextmake update-all" behavior → replaced by routing logicnextNew:
content/en/docs/next/directoryhack/release_next.shscriptmake release-nextandmake init-nexttargetsAdditional build-config details
netlify.toml,.github/workflows/hugo.yaml) — required for thefiles:mount-filter syntax, which replaces the deprecatedexcludeFiles:.hack/register_version.shand the Makefile routing conditional.Test plan
/docs/next/with the "Cozystack Next (unreleased)" draft bannernext(hidden),/docs/landing table does not list itHUGO_ENV=production hugo --gc --minify) produces nopublic/docs/next/directory — verified locally ✅HUGO_ENV=preview hugo --gc --minify) producespublic/docs/next/populated from the trunk — verified locally ✅make show-targetprints correct routing:DOC_VERSION=next,BRANCH=mainRELEASE_TAG=v1.2.9→DOC_VERSION=v1.2(v1.2 is non-hidden)RELEASE_TAG=v1.3.0→DOC_VERSION=next(v1.3 doesn't exist)make init-nextwipescontent/en/docs/next/and repopulates from the latest released version with the draft banner prependedmake release-next RELEASE_TAG=v1.3.0(dry-run in a throwaway branch) copiesnext/→v1.3/, rewrites links, strips banner, registers the version, leavesnext/intact/docs/next/install/→/docs/v1.3/install/)/docs/landing page table reflects all non-hidden versions with "Latest (stable)" marker onlatest_version_idNotes
🤖 Generated with Claude Code