mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
fix(release): enforce unified Preview publication
Problem: - Preview events for different versions could overlap and let an older npm canary publish last. - CLI, Desktop, and npm child workflows still exposed standalone public Preview paths that bypassed the all-surface release marker. Root cause: - The Preview concurrency key included the version tag, while npm had no channel-level serialization. - Child workflow dispatch inputs and resolvers treated Preview publication as independently recoverable. Fix: - Serialize every Preview event and npm dist-tag publisher, and require public CLI, Desktop, and npm Preview releases to come from release-preview.yml. - Keep Stable/RC recovery and non-publishing Desktop signing checks available, document unified Preview recovery, and add regression coverage. Verification: - bash scripts/release-workflows.test.sh - actionlint v1.7.7 on all release workflows - git diff --check
This commit is contained in:
1 parent
c54516a516
commit
413422feee
9 files changed
+152
-71
No files matched your search
@@ -12,13 +12,11 @@ name: Release desktop
|
||||
# release and mirrored to R2 (the updater reads R2 first, then the crash worker
|
||||
# release gateway; stable desktop releases own GitHub's repository-wide "latest").
|
||||
#
|
||||
# The same build/sign/manifest pipeline serves two channels. An orchestrated
|
||||
# `desktop-v*` tag (or manual stable recovery) publishes a GitHub release and
|
||||
# moves R2's latest/ pointer. A manual `channel: preview` dispatch builds with
|
||||
# -X main.channel=preview
|
||||
# and uploads only to R2's preview/ pointer — no GitHub release, so Preview never
|
||||
# shows on the releases page and never touches latest/. The legacy canary/
|
||||
# pointer is mirrored for clients released before the channel rename.
|
||||
# The same build/sign/manifest pipeline serves two channels. Approved
|
||||
# orchestrators publish Stable or Preview, while manual dispatch supports
|
||||
# Stable/RC recovery and non-publishing Preview signing checks. Preview advances
|
||||
# only R2's preview/ pointer and never appears on the GitHub releases page. The
|
||||
# legacy canary/ pointer is mirrored for clients released before the rename.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -32,7 +30,7 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
base_version:
|
||||
description: "preview: intended next stable version, e.g. 1.5.0"
|
||||
description: "Preview signing checks: intended next stable version, e.g. 1.5.0"
|
||||
required: false
|
||||
type: string
|
||||
production_signing_smoke:
|
||||
@@ -70,7 +68,7 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
orchestrated:
|
||||
description: "True only when called by release-stable.yml after approval"
|
||||
description: "True only when called by an approved release orchestrator"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
@@ -127,9 +125,12 @@ jobs:
|
||||
id: release
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
IN_ORCHESTRATED: ${{ inputs.orchestrated }}
|
||||
IN_CHANNEL: ${{ inputs.channel }}
|
||||
IN_TAG: ${{ inputs.tag }}
|
||||
IN_BASE_VERSION: ${{ inputs.base_version }}
|
||||
IN_PRODUCTION_SIGNING_SMOKE: ${{ inputs.production_signing_smoke }}
|
||||
IN_SIGNING_PREFLIGHT: ${{ inputs.signing_preflight }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
RUN_NUMBER: ${{ github.run_number }}
|
||||
IN_PREVIEW_NUMBER: ${{ inputs.preview_number }}
|
||||
@@ -186,9 +187,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
# Keep Preview fast, but do not make its public, formally signed binaries an
|
||||
# unreviewed path. The `canary` environment must use the same required
|
||||
# reviewers as `release`.
|
||||
# Standalone Preview is limited to non-publishing signing checks, but still
|
||||
# exercises the production policy behind the protected `canary` environment.
|
||||
environment: ${{ needs.resolve.outputs.channel == 'preview' && 'canary' || 'release' }}
|
||||
steps:
|
||||
- env:
|
||||
@@ -533,10 +533,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
# The stable caller has already passed the single GitHub release approval.
|
||||
# Direct prereleases, manual stable recovery, and Preview all pass the
|
||||
# appropriate release gate. The SignPath CI identity records each payload
|
||||
# and installer approval after that GitHub gate.
|
||||
# Approved orchestrators have already passed the matching GitHub environment.
|
||||
# Direct prereleases and manual Stable recovery pass release-gate above. The
|
||||
# SignPath CI identity records each payload and installer approval after it.
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
|
||||
@@ -7,12 +7,12 @@ name: Release npm
|
||||
# git tag npm-vX.Y.Z-rc.N # prerelease -> publishes under `next`
|
||||
# git push origin <tag>
|
||||
#
|
||||
# A manual workflow_dispatch can publish either an opt-in canary from the current
|
||||
# ref or recover an approved stable version from an existing tag. Canary publishes
|
||||
# to the `canary` dist-tag (npm i reasonix@canary) and never moves
|
||||
# `next`/`latest`. build.mjs decides the dist-tag: a `-canary.` build is `canary`,
|
||||
# any other prerelease is `next`, and a stable version is `latest` (#5822 — the
|
||||
# old "promote latest by hand" rule left it pinned at 0.53.2 and downgraded
|
||||
# Manual workflow_dispatch recovers only an approved Stable version from an
|
||||
# existing tag. Public canary publication is owned by release-preview.yml so its
|
||||
# version remains aligned with CLI, Desktop, and the immutable release marker.
|
||||
# build.mjs decides the dist-tag: a `-canary.` build is `canary`, any other
|
||||
# prerelease is `next`, and a stable version is `latest` (#5822 — the old
|
||||
# "promote latest by hand" rule left it pinned at 0.53.2 and downgraded
|
||||
# `npm update -g` users). The verify step below asserts the tag actually landed.
|
||||
on:
|
||||
push:
|
||||
@@ -20,15 +20,14 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: "Publish channel"
|
||||
description: "Standalone npm recovery channel"
|
||||
required: true
|
||||
default: canary
|
||||
default: stable
|
||||
type: choice
|
||||
options:
|
||||
- canary
|
||||
- stable
|
||||
base_version:
|
||||
description: "Version to publish. Canary appends -canary.<run_number>; stable publishes exactly this version."
|
||||
description: "Stable version to recover exactly"
|
||||
required: true
|
||||
type: string
|
||||
tag:
|
||||
@@ -59,7 +58,7 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
orchestrated:
|
||||
description: "True only when called by release-stable.yml after approval"
|
||||
description: "True only when called by an approved release orchestrator"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
@@ -77,6 +76,12 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
# Serialize every publisher for one npm dist-tag. In particular, canary
|
||||
# remains ordered even if another approved orchestrator is added later.
|
||||
group: release-npm-${{ inputs.channel || 'next' }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
orchestration-guard:
|
||||
name: verify approved orchestrator
|
||||
@@ -109,7 +114,7 @@ jobs:
|
||||
|
||||
release-gate:
|
||||
name: approve standalone npm release
|
||||
if: ${{ !inputs.orchestrated && !(github.event_name == 'workflow_dispatch' && inputs.channel == 'canary') }}
|
||||
if: ${{ !inputs.orchestrated }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: release
|
||||
steps:
|
||||
@@ -120,7 +125,7 @@ jobs:
|
||||
cache-guard:
|
||||
name: cache hit guard
|
||||
needs: [orchestration-guard, release-gate]
|
||||
if: ${{ always() && !cancelled() && ((inputs.orchestrated && needs.orchestration-guard.result == 'success') || (!inputs.orchestrated && ((github.event_name == 'workflow_dispatch' && inputs.channel == 'canary') || needs.release-gate.result == 'success'))) }}
|
||||
if: ${{ always() && !cancelled() && ((inputs.orchestrated && needs.orchestration-guard.result == 'success') || (!inputs.orchestrated && needs.release-gate.result == 'success')) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
@@ -137,9 +142,8 @@ jobs:
|
||||
needs: cache-guard
|
||||
if: ${{ always() && !cancelled() && needs.cache-guard.result == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
# The stable caller has already passed the single GitHub release approval.
|
||||
# Direct prereleases/manual stable recovery pass release-gate above; canaries
|
||||
# run free.
|
||||
# Orchestrated releases have already passed their GitHub environment
|
||||
# approval. Direct prereleases and manual Stable recovery pass release-gate.
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
@@ -152,8 +156,8 @@ jobs:
|
||||
with:
|
||||
node-version: '22'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
# Tag push uses the npm-v* tag. A canary dispatch synthesizes a
|
||||
# <base>-canary.<run_number> version; a manual stable dispatch publishes
|
||||
# Tag push uses the npm-v* tag. The Preview orchestrator synthesizes a
|
||||
# <base>-canary.<preview_number> version; a manual Stable dispatch publishes
|
||||
# the requested semver exactly. build.mjs strips the leading `npm-`/`v`.
|
||||
- name: Resolve version
|
||||
id: ver
|
||||
|
||||
@@ -13,7 +13,9 @@ on:
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: preview-release-${{ inputs.tag }}
|
||||
# Every Preview version advances the same public CLI, Desktop, and npm
|
||||
# channels. Keep the whole all-surface event serialized across versions.
|
||||
group: preview-release
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
name: Release
|
||||
|
||||
# Native CLI binary line. Stable releases are called by release-stable.yml after
|
||||
# its single GitHub `release`-environment approval. Preview uses immutable
|
||||
# vX.Y.Z-preview.N tags, publishes a GitHub prerelease behind the same `canary`
|
||||
# gate as Desktop Preview, and never moves Homebrew or GitHub Latest. Other
|
||||
# standalone prereleases remain internal stable-channel checkpoints behind the
|
||||
# `release` gate.
|
||||
# Native CLI binary line. Stable and Preview releases are called by their
|
||||
# approved all-surface orchestrators. Manual dispatch remains available only for
|
||||
# Stable/RC recovery; standalone prereleases remain internal stable-channel
|
||||
# checkpoints behind the `release` gate.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: "Native CLI release channel"
|
||||
description: "Standalone CLI recovery channel"
|
||||
required: true
|
||||
# Preserve existing tag-only recovery dispatches as Stable. Preview must
|
||||
# be an explicit operator choice or arrive through the tag relay.
|
||||
# Public Preview recovery reruns release-preview.yml so every surface and
|
||||
# its immutable release-event marker stay aligned.
|
||||
default: stable
|
||||
type: choice
|
||||
options: [stable, preview]
|
||||
options: [stable]
|
||||
tag:
|
||||
description: "Existing protected CLI tag (Preview: v1.18.0-preview.1; Stable/RC: v1.18.0-rc.1)"
|
||||
description: "Existing protected Stable/RC CLI tag (for example v1.18.0 or v1.18.0-rc.1)"
|
||||
required: true
|
||||
type: string
|
||||
workflow_call:
|
||||
@@ -41,7 +39,7 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
orchestrated:
|
||||
description: "True only when called by release-stable.yml after approval"
|
||||
description: "True only when called by an approved release orchestrator"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
@@ -149,7 +147,7 @@ jobs:
|
||||
needs: resolve
|
||||
if: ${{ !inputs.orchestrated }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ needs.resolve.outputs.channel == 'preview' && 'canary' || 'release' }}
|
||||
environment: release
|
||||
steps:
|
||||
- env:
|
||||
RELEASE_TAG: ${{ needs.resolve.outputs.tag }}
|
||||
|
||||
@@ -213,6 +213,12 @@ strict separation from repository writers is required.
|
||||
npm, and Desktop tags to remain aligned on an ancestor of current `main-v2`,
|
||||
then uses the same single approval and postflight. Never move or recreate the
|
||||
published tags to pick up a workflow fix.
|
||||
- Recover an interrupted Preview release by rerunning **Release preview** from
|
||||
protected `main-v2` with the existing `vX.Y.Z-preview.N` tag. Do not dispatch
|
||||
the CLI, Desktop, or npm publisher directly: those paths cannot create the
|
||||
all-surface `release-event.json` marker and are blocked from public Preview
|
||||
publication. Standalone Desktop Preview dispatch remains available only for
|
||||
non-publishing SignPath preflight and production-signing smoke checks.
|
||||
- Windows release signing uses SignPath trusted-build, origin verification, and
|
||||
malware scanning. Keep the checked-in `windows-payload` and
|
||||
`windows-installer-v2` artifact configurations synchronized with the matching
|
||||
|
||||
@@ -35,6 +35,11 @@ grep -Fq "workflow_id: preview ? 'release-preview.yml' : 'release.yml'" \
|
||||
"$repo_root/.github/workflows/release-cli-trigger.yml"
|
||||
grep -Eq "preview\\\\\." "$repo_root/.github/workflows/release-cli-trigger.yml"
|
||||
grep -Eq '^name: Release preview$' "$repo_root/.github/workflows/release-preview.yml"
|
||||
grep -Eq '^ group: preview-release$' "$repo_root/.github/workflows/release-preview.yml"
|
||||
if grep -Fq 'group: preview-release-${{ inputs.tag }}' "$repo_root/.github/workflows/release-preview.yml"; then
|
||||
echo "Preview releases must serialize across versions" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Eq '^ environment: canary$' "$repo_root/.github/workflows/release-preview.yml"
|
||||
grep -Eq '^ signpath-preflight:$' "$repo_root/.github/workflows/release-preview.yml"
|
||||
grep -Eq 'signing_preflight: true' "$repo_root/.github/workflows/release-preview.yml"
|
||||
@@ -57,11 +62,10 @@ for workflow in release.yml release-npm.yml release-desktop.yml; do
|
||||
grep -Eq 'release-\{1\}\.yml' "$repo_root/.github/workflows/$workflow"
|
||||
grep -Eq "needs\.cache-guard\.result == 'success'" "$repo_root/.github/workflows/$workflow"
|
||||
done
|
||||
grep -Eq 'options: \[stable, preview\]' "$repo_root/.github/workflows/release.yml"
|
||||
grep -Eq 'options: \[stable\]' "$repo_root/.github/workflows/release.yml"
|
||||
grep -A6 -E '^ channel:' "$repo_root/.github/workflows/release.yml" |
|
||||
grep -Eq 'default: stable'
|
||||
grep -Eq "needs\.resolve\.outputs\.channel == 'preview'.*'canary'.*'release'" \
|
||||
"$repo_root/.github/workflows/release.yml"
|
||||
grep -Eq '^ environment: release$' "$repo_root/.github/workflows/release.yml"
|
||||
grep -Eq 'GORELEASER_CURRENT_TAG:.*needs\.resolve\.outputs\.tag' \
|
||||
"$repo_root/.github/workflows/release.yml"
|
||||
grep -Eq 'bash scripts/resolve-cli-release\.sh' "$repo_root/.github/workflows/release.yml"
|
||||
@@ -98,6 +102,20 @@ if grep -Fq 'ref: ${{ inputs.approved_sha || inputs.tag || github.ref }}' \
|
||||
fi
|
||||
grep -Fq "group: release-desktop-\${{ (inputs.channel == 'preview' || inputs.channel == 'canary') && 'preview' || 'stable' }}" \
|
||||
"$repo_root/.github/workflows/release-desktop.yml"
|
||||
grep -Eq 'IN_PRODUCTION_SIGNING_SMOKE:.*inputs\.production_signing_smoke' \
|
||||
"$repo_root/.github/workflows/release-desktop.yml"
|
||||
grep -Eq 'IN_SIGNING_PREFLIGHT:.*inputs\.signing_preflight' \
|
||||
"$repo_root/.github/workflows/release-desktop.yml"
|
||||
grep -Fq "group: release-npm-\${{ inputs.channel || 'next' }}" \
|
||||
"$repo_root/.github/workflows/release-npm.yml"
|
||||
sed -n '/^ workflow_dispatch:/,/^ workflow_call:/p' "$repo_root/.github/workflows/release-npm.yml" |
|
||||
grep -Eq 'default: stable'
|
||||
if sed -n '/^ workflow_dispatch:/,/^ workflow_call:/p' "$repo_root/.github/workflows/release-npm.yml" |
|
||||
grep -Eq '^ - canary$'; then
|
||||
echo "Standalone npm dispatch must not expose public Canary publication" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Fq 'if: ${{ !inputs.orchestrated }}' "$repo_root/.github/workflows/release-npm.yml"
|
||||
grep -Eq 'signing-policy-slug: release-signing' "$repo_root/.github/workflows/release-desktop.yml"
|
||||
if grep -Eq 'signing-policy-slug:.*test-signing' "$repo_root/.github/workflows/release-desktop.yml"; then
|
||||
echo "public desktop workflow must not use the SignPath test certificate" >&2
|
||||
@@ -1072,14 +1090,15 @@ grep -Eq '^tag=desktop-v1\.2\.3$' "$test_root/desktop-stable.out"
|
||||
grep -Eq '^version=v1\.2\.3$' "$test_root/desktop-stable.out"
|
||||
grep -Eq '^notes_version=v1\.2\.3$' "$test_root/desktop-stable.out"
|
||||
|
||||
EVENT_NAME=workflow_dispatch IN_CHANNEL=preview IN_BASE_VERSION=1.3.0 IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=42 \
|
||||
EVENT_NAME=workflow_call IN_ORCHESTRATED=true IN_CHANNEL=preview IN_BASE_VERSION=1.3.0 \
|
||||
IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=999 IN_PREVIEW_NUMBER=42 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-preview.out" bash "$repo_root/scripts/resolve-desktop-release.sh"
|
||||
grep -Eq '^version=v1\.3\.0-preview\.42$' "$test_root/desktop-preview.out"
|
||||
grep -Eq '^tag=desktop-v1\.3\.0-preview\.42$' "$test_root/desktop-preview.out"
|
||||
grep -Eq '^channel=preview$' "$test_root/desktop-preview.out"
|
||||
grep -Eq '^notes_version=v1\.3\.0-preview\.42$' "$test_root/desktop-preview.out"
|
||||
|
||||
if EVENT_NAME=workflow_dispatch IN_CHANNEL=preview IN_BASE_VERSION=1.3.0 \
|
||||
if EVENT_NAME=workflow_call IN_ORCHESTRATED=true IN_CHANNEL=preview IN_BASE_VERSION=1.3.0 \
|
||||
IN_TAG=desktop-v1.3.0-preview.42 REF_NAME=main-v2 RUN_NUMBER=42 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-preview-tagged.out" \
|
||||
bash "$repo_root/scripts/resolve-desktop-release.sh" \
|
||||
@@ -1090,14 +1109,31 @@ fi
|
||||
grep -Eq 'Desktop Preview versions are synthesized from protected main-v2' \
|
||||
"$test_root/desktop-preview-tagged.log"
|
||||
|
||||
# Legacy automation may still dispatch `canary`; normalize it to Preview without
|
||||
# exposing a third user-facing release channel.
|
||||
EVENT_NAME=workflow_dispatch IN_CHANNEL=canary IN_BASE_VERSION=1.3.0 IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=43 \
|
||||
# Legacy signing automation may still dispatch `canary`; normalize it to Preview
|
||||
# without exposing a third public release path.
|
||||
EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_SIGNING_PREFLIGHT=true \
|
||||
IN_CHANNEL=canary IN_BASE_VERSION=1.3.0 IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=43 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-canary-compat.out" bash "$repo_root/scripts/resolve-desktop-release.sh"
|
||||
grep -Eq '^version=v1\.3\.0-preview\.43$' "$test_root/desktop-canary-compat.out"
|
||||
grep -Eq '^tag=desktop-v1\.3\.0-preview\.43$' "$test_root/desktop-canary-compat.out"
|
||||
grep -Eq '^channel=preview$' "$test_root/desktop-canary-compat.out"
|
||||
|
||||
EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_PRODUCTION_SIGNING_SMOKE=true \
|
||||
IN_CHANNEL=preview IN_BASE_VERSION=1.3.0 IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=44 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-preview-smoke.out" bash "$repo_root/scripts/resolve-desktop-release.sh"
|
||||
grep -Eq '^version=v1\.3\.0-preview\.44$' "$test_root/desktop-preview-smoke.out"
|
||||
|
||||
if EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_CHANNEL=preview \
|
||||
IN_BASE_VERSION=1.3.0 IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=45 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-preview-direct.out" \
|
||||
bash "$repo_root/scripts/resolve-desktop-release.sh" \
|
||||
>"$test_root/desktop-preview-direct.log" 2>&1; then
|
||||
echo "standalone public Desktop Preview unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Eq 'public Desktop Preview releases must be dispatched by release-preview.yml' \
|
||||
"$test_root/desktop-preview-direct.log"
|
||||
|
||||
EVENT_NAME=push IN_CHANNEL='' IN_TAG='' REF_NAME=desktop-v1.4.0-rc.1 RUN_NUMBER=50 \
|
||||
GITHUB_OUTPUT="$test_root/desktop-rc.out" bash "$repo_root/scripts/resolve-desktop-release.sh"
|
||||
grep -Eq '^prerelease=true$' "$test_root/desktop-rc.out"
|
||||
@@ -1121,20 +1157,26 @@ if EVENT_NAME=workflow_dispatch IN_CHANNEL=stable IN_TAG='' REF_NAME=main-v2 RUN
|
||||
fi
|
||||
grep -Eq 'stable dispatch requires tag' "$test_root/desktop-missing-tag.log"
|
||||
|
||||
EVENT_NAME=push IN_CHANNEL='' IN_TAG='' REF_NAME=v1.3.0-preview.42 \
|
||||
GITHUB_OUTPUT="$test_root/cli-preview-push.out" bash "$repo_root/scripts/resolve-cli-release.sh"
|
||||
grep -Eq '^tag=v1\.3\.0-preview\.42$' "$test_root/cli-preview-push.out"
|
||||
grep -Eq '^version=1\.3\.0-preview\.42$' "$test_root/cli-preview-push.out"
|
||||
grep -Eq '^base_version=1\.3\.0$' "$test_root/cli-preview-push.out"
|
||||
grep -Eq '^notes_version=v1\.3\.0-preview\.42$' "$test_root/cli-preview-push.out"
|
||||
grep -Eq '^channel=preview$' "$test_root/cli-preview-push.out"
|
||||
grep -Eq '^prerelease=true$' "$test_root/cli-preview-push.out"
|
||||
EVENT_NAME=workflow_call IN_ORCHESTRATED=true IN_CHANNEL=preview IN_TAG=v1.3.0-preview.42 \
|
||||
REF_NAME=main-v2 GITHUB_OUTPUT="$test_root/cli-preview-call.out" \
|
||||
bash "$repo_root/scripts/resolve-cli-release.sh"
|
||||
grep -Eq '^tag=v1\.3\.0-preview\.42$' "$test_root/cli-preview-call.out"
|
||||
grep -Eq '^version=1\.3\.0-preview\.42$' "$test_root/cli-preview-call.out"
|
||||
grep -Eq '^base_version=1\.3\.0$' "$test_root/cli-preview-call.out"
|
||||
grep -Eq '^notes_version=v1\.3\.0-preview\.42$' "$test_root/cli-preview-call.out"
|
||||
grep -Eq '^channel=preview$' "$test_root/cli-preview-call.out"
|
||||
grep -Eq '^prerelease=true$' "$test_root/cli-preview-call.out"
|
||||
|
||||
EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_CHANNEL=preview \
|
||||
if EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_CHANNEL=preview \
|
||||
IN_TAG=v1.3.0-preview.42 REF_NAME=main-v2 CALLER_REF=refs/heads/main-v2 \
|
||||
CALLER_REF_PROTECTED=true GITHUB_OUTPUT="$test_root/cli-preview-dispatch.out" \
|
||||
bash "$repo_root/scripts/resolve-cli-release.sh"
|
||||
grep -Eq '^channel=preview$' "$test_root/cli-preview-dispatch.out"
|
||||
bash "$repo_root/scripts/resolve-cli-release.sh" \
|
||||
>"$test_root/cli-preview-dispatch.log" 2>&1; then
|
||||
echo "standalone public CLI Preview unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Eq 'public CLI Preview releases must be dispatched by release-preview.yml' \
|
||||
"$test_root/cli-preview-dispatch.log"
|
||||
|
||||
EVENT_NAME=push IN_CHANNEL='' IN_TAG='' REF_NAME=v1.3.0-rc.1 \
|
||||
GITHUB_OUTPUT="$test_root/cli-rc.out" bash "$repo_root/scripts/resolve-cli-release.sh"
|
||||
@@ -1178,6 +1220,21 @@ EVENT_NAME=push IN_ORCHESTRATED=true IN_CHANNEL=stable IN_BASE_VERSION=1.5.0 \
|
||||
bash "$repo_root/scripts/resolve-npm-release.sh"
|
||||
grep -Eq '^arg=v1\.5\.0$' "$test_root/npm-stable.out"
|
||||
|
||||
EVENT_NAME=workflow_call IN_ORCHESTRATED=true IN_CHANNEL=canary IN_BASE_VERSION=1.5.0 \
|
||||
IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=999 IN_PREVIEW_NUMBER=42 \
|
||||
GITHUB_OUTPUT="$test_root/npm-canary.out" bash "$repo_root/scripts/resolve-npm-release.sh"
|
||||
grep -Eq '^arg=v1\.5\.0-canary\.42$' "$test_root/npm-canary.out"
|
||||
|
||||
if EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_CHANNEL=canary IN_BASE_VERSION=1.5.0 \
|
||||
IN_TAG='' REF_NAME=main-v2 RUN_NUMBER=52 GITHUB_OUTPUT="$test_root/npm-canary-direct.out" \
|
||||
bash "$repo_root/scripts/resolve-npm-release.sh" \
|
||||
>"$test_root/npm-canary-direct.log" 2>&1; then
|
||||
echo "standalone public npm Canary unexpectedly passed" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -Eq 'public npm Canary releases must be dispatched by release-preview.yml' \
|
||||
"$test_root/npm-canary-direct.log"
|
||||
|
||||
if EVENT_NAME=workflow_dispatch IN_ORCHESTRATED=false IN_CHANNEL=stable IN_BASE_VERSION=1.5.0 \
|
||||
IN_TAG=npm-v1.5.1 REF_NAME=main-v2 RUN_NUMBER=52 GITHUB_OUTPUT="$test_root/npm-mismatch.out" \
|
||||
bash "$repo_root/scripts/resolve-npm-release.sh" >"$test_root/npm-mismatch.log" 2>&1; then
|
||||
|
||||
@@ -66,6 +66,11 @@ if [ -n "$requested_channel" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$channel" = "preview" ] && [ "${IN_ORCHESTRATED:-false}" != "true" ]; then
|
||||
echo "::error::public CLI Preview releases must be dispatched by release-preview.yml" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{
|
||||
echo "tag=$tag"
|
||||
echo "version=$version"
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#
|
||||
# stable: from a desktop-v* prerelease tag push, a manual dispatch with `tag`,
|
||||
# or the stable release orchestrator's workflow_call input.
|
||||
# preview: a manual dispatch with channel=preview (legacy canary accepted);
|
||||
# version is synthesized from base_version + the monotonic run_number,
|
||||
# tag is the matching immutable asset directory, and it is always a
|
||||
# prerelease.
|
||||
# preview: public publication requires the approved Preview orchestrator;
|
||||
# standalone Preview is limited to non-publishing signing checks.
|
||||
# Legacy canary input is accepted for those checks. The version uses
|
||||
# the orchestrator ordinal or, for a signing check, the run number.
|
||||
set -euo pipefail
|
||||
|
||||
stable_semver_re='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$'
|
||||
@@ -16,6 +16,12 @@ release_semver_re='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-([0-9A-Za
|
||||
preview_semver_re='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)-preview\.(0|[1-9][0-9]*)$'
|
||||
|
||||
if [ "${IN_CHANNEL:-stable}" = "preview" ] || [ "${IN_CHANNEL:-stable}" = "canary" ]; then
|
||||
if [ "${IN_ORCHESTRATED:-false}" != "true" ] && \
|
||||
[ "${IN_PRODUCTION_SIGNING_SMOKE:-false}" != "true" ] && \
|
||||
[ "${IN_SIGNING_PREFLIGHT:-false}" != "true" ]; then
|
||||
echo "::error::public Desktop Preview releases must be dispatched by release-preview.yml" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "${IN_TAG:-}" ]; then
|
||||
echo "::error::Desktop Preview versions are synthesized from protected main-v2; tag must be empty" >&2
|
||||
exit 1
|
||||
|
||||
@@ -15,6 +15,10 @@ if [ "${EVENT_NAME:-}" = "workflow_dispatch" ] || [ "${IN_ORCHESTRATED:-false}"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${IN_CHANNEL:-stable}" = "canary" ]; then
|
||||
if [ "${IN_ORCHESTRATED:-false}" != "true" ]; then
|
||||
echo "::error::public npm Canary releases must be dispatched by release-preview.yml" >&2
|
||||
exit 1
|
||||
fi
|
||||
preview_number="${IN_PREVIEW_NUMBER:-${RUN_NUMBER:-}}"
|
||||
if [[ ! "$preview_number" =~ ^(0|[1-9][0-9]*)$ ]]; then
|
||||
echo "::error::canary preview number must be a non-negative integer, got: $preview_number" >&2
|
||||
|
||||
Reference in new issue
Block a user