返回 DeepSeek-TUI-2026
RELEASE_RUNBOOK.md
根目录 / docs / RELEASE_RUNBOOK.md
1 # DeepSeek TUI Release Runbook
2
3 This runbook is the source of truth for shipping Rust crates, GitHub release assets,
4 and the `deepseek-tui` npm wrapper.
5
6 Current packaging note:
7 - `deepseek-tui` is the live runtime and TUI package shipped to users today.
8 - `deepseek-tui-core` is a supporting workspace crate for the extraction/parity effort, not a replacement for the shipping runtime.
9
10 ## Canonical Publish Targets
11
12 - End-user crates:
13 - `deepseek-tui`
14 - `deepseek-tui-cli`
15 - Supporting crates published from this workspace:
16 - `deepseek-secrets`
17 - `deepseek-config`
18 - `deepseek-protocol`
19 - `deepseek-state`
20 - `deepseek-agent`
21 - `deepseek-execpolicy`
22 - `deepseek-hooks`
23 - `deepseek-mcp`
24 - `deepseek-tools`
25 - `deepseek-core`
26 - `deepseek-app-server`
27 - `deepseek-tui-core`
28 - `deepseek-cli` on crates.io is an unrelated crate and is not part of this release flow.
29
30 ## Version Coordination
31
32 - Rust crates inherit the shared workspace version from [Cargo.toml](../Cargo.toml).
33 - Internal path dependency versions should match the shared workspace version; stale older pins are release blockers once the workspace version moves.
34 - The npm wrapper version lives in [npm/deepseek-tui/package.json](../npm/deepseek-tui/package.json).
35 - `deepseekBinaryVersion` controls which GitHub release binaries the npm wrapper downloads.
36 - Packaging-only npm releases are allowed:
37 - bump the npm package version
38 - leave `deepseekBinaryVersion` pinned to the previously released Rust binaries
39 - rerun `npm pack` smoke checks before `npm publish`
40
41 ## Preflight
42
43 Run these from the repository root before cutting a tag:
44
45 ```bash
46 ./scripts/release/check-versions.sh # version drift between workspace, npm, lockfile
47 cargo fmt --all -- --check
48 cargo check --workspace --all-targets --locked
49 cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
50 cargo test --workspace --all-features --locked
51 cargo publish --dry-run --locked --allow-dirty -p deepseek-tui
52 ./scripts/release/publish-crates.sh dry-run
53 ```
54
55 `check-versions.sh` also runs in CI on every push/PR (the `versions` job in
56 `.github/workflows/ci.yml`), so drift between `Cargo.toml`, the per-crate
57 manifests, `npm/deepseek-tui/package.json`, and `Cargo.lock` is caught before
58 release time rather than at it.
59
60 `publish-crates.sh dry-run` performs a full `cargo publish --dry-run` for crates
61 without unpublished workspace dependencies and a packaging preflight for dependent
62 workspace crates. That avoids false negatives from crates.io not yet containing the
63 new workspace version while still validating package contents before publish.
64
65 For npm wrapper verification, build the two shipped binaries and run the
66 cross-platform smoke harness. This packs the npm wrapper, installs it into a
67 clean temporary project, serves local release assets over HTTP, and checks both
68 the dispatcher-to-TUI path (`deepseek doctor --help`) and the direct TUI
69 entrypoint (`deepseek-tui --help`).
70
71 ```bash
72 cargo build --release --locked -p deepseek-tui-cli -p deepseek-tui
73 node scripts/release/npm-wrapper-smoke.js
74 ```
75
76 Set `DEEPSEEK_TUI_KEEP_SMOKE_DIR=1` to keep the temporary pack/install
77 directory for inspection.
78
79 To exercise `npm run release:check` locally as well, regenerate the local asset
80 directory with a full asset matrix fixture before starting the server:
81
82 ```bash
83 DEEPSEEK_TUI_PREPARE_ALL_ASSETS=1 node scripts/release/prepare-local-release-assets.js
84 cd npm/deepseek-tui
85 DEEPSEEK_TUI_VERSION=X.Y.Z DEEPSEEK_TUI_RELEASE_BASE_URL=http://127.0.0.1:8123/ npm run release:check
86 ```
87
88 Set `DEEPSEEK_TUI_VERSION` to the npm package version you are verifying for that local run.
89
90 The CI workflow runs the same tarball install + delegated-entrypoint smoke test
91 on Linux, macOS, and Windows.
92
93 After publishing, prove the release is visible in both registries:
94
95 ```bash
96 ./scripts/release/check-published.sh X.Y.Z
97 ```
98
99 Do not mark a Rust release complete until that command sees `deepseek-tui@X.Y.Z`
100 on npm and every `deepseek-*` crate at `X.Y.Z` on crates.io. For a rare
101 npm packaging-only release, run with `--allow-npm-binary-mismatch` and keep the
102 release notes explicit that no new Rust binary version shipped.
103
104 ## Rust Crates Release
105
106 Crate publishing to crates.io is **manual** — there is no automated
107 `crates-publish` GitHub workflow. Operators run the helpers in
108 `scripts/release/` from a developer workstation that has `cargo login`
109 configured.
110
111 1. Update the workspace version in [Cargo.toml](../Cargo.toml).
112 2. Run `./scripts/release/check-versions.sh` and
113 `./scripts/release/publish-crates.sh dry-run` locally; both must be clean.
114 3. Tag the release as `vX.Y.Z` (typically by pushing the version bump to
115 `main` and letting `auto-tag.yml` create the tag — see the npm wrapper
116 release section below for the `RELEASE_TAG_PAT` requirement).
117 4. Publish crates in this order with `./scripts/release/publish-crates.sh publish`:
118 - `deepseek-secrets`
119 - `deepseek-config`
120 - `deepseek-protocol`
121 - `deepseek-state`
122 - `deepseek-agent`
123 - `deepseek-execpolicy`
124 - `deepseek-hooks`
125 - `deepseek-mcp`
126 - `deepseek-tools`
127 - `deepseek-core`
128 - `deepseek-app-server`
129 - `deepseek-tui-core`
130 - `deepseek-tui-cli`
131 - `deepseek-tui`
132 5. Wait for each published crate version to appear on crates.io before publishing dependents.
133
134 The publish helper is idempotent for reruns: already-published crate versions are skipped.
135
136 ## GitHub Release Assets
137
138 `.github/workflows/release.yml` builds these binaries:
139
140 - `deepseek-linux-x64`
141 - `deepseek-macos-x64`
142 - `deepseek-macos-arm64`
143 - `deepseek-windows-x64.exe`
144 - `deepseek-tui-linux-x64`
145 - `deepseek-tui-macos-x64`
146 - `deepseek-tui-macos-arm64`
147 - `deepseek-tui-windows-x64.exe`
148
149 The release job also uploads `deepseek-artifacts-sha256.txt`. The npm installer and
150 release verification script both depend on that checksum manifest.
151
152 ## npm Wrapper Release
153
154 **The npm publish step is manual.** `release.yml` no longer runs `npm publish`
155 because the npm account requires 2FA OTP on every publish, and an automation
156 token that bypasses 2FA has not been provisioned. The GitHub Release flow
157 remains fully automated; only the npm wrapper publish requires a developer
158 on a workstation with `npm login` and an authenticator app.
159
160 ### Steps
161
162 1. Set the npm package version in [npm/deepseek-tui/package.json](../npm/deepseek-tui/package.json) to match the workspace `Cargo.toml`. CI's version-drift guard will catch mismatches before tag.
163 2. Set `deepseekBinaryVersion` to the GitHub release tag that should supply binaries.
164 3. Push the version bump to `main`. `auto-tag.yml` creates the matching `vX.Y.Z` tag, and `release.yml` builds the binary matrix and drafts the GitHub Release.
165 4. **Wait for the GitHub Release to finalize** with all eight signed binaries plus `deepseek-artifacts-sha256.txt`. The npm `prepublishOnly` hook (`scripts/verify-release-assets.js`) requires every asset to be present.
166 5. From a developer machine, publish the npm wrapper manually:
167
168 ```bash
169 cd npm/deepseek-tui
170 npm publish --access public
171 # (you will be prompted for the npm OTP from your authenticator)
172 ```
173
174 ### Why not automated?
175
176 - `release.yml`'s old `publish-npm` job used `secrets.NPM_TOKEN`, but npm's 2FA-by-default policy means a publish token must be either an automation token with "Bypass 2FA for token authentication" enabled OR an account-level 2FA-disabled state. We don't have either configured.
177 - The standalone `publish-npm.yml` and `crates-publish.yml` workflows have been removed; no inert automation plumbing remains. A future move to npm Trusted Publishing (OIDC) would re-introduce a dedicated workflow at that point.
178
179 ### If you fix the token later
180
181 To re-enable automated publish: provision an npm automation token with "Bypass 2FA for token authentication" enabled (or set up npm Trusted Publishing via OIDC), store the corresponding secret on the repo, and re-add a `publish-npm` job to `release.yml` (or a dedicated workflow) along with reverting this section's "manual" framing.
182
183 ## Recovery and Rollback
184
185 - Crates publish partially:
186 - rerun `./scripts/release/publish-crates.sh publish`
187 - already-published crate versions will be skipped
188 - GitHub assets missing or checksum manifest incomplete:
189 - fix `.github/workflows/release.yml`
190 - retag or upload corrected assets before `npm publish`
191 - npm packaging-only problem:
192 - bump only the npm package version
193 - keep `deepseekBinaryVersion` on the last known-good Rust release
194 - repack and republish the wrapper
195 - A bad npm publish cannot be overwritten:
196 - publish a new npm version with corrected metadata or install logic
197
197 lines MARKDOWN