Durable @next integration-line publish: on next pushes, compute <patch+1>-next.<pipeline#> prerelease versions (in-CI, uncommitted) and publish @mosaicstack/* under the next dist-tag; gateway image sha-only on next. Strict guardrails: next-only, never writes latest, never tags from next; main path unchanged. PR-event CI 1631 fully green + review-of-record APPROVE (head b1a887a2). Guardrails independently verified.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.3 KiB
B1 / @next Durable Publish Pipeline — Design
Objective
Make next a durable integration line that publishes the artifacts required by downstream federation boot tests without manual builds.
Every merge to next publishes:
- npm prerelease packages to the Gitea npm registry with dist-tag
next. - Gateway container image tagged only as
gateway:sha-<short>.
The existing stable release behavior remains isolated to main / tags.
Registry verification
Target registry: https://git.mosaicstack.dev/api/packages/mosaicstack/npm/.
Pre-implementation checks:
npm view @mosaicstack/mosaic dist-tags --registry https://git.mosaicstack.dev/api/packages/mosaicstack/npm/ --jsonreturned a dist-tags object (latest: 0.0.48).npm view @mosaicstack/mosaic@latest version --registry https://git.mosaicstack.dev/api/packages/mosaicstack/npm/resolved0.0.48.@nextcurrently returns 404 because nonextdist-tag exists yet; this is expected before the first next prerelease publish.
Pipeline design includes a post-publish verification that npm view @mosaicstack/mosaic@next version resolves to the exact CI-computed prerelease version. If Gitea fails to honor the next dist-tag, the pipeline fails closed.
Version scheme
The prerelease version is computed at publish time only; no package.json version changes are committed.
For each non-private @mosaicstack/* package:
<target-stable>-next.<CI_PIPELINE_NUMBER>
Where:
CI_PIPELINE_NUMBERis Woodpecker's monotonic pipeline number.target-stableis the package's current committed stable version with the patch component incremented.- Example:
@mosaicstack/mosaic0.0.48publishes as0.0.49-next.1626. - Example:
@mosaicstack/gateway0.0.6publishes as0.0.7-next.1626.
- Example:
Rationale:
- npm semver sorts
0.0.49-next.1627above0.0.49-next.1626. - The prerelease does not overtake the future stable
0.0.49. - The monotonic pipeline number avoids conflicts across repeated
nextmerges.
Branch and tag guardrails
| Pipeline path | Branch/event | Publishes | Forbidden |
|---|---|---|---|
| stable npm publish | main push/manual or tag |
package versions already committed in package manifests | @next dist-tag |
| next npm publish | next push/manual only |
CI-computed prereleases with --tag next |
latest dist-tag |
| gateway image | main push/manual or tag |
sha-<short> + latest on main + tag on tag events |
next prerelease npm |
| gateway image | next push/manual only |
sha-<short> only |
latest |
| appservice/web images | main push/manual or tag only |
existing stable image behavior | next image publication |
The pipeline has explicit branch checks inside the publish commands as a second fail-closed layer beyond Woodpecker when clauses.
Implementation plan
- Widen
.woodpecker/publish.ymltop-levelwhento includenextso the publish pipeline runs on next merges. - Keep existing
publish-npmonmain/ tags only. - Add
publish-next-npmfornextpush/manual only:- configure Gitea npm auth from existing
gitea_tokensecret asNPM_TOKEN; - preflight registry dist-tag metadata;
- compute prerelease versions in CI by temporarily editing package manifests in the workspace;
- run
pnpm publish ... --tag nextagainst non-private@mosaicstack/*packages; - verify
@mosaicstack/mosaic@nextresolves to the computed version.
- configure Gitea npm auth from existing
- Split image
whenanchors:image_build_whenincludesnextand is used bybuild-gateway;main_image_build_whenkeeps appservice/web on main/tags only.
- Keep gateway next image destinations to
sha-<short>only; nolateston next.
Risk controls
- Auth/registry failures are fatal.
- No manual image build/push path is introduced.
- No production
latesttags are touched fromnext. - No
@latestnpm dist-tags are touched fromnext. - All changes live in CI config and docs; no runtime source behavior changes.