返回 DeepSeek-Reasonix
release-npm.yml
根目录 / .github / workflows / release-npm.yml
1 name: Release npm
2
3 # npm line. Stable releases are called by release-stable.yml after its single
4 # GitHub environment approval. Direct prerelease tag publication is disabled;
5 # manual workflow_dispatch recovers only an approved Stable version from an
6 # existing tag. Historical canary and next package identities remain readable,
7 # but normal publication advances only the official release.
8 on:
9 workflow_dispatch:
10 inputs:
11 channel:
12 description: "Standalone npm recovery channel"
13 required: true
14 default: stable
15 type: choice
16 options:
17 - stable
18 base_version:
19 description: "Stable version to recover exactly"
20 required: true
21 type: string
22 tag:
23 description: "stable: existing npm tag to publish (for example npm-v1.18.0)"
24 required: false
25 type: string
26 workflow_call:
27 inputs:
28 channel:
29 description: "Publish channel selected by the approved release orchestrator"
30 required: true
31 type: string
32 base_version:
33 description: "Version to publish"
34 required: true
35 type: string
36 tag:
37 description: "Existing npm tag to check out for stable publication"
38 required: false
39 default: ""
40 type: string
41 approved_cli_tag:
42 description: "Stable CLI tag recorded by the approved orchestrator"
43 required: true
44 type: string
45 approved_sha:
46 description: "Immutable commit recorded by the approved orchestrator"
47 required: true
48 type: string
49 orchestrated:
50 description: "True only when called by an approved release orchestrator"
51 required: false
52 default: false
53 type: boolean
54 orchestrator:
55 description: "Trusted release orchestrator (legacy Preview calls remain readable)"
56 required: false
57 default: stable
58 type: string
59 preview_number:
60 description: "Legacy Preview ordinal for old workflow-call compatibility"
61 required: false
62 default: ""
63 type: string
64
65 permissions:
66 contents: read
67
68 concurrency:
69 # Serialize every publisher for one npm dist-tag. Historical canary calls
70 # remain ordered even though normal publication now uses Stable only.
71 group: release-npm-${{ inputs.channel || 'next' }}
72 cancel-in-progress: false
73
74 jobs:
75 orchestration-guard:
76 name: verify approved orchestrator
77 if: ${{ inputs.orchestrated }}
78 runs-on: ubuntu-latest
79 permissions:
80 contents: read
81 steps:
82 - uses: actions/checkout@v7
83 with:
84 fetch-depth: 0
85 ref: ${{ github.sha }}
86 - name: Verify caller and approved release ref
87 env:
88 ACTUAL_CALLER_WORKFLOW_REF: ${{ github.workflow_ref }}
89 EXPECTED_CALLER_WORKFLOW_REF: ${{ format('{0}/.github/workflows/release-{1}.yml@{2}', github.repository, inputs.orchestrator, github.ref) }}
90 CALLER_EVENT_NAME: ${{ github.event_name }}
91 CALLER_REF: ${{ github.ref }}
92 CALLER_REF_PROTECTED: ${{ github.ref_protected }}
93 CALLER_WORKFLOW_SHA: ${{ github.workflow_sha }}
94 CALLER_SHA: ${{ github.sha }}
95 APPROVED_CLI_TAG: ${{ inputs.approved_cli_tag }}
96 APPROVED_SHA: ${{ inputs.approved_sha }}
97 APPROVED_CHANNEL: ${{ inputs.orchestrator }}
98 RELEASE_TAG: ${{ inputs.approved_cli_tag }}
99 VERIFY_RELEASE_CHECKOUT: false
100 run: |
101 bash scripts/verify-release-authorization.sh
102 bash scripts/verify-release-tag.sh
103
104 release-gate:
105 name: approve standalone npm release
106 if: ${{ !inputs.orchestrated }}
107 runs-on: ubuntu-latest
108 environment: release
109 steps:
110 - env:
111 RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
112 run: echo "Approved standalone npm release $RELEASE_TAG"
113
114 cache-guard:
115 name: cache hit guard
116 needs: [orchestration-guard, release-gate]
117 if: ${{ always() && !cancelled() && ((inputs.orchestrated && needs.orchestration-guard.result == 'success') || (!inputs.orchestrated && needs.release-gate.result == 'success')) }}
118 runs-on: ubuntu-latest
119 steps:
120 - uses: actions/checkout@v7
121 with:
122 ref: ${{ inputs.approved_sha || inputs.tag || github.ref }}
123 - uses: actions/setup-go@v7
124 with:
125 go-version-file: go.mod
126 cache: true
127 - run: ./scripts/cache-guard.sh
128 - name: Verify embedded documentation identity
129 env:
130 DOCS_BUILD_VERSION: v${{ inputs.base_version }}
131 DOCS_SOURCE_REVISION: ${{ inputs.approved_sha }}
132 run: |
133 if [ ! -f scripts/verify-embedded-docs.sh ]; then
134 echo "Legacy candidate predates the embedded docs contract; skipping."
135 exit 0
136 fi
137 revision="$DOCS_SOURCE_REVISION"
138 if [ -z "$revision" ]; then revision="$(git rev-parse HEAD)"; fi
139 bash scripts/verify-embedded-docs.sh "$DOCS_BUILD_VERSION" "$revision"
140
141 npm:
142 name: publish npm packages
143 needs: cache-guard
144 if: ${{ always() && !cancelled() && needs.cache-guard.result == 'success' }}
145 runs-on: ubuntu-latest
146 # Orchestrated releases have already passed their GitHub environment
147 # approval. Direct prereleases and manual Stable recovery pass release-gate.
148 steps:
149 - uses: actions/checkout@v7
150 with:
151 ref: ${{ inputs.approved_sha || inputs.tag || github.ref }}
152 - name: Load approved standalone recovery control plane
153 if: ${{ !inputs.orchestrated }}
154 env:
155 RECOVERY_CONTROL_SHA: ${{ github.workflow_sha }}
156 run: |
157 set -euo pipefail
158 git fetch --no-tags --depth=1 origin "$RECOVERY_CONTROL_SHA"
159 git restore --source="$RECOVERY_CONTROL_SHA" -- \
160 npm/publish.mjs \
161 scripts/finalize-npm-official-release.mjs
162 - uses: actions/setup-go@v7
163 with:
164 go-version-file: go.mod
165 cache: true
166 - uses: actions/setup-node@v7
167 with:
168 node-version: '22'
169 registry-url: 'https://registry.npmjs.org'
170 # Stable publication uses the exact npm-v* tag. build.mjs strips the
171 # leading `npm-`/`v`; historical Preview inputs remain only for old
172 # workflow-call compatibility and are not reachable from a public entry.
173 - name: Resolve version
174 id: ver
175 env:
176 EVENT_NAME: ${{ github.event_name }}
177 IN_ORCHESTRATED: ${{ inputs.orchestrated }}
178 IN_CHANNEL: ${{ inputs.channel }}
179 IN_BASE_VERSION: ${{ inputs.base_version }}
180 IN_TAG: ${{ inputs.tag }}
181 REF_NAME: ${{ github.ref_name }}
182 RUN_NUMBER: ${{ github.run_number }}
183 IN_PREVIEW_NUMBER: ${{ inputs.preview_number }}
184 run: bash scripts/resolve-npm-release.sh
185 - name: Revalidate approved release ref
186 if: ${{ inputs.orchestrated }}
187 env:
188 RELEASE_TAG: ${{ inputs.approved_cli_tag }}
189 APPROVED_SHA: ${{ inputs.approved_sha }}
190 run: bash scripts/verify-release-tag.sh
191 - name: Publish or recover immutable npm packages
192 env:
193 VERSION_ARG: ${{ steps.ver.outputs.arg }}
194 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
195 run: node npm/build.mjs "$VERSION_ARG" --publish
196 - name: Align legacy aliases with the official release
197 if: ${{ inputs.channel == 'stable' }}
198 env:
199 VERSION: ${{ inputs.base_version }}
200 APPROVED_SHA: ${{ inputs.approved_sha }}
201 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
202 run: |
203 set -euo pipefail
204 candidate="$APPROVED_SHA"
205 if [ -z "$candidate" ]; then candidate="$(git rev-parse HEAD)"; fi
206 EXPECTED_SHA="$candidate" node scripts/finalize-npm-official-release.mjs "$VERSION"
207
207 lines YAML