mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
fix(release)!: decouple npm @latest from Docker rc.1 soak (REV11) (#1277)
Reverts the loop-1 prerelease channel that was publishing npm as vX.Y.Z-rc.N to the `rc` dist-tag instead of `latest`. `main` is now a stable semantic-release channel again: every merge publishes vX.Y.Z immediately to npm @latest. The rc.1 soak window that guards Docker mutable tags is moved entirely into the Docker publish workflow: - `.releaserc.cjs`: remove `prerelease: 'rc'` from productionConfig, restore `branches: ['main']` (stable). Restore full successComment and `released` label. Keep loop-1 releaseNotesGenerator additions (revert section, breaking change comment). - `docker-release.yml`: every `release: published` event publishes only the immutable `:<ver>` Docker tag. `promote-mutable-tags` job now gates exclusively on `workflow_dispatch` with `promote_to_latest=true` — no longer triggered automatically by non-prerelease release events. - `promote-release.yml`: rewritten as a dispatch wrapper that validates the stable tag exists and is not a prerelease, verifies the immutable Docker image is in the registry, then dispatches docker-release.yml with `promote_to_latest=true`. Removes the `gh release edit --prerelease=false` approach that required the rc soak to be wired through GitHub release state. - `docs/release-process.md`: updated to reflect the decoupled model — npm @latest is immediate; Docker :latest requires manual promote after soak. Documents the `why` split between npm and Docker soak windows.
This commit is contained in:
@@ -31,7 +31,8 @@ jobs:
|
||||
# ---------------------------------------------------------------------------
|
||||
publish-dashboard:
|
||||
name: Publish legacy ccs-dashboard image
|
||||
# Skip on prerelease events — rc builds do not publish the legacy image
|
||||
# Skip on prerelease release events — only stable vX.Y.Z GitHub releases
|
||||
# publish the legacy image. workflow_dispatch always passes through.
|
||||
if: ${{ github.event_name != 'release' || !github.event.release.prerelease }}
|
||||
runs-on: [self-hosted, linux, x64, cliproxy]
|
||||
|
||||
@@ -143,14 +144,15 @@ jobs:
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Job 2: Integrated image — CCS + CLIProxy (single build, no :full variant)
|
||||
# Publishes ONLY the immutable :<ver> tag here.
|
||||
# Publishes ONLY the immutable :<ver> tag here on every release event.
|
||||
# Mutable :latest / major / minor aliases are added by promote-mutable-tags
|
||||
# AFTER smoke tests pass, preventing a bad image from reaching :latest.
|
||||
# ONLY via explicit workflow_dispatch (promote_to_latest=true) after the
|
||||
# operator has verified the immutable image is stable. This keeps the rc.1
|
||||
# soak window entirely in the Docker promotion path — npm @latest is always
|
||||
# published immediately by semantic-release on the stable release.
|
||||
# ---------------------------------------------------------------------------
|
||||
publish-integrated:
|
||||
name: Publish integrated image
|
||||
# Prerelease events (rc.N) publish the immutable version tag only.
|
||||
# Mutable tags are never set on rc builds — promotion is always explicit.
|
||||
runs-on: [self-hosted, linux, x64, cliproxy]
|
||||
|
||||
permissions:
|
||||
@@ -284,16 +286,15 @@ jobs:
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Job 3: Smoke test — pull the immutable :<ver> tag and verify it boots
|
||||
# Runs after publish-integrated; mutable tags are only added if this passes.
|
||||
# Runs after publish-integrated; mutable tags are only promoted if this passes.
|
||||
# ---------------------------------------------------------------------------
|
||||
smoke-test:
|
||||
name: Smoke test integrated image
|
||||
# Depends only on publish-integrated, NOT publish-dashboard.
|
||||
# publish-dashboard is skipped on prerelease (rc.N) events — if it were
|
||||
# listed here, GitHub Actions would also skip smoke-test and
|
||||
# promote-mutable-tags on every rc publish, breaking the rc soak flow.
|
||||
# publish-dashboard is skipped on GitHub prerelease events — if it were
|
||||
# listed here, GitHub Actions would also skip smoke-test when that condition
|
||||
# is not met, preventing the immutable tag from being verified.
|
||||
needs: [publish-integrated]
|
||||
# Run on both rc and stable releases; skip if integrated publish was skipped
|
||||
if: ${{ needs.publish-integrated.outputs.publish == 'true' }}
|
||||
runs-on: [self-hosted, linux, x64, cliproxy]
|
||||
|
||||
@@ -399,17 +400,19 @@ jobs:
|
||||
# ---------------------------------------------------------------------------
|
||||
# Job 4: Promote mutable tags — runs ONLY after smoke tests pass
|
||||
# Adds :latest, :<major>, :<minor> aliases pointing to the immutable digest.
|
||||
# Never runs for prerelease (rc) events.
|
||||
# Never triggered automatically by release events — requires an explicit
|
||||
# workflow_dispatch with promote_to_latest=true (via promote-release.yml or
|
||||
# direct gh CLI call) after the operator confirms the immutable :<ver> image
|
||||
# is stable. This is the sole rc.1 soak gate for Docker mutable tags.
|
||||
# ---------------------------------------------------------------------------
|
||||
promote-mutable-tags:
|
||||
name: Promote mutable tags (:latest / major / minor)
|
||||
needs: [smoke-test, publish-integrated]
|
||||
# Only promote on stable release events or explicit promote_to_latest dispatch
|
||||
# Only promote on explicit operator dispatch — never on automatic release events.
|
||||
# Release events publish the immutable :<ver> tag only (see publish-integrated).
|
||||
if: |
|
||||
needs.publish-integrated.outputs.publish == 'true' && (
|
||||
(github.event_name == 'release' && !github.event.release.prerelease) ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.promote_to_latest == true)
|
||||
)
|
||||
needs.publish-integrated.outputs.publish == 'true' &&
|
||||
github.event_name == 'workflow_dispatch' && inputs.promote_to_latest == true
|
||||
runs-on: [self-hosted, linux, x64, cliproxy]
|
||||
|
||||
permissions:
|
||||
|
||||
@@ -1,69 +1,98 @@
|
||||
name: Promote rc to Stable Release
|
||||
name: Promote Stable Release to Docker Latest
|
||||
|
||||
# Manual workflow to promote a pre-release rc tag to a stable GitHub release.
|
||||
# Manual workflow to promote a stable vX.Y.Z release to Docker mutable tags
|
||||
# (:latest, :MAJOR, :MINOR) after the rc.1 soak window.
|
||||
#
|
||||
# Flow:
|
||||
# 1. Flip the GitHub release from prerelease=true to prerelease=false using
|
||||
# `gh release edit --prerelease=false`.
|
||||
# 2. The resulting `release: published` event (with prerelease=false) triggers
|
||||
# docker-release.yml, which builds/signs the image, runs smoke tests, then
|
||||
# adds the mutable :latest/:MAJOR/:MINOR Docker tags via promote-mutable-tags.
|
||||
# 1. Validate that the input tag exists as a stable (non-prerelease) GitHub release.
|
||||
# 2. Dispatch docker-release.yml with promote_to_latest=true for the given tag.
|
||||
# This triggers the promote-mutable-tags job (gated on workflow_dispatch
|
||||
# with promote_to_latest=true) which adds :latest/:MAJOR/:MINOR Docker aliases.
|
||||
#
|
||||
# Pre-conditions:
|
||||
# - The rc tag must already exist as a GitHub prerelease (cut by semantic-release).
|
||||
# - Smoke tests on the rc image must have passed (manual verification step).
|
||||
# - The stable tag must already exist as a GitHub release (created automatically
|
||||
# by semantic-release when the PR merges to main).
|
||||
# - The immutable :<ver> Docker image must already be published and smoke-tested
|
||||
# (done automatically by docker-release.yml on the release: published event).
|
||||
# - Operator has verified the immutable image is stable (24h soak recommended).
|
||||
#
|
||||
# See docs/release-process.md for the full soak + promote procedure.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
rc_tag:
|
||||
tag:
|
||||
description: >
|
||||
Pre-release rc tag to promote, e.g. v7.80.0-rc.1.
|
||||
Must already exist as a GitHub prerelease.
|
||||
Stable tag to promote, e.g. v7.80.0.
|
||||
Must already exist as a GitHub stable release with the immutable
|
||||
Docker :<ver> image already published and smoke-tested.
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
promote:
|
||||
name: Promote ${{ inputs.rc_tag }} to stable
|
||||
name: Promote ${{ inputs.tag }} Docker mutable tags
|
||||
runs-on: [self-hosted, linux, x64, cliproxy]
|
||||
|
||||
permissions:
|
||||
contents: write # required to edit GitHub releases
|
||||
contents: read # to verify the release
|
||||
actions: write # to dispatch docker-release.yml
|
||||
|
||||
steps:
|
||||
- name: Validate rc tag format
|
||||
- name: Validate stable semver tag format
|
||||
run: |
|
||||
if [[ "${{ inputs.rc_tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$ ]]; then
|
||||
echo "[OK] Tag format valid: ${{ inputs.rc_tag }}"
|
||||
if [[ "${{ inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "[OK] Tag format valid: ${{ inputs.tag }}"
|
||||
else
|
||||
echo "[X] Expected vX.Y.Z-rc.N format, got: ${{ inputs.rc_tag }}"
|
||||
echo "[X] Expected vX.Y.Z format, got: ${{ inputs.tag }}"
|
||||
echo " For rc tags use docker-release.yml directly with promote_to_latest=true."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify release exists and is a prerelease
|
||||
- name: Verify release exists and is stable (not a prerelease)
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
IS_PRERELEASE=$(gh release view "${{ inputs.rc_tag }}" \
|
||||
IS_PRERELEASE=$(gh release view "${{ inputs.tag }}" \
|
||||
--repo "${{ github.repository }}" \
|
||||
--json isPrerelease --jq '.isPrerelease')
|
||||
if [[ "${IS_PRERELEASE}" != "true" ]]; then
|
||||
echo "[X] Release ${{ inputs.rc_tag }} is not a prerelease (isPrerelease=${IS_PRERELEASE})"
|
||||
echo " Either it was already promoted, or the tag does not exist."
|
||||
if [[ "${IS_PRERELEASE}" == "true" ]]; then
|
||||
echo "[X] Release ${{ inputs.tag }} is still a prerelease (isPrerelease=true)"
|
||||
echo " Semantic-release publishes stable releases to main automatically."
|
||||
echo " Check that the tag was created from a main merge, not a dev prerelease."
|
||||
exit 1
|
||||
fi
|
||||
echo "[OK] Release ${{ inputs.rc_tag }} is a prerelease — proceeding with promotion"
|
||||
if [[ "${IS_PRERELEASE}" != "false" ]]; then
|
||||
echo "[X] Could not read release state for ${{ inputs.tag }} (got: ${IS_PRERELEASE})"
|
||||
echo " Verify the tag exists: gh release view ${{ inputs.tag }} --repo ${{ github.repository }}"
|
||||
exit 1
|
||||
fi
|
||||
echo "[OK] Release ${{ inputs.tag }} is stable — proceeding with Docker mutable tag promotion"
|
||||
|
||||
- name: Promote release to stable
|
||||
- name: Verify immutable Docker image exists
|
||||
run: |
|
||||
TAG_SANS_V="${{ inputs.tag }}"
|
||||
TAG_SANS_V="${TAG_SANS_V#v}"
|
||||
OWNER_LOWER=$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')
|
||||
IMAGE_REF="ghcr.io/${OWNER_LOWER}/ccs:${TAG_SANS_V}"
|
||||
echo "[i] Verifying immutable image: ${IMAGE_REF}"
|
||||
if ! docker manifest inspect "${IMAGE_REF}" > /dev/null 2>&1; then
|
||||
echo "[X] Immutable image ${IMAGE_REF} not found in ghcr.io"
|
||||
echo " Run docker-release.yml for this tag first, or wait for smoke tests to complete."
|
||||
exit 1
|
||||
fi
|
||||
echo "[OK] Immutable image ${IMAGE_REF} confirmed in registry"
|
||||
|
||||
- name: Dispatch Docker mutable tag promotion
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh release edit "${{ inputs.rc_tag }}" \
|
||||
RUN_URL=$(gh workflow run "Publish Docker Image" \
|
||||
--repo "${{ github.repository }}" \
|
||||
--prerelease=false \
|
||||
--latest
|
||||
echo "[OK] Promoted ${{ inputs.rc_tag }} to stable (prerelease=false, latest=true)"
|
||||
echo "[i] docker-release.yml will now trigger to add :latest/:MAJOR/:MINOR Docker tags"
|
||||
--field "tag=${{ inputs.tag }}" \
|
||||
--field "promote_to_latest=true" \
|
||||
2>&1)
|
||||
echo "[OK] Dispatched docker-release.yml with tag=${{ inputs.tag }} promote_to_latest=true"
|
||||
echo "[i] Monitor the run at: https://github.com/${{ github.repository }}/actions/workflows/docker-release.yml"
|
||||
echo "[i] After the run completes, verify with:"
|
||||
echo " docker buildx imagetools inspect ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/ccs:latest"
|
||||
|
||||
+14
-16
@@ -3,7 +3,13 @@
|
||||
*
|
||||
* Branch-aware config:
|
||||
* - dev branch: Uses dev release configuration (prerelease)
|
||||
* - main branch: Uses production release configuration
|
||||
* - main branch: Uses production release configuration (stable, npm @latest)
|
||||
*
|
||||
* RC soak window for Docker mutable tags is handled entirely in docker-release.yml:
|
||||
* every release event publishes the immutable :<ver> Docker tag immediately;
|
||||
* mutable :latest/:MAJOR/:MINOR tags require an explicit operator action via
|
||||
* `gh workflow run promote-release.yml -f tag=vX.Y.Z` (workflow_dispatch).
|
||||
* npm @latest is always set immediately on stable release — no rc soak needed.
|
||||
*/
|
||||
|
||||
const currentBranch =
|
||||
@@ -93,18 +99,12 @@ const devConfig = {
|
||||
};
|
||||
|
||||
// Production release configuration
|
||||
// Every merge to main auto-cuts as vX.Y.Z-rc.N (prerelease channel "rc").
|
||||
// A separate promote-release.yml workflow_dispatch promotes a specific rc tag
|
||||
// to stable by flipping the GitHub release to non-prerelease, which triggers
|
||||
// docker-release.yml to add the mutable :latest/:MAJOR/:MINOR Docker tags.
|
||||
// See docs/release-process.md for the full soak + promote procedure.
|
||||
// Every merge to main publishes a stable vX.Y.Z release immediately to npm @latest.
|
||||
// Docker immutable :<ver> tag is pushed by docker-release.yml on the release: published event.
|
||||
// Docker mutable :latest/:MAJOR/:MINOR tags require a separate manual promote step — see
|
||||
// docs/release-process.md and promote-release.yml for the soak + promote procedure.
|
||||
const productionConfig = {
|
||||
branches: [
|
||||
{
|
||||
name: 'main',
|
||||
prerelease: 'rc',
|
||||
},
|
||||
],
|
||||
branches: ['main'],
|
||||
plugins: [
|
||||
commitAnalyzer,
|
||||
releaseNotesGenerator,
|
||||
@@ -118,11 +118,9 @@ const productionConfig = {
|
||||
[
|
||||
'@semantic-release/github',
|
||||
{
|
||||
// rc releases are prerelease — use a minimal comment; stable promotion
|
||||
// gets the full resolution comment via the promote-release workflow.
|
||||
successComment:
|
||||
'This issue is included in pre-release version ${nextRelease.version}. A stable release will follow after the rc soak period.',
|
||||
releasedLabels: ['pending-release'],
|
||||
':tada: This issue has been resolved in version ${nextRelease.version} :tada:\n\nThe release is available on:\n- [npm package (@latest)](https://www.npmjs.com/package/@kaitranntt/ccs)\n- [GitHub release](${releases[0].url})',
|
||||
releasedLabels: ['released'],
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
+50
-36
@@ -1,35 +1,38 @@
|
||||
# CCS Release Process
|
||||
|
||||
CCS uses a two-phase release model: every merge to `main` auto-cuts a
|
||||
pre-release rc build, and a separate manual promotion step flips it to stable.
|
||||
This gives a soak window before `:latest` Docker tags and npm `@latest` reach
|
||||
end users.
|
||||
CCS uses a decoupled release model: every merge to `main` immediately publishes
|
||||
a stable npm `@latest` release and an immutable Docker `:<ver>` tag. Docker
|
||||
mutable tags (`:latest`, `:<MAJOR>`, `:<MINOR>`) require a separate manual
|
||||
promote step after an operator-verified soak window. This decouples the npm
|
||||
ecosystem from the Docker stability gate.
|
||||
|
||||
## Phase 1 — Automatic rc cut (on every merge to `main`)
|
||||
## Phase 1 — Automatic stable release (on every merge to `main`)
|
||||
|
||||
1. A PR is merged into `main` with a conventional commit (`feat:`, `fix:`, etc.).
|
||||
2. `release.yml` triggers semantic-release, which reads `.releaserc.cjs`.
|
||||
3. Because `main` is configured as `{ name: 'main', prerelease: 'rc' }`,
|
||||
semantic-release cuts a GitHub pre-release tagged `vX.Y.Z-rc.N`.
|
||||
4. The npm package is published to the `rc` dist-tag
|
||||
(`npm install @kaitranntt/ccs@rc`).
|
||||
5. `docker-release.yml` triggers on the `release: published` event and:
|
||||
3. Because `main` is a stable channel, semantic-release cuts a GitHub release
|
||||
tagged `vX.Y.Z` and publishes the npm package to the `@latest` dist-tag
|
||||
immediately. No rc channel, no soak delay on npm.
|
||||
4. `docker-release.yml` triggers on the `release: published` event and:
|
||||
- Validates the tag as stable semver (`vX.Y.Z`).
|
||||
- Builds the integrated image for `linux/amd64` and `linux/arm64`.
|
||||
- Pushes **only the immutable** `ghcr.io/kaitranntt/ccs:X.Y.Z-rc.N` tag.
|
||||
- Pushes **only the immutable** `ghcr.io/kaitranntt/ccs:X.Y.Z` tag.
|
||||
- Signs the image with cosign (keyless OIDC).
|
||||
- Runs smoke tests (`smoke-test` job).
|
||||
- Mutable tags (`:latest`, `:<MAJOR>`, `:<MINOR>`) are **not** added at
|
||||
this stage — `promote-mutable-tags` is gated on `!github.event.release.prerelease`.
|
||||
this stage — `promote-mutable-tags` only runs on explicit
|
||||
`workflow_dispatch` with `promote_to_latest=true`.
|
||||
|
||||
## Phase 2 — Manual promotion to stable
|
||||
## Phase 2 — Manual promotion to Docker mutable tags (rc.1 soak window)
|
||||
|
||||
After the rc image has soaked (typically 24–48 h with no reported issues):
|
||||
After the immutable `:<ver>` Docker image has soaked (typically 24 h with no
|
||||
reported issues), the operator promotes mutable tags:
|
||||
|
||||
1. Verify the rc image is healthy:
|
||||
1. Verify the immutable image is healthy:
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/kaitranntt/ccs:X.Y.Z-rc.N
|
||||
docker run --rm -p 3000:3000 -p 8317:8317 ghcr.io/kaitranntt/ccs:X.Y.Z-rc.N
|
||||
docker pull ghcr.io/kaitranntt/ccs:X.Y.Z
|
||||
docker run --rm -p 3000:3000 -p 8317:8317 ghcr.io/kaitranntt/ccs:X.Y.Z
|
||||
# check http://localhost:3000 and http://localhost:8317
|
||||
```
|
||||
|
||||
@@ -39,25 +42,37 @@ After the rc image has soaked (typically 24–48 h with no reported issues):
|
||||
cosign verify \
|
||||
--certificate-identity-regexp "https://github.com/kaitranntt/ccs/.github/workflows/docker-release.yml" \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
ghcr.io/kaitranntt/ccs:X.Y.Z-rc.N
|
||||
ghcr.io/kaitranntt/ccs:X.Y.Z
|
||||
```
|
||||
|
||||
3. Run the `promote-release` workflow via GitHub Actions UI or CLI:
|
||||
|
||||
```bash
|
||||
gh workflow run promote-release.yml \
|
||||
--field rc_tag=vX.Y.Z-rc.N
|
||||
--field tag=vX.Y.Z
|
||||
```
|
||||
|
||||
4. The workflow calls `gh release edit vX.Y.Z-rc.N --prerelease=false --latest`,
|
||||
which fires a new `release: published` event with `prerelease=false`.
|
||||
This dispatches `docker-release.yml` with `promote_to_latest=true`, which
|
||||
triggers the `promote-mutable-tags` job to add `:latest`, `:<MAJOR>`, and
|
||||
`:<MINOR>` via `docker buildx imagetools create`.
|
||||
|
||||
5. `docker-release.yml` picks up the stable event and the `promote-mutable-tags`
|
||||
job runs, adding `:latest`, `:<MAJOR>`, `:<MINOR>` via
|
||||
`docker buildx imagetools create`.
|
||||
Alternatively, dispatch `docker-release.yml` directly:
|
||||
|
||||
6. npm `@latest` is already set by semantic-release during the rc phase for the
|
||||
stable semver portion — no separate npm step is needed.
|
||||
```bash
|
||||
gh workflow run "Publish Docker Image" \
|
||||
--field tag=vX.Y.Z \
|
||||
--field promote_to_latest=true
|
||||
```
|
||||
|
||||
## Why npm and Docker have different soak windows
|
||||
|
||||
- **npm `@latest`**: Published immediately on every `main` merge. npm users who
|
||||
pin a version are unaffected; users who run `npm install -g @kaitranntt/ccs`
|
||||
get the latest immediately. Rollback is `npm install -g @kaitranntt/ccs@X.Y.Z`.
|
||||
- **Docker `:latest`**: Promoted only after operator confirmation. Users who
|
||||
pull `:latest` or run `docker pull` without a pinned tag are shielded from
|
||||
a bad image. The immutable `:<ver>` tag is always available for pinned usage
|
||||
from the moment of release.
|
||||
|
||||
## Verifying the promotion
|
||||
|
||||
@@ -65,7 +80,7 @@ After the rc image has soaked (typically 24–48 h with no reported issues):
|
||||
# Confirm :latest points to the promoted digest
|
||||
docker buildx imagetools inspect ghcr.io/kaitranntt/ccs:latest
|
||||
|
||||
# Confirm npm @latest updated
|
||||
# Confirm npm @latest updated (happens automatically at Phase 1)
|
||||
npm view @kaitranntt/ccs dist-tags
|
||||
```
|
||||
|
||||
@@ -74,19 +89,18 @@ npm view @kaitranntt/ccs dist-tags
|
||||
If a promoted release is found to be bad:
|
||||
|
||||
```bash
|
||||
# Re-mark as prerelease on GitHub (stops new users from pulling :latest via UI)
|
||||
gh release edit vX.Y.Z-rc.N --prerelease=true --latest=false
|
||||
|
||||
# Repoint :latest to the previous known-good version
|
||||
# Repoint :latest to the previous known-good immutable tag
|
||||
docker buildx imagetools create \
|
||||
--tag ghcr.io/kaitranntt/ccs:latest \
|
||||
ghcr.io/kaitranntt/ccs:PREVIOUS.VERSION
|
||||
|
||||
# For npm, publish a fix as a new patch release (do not unpublish)
|
||||
# Unpublishing npm packages causes downstream breakage for pinned consumers.
|
||||
```
|
||||
|
||||
## Branch / tag taxonomy
|
||||
|
||||
| Branch | Semantic-release channel | npm dist-tag | Docker tag |
|
||||
|--------|--------------------------|--------------|------------|
|
||||
| `main` | `rc` prerelease | `@rc` | `:<ver>-rc.N` (immutable only) |
|
||||
| `main` (after promote) | stable | `@latest` | `:latest`, `:<MAJOR>`, `:<MINOR>`, `:<ver>` |
|
||||
| `dev` | `dev` prerelease | `@dev` | not published |
|
||||
| Branch | Semantic-release channel | npm dist-tag | Docker tag (on release event) | Docker mutable (on promote) |
|
||||
|--------|--------------------------|--------------|-------------------------------|------------------------------|
|
||||
| `main` | stable | `@latest` | `:<ver>` (immutable, immediate) | `:latest`, `:<MAJOR>`, `:<MINOR>` (after soak) |
|
||||
| `dev` | `dev` prerelease | `@dev` | not published | not published |
|
||||
|
||||
Reference in New Issue
Block a user