fix(packaging): require explicit release versions

This commit is contained in:
Qiu Yuzhou
2026-10-22 16:16:05 +08:00
parent 4426d0b331
commit 7b7d572fb5
3 changed files with 16 additions and 13 deletions
+7 -6
View File
@@ -133,16 +133,17 @@ tasks:
build:release:
desc: Build the ShadowsocksX-NG2 macOS application with Release Config
requires:
vars: [MARKETING_VERSION, CURRENT_PROJECT_VERSION]
vars:
BUNDLE_MARKETING_VERSION: '{{regexFind "[0-9]+\\.[0-9]+\\.[0-9]+" (default "" .MARKETING_VERSION)}}'
preconditions:
- sh: '{{if or (empty .MARKETING_VERSION) (regexMatch .RELEASE_VERSION_PATTERN .MARKETING_VERSION)}}true{{else}}false{{end}}'
- sh: '{{if regexMatch .RELEASE_VERSION_PATTERN .MARKETING_VERSION}}true{{else}}false{{end}}'
msg: 'MARKETING_VERSION must be a release version (for example, 2.1.0 or v2.0.0-alpha-1).'
- sh: '{{if or (empty .CURRENT_PROJECT_VERSION) (regexMatch "^[0-9]+(\\.[0-9]+){0,2}$" .CURRENT_PROJECT_VERSION)}}true{{else}}false{{end}}'
- sh: '{{if regexMatch "^[0-9]+(\\.[0-9]+){0,2}$" .CURRENT_PROJECT_VERSION}}true{{else}}false{{end}}'
msg: 'CURRENT_PROJECT_VERSION must have one to three numeric components.'
deps:
- gen:prj
cmds:
- task: gen:prj
- >-
xcodebuild
-project ShadowsocksX-NG2.xcodeproj
@@ -150,8 +151,8 @@ tasks:
-configuration Release
-destination 'platform=macOS,arch=arm64'
-derivedDataPath {{.DERIVED_DATA_DIR | shellQuote}}
{{if .MARKETING_VERSION}}{{printf "MARKETING_VERSION=%s" .BUNDLE_MARKETING_VERSION | shellQuote}}{{end}}
{{if .CURRENT_PROJECT_VERSION}}{{printf "CURRENT_PROJECT_VERSION=%s" .CURRENT_PROJECT_VERSION | shellQuote}}{{end}}
{{printf "MARKETING_VERSION=%s" .BUNDLE_MARKETING_VERSION | shellQuote}}
{{printf "CURRENT_PROJECT_VERSION=%s" .CURRENT_PROJECT_VERSION | shellQuote}}
build
format:
+6 -4
View File
@@ -10,13 +10,13 @@ tasks:
desc: Build, sign, notarize and publish an arm64 Release DMG
dir: '{{.TASKFILE_DIR}}'
requires:
vars: [NOTARY_PROFILE]
vars: [NOTARY_PROFILE, MARKETING_VERSION, CURRENT_PROJECT_VERSION]
preconditions:
- sh: 'test -n {{.NOTARY_PROFILE | shellQuote}}'
msg: 'NOTARY_PROFILE must name credentials stored by notarytool store-credentials.'
- sh: '{{if or (empty .MARKETING_VERSION) (regexMatch .RELEASE_VERSION_PATTERN .MARKETING_VERSION)}}true{{else}}false{{end}}'
- sh: '{{if regexMatch .RELEASE_VERSION_PATTERN .MARKETING_VERSION}}true{{else}}false{{end}}'
msg: 'MARKETING_VERSION must be a release version (for example, 2.1.0 or v2.0.0-alpha-1).'
- sh: '{{if or (empty .CURRENT_PROJECT_VERSION) (regexMatch "^[0-9]+(\\.[0-9]+){0,2}$" .CURRENT_PROJECT_VERSION)}}true{{else}}false{{end}}'
- sh: '{{if regexMatch "^[0-9]+(\\.[0-9]+){0,2}$" .CURRENT_PROJECT_VERSION}}true{{else}}false{{end}}'
msg: 'CURRENT_PROJECT_VERSION must have one to three numeric components.'
vars:
RUN_DIR:
@@ -47,12 +47,14 @@ tasks:
package:image:
internal: true
dir: '{{.TASKFILE_DIR}}'
requires:
vars: [MARKETING_VERSION]
vars:
APP_VERSION:
sh: plutil -extract CFBundleShortVersionString raw -expect string -o - {{.APP_PATH | shellQuote}}/Contents/Info.plist
APP_BUILD:
sh: plutil -extract CFBundleVersion raw -expect string -o - {{.APP_PATH | shellQuote}}/Contents/Info.plist
IMAGE_VERSION: '{{default .APP_VERSION .MARKETING_VERSION}}'
IMAGE_VERSION: '{{.MARKETING_VERSION}}'
IMAGE_NAME: 'ShadowsocksX-NG2-{{.IMAGE_VERSION}}-{{.APP_BUILD}}-arm64.dmg'
IMAGE_PATH: '{{.RUN_DIR}}/{{.IMAGE_NAME}}'
preconditions:
+3 -3
View File
@@ -55,7 +55,7 @@ task package NOTARY_PROFILE=shadowsocks-release \
MARKETING_VERSION=2.1.0 CURRENT_PROJECT_VERSION=21
```
`MARKETING_VERSION` 和 `CURRENT_PROJECT_VERSION` 分别可选。未传的参数使用工程默认值;传入的参数只覆盖本次 Release 构建,不改写 `project.yml`。`MARKETING_VERSION` 接受三个以点分隔的数字、可选的 `v` 前缀和以 `-` 开头的预发布后缀。后缀中的标识符使用 ASCII 字母、数字或连字符,以点分隔,例如 `v2.0.0-alpha-1`、`2.0.0-beta.2` 和 `v2.0.0-rc.1`。`CURRENT_PROJECT_VERSION` 接受一至三个以点分隔的数字。单独运行 `task build:release` 也支持这两个覆盖参数。
`task package`、`task build:release` 和 `task i:release` 必须提供非空的 `MARKETING_VERSION` 与 `CURRENT_PROJECT_VERSION`,不使用工程默认版本。参数可以通过命令行、环境变量或本机 `.env` 提供,只覆盖本次 Release 构建,不改写 `project.yml`。`MARKETING_VERSION` 接受三个以点分隔的数字、可选的 `v` 前缀和以 `-` 开头的预发布后缀。后缀中的标识符使用 ASCII 字母、数字或连字符,以点分隔,例如 `v2.0.0-alpha-1`、`2.0.0-beta.2` 和 `v2.0.0-rc.1`。`CURRENT_PROJECT_VERSION` 接受一至三个以点分隔的数字。`package:notarize` 复用已有 DMG,不要求重新提供版本参数。
预发布构建示例:
@@ -68,7 +68,7 @@ DMG 文件名保留完整发布版本:`ShadowsocksX-NG2-v2.0.0-alpha-1-22-arm6
流程由 `Taskfile.package.yml` 编排:检查公证凭据 → 获取外部二进制 → 真实进程冒烟 → Release 构建 → App 打包门槛 → 制作压缩 DMG → DMG 签名 → Apple 公证 → 装订票据 → 签名、票据及 Gatekeeper 检查 → 发布到 `dist/`。构建只支持 arm64。DMG 只包含 App 和指向 `/Applications` 的快捷方式,不增加背景图或 Finder 自动化依赖。
DMG 复用 App 实际签名证书的 SHA-1 指纹选择签名身份,使用安全时间戳。公证仅接收 `NOTARY_PROFILE` 指定的钥匙串配置名称。发布产物示例为 `dist/ShadowsocksX-NG2-2.1.0-21-arm64.dmg`。名称优先保留传入的完整发布版本;未传版本时使用 App 的版本。构建号始终从 App 的 Info.plist 读取。打包前校验发布版本的数字部分与 App 版本一致,防止文件名与包内版本不符。已有同名发布产物时明确失败,不覆盖文件。
DMG 复用 App 实际签名证书的 SHA-1 指纹选择签名身份,使用安全时间戳。公证仅接收 `NOTARY_PROFILE` 指定的钥匙串配置名称。发布产物示例为 `dist/ShadowsocksX-NG2-2.1.0-21-arm64.dmg`。名称保留传入的完整发布版本。构建号始终从 App 的 Info.plist 读取。打包前校验发布版本的数字部分与 App 版本一致,防止文件名与包内版本不符。已有同名发布产物时明确失败,不覆盖文件。
每次构建使用独立的 `.build/packaging/run-*/`,其中保留签名 DMG、构建产物与冒烟结果。每次公证在 `.build/notarization/run-*/` 保存提交响应、提交编号、等待结果与 Apple 诊断日志。控制台打印这两个目录。提交和等待分别执行,等待中断时仍保留提交编号。公证等待上限为 30 分钟;本地等待结束后 Apple 仍可能继续处理。
@@ -99,7 +99,7 @@ xcrun notarytool info SUBMISSION_ID --keychain-profile shadowsocks-release
```bash
# 发布门槛(必须全绿):真实进程冒烟 + 打包门槛
task test:smoke
task build:release
task build:release MARKETING_VERSION=2.1.0 CURRENT_PROJECT_VERSION=21
Scripts/packaging-gate.sh \
.build/derivedData/Build/Products/Release/ShadowsocksX-NG2.app
```