Skip to content

Commit 407e2d2

Browse files
authored
fix(cli): stabilize machine API and preserve Android/Desktop compatibility (#147)
* fix(cli): stabilize machine API and build contracts * fix(cli): keep sensitive data out of logs * fix(cli): preserve auth and locale compatibility * fix(cli): preserve API and run state integrity
1 parent 6bc849f commit 407e2d2

24 files changed

Lines changed: 4392 additions & 339 deletions

.github/workflows/build-abk-cli.yml

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,34 @@ on:
88
push:
99
paths:
1010
- "cli/**"
11+
- "LICENSE"
1112
- ".github/workflows/build-abk-cli.yml"
13+
- ".github/workflows/kernel-a12-5-10.yml"
14+
- ".github/workflows/kernel-a13-5-15.yml"
15+
- ".github/workflows/kernel-a14-6-1.yml"
16+
- ".github/workflows/kernel-a15-6-6.yml"
17+
- ".github/workflows/kernel-a16-6-12.yml"
18+
- ".github/workflows/kernel-custom.yml"
19+
- ".github/workflows/kernel-full-feature-matrix.yml"
20+
- ".github/workflows/all-managers-full-feature-matrix.yml"
21+
- ".github/workflows/oneplus-custom.yml"
1222
pull_request:
1323
paths:
1424
- "cli/**"
25+
- "LICENSE"
1526
- ".github/workflows/build-abk-cli.yml"
27+
- ".github/workflows/kernel-a12-5-10.yml"
28+
- ".github/workflows/kernel-a13-5-15.yml"
29+
- ".github/workflows/kernel-a14-6-1.yml"
30+
- ".github/workflows/kernel-a15-6-6.yml"
31+
- ".github/workflows/kernel-a16-6-12.yml"
32+
- ".github/workflows/kernel-custom.yml"
33+
- ".github/workflows/kernel-full-feature-matrix.yml"
34+
- ".github/workflows/all-managers-full-feature-matrix.yml"
35+
- ".github/workflows/oneplus-custom.yml"
1636

1737
concurrency:
18-
group: build-abk-cli-${{ github.event.pull_request.number || github.ref }}
38+
group: build-abk-cli-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.event.pull_request.number || github.ref }}
1939
cancel-in-progress: true
2040

