Skip to content

Promotion

Promotion means moving an already-published version from one channel (dist-tag) to another. It does not produce a new tarball; only the dist-tag pointers change.

Today

The publish pipeline currently writes only the latest dist-tag. Therefore promotion is not exercised today: every publish goes straight to latest.

For pre-launch testing of a candidate before it becomes default, the current workaround is to either:

  • Publish to a separate package name (e.g. @open-matrix/chat-rc), or
  • Pin the candidate version explicitly in dependents and avoid touching latest until validated.

Both are awkward. Real channel-based promotion is target state.

Target state

Once next and beta channels are in active use, the promotion flow looks like:

1. Publish version 0.3.0-rc.1 with dist-tag = next
2. Internal smoke-test against `npm install @open-matrix/chat@next`
3. After validation, promote to latest:
     npm dist-tag add @open-matrix/chat@0.3.0-rc.1 latest
4. Consumers using `@open-matrix/chat@latest` pick up 0.3.0-rc.1 on next install

The npm dist-tag command is npm-canonical; Gitea supports it through the standard npm packages API.

Promotion mechanics

bash
# Add a tag to an existing version (does not unset other tags)
npm dist-tag add @open-matrix/chat@0.3.0-rc.1 latest

# Remove a tag from a version
npm dist-tag rm @open-matrix/chat next

# List current tags
npm dist-tag ls @open-matrix/chat

A single version can hold multiple tags simultaneously. Promotion is adding the new tag; demotion is adding the same tag to a different version (the tag re-points).

Atomic promotion is not guaranteed

npm dist-tag add updates one tag at a time. If you want "latest→0.3.0-rc.1, next→0.3.0" simultaneously, you must run two commands. There is a window where one tag is updated and the other is stale. For most purposes that is harmless; for tightly coupled releases, coordinate.

Catalog implications

discovery-index.json is not aware of dist-tags. The catalog reads only literal versions. A dist-tag change does not require a catalog re-index.

A consumer who searches the catalog sees the latest known version per package (per readLatestMetadata in SystemPackageRegistryActor). The catalog's "latest" is the highest version key in discovery-index.json, not the artifact registry's latest dist-tag. These usually match; they can drift if operators retag without re-indexing.

See also

Source: Current publish pipeline writes only latest. Multi-channel promotion is target state in the publishing workstream.