macOS 按 Apple Silicon 和 Intel 分别发布安装包
发布流程改为按 aarch64、x86_64 构建矩阵,分别签名、公证并上传 DMG 和升级 ZIP, 不再合成 universal 应用。两个任务使用独立缓存和产物名称,发布时收集全部架构。 更新清单保留原有平台键,分别记录对应架构包的地址、大小和 SHA-256。 已有 universal 客户端按运行架构升级;Rosetta 下的 Intel 版仍接收 Intel 包。 同步更新中英文下载说明、发布文档和示例清单,增加双架构校验与错包拒绝断言。 验证:52 项更新模块测试通过,Clippy、格式、YAML 和 shell 语法检查通过。
This commit is contained in:
1 parent
5ca6e53366
commit
e91bab0d09
8 files changed
+77
-44
No files matched your search
@@ -1,7 +1,7 @@
|
||||
# A release: push a tag `v<version>` matching Cargo.toml's version.
|
||||
#
|
||||
# verify the tag, the CHANGELOG section, the update keys
|
||||
# macos universal app: signed, notarized, stapled; update zip and DMG
|
||||
# macos per-architecture apps: signed, notarized, stapled; update zip and DMG
|
||||
# windows per-user Inno Setup installer (unsigned for now)
|
||||
# linux AppImage
|
||||
# publish (environment `release`, approved by hand) uploads to R2 behind
|
||||
@@ -83,8 +83,13 @@ jobs:
|
||||
macos:
|
||||
needs: verify
|
||||
runs-on: macos-14
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [aarch64, x86_64]
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
VERSION: ${{ needs.verify.outputs.version }}
|
||||
SHELLRS_UPDATE_CHANNEL: ${{ needs.verify.outputs.channel }}
|
||||
SHELLRS_COMMIT: ${{ github.sha }}
|
||||
@@ -92,18 +97,17 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: rustup toolchain install
|
||||
- run: rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
||||
- run: rustup target add "$ARCH-apple-darwin"
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Build both halves and join them
|
||||
with:
|
||||
key: macos-${{ matrix.arch }}
|
||||
- name: Build the architecture-specific app
|
||||
run: |
|
||||
export SHELLRS_BUILD_DATE=$(date -u +%Y-%m-%d)
|
||||
cargo build --release --locked --bin shellrs --target aarch64-apple-darwin
|
||||
cargo build --release --locked --bin shellrs --target x86_64-apple-darwin
|
||||
cargo build --release --locked --bin shellrs --target "$ARCH-apple-darwin"
|
||||
mkdir -p dist build
|
||||
lipo -create -output build/shellrs \
|
||||
target/aarch64-apple-darwin/release/shellrs \
|
||||
target/x86_64-apple-darwin/release/shellrs
|
||||
packaging/macos/bundle.sh build/shellrs "$VERSION" "$GITHUB_RUN_NUMBER" build
|
||||
lipo -verify_arch "${ARCH/aarch64/arm64}" "target/$ARCH-apple-darwin/release/shellrs"
|
||||
packaging/macos/bundle.sh "target/$ARCH-apple-darwin/release/shellrs" "$VERSION" "$GITHUB_RUN_NUMBER" build
|
||||
- name: Sign
|
||||
env:
|
||||
CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE_P12 }}
|
||||
@@ -147,12 +151,12 @@ jobs:
|
||||
xcrun stapler staple build/ShellRS.app
|
||||
# The update package: the stapled bundle, zipped the way the
|
||||
# updater unzips it (ditto keeps the signature intact).
|
||||
ditto -c -k --keepParent build/ShellRS.app "dist/ShellRS-$VERSION-macos-universal.app.zip"
|
||||
ditto -c -k --keepParent build/ShellRS.app "dist/ShellRS-$VERSION-macos-$ARCH.app.zip"
|
||||
# The first-install disk image, with the Applications shortcut.
|
||||
mkdir -p "$RUNNER_TEMP/dmg"
|
||||
cp -R build/ShellRS.app "$RUNNER_TEMP/dmg/"
|
||||
ln -s /Applications "$RUNNER_TEMP/dmg/Applications"
|
||||
dmg="dist/ShellRS-$VERSION-macos-universal.dmg"
|
||||
dmg="dist/ShellRS-$VERSION-macos-$ARCH.dmg"
|
||||
# hdiutil's own estimate of the image size once came out too small
|
||||
# for the app ("No space left on device"), so the size is given,
|
||||
# with room to spare; the compressed image is about half the app.
|
||||
@@ -171,7 +175,7 @@ jobs:
|
||||
spctl -a -vv -t install "$dmg"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
name: macos-${{ matrix.arch }}
|
||||
path: dist/*
|
||||
|
||||
windows:
|
||||
@@ -265,7 +269,7 @@ jobs:
|
||||
- name: Collect
|
||||
run: |
|
||||
mkdir -p dist
|
||||
cp artifacts/macos/* artifacts/windows/* artifacts/linux/* dist/
|
||||
cp artifacts/macos-aarch64/* artifacts/macos-x86_64/* artifacts/windows/* artifacts/linux/* dist/
|
||||
cp artifacts/notes/notes.md notes.md
|
||||
ls -l dist
|
||||
- name: Signing key
|
||||
|
||||
@@ -119,7 +119,8 @@ Download from [shellrs.com/download](https://shellrs.com/download), which offers
|
||||
|
||||
| System | Package | Notes |
|
||||
| --- | --- | --- |
|
||||
| macOS 11+ (Apple Silicon and Intel) | `ShellRS-<version>-macos-universal.dmg` | Signed and notarized. Open the DMG and drag ShellRS into Applications |
|
||||
| macOS 11+ (Apple Silicon) | `ShellRS-<version>-macos-aarch64.dmg` | Signed and notarized. Open the DMG and drag ShellRS into Applications |
|
||||
| macOS 11+ (Intel) | `ShellRS-<version>-macos-x86_64.dmg` | Signed and notarized. Open the DMG and drag ShellRS into Applications |
|
||||
| Windows x64 | `ShellRS-<version>-windows-x86_64-setup.exe` | Installs per user, no administrator rights needed. The installer is not signed yet; if SmartScreen stops it, choose "More info › Run anyway" |
|
||||
| Linux x64 | `ShellRS-<version>-linux-x86_64.AppImage` | `chmod +x` and run. Needs glibc 2.35 or newer (Ubuntu 22.04, Debian 12 and later) |
|
||||
|
||||
|
||||
+2
-1
@@ -119,7 +119,8 @@ ShellRS 把 Xshell 式的主机管理和多标签终端、WinSCP 式的双栏 SF
|
||||
|
||||
| 系统 | 安装包 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| macOS 11+(Apple Silicon 和 Intel) | `ShellRS-<版本>-macos-universal.dmg` | 已签名并经过 Apple 公证。打开 DMG,把 ShellRS 拖进「应用程序」 |
|
||||
| macOS 11+(Apple Silicon) | `ShellRS-<版本>-macos-aarch64.dmg` | 已签名并经过 Apple 公证。打开 DMG,把 ShellRS 拖进「应用程序」 |
|
||||
| macOS 11+(Intel) | `ShellRS-<版本>-macos-x86_64.dmg` | 已签名并经过 Apple 公证。打开 DMG,把 ShellRS 拖进「应用程序」 |
|
||||
| Windows x64 | `ShellRS-<版本>-windows-x86_64-setup.exe` | 按当前用户安装,不需要管理员权限。安装程序暂未签名,SmartScreen 拦下时点「更多信息 › 仍要运行」 |
|
||||
| Linux x64 | `ShellRS-<版本>-linux-x86_64.AppImage` | `chmod +x` 后直接运行,需要 glibc 2.35 以上(Ubuntu 22.04、Debian 12 及更新的版本) |
|
||||
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
在 `CHANGELOG.md` 里写好 `## [x.y.z]` 一节,把 `Cargo.toml` 的版本改成 `x.y.z`,提交后推送 tag `vx.y.z`。`.github/workflows/release.yml` 依次:
|
||||
|
||||
1. 核对 tag 与 `Cargo.toml` 一致,截出更新说明,确认代码里有发布公钥;
|
||||
2. 构建并打包:macOS 合成 universal,签名、公证、staple,产出升级用的 `.app.zip` 和首次安装用的 `.dmg`;Windows 用 Inno Setup 打安装程序;Linux 打 AppImage;
|
||||
2. 构建并打包:macOS 按 `aarch64`(Apple Silicon)和 `x86_64`(Intel)分别构建、签名、公证、staple,各自产出升级用的 `.app.zip` 和首次安装用的 `.dmg`;Windows 用 Inno Setup 打安装程序;Linux 打 AppImage;
|
||||
3. 在 `release` 环境里人工批准后:给每个包签名,上传到 R2(`dl.shellrs.com/releases/<版本>/`),建 GitHub Release,**最后**才替换更新清单 `dl.shellrs.com/update/v1/<通道>.json` 并清 CDN 缓存,然后调用官网的部署挂钩重新构建 shellrs.com(官网的下载页和更新日志在构建时读这份清单)。清单里每个包有两个下载地址:先 R2,下载失败时客户端接着试 GitHub Release(仓库是公开的,下载不用登录)。
|
||||
|
||||
版本号带 `-` 的(如 `0.3.0-beta.1`)只发到 beta 通道;正式版同时成为 beta 通道的最新版。在 Actions 里手动运行这个 workflow 只构建打包、不发布,用来演练。客户端只接受比自己新的版本,所以发错的版本撤不回来:把清单改回上一版能阻止更多人升级,修复要发新的补丁版。
|
||||
@@ -19,3 +19,5 @@
|
||||
- **GitHub secrets**:仓库级的 `APPLE_CERTIFICATE_P12`(base64)、`APPLE_CERTIFICATE_PASSWORD`、`APPLE_SIGNING_IDENTITY`、`APPLE_TEAM_ID`、`APPLE_API_KEY_P8`(base64)、`APPLE_API_KEY_ID`、`APPLE_API_ISSUER`;`release` 环境(设为需要审批)里的 `MINISIGN_SECRET_KEY`、`MINISIGN_PASSWORD`、`R2_ACCOUNT_ID`、`R2_ACCESS_KEY_ID`、`R2_SECRET_ACCESS_KEY`、`R2_BUCKET`、`CF_ZONE_ID`、`CF_API_TOKEN`、`SITE_DEPLOY_HOOK`(官网部署挂钩的地址,拿到它的人能触发官网重新构建,泄露了就删掉重建)。
|
||||
|
||||
清单格式见 `packaging/manifest.example.json`,由 `packaging/make-manifest.sh` 生成:一个文件里是清单原文和它的 minisign 签名,签名的 trusted comment 写明通道和版本。格式只增加字段、不改已有的;已发出去的 ShellRS 一直按 `/update/v1/` 这个地址检查。
|
||||
|
||||
macOS 产物名分别为 `ShellRS-<版本>-macos-aarch64.{app.zip,dmg}` 和 `ShellRS-<版本>-macos-x86_64.{app.zip,dmg}`。更新清单保留原有的两个平台键,分别记录对应架构包的地址、大小和 SHA-256;已有 universal 客户端按当前运行的架构升级。Apple Silicon 上通过 Rosetta 运行 Intel 版时仍会收到 Intel 包,需要手动安装 ARM 版才能切换。官网在独立仓库中,下载页也需提供 Apple Silicon / Intel 两个入口,读取清单中各自的 installer 地址。
|
||||
@@ -23,8 +23,10 @@ out=$5
|
||||
base="https://dl.shellrs.com/releases/$version"
|
||||
mirror=${SHELLRS_MIRROR_BASE:-}
|
||||
|
||||
mac="ShellRS-$version-macos-universal.app.zip"
|
||||
dmg="ShellRS-$version-macos-universal.dmg"
|
||||
mac_arm="ShellRS-$version-macos-aarch64.app.zip"
|
||||
mac_intel="ShellRS-$version-macos-x86_64.app.zip"
|
||||
dmg_arm="ShellRS-$version-macos-aarch64.dmg"
|
||||
dmg_intel="ShellRS-$version-macos-x86_64.dmg"
|
||||
win="ShellRS-$version-windows-x86_64-setup.exe"
|
||||
linux="ShellRS-$version-linux-x86_64.AppImage"
|
||||
|
||||
@@ -58,10 +60,12 @@ jq -n -j \
|
||||
--arg published "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||
--rawfile notes "$notes" \
|
||||
--arg notes_url "https://shellrs.com/changelog#$version" \
|
||||
--argjson mac "$(asset "$mac")" \
|
||||
--argjson mac_arm "$(asset "$mac_arm")" \
|
||||
--argjson mac_intel "$(asset "$mac_intel")" \
|
||||
--argjson win "$(asset "$win")" \
|
||||
--argjson linux "$(asset "$linux")" \
|
||||
--arg dmg "$base/$dmg" \
|
||||
--arg dmg_arm "$base/$dmg_arm" \
|
||||
--arg dmg_intel "$base/$dmg_intel" \
|
||||
--arg win_url "$base/$win" \
|
||||
--arg linux_url "$base/$linux" \
|
||||
'{
|
||||
@@ -74,14 +78,14 @@ jq -n -j \
|
||||
notes: $notes,
|
||||
notes_url: $notes_url,
|
||||
assets: {
|
||||
"macos-aarch64": $mac,
|
||||
"macos-x86_64": $mac,
|
||||
"macos-aarch64": $mac_arm,
|
||||
"macos-x86_64": $mac_intel,
|
||||
"windows-x86_64": $win,
|
||||
"linux-x86_64": $linux
|
||||
},
|
||||
installers: {
|
||||
"macos-aarch64": $dmg,
|
||||
"macos-x86_64": $dmg,
|
||||
"macos-aarch64": $dmg_arm,
|
||||
"macos-x86_64": $dmg_intel,
|
||||
"windows-x86_64": $win_url,
|
||||
"linux-x86_64": $linux_url
|
||||
}
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
"assets": {
|
||||
"macos-aarch64": {
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip"
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-aarch64.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-aarch64.app.zip"
|
||||
],
|
||||
"size": 41234567,
|
||||
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip"
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-x86_64.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-x86_64.app.zip"
|
||||
],
|
||||
"size": 41234567,
|
||||
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
@@ -42,8 +42,8 @@
|
||||
}
|
||||
},
|
||||
"installers": {
|
||||
"macos-aarch64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.dmg",
|
||||
"macos-x86_64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.dmg",
|
||||
"macos-aarch64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-aarch64.dmg",
|
||||
"macos-x86_64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-x86_64.dmg",
|
||||
"windows-x86_64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-windows-x86_64-setup.exe",
|
||||
"linux-x86_64": "https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-linux-x86_64.AppImage"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
//! Which package of a release fits this machine.
|
||||
//!
|
||||
//! The keys are part of the manifest format, so they never change. A
|
||||
//! universal macOS build runs its native half, so an Apple Silicon Mac asks
|
||||
//! for `macos-aarch64` even though both keys point at the same package; an
|
||||
//! Intel-only build under Rosetta would ask for `macos-x86_64` and keep
|
||||
//! getting Intel builds, which is why macOS ships universal.
|
||||
//! The keys are part of the manifest format, so they never change. macOS
|
||||
//! packages match the running binary's architecture. Existing universal
|
||||
//! builds select their native half's package; an Intel build under Rosetta
|
||||
//! keeps receiving Intel packages until the user installs the ARM build.
|
||||
|
||||
/// The manifest's key for this build's platform.
|
||||
pub fn platform_key() -> &'static str {
|
||||
|
||||
+31
-9
@@ -319,7 +319,8 @@ pub(crate) mod tests {
|
||||
let dist = dir.path().join("dist");
|
||||
std::fs::create_dir(&dist).unwrap();
|
||||
for name in [
|
||||
"ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"ShellRS-0.2.0-macos-aarch64.app.zip",
|
||||
"ShellRS-0.2.0-macos-x86_64.app.zip",
|
||||
"ShellRS-0.2.0-windows-x86_64-setup.exe",
|
||||
"ShellRS-0.2.0-linux-x86_64.AppImage",
|
||||
] {
|
||||
@@ -355,15 +356,36 @@ pub(crate) mod tests {
|
||||
};
|
||||
assert_eq!(manifest.version, Version::new(0, 2, 0));
|
||||
assert_eq!(manifest.notes, "### 新增\n\n- 在线升级\n");
|
||||
let mac = &manifest.assets["macos-aarch64"];
|
||||
assert_eq!(mac, &manifest.assets["macos-x86_64"]);
|
||||
// dl.shellrs.com first, the GitHub release only when it fails.
|
||||
for arch in ["aarch64", "x86_64"] {
|
||||
let key = format!("macos-{arch}");
|
||||
let name = format!("ShellRS-0.2.0-{key}.app.zip");
|
||||
let asset = &manifest.assets[&key];
|
||||
// Each architecture has its own package and both download sources.
|
||||
assert_eq!(
|
||||
asset.urls,
|
||||
[
|
||||
format!("https://dl.shellrs.com/releases/0.2.0/{name}"),
|
||||
format!(
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/{name}"
|
||||
),
|
||||
]
|
||||
);
|
||||
assert_eq!(verify_file(&dist.join(&name), asset), Ok(()));
|
||||
assert_eq!(
|
||||
manifest.installers[&key],
|
||||
format!("https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-{key}.dmg")
|
||||
);
|
||||
}
|
||||
assert_ne!(
|
||||
manifest.assets["macos-aarch64"].sha256,
|
||||
manifest.assets["macos-x86_64"].sha256
|
||||
);
|
||||
assert_eq!(
|
||||
mac.urls,
|
||||
[
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
]
|
||||
verify_file(
|
||||
&dist.join("ShellRS-0.2.0-macos-x86_64.app.zip"),
|
||||
&manifest.assets["macos-aarch64"],
|
||||
),
|
||||
Err(UpdateError::Corrupt)
|
||||
);
|
||||
let package = dist.join("ShellRS-0.2.0-linux-x86_64.AppImage");
|
||||
assert_eq!(
|
||||
|
||||
Reference in new issue
Block a user