2141
jobs:
@@ -359,7 +379,7 @@ jobs:
359379
Environment:
360380
Set GITHUB_TOKEN before triggering builds that require authentication.
361381
EOF
362-
curl https://raw.githubusercontent.com/xingguangcuican6666/ABK/refs/heads/dev/LICENSE --output dist/abk/LICENSE
382+
cp LICENSE dist/abk/LICENSE
363383
364384
- name: Add bundled README
365385
if: runner.os == 'Windows'
@@ -377,7 +397,7 @@ jobs:
377397
Set GITHUB_TOKEN before triggering builds that require authentication.
378398
"@ | Set-Content -Path dist/abk/README.txt
379399
380-
curl https://raw.githubusercontent.com/xingguangcuican6666/ABK/refs/heads/dev/LICENSE --output dist/abk/LICENSE
400+
Copy-Item -LiteralPath "LICENSE" -Destination "dist/abk/LICENSE" -Force
381401
382402
- name: Verify bundle contents
383403
if: runner.os != 'Windows'
@@ -386,6 +406,7 @@ jobs:
386406
set -euo pipefail
387407
test -f "dist/abk/${{ matrix.binary_name }}"
388408
test -f "dist/abk/README.txt"
409+
test -f "dist/abk/LICENSE"
389410
test -f "dist/abk/_internal/i18n/zh-cn.json"
390411
test -f "dist/abk/_internal/i18n/en-us.json"
391412
@@ -395,6 +416,7 @@ jobs:
395416
run: |
396417
if (!(Test-Path "dist/abk/${{ matrix.binary_name }}")) { throw "Missing binary" }
397418
if (!(Test-Path "dist/abk/README.txt")) { throw "Missing README" }
419+
if (!(Test-Path "dist/abk/LICENSE")) { throw "Missing LICENSE" }
398420
if (!(Test-Path "dist/abk/_internal/i18n/zh-cn.json")) { throw "Missing zh-cn.json" }
399421
if (!(Test-Path "dist/abk/_internal/i18n/en-us.json")) { throw "Missing en-us.json" }
400422
@@ -404,26 +426,44 @@ jobs:
404426
run: |
405427
set -euo pipefail
406428
./dist/abk/abk --help > /dev/null
429+
./dist/abk/abk --json self-test | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["command"] == "self-test" and result["cryptoBackend"] and result["pynacl"] is True and result["caBundle"] is True and result["tlsContext"] is True'
430+
./dist/abk/abk --json build --dry-run --matrix a14 --ksu Official | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["dispatches"][0]["workflowName"] == "内核构建 - Android 14 (6.1)"'
407431
408432
- name: Smoke test linux-armhf
409433
if: ${{ matrix.target_id == 'linux-armhf' }}
410434
shell: bash
411435
run: |
412436
set -euo pipefail
413437
docker run --rm --platform linux/arm/v7 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --help > /dev/null
438+
docker run --rm --platform linux/arm/v7 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --json self-test | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["command"] == "self-test" and result["cryptoBackend"] and result["pynacl"] is True and result["caBundle"] is True and result["tlsContext"] is True'
439+
docker run --rm --platform linux/arm/v7 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --json build --dry-run --matrix a14 --ksu Official | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["dispatches"][0]["workflowName"] == "内核构建 - Android 14 (6.1)"'
414440
415441
- name: Smoke test linux-x86
416442
if: ${{ matrix.target_id == 'linux-x86' }}
417443
shell: bash
418444
run: |
419445
set -euo pipefail
420446
docker run --rm --platform linux/386 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --help > /dev/null
447+
docker run --rm --platform linux/386 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --json self-test | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["command"] == "self-test" and result["cryptoBackend"] and result["pynacl"] is True and result["caBundle"] is True and result["tlsContext"] is True'
448+
docker run --rm --platform linux/386 -v "$PWD/dist:/work/dist" debian:bookworm-slim /work/dist/abk/abk --json build --dry-run --matrix a14 --ksu Official | python -c 'import json, sys; result = json.load(sys.stdin); assert result["schemaVersion"] == 1 and result["ok"] is True and result["dispatches"][0]["workflowName"] == "内核构建 - Android 14 (6.1)"'
421449
422450
- name: Smoke test Windows
423451
if: runner.os == 'Windows'
424452
shell: pwsh
425453
run: |
426454
.\dist\abk\abk.exe --lang en-us --help | Out-Null
455+
$selfTest = & .\dist\abk\abk.exe --json self-test
456+
if ($LASTEXITCODE -ne 0) { throw "Frozen CLI self-test failed" }
457+
$result = $selfTest | ConvertFrom-Json
458+
if ($result.schemaVersion -ne 1 -or $result.ok -ne $true -or $result.command -ne "self-test" -or -not $result.cryptoBackend -or $result.pynacl -ne $true -or $result.caBundle -ne $true -or $result.tlsContext -ne $true) {
459+
throw "Unexpected frozen CLI self-test result"
460+
}
461+
$dryRun = & .\dist\abk\abk.exe --json build --dry-run --matrix a14 --ksu Official
462+
if ($LASTEXITCODE -ne 0) { throw "Frozen CLI UTF-8 dry-run failed" }
463+
$plan = $dryRun | ConvertFrom-Json
464+
if ($plan.schemaVersion -ne 1 -or $plan.ok -ne $true -or $plan.dispatches[0].workflowName -ne "内核构建 - Android 14 (6.1)") {
465+
throw "Unexpected frozen CLI UTF-8 dry-run result"
466+
}
427467
428468
- name: Package artifact
429469
if: runner.os != 'Windows'

cli/README.md

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ CLI 也兼容 `pycryptodome` / `pycryptodomex`:
3131

3232
```bash
3333
python3 -m pip install -r ~/ABK/cli/requirements.txt
34-
# 或:python3 -m pip install pycryptodome PyNaCl
34+
# 或:python3 -m pip install pycryptodome PyNaCl certifi
3535
```
3636

3737
## 配置 / Configuration
@@ -96,14 +96,14 @@ abk sync # 同步 fork 与上游
9696
需指定 `--sub-level``--os-patch-level`
9797

9898
```bash
99-
abk build --sub-level 162 --os-patch-level 2026-03
99+
abk build --sub-level 246 --os-patch-level 2025-12
100100
abk build --android-version android14 --kernel-version 6.1 --sub-level 162 --os-patch-level 2026-03
101101
```
102102

103103
#### 预览构建计划 / Preview Build Plan
104104

105105
```bash
106-
abk build --sub-level 162 --os-patch-level 2026-03 --dry-run
106+
abk build --sub-level 246 --os-patch-level 2025-12 --dry-run
107107
abk build --matrix both --ksu all --dry-run
108108
```
109109

