返回 DeepSeek-TUI-2026
release.yml
根目录 / .github / workflows / release.yml
1 name: Release
2
3 on:
4 push:
5 tags: ['v*']
6 workflow_dispatch:
7 inputs:
8 version:
9 description: 'Package/release version to publish to npm, without the leading v'
10 required: true
11 type: string
12
13 env:
14 CARGO_TERM_COLOR: always
15 RUSTFLAGS: -Dwarnings
16
17 jobs:
18 parity:
19 if: github.event_name == 'push'
20 runs-on: ubuntu-latest
21 steps:
22 - uses: actions/checkout@v4
23 - uses: dtolnay/rust-toolchain@stable
24 with:
25 components: clippy, rustfmt
26 - name: Install Linux system dependencies
27 if: runner.os == 'Linux'
28 run: |
29 for i in 1 2 3 4 5; do
30 sudo apt-get update && break
31 echo "apt-get update failed (attempt $i); retrying in 15s"
32 sleep 15
33 done
34 sudo apt-get install -y libdbus-1-dev pkg-config
35 - uses: Swatinem/rust-cache@v2
36 - name: Format check
37 run: cargo fmt --all -- --check
38 - name: Compile check
39 run: cargo check --workspace --all-targets --locked
40 - name: Clippy
41 run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
42 - name: Workspace tests
43 run: cargo test --workspace --all-features --locked
44 - name: TUI snapshot parity
45 run: cargo test -p deepseek-tui-core --test snapshot --locked
46 - name: Protocol schema parity
47 run: cargo test -p deepseek-protocol --test parity_protocol --locked
48 - name: State persistence parity
49 run: cargo test -p deepseek-state --test parity_state --locked
50 - name: Lockfile drift guard
51 run: git diff --exit-code -- Cargo.lock
52
53 build:
54 needs: parity
55 # `parity` is gated to tag-push events. On manual `workflow_dispatch`,
56 # parity is skipped, so let `build` proceed when parity either succeeded
57 # or was skipped — but never when it actually failed or the run was
58 # cancelled. Operators using dispatch are expected to have already run
59 # the same gates locally / via ci.yml on `main`.
60 if: ${{ !cancelled() && (needs.parity.result == 'success' || needs.parity.result == 'skipped') }}
61 strategy:
62 matrix:
63 include:
64 # --- deepseek (cli) ---
65 - os: ubuntu-latest
66 target: x86_64-unknown-linux-gnu
67 target_zig: x86_64-unknown-linux-gnu.2.28
68 binary: deepseek
69 artifact_name: deepseek-linux-x64
70 - os: ubuntu-24.04-arm
71 target: aarch64-unknown-linux-gnu
72 target_zig: aarch64-unknown-linux-gnu.2.28
73 binary: deepseek
74 artifact_name: deepseek-linux-arm64
75 - os: macos-latest
76 target: x86_64-apple-darwin
77 binary: deepseek
78 artifact_name: deepseek-macos-x64
79 - os: macos-latest
80 target: aarch64-apple-darwin
81 binary: deepseek
82 artifact_name: deepseek-macos-arm64
83 - os: windows-latest
84 target: x86_64-pc-windows-msvc
85 binary: deepseek.exe
86 artifact_name: deepseek-windows-x64.exe
87 # --- deepseek-tui (TUI) ---
88 - os: ubuntu-latest
89 target: x86_64-unknown-linux-gnu
90 target_zig: x86_64-unknown-linux-gnu.2.28
91 binary: deepseek-tui
92 artifact_name: deepseek-tui-linux-x64
93 - os: ubuntu-24.04-arm
94 target: aarch64-unknown-linux-gnu
95 target_zig: aarch64-unknown-linux-gnu.2.28
96 binary: deepseek-tui
97 artifact_name: deepseek-tui-linux-arm64
98 - os: macos-latest
99 target: x86_64-apple-darwin
100 binary: deepseek-tui
101 artifact_name: deepseek-tui-macos-x64
102 - os: macos-latest
103 target: aarch64-apple-darwin
104 binary: deepseek-tui
105 artifact_name: deepseek-tui-macos-arm64
106 - os: windows-latest
107 target: x86_64-pc-windows-msvc
108 binary: deepseek-tui.exe
109 artifact_name: deepseek-tui-windows-x64.exe
110 runs-on: ${{ matrix.os }}
111 steps:
112 - uses: actions/checkout@v4
113 - uses: dtolnay/rust-toolchain@stable
114 with:
115 targets: ${{ matrix.target }}
116 - uses: Swatinem/rust-cache@v2
117 - name: Install Linux system dependencies
118 if: runner.os == 'Linux'
119 run: |
120 for i in 1 2 3 4 5; do
121 sudo apt-get update && break
122 echo "apt-get update failed (attempt $i); retrying in 15s"
123 sleep 15
124 done
125 sudo apt-get install -y libdbus-1-dev pkg-config
126 - name: Install zig
127 if: runner.os == 'Linux'
128 uses: goto-bus-stop/setup-zig@v2
129 with:
130 version: '0.13.0'
131 - name: Install cargo-zigbuild
132 if: runner.os == 'Linux'
133 run: cargo install cargo-zigbuild --locked
134 - name: Build
135 shell: bash
136 run: |
137 if [ -n "${{ matrix.target_zig }}" ]; then
138 cargo zigbuild --release --locked --target ${{ matrix.target_zig }}
139 else
140 cargo build --release --locked --target ${{ matrix.target }}
141 fi
142 - name: Rename binary
143 shell: bash
144 run: |
145 # cargo zigbuild writes binaries to target/<rust-target>/release/ —
146 # the .glibc suffix in matrix.target_zig is consumed by zig as a CC
147 # flag, not by cargo as a target dir. Always use the rust target.
148 BIN_PATH="target/${{ matrix.target }}/release/${{ matrix.binary }}"
149 if [ ! -f "${BIN_PATH}" ]; then
150 echo "Binary not at ${BIN_PATH}; searching target/ for ${{ matrix.binary }}:"
151 find target -name "${{ matrix.binary }}" -type f
152 exit 1
153 fi
154 cp "${BIN_PATH}" "${{ matrix.artifact_name }}"
155 - uses: actions/upload-artifact@v4
156 with:
157 name: ${{ matrix.artifact_name }}
158 path: ${{ matrix.artifact_name }}
159 docker:
160 needs: build
161 if: ${{ !cancelled() && needs.build.result == 'success' }}
162 runs-on: ubuntu-latest
163 permissions:
164 contents: read
165 packages: write
166 steps:
167 - uses: actions/checkout@v4
168 - name: Set up QEMU
169 uses: docker/setup-qemu-action@v3
170 - name: Set up Docker Buildx
171 uses: docker/setup-buildx-action@v3
172 - name: Log in to GitHub Container Registry
173 uses: docker/login-action@v3
174 with:
175 registry: ghcr.io
176 username: ${{ github.repository_owner }}
177 password: ${{ secrets.GITHUB_TOKEN }}
178 - name: Extract metadata
179 id: meta
180 uses: docker/metadata-action@v5
181 with:
182 images: |
183 ghcr.io/${{ github.repository }}
184 tags: |
185 type=semver,pattern={{version}}
186 type=semver,pattern={{major}}.{{minor}}
187 type=semver,pattern=v{{major}}
188 type=ref,event=tag
189 - name: Build and push
190 uses: docker/build-push-action@v6
191 with:
192 context: .
193 platforms: linux/amd64,linux/arm64
194 push: true
195 tags: ${{ steps.meta.outputs.tags }}
196 labels: ${{ steps.meta.outputs.labels }}
197 cache-from: type=gha
198 cache-to: type=gha,mode=max
199
200 release:
201 needs: build
202 if: ${{ !cancelled() && needs.build.result == 'success' }}
203 runs-on: ubuntu-latest
204 permissions:
205 contents: write
206 steps:
207 - uses: actions/download-artifact@v4
208 with:
209 path: artifacts
210 - name: List artifacts
211 run: find artifacts -type f
212 - name: Generate checksum manifest
213 shell: bash
214 run: |
215 mkdir -p artifacts/checksums
216 manifest="artifacts/checksums/deepseek-artifacts-sha256.txt"
217 : > "${manifest}"
218 while IFS= read -r -d '' file; do
219 hash="$(sha256sum "${file}" | awk '{print $1}')"
220 base="$(basename "${file}")"
221 printf '%s %s\n' "${hash}" "${base}" >> "${manifest}"
222 done < <(find artifacts -type f ! -path 'artifacts/checksums/*' -print0 | sort -z)
223 cat "${manifest}"
224 - uses: softprops/action-gh-release@v1
225 with:
226 files: artifacts/*/*
227 prerelease: false
228 body: |
229 ## Install
230
231 ### Recommended — npm (one command, both binaries)
232
233 ```bash
234 npm install -g deepseek-tui
235 ```
236
237 The wrapper downloads both binaries from this Release and places them in the same directory.
238
239 ### Cargo (Linux / macOS)
240
241 ```bash
242 cargo install deepseek-tui-cli deepseek-tui --locked
243 ```
244
245 Both crates are required — `deepseek-tui-cli` produces the `deepseek` dispatcher and `deepseek-tui` produces the interactive runtime that the dispatcher delegates to. Installing only one binary will fail at runtime with a `MISSING_COMPANION_BINARY` error.
246
247 ### Manual download
248
249 **Both** binaries below must be downloaded for your platform and dropped into the same directory (e.g. `~/.local/bin/`):
250
251 | Platform | Dispatcher | TUI runtime |
252 |---|---|---|
253 | Linux x64 | `deepseek-linux-x64` | `deepseek-tui-linux-x64` |
254 | Linux ARM64 | `deepseek-linux-arm64` | `deepseek-tui-linux-arm64` |
255 | macOS x64 | `deepseek-macos-x64` | `deepseek-tui-macos-x64` |
256 | macOS ARM | `deepseek-macos-arm64` | `deepseek-tui-macos-arm64` |
257 | Windows x64 | `deepseek-windows-x64.exe` | `deepseek-tui-windows-x64.exe` |
258
259 Then `chmod +x` both (Unix) and run `./deepseek`.
260
261 ### Verify (recommended)
262
263 Download `deepseek-artifacts-sha256.txt` from this Release and verify:
264
265 ```bash
266 # Linux
267 sha256sum -c deepseek-artifacts-sha256.txt
268
269 # macOS
270 shasum -a 256 -c deepseek-artifacts-sha256.txt
271 ```
272
273 ## Changelog
274
275 See [CHANGELOG.md](https://github.com/Hmbown/DeepSeek-TUI/blob/main/CHANGELOG.md) for the full notes for this release.
276
277 # npm publish is intentionally not automated. The npm account requires 2FA OTP
278 # on every publish, and a granular automation token that bypasses 2FA has not
279 # been provisioned. Release the npm wrapper manually from a developer machine
280 # after the GitHub Release has been created — see CLAUDE.md "Releases" for the
281 # exact commands.
282
282 lines YAML