返回 CodeWhale
CNB_MIRROR.md
根目录 / docs / CNB_MIRROR.md
1 # CNB Cool mirror
2
3 > 阅读简体中文版:[zh_hans/CNB_MIRROR.md](zh_hans/CNB_MIRROR.md)。
4
5 `cnb.cool/codewhale.net/codewhale` is a one-way mirror of this
6 GitHub repository for users on networks where GitHub is slow or blocked
7 (primarily mainland China). The mirror receives every push to `main`, every
8 `fix/*`, `rebrand/*`, and `work/v*` branch used for first-party release work,
9 and each `v*` release tag after its complete GitHub Release is published.
10
11 ## Provenance
12
13 **GitHub is the sole canonical source.** All releases, tags, and source code
14 originate at `github.com/codewhale-hq/CodeWhale`. The CNB mirror is a read-only
15 replica maintained by the `Sync to CNB` workflow — it exists solely to serve
16 users behind GFW-blocked or slow GitHub connections.
17
18 Every CNB release includes `codewhale-artifacts-sha256.txt` — a SHA256 manifest
19 of the CNB-built Linux x64 binaries, generated from the same source commit that
20 is tagged on GitHub. (CNB builds from source, so these checksums cover the
21 CNB-built artifacts, not GitHub's release assets.) Verify a downloaded binary
22 against it:
23
24 ```bash
25 # Verify a downloaded CNB binary against the CNB manifest
26 sha256sum -c codewhale-artifacts-sha256.txt --ignore-missing
27 ```
28
29 ## How it works
30
31 The mirror is maintained by the [`Sync to CNB`](../.github/workflows/sync-cnb.yml)
32 GitHub Actions workflow:
33
34 - **Trigger:** `push` to `main`, the release workflow after canonical publication,
35 release work branches matching `work/v*`, first-party fix and rebrand
36 branches matching `fix/*` and `rebrand/*`, or `workflow_dispatch` for manual
37 recovery. A tag push alone does not mirror a release tag. Manual tag recovery
38 also verifies the complete public GitHub asset inventory and immutable source.
39 - **Auth:** HTTPS basic auth as user `cnb` with the `CNB_GIT_TOKEN`
40 repository secret as the password.
41 - **Scope:** only the ref that triggered the run is pushed. Tag pushes
42 push exactly that tag. Branch pushes mirror `main`, first-party
43 `fix/*`/`rebrand/*` branches, or explicitly matched release branches. Other
44 feature branches and dependabot refs are intentionally *not* mirrored.
45 - **Concurrency:** runs are serialized via a `cnb-sync` concurrency
46 group so the back-to-back `main` push and tag push from
47 `auto-tag.yml` cannot race each other.
48 - **Retry:** each push is retried up to three times with linear
49 backoff (5s, 10s) before the workflow gives up.
50
51 CNB pipeline configuration is also source-controlled in GitHub at
52 [`/.cnb.yml`](../.cnb.yml). This is deliberate: the sync workflow force-mirrors
53 GitHub refs to CNB, so pipeline files created only on the CNB side will be
54 overwritten. Submit `.cnb.yml` changes through GitHub PRs and let the one-way
55 mirror carry them to CNB.
56
57 ## CNB tag releases
58
59 When CNB receives a `v*` tag, the root `.cnb.yml` tag pipeline builds Linux x64
60 release assets from source and publishes a CNB release with:
61
62 - `codewhale-linux-x64`
63 - `codew-linux-x64`
64 - `codewhale-tui-linux-x64` (compatibility-only release filename; not a third
65 installed command)
66 - `codewhale-artifacts-sha256.txt`
67
68 This gives users who can reach CNB but not GitHub a CNB-native release path.
69 GitHub remains the canonical macOS/Windows release matrix; the CNB tag pipeline
70 is the China-friendly Linux x64 fallback.
71 The GitHub release workflow calls the mirror only after publishing its complete,
72 verified asset set. CNB cannot publish a version whose canonical release failed.
73 An existing CNB tag must match; recovery never force-updates a release tag.
74
75 ## CNB Linux CI and release preflight
76
77 First-party `fix/*` and `rebrand/*` branches are mirrored to CNB so the heavy
78 Linux Rust gates run on Tencent-hosted runners instead of GitHub Actions:
79
80 - `./scripts/release/check-versions.sh`
81 - `cargo fmt --all -- --check`
82 - `cargo check --workspace --all-targets --locked`
83 - `cargo clippy --workspace --all-targets --all-features --locked -- -D warnings`
84 - `cargo test --workspace --all-features --locked`
85 - `cargo build --release --locked -p codewhale-cli --bin codewhale`
86 - `node scripts/release/npm-wrapper-smoke.js`
87
88 Release branches matching `work/v*` also run
89 `./scripts/release/publish-crates.sh dry-run`. GitHub Actions keeps the cheap
90 drift/fmt statuses plus the macOS and Windows jobs that CNB cannot replace.
91
92 ## Verifying the mirror after a release
93
94 After `release.yml` completes for a `vX.Y.Z` tag, the CNB mirror
95 should have both the new commit on `main` and the new tag:
96
97 ```bash
98 # Quick check: does the new tag exist on CNB?
99 git ls-remote https://cnb.cool/codewhale.net/codewhale.git \
100 refs/tags/vX.Y.Z
101
102 # Quick check: is CNB's main at the same commit as origin/main?
103 gh_main=$(git ls-remote https://github.com/codewhale-hq/CodeWhale.git refs/heads/main | awk '{print $1}')
104 cnb_main=$(git ls-remote https://cnb.cool/codewhale.net/codewhale.git refs/heads/main | awk '{print $1}')
105 test "$gh_main" = "$cnb_main" && echo "in sync" || echo "DIVERGED: gh=$gh_main cnb=$cnb_main"
106 ```
107
108 Or check the workflow run directly:
109
110 ```bash
111 gh run list --workflow=sync-cnb.yml --repo codewhale-hq/CodeWhale --limit 5
112 ```
113
114 If the most recent run for the release tag is `success`, the mirror
115 caught it. If it's `failure`, fix or re-run the mirror workflow before
116 directing users to the mirrored tag.
117
118 ## Manual fallback
119
120 Manual mirror repair is maintainer-only. Do not put PATs in remote URLs or
121 publish force-push recipes in contributor-facing docs. Use the configured
122 GitHub Actions secret and the workflow dispatch path whenever possible.
123
124 ### Re-trigger the workflow manually
125
126 If the workflow is healthy but happened to fail on the release run
127 (e.g. a transient CNB outage that's since cleared), retrigger it
128 without pushing anything:
129
130 ```bash
131 # Prefer rerunning the existing failed tag run when one exists.
132 gh run rerun <failed-tag-run-id> --repo codewhale-hq/CodeWhale
133
134 # If no tag run exists, dispatch from the exact existing release tag.
135 gh workflow run sync-cnb.yml --repo codewhale-hq/CodeWhale --ref vX.Y.Z
136 ```
137
138 Do not omit `--ref` when repairing a tag: a default-branch dispatch syncs
139 `main`, not `refs/tags/vX.Y.Z`. Afterward, prove the tag and its Linux x64
140 release assets exist before directing users to CNB.
141
142 ## Rotating `CNB_GIT_TOKEN`
143
144 If the workflow starts failing with auth errors and the token has
145 expired:
146
147 1. Log in to `cnb.cool` and generate a new personal access token
148 with `repo` (push) scope.
149 2. Update the `CNB_GIT_TOKEN` repository secret:
150 ```bash
151 gh secret set CNB_GIT_TOKEN --repo codewhale-hq/CodeWhale
152 ```
153 3. Re-trigger the workflow on a recent commit:
154 ```bash
155 gh workflow run sync-cnb.yml --repo codewhale-hq/CodeWhale
156 ```
157 4. Confirm the run succeeds via `gh run list --workflow=sync-cnb.yml`.
158
159 ## Binary release assets and `codewhale update`
160
161 CNB now builds Linux x64 assets for `v*` tags from the source-controlled
162 `.cnb.yml` pipeline. GitHub remains the canonical macOS/Windows release matrix.
163
164 ### Automatic source selection (Linux x64)
165
166 On Linux x64, `codewhale update` picks its asset source before it downloads
167 anything large. Once the target tag is known, it requests
168 `codewhale-artifacts-sha256.txt` for that exact tag from GitHub Releases and
169 from the CNB release **at the same time**, and takes the first source that
170 answers with a manifest listing `codewhale-linux-x64`. The straggler's answer is
171 discarded.
172
173 Three properties this relies on:
174
175 - **The manifest is the probe.** It is a few hundred bytes, so a blocked or slow
176 source loses in about the time its connection takes to fail — the user never
177 waits out a stalled multi-megabyte asset download, and no timeout is doing the
178 choosing.
179 - **Manifest and binary come from the same source.** CNB builds its own
180 artifacts from the tagged source (musl-static, not GitHub's glibc build), so
181 the two manifests describe different bytes and are not interchangeable. The
182 winning source supplies both, and a checksum mismatch fails the update rather
183 than falling back to the loser.
184 - **Selection never changes which release is installed.** The tag still comes
185 from GitHub's stable-release or beta-release lookup, so `--beta` keeps its
186 meaning; only where the bytes for that tag are fetched from is decided by the
187 probe.
188
189 `codewhale update` and `codewhale update --check` both print the result as a
190 `Release source:` line, and the post-install summary repeats it, so the source a
191 given binary came from is recoverable after the fact.
192
193 Every other target keeps a single canonical source: CNB publishes Linux x64 and
194 nothing else, so macOS, Windows, Android, and Linux arm64 do not race CNB;
195 Linux riscv64 remains explicitly unsupported. All supported self-update paths
196 are nevertheless checksum-required: the chosen source must publish a valid
197 `codewhale-artifacts-sha256.txt` entry for the exact platform binary, or
198 `codewhale update` stops before downloading that binary. There is no
199 unverified-install fallback.
200
201 Setting `CODEWHALE_RELEASE_BASE_URL` (or a legacy alias) or
202 `CODEWHALE_USE_CNB_MIRROR` turns selection off entirely — an explicitly named
203 source is used as named, including its own checksum manifest, with
204 `CODEWHALE_RELEASE_BASE_URL` outranking `CODEWHALE_USE_CNB_MIRROR`.
205
206 ### Manual paths
207
208 Users behind GitHub-blocking networks can also select a source explicitly:
209
210 - **`cargo install`** from the CNB mirror:
211 ```bash
212 cargo install --git https://cnb.cool/codewhale.net/codewhale --tag vX.Y.Z codewhale-cli --locked
213 ```
214 The current `codewhale` binary runs the TUI in-process. Cargo users who want
215 the optional short command can add a `codew` symlink beside it; a separate
216 `codewhale-tui` install is not required.
217 Linux build-time dependencies (`build-essential`, `pkg-config`,
218 `libdbus-1-dev` on Debian/Ubuntu) are required — see
219 [INSTALL.md](INSTALL.md#5-cargo-and-building-from-source).
220
221 - **CNB release assets** for Linux x64, when the matching CNB tag pipeline has
222 completed successfully. Download `codewhale-linux-x64`, `codew-linux-x64`,
223 and `codewhale-artifacts-sha256.txt` from the CNB release for `vX.Y.Z`, then
224 verify the binaries against the manifest. The published
225 `codewhale-tui-linux-x64` file is a legacy-client bridge and is not required
226 by current installs. On Linux x64 and OpenHarmony x64 the npm wrapper probes
227 that CNB checksum manifest concurrently with GitHub Releases for the exact
228 package version and locks onto the first source whose HTTP response and
229 manifest validate — it does not wait for a slow GitHub binary download. Set
230 `CODEWHALE_USE_CNB_MIRROR=1` to force CNB only, or
231 `CODEWHALE_RELEASE_BASE_URL` to skip the race. Other platforms must use
232 GitHub or a complete `CODEWHALE_RELEASE_BASE_URL` mirror.
233
234 - **`CODEWHALE_RELEASE_BASE_URL`** environment variable, if a CDN mirror of
235 release assets exists. The npm wrapper installer and `codewhale update` read
236 this variable to redirect binary downloads. For `codewhale update`, also set
237 `CODEWHALE_VERSION=X.Y.Z` so the updater can label the mirrored
238 release without contacting GitHub. The directory pointed to must contain
239 `codewhale-artifacts-sha256.txt` and the platform binaries; format matches
240 a GitHub Release asset directory. The earlier `DEEPSEEK_TUI_*` names remain
241 accepted as compatibility aliases.
242
243 ## Clone from CNB
244
245 For a stable install, clone `main` or a release tag from:
246
247 ```bash
248 https://cnb.cool/codewhale.net/codewhale.git
249 ```
250
251 The mirror receives `main`, release tags, and matched release branches. GitHub
252 is the fallback when the CNB workflow or credentials are unhealthy.
253
254 CNB deploy-button examples live in `deploy/tencent-lighthouse/cnb/`. They are
255 not active until copied into `.cnb.yml` and `.cnb/tag_deploy.yml`, because live
256 deploy jobs require a Lighthouse deploy key, target host, and explicit CNB
257 quota/billing policy.
258
258 lines MARKDOWN