@@ -150,15 +150,15 @@ abk build --oneplus --device oneplus_12_b
150150
- ZRAM / DDK / NTsync / 网络增强 / Re-Kernel / 虚拟化 / 自定义外部模块 → 自动禁用
151151
- MTK CPU 设备 → 代理优化自动禁用
152152
- SUSFS 仅支持 android14/6.1 和 android15/6.6
153-
- KPM 仅支持 SukiSU;ReSukiSU `main` 不支持 KPM,会自动禁用
154-
- 全管理器 OnePlus 矩阵包含 ReSukiSU 时,OnePlus KPM 会对该矩阵整体禁用
153+
- KPM 仅对 SukiSU / ReSukiSU 生效;其他变体会自动禁用
154+
- 全管理器 OnePlus 矩阵由工作流按每个 KernelSU 变体独立决定 KPM
155155

156156
不兼容的选项会被自动禁用并给出警告。
157157

158158
#### 全 KSU 变体 / All KSU Variants
159159

160160
```bash
161-
abk build --sub-level 162 --os-patch-level 2026-03 --ksu all
161+
abk build --sub-level 246 --os-patch-level 2025-12 --ksu all
162162
abk build --matrix both --ksu all # 全版本 × 全 KSU
163163
```
164164

@@ -175,10 +175,26 @@ abk status --status in_progress # 按状态过滤
175175
```bash
176176
abk artifacts --run-id 12345 # 列出产物
177177
abk artifacts --run-id 12345 --download # 下载到当前用户的 Downloads 目录
178+
abk artifacts --run-id 12345 --download --artifact-id 67890 # 仅下载指定产物
178179
abk artifacts --run-id 12345 -o ./out # 指定目录
179180
abk artifacts --set-download-dir ./out # 持久化默认目录
180181
```
181182

183+
### 机器可读 JSON / Machine-readable JSON
184+
185+
自动化调用可使用全局前置参数 `--json`。命令执行时 stdout 始终只有一个
186+
`schemaVersion: 1` JSON 文档;该模式不会读取 stdin 或打开浏览器。
187+
`--help` 仍是供人阅读的文本,不属于 JSON 合同:
188+
189+
```bash
190+
abk --json whoami
191+
abk --json status --limit 20
192+
abk --json build --matrix a14 --ksu ReSukiSU --force
193+
abk --json artifacts --run-id 12345 --download --artifact-id 67890
194+
```
195+
196+
冻结产物可用 `abk --json self-test` 离线验证 RSA、PyNaCl 和 CA bundle。
197+
182198
### 列出可用选项 / List Options
183199

184200
```bash
@@ -205,11 +221,16 @@ abk list
205221
| `--kernel-version` | 5.10/5.15/6.1/6.6/6.12 (默认: 5.10) |
206222
| `--sub-level` | 子版本号,如 66, 162 |
207223
| `--os-patch-level` | 安全补丁级别,如 2022-01, 2026-03 |
208-
| `--revision` | 修订版本,如 r11 (仅 5.10) |
224+
| `--revision` | 修订版本,如 r11;仅 custom 5.10、full、all-managers 接收 |
225+
226+
自定义 LTS 构建使用固定组合 `--sub-level X --os-patch-level lts`;两项必须
227+
同时指定。Android 与内核版本也必须使用上游支持的配对(android12/5.10 至
228+
android16/6.12)。
209229

210230
为避免自由文本进入现有 Actions Shell,CLI 会在本地拒绝不安全参数:
211-
`--sub-level` 必须为数字,补丁级别必须为 `YYYY-MM`,自定义 ref 必须符合
212-
Git ref 规则;版本、构建时间、ZRAM 算法及自定义模块参数也会做长度和字符校验。
231+
除固定的 `X`/`lts` 组合外,`--sub-level` 必须为数字,补丁级别必须为
232+
`YYYY-MM`;自定义 ref 必须符合 Git ref 规则。版本、构建时间、ZRAM 算法及
233+
自定义模块参数也会做长度和字符校验。
213234

214235
## 功能开关 / Feature Flags
215236

@@ -242,6 +263,7 @@ Git ref 规则;版本、构建时间、ZRAM 算法及自定义模块参数也
242263
| 分支 / Branch | 描述 / Description |
243264
|------|------|
244265
| `Stable` | 稳定版 (默认),映射到 Stable(标准) |
266+
| `Latest` | 最新版,映射到 Latest(最新) |
245267
| `Dev` | 开发版,映射到 Dev(开发) |
246268
| `Custom` | 自定义引用,映射到 Custom(自定义) |
247269

@@ -250,6 +272,7 @@ Git ref 规则;版本、构建时间、ZRAM 算法及自定义模块参数也
250272
| 选项 / Option | 描述 / Description |
251273
|------|------|
252274
| `off` | 关闭(默认) |
275+
| `on` | 启用(旧内核映射到 678,6.12 映射到 on) |
253276
| `678` | 6_7_8 槽位补丁(推荐) |
254277
| `123` | 1_2_3 槽位补丁(备用) |
255278
| `345` | 3_4_5 槽位补丁(备用) |
@@ -262,7 +285,7 @@ abk login
262285
abk fork
263286

264287
# 自定义构建
265-
abk build --sub-level 162 --os-patch-level 2026-03
288+
abk build --sub-level 246 --os-patch-level 2025-12
266289

267290
# 全版本矩阵
268291
abk build --matrix both
@@ -294,37 +317,44 @@ abk sync
294317
使用 `--lang` 切换语言(持久化保存):
295318

296319
```bash
297-
abk --lang en-us --help # English
298-
abk --lang ja-jp --help # 日本語
299-
abk --lang zh-neko --help # 中文猫娘 🐱
320+
abk --lang en-US --help # English
321+
abk --lang ja-JP --help # 日本語
322+
abk --lang zh-CN-x-neko --help # 中文猫娘 🐱
300323
```
301324

302325
| Code | Language |
303326
|------|----------|
304-
| `zh-cn` | 中文 (默认) |
305-
| `en-us` | English |
306-
| `ru-ru` | Русский |
307-
| `ja-jp` | 日本語 |
308-
| `ko-kr` | 한국어 |
309-
| `hi-in` | हिन्दी |
310-
| `de-de` | Deutsch |
311-
| `fr-fr` | Français |
312-
| `es-es` | Español |
313-
| `pt-br` | Português |
314-
| `jp-neko` | 日本語猫娘 🐱 |
315-
| `zh-neko` | 中文猫娘 🐱 |
327+
| `zh-CN` | 中文 (默认) |
328+
| `en-US` | English |
329+
| `ru-RU` | Русский |
330+
| `ja-JP` | 日本語 |
331+
| `ko-KR` | 한국어 |
332+
| `hi-IN` | हिन्दी |
333+
| `de-DE` | Deutsch |
334+
| `fr-FR` | Français |
335+
| `es-ES` | Español |
336+
| `pt-BR` | Português |
337+
| `ja-JP-x-neko` | 日本語猫娘 🐱 |
338+
| `zh-CN-x-neko` | 中文猫娘 🐱 |
316339
| `eo` | Esperanto |
317-
| `zh-zako` | zako~ zako~ |
340+
| `zh-CN-x-zako` | zako~ zako~ |
341+
342+
Language tags are matched case-insensitively. Existing lowercase values and the
343+
legacy custom IDs `jp-neko`, `zh-neko`, and `zh-zako` remain accepted for
344+
backward compatibility. The CLI exposes canonical tags, while its shared config
345+
continues to store the older IDs so previous CLI/Desktop builds can still read it.
318346

319347
## 添加新语言 / Adding New Languages
320348

321-
1.`cli/i18n/` 目录下创建新的 JSON 文件,文件名使用语言代码(如 `fr-fr.json`
349+
1.`cli/i18n/` 目录下创建新的 JSON 文件`LANGUAGE_CATALOGS` 将规范语言标签映射到全小写的目录文件名(例如对外使用 `fr-FR`,文件名为 `fr-fr.json`
322350
2. 复制 `zh-cn.json` 的内容,将所有值翻译为目标语言
323-
3. 更新 `cli/i18n/__init__.py`,将新语言代码添加到 `detect_language()` 函数的白名单
324-
4. 更新 `cli/abk.py` 中的 `SUPPORTED_LANGUAGES`
325-
5. 更新本 README 的语言支持表格
351+
3. 更新 `cli/i18n/__init__.py` 中的 `LANGUAGE_CATALOGS`;如需迁移旧值,同时添加兼容别名
352+
4. 更新本 README 的语言支持表格
326353

327-
**注意:** KernelSU 分支名作为 API 参数时**不能翻译**,CLI 会自动将 `Stable`/`Dev`/`Custom` 映射为 `Stable(标准)`/`Dev(开发)`/`Custom(自定义)`。语言文件只需展示短名。其他 API 值同理(如设备名、KSU 变体名)。
354+
**注意:** KernelSU 分支名作为 API 参数时**不能翻译**,CLI 会自动将
355+
`Stable`/`Latest`/`Dev`/`Custom` 映射为
356+
`Stable(标准)`/`Latest(最新)`/`Dev(开发)`/`Custom(自定义)`。语言文件只需展示
357+
短名。其他 API 值同理(如设备名、KSU 变体名)。
328358

329359
## 语言维护 / Language Maintenance
330360

0 commit comments

Comments
 (0)