Cli agent block fix (#286) #23
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Zap 发布流水线 — 在 openWarp 分支上 push tag (v*) 即触发 | |
| # | |
| # 与上游 create_release.yml 的差异: | |
| # - 仅 macOS arm64 + macOS Intel + Windows x64 + Linux x86_64, | |
| # Web/CLI/Universal/Win-arm64 全砍 | |
| # (macOS 双架构分别产单架构 DMG 与 CLI tarball;Linux 产 AppImage/deb/rpm | |
| # 以及尽力而为的 Arch 包,不发布上游 Zap 仓库源或签名 key) | |
| # - 单 channel: preview(由 release_configurations.json 提供配置) | |
| # - 不签名:不传 --read-passwords-from-env(macOS) / 不设 SIGN_TOOL_CMD(Windows) | |
| # - 不上传 GCS / 第三方 crash 平台 / Slack / changelog,不调 channel-versions repository_dispatch | |
| # - 复用 ./.github/actions/{prepare_environment,get_channel_config} | |
| # | |
| # 流水线结构(先打包后发布,避免出现空 Release): | |
| # prepare_metadata → release_{macos,windows,linux} (上传成 workflow artifact) | |
| # → publish_release (全部 build 成功后下载 artifact 并创建 Release) | |
| # 任意 build job 失败 → publish_release 因 needs 跳过 → 不会留下没有安装包的 Release。 | |
| name: Zap Release | |
| # PR 验证由 .github/workflows/pr-check.yml 负责(Linux cargo check)。 | |
| # 本 workflow 只在 push tag / 手动 dispatch 时跑全量三平台打包,避免 PR 跑 ~3h 浪费。 | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| # 创建 release + 上传 asset 需要写权限。默认 GITHUB_TOKEN 在 fork/受限仓库下是只读, | |
| # 这里显式声明 contents: write 兜底 403 "Resource not accessible by integration"。 | |
| # actions: write 用于 publish_release 末尾删除本次 run 的 workflow artifact(释放 Actions storage)。 | |
| permissions: | |
| contents: write | |
| actions: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| CONFIG_FILE: ".github/workflows/release_configurations.json" | |
| # Zap fork 用 oss channel(对应 app/src/bin/oss.rs 内联 ChannelConfig, | |
| # 不依赖 warp-channel-config 私有二进制),preview 等内部 channel 走 | |
| # channel_config::load_config!() 宏 → build.rs 调 warp-channel-config 失败 → | |
| # *_config.json 不生成 → include_str! 编译失败。 | |
| CHANNEL: oss | |
| jobs: | |
| prepare_metadata: | |
| name: Prepare metadata | |
| runs-on: ubuntu-latest | |
| outputs: | |
| release_tag: ${{ steps.compute_tag.outputs.tag }} | |
| release_branch: ${{ steps.compute_tag.outputs.branch }} | |
| release_name: ${{ steps.get-config.outputs.release_base_name }} ${{ steps.compute_tag.outputs.tag }} | |
| steps: | |
| # fetch-depth: 0 让 git-cliff 能看到完整 tag/commit 历史; | |
| # shallow clone 下 `git describe` 找不到上一个 tag,会退化成空 release notes。 | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get channel configuration | |
| id: get-config | |
| uses: ./.github/actions/get_channel_config/ | |
| with: | |
| config_file: ${{ env.CONFIG_FILE }} | |
| channel: ${{ env.CHANNEL }} | |
| - name: Compute release tag and branch | |
| id: compute_tag | |
| shell: bash | |
| run: | | |
| # tag-触发场景:GITHUB_REF=refs/tags/<tag> | |
| # workflow_dispatch:GITHUB_REF=refs/heads/<branch>,无 tag,生成临时 tag | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| BRANCH="$TAG" | |
| else | |
| TAG="v0.$(date +%Y.%m.%d.%H%M)" | |
| BRANCH="${GITHUB_REF#refs/heads/}" | |
| fi | |
| echo "tag=$TAG" >> $GITHUB_OUTPUT | |
| echo "branch=$BRANCH" >> $GITHUB_OUTPUT | |
| echo "Release tag: $TAG / build ref: $BRANCH" | |
| # 找上一个 release tag(匹配 v*),用于限定 git-cliff 的 commit 范围。 | |
| # tag-触发:HEAD == 当前 tag,要从 HEAD^ 起找最近的 v* tag。 | |
| # dispatch:HEAD 不是 tag,直接从 HEAD 起找。 | |
| # 找不到(首次发布)时输出空字符串,后面 git-cliff 不限定范围。 | |
| - name: Compute previous release tag | |
| id: prev_tag | |
| shell: bash | |
| run: | | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| PREV=$(git describe --tags --abbrev=0 --match='v*' HEAD^ 2>/dev/null || echo "") | |
| else | |
| PREV=$(git describe --tags --abbrev=0 --match='v*' HEAD 2>/dev/null || echo "") | |
| fi | |
| echo "prev=$PREV" >> $GITHUB_OUTPUT | |
| echo "Previous tag: ${PREV:-<none, first release>}" | |
| # 用官方推荐的 orhun/git-cliff-action 生成「上个 tag 到 HEAD」的变更说明。 | |
| # --strip header 去掉模板顶部空 header;--tag 把 unreleased 段标记为本次发布版本。 | |
| # 范围参数 `<prev>..HEAD` 通过三元表达式注入:有 prev 时限定范围,无 prev 时让 | |
| # git-cliff 输出全部历史(首次发布场景)。 | |
| - name: Generate release notes via git-cliff | |
| uses: orhun/git-cliff-action@98c93442bb05a455a77bee982867857ae748eeea # v4.5.1 | |
| with: | |
| config: cliff.toml | |
| args: >- | |
| --strip header | |
| --tag ${{ steps.compute_tag.outputs.tag }} | |
| ${{ steps.prev_tag.outputs.prev != '' && format('{0}..HEAD', steps.prev_tag.outputs.prev) || '' }} | |
| env: | |
| OUTPUT: release-notes.md | |
| GITHUB_REPO: ${{ github.repository }} | |
| # 把 release_configurations.json 里的一句固定说明拼到 git-cliff 输出之前, | |
| # 形成最终的 release body。后续 publish_release 用 body_path 注入到 GitHub Release。 | |
| - name: Assemble final release body | |
| shell: bash | |
| env: | |
| RELEASE_BODY_TEXT: ${{ steps.get-config.outputs.release_body_text }} | |
| PREV_TAG: ${{ steps.prev_tag.outputs.prev }} | |
| THIS_TAG: ${{ steps.compute_tag.outputs.tag }} | |
| run: | | |
| { | |
| echo "$RELEASE_BODY_TEXT" | |
| echo | |
| if [[ -n "$PREV_TAG" ]]; then | |
| echo "## 自 \`$PREV_TAG\` 以来的更新" | |
| else | |
| echo "## 首发版本变更" | |
| fi | |
| echo | |
| cat release-notes.md | |
| } > release-body.md | |
| echo "---- release-body.md ----" | |
| cat release-body.md | |
| - name: Upload release body artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: release-body | |
| path: release-body.md | |
| if-no-files-found: error | |
| retention-days: 7 | |
| release_macos: | |
| name: Build Release (macOS ${{ matrix.dmg_name_suffix }}) | |
| runs-on: ${{ matrix.runner }} | |
| needs: prepare_metadata | |
| # macos-26 / macos-26-intel(Pro standard)无 sccache,full cargo build + bundle + create-dmg | |
| # 耗时高;Intel 构建历史上超过 180min,这里放宽到 GitHub-hosted job 6h 执行上限。 | |
| timeout-minutes: 360 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: aarch64 | |
| dmg_name_suffix: arm64 | |
| runner: macos-26 # Pro standard arm64 (M2 Pro) | |
| - arch: x86_64 | |
| dmg_name_suffix: intel | |
| runner: macos-26-intel # Pro standard Intel | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| ref: ${{ needs.prepare_metadata.outputs.release_branch }} | |
| - uses: ./.github/actions/prepare_environment | |
| with: | |
| target_os: macos | |
| cache_key: macos-${{ matrix.arch }} | |
| is_self_hosted: false | |
| install_release_deps: true | |
| - name: Ensure rust target is installed | |
| run: rustup target add ${{ matrix.arch }}-apple-darwin | |
| shell: bash | |
| - name: Check ${{ matrix.arch }} release compile | |
| run: | | |
| script/bundle --check-only --channel "$CHANNEL" --arch ${{ matrix.arch }} --dmg-name-suffix "${{ matrix.dmg_name_suffix }}" --selfsign | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Setup Go | |
| uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 | |
| with: | |
| go-version: stable | |
| - name: Install cargo-bundle | |
| run: script/install_cargo_bundle | |
| - name: Install create-dmg | |
| run: brew install create-dmg | |
| # 用 --selfsign 走 ad-hoc 签名(无 Apple Developer cert 时 fallback 到 `-`): | |
| # 1. 让 .app 拥有 cdhash → UNUserNotificationCenter 才肯把 Zap 注册到 | |
| # System Settings → Notifications(否则桌面通知静默失效,见 issue #40)。 | |
| # 2. ad-hoc + Hardened Runtime + Debug-Entitlements.plist(disable-library-validation | |
| # + get-task-allow)是合法组合,可在 macos-26 runner 上无凭证完成。 | |
| # 3. notarize 整段被 `script/macos/bundle` 的 CODESIGN=false 分支跳过;DMG 从 | |
| # BUNDLE_DIR 直接 create-dmg,不进 codesign / staple 步骤。 | |
| # 4. 用户首次打开仍会触发 Gatekeeper 的「未识别开发者」对话框(无 Developer ID | |
| # notarize 的固有限制);issue #51 提供的 `xattr -rd com.apple.quarantine` | |
| # 自助方案继续有效。 | |
| - name: Build ${{ matrix.arch }} bundle (ad-hoc signed) | |
| id: bundle_app | |
| run: | | |
| script/bundle --channel "$CHANNEL" --arch ${{ matrix.arch }} --dmg-name-suffix "${{ matrix.dmg_name_suffix }}" --selfsign | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Upload DMG artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: zap-macos-${{ matrix.dmg_name_suffix }} | |
| path: ${{ steps.bundle_app.outputs.dmg_path }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| - name: Build CLI | |
| id: bundle_cli | |
| run: | | |
| script/bundle --channel "$CHANNEL" --arch ${{ matrix.arch }} --artifact cli --nosign | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Package CLI tarball | |
| run: | | |
| cp "${{ steps.bundle_cli.outputs.binary_path }}" zap-oss | |
| tar czf zap-macos-${{ matrix.arch }}.tar.gz \ | |
| zap-oss \ | |
| -C "$(dirname "${{ steps.bundle_cli.outputs.bundled_resources_dir }}")" resources | |
| shell: bash | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: zap-cli-macos-${{ matrix.arch }} | |
| path: zap-macos-${{ matrix.arch }}.tar.gz | |
| if-no-files-found: error | |
| retention-days: 7 | |
| release_windows: | |
| name: Build Release (Windows x64) | |
| runs-on: windows-latest | |
| needs: prepare_metadata | |
| timeout-minutes: 180 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| ref: ${{ needs.prepare_metadata.outputs.release_branch }} | |
| - uses: ./.github/actions/prepare_environment | |
| with: | |
| target_os: windows | |
| cache_key: x64 | |
| is_self_hosted: false | |
| install_release_deps: true | |
| - name: Build binary (unsigned) | |
| id: build_binary | |
| run: script/bundle -Channel $CHANNEL -skip_build_installer --arch x64 | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Bundle app (unsigned installer) | |
| id: bundle_app | |
| run: script/bundle -Channel $CHANNEL -skip_build_binary --arch x64 | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Upload installer artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: zap-windows-x64 | |
| path: ${{ steps.bundle_app.outputs.installer_path }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| release_linux: | |
| name: Build Release (Linux x86_64) | |
| runs-on: ubuntu-22.04 | |
| needs: prepare_metadata | |
| # 用 22.04 (glibc 2.35) 而不是 ubuntu-latest (24.04, glibc 2.39), | |
| # AppImage 用 host glibc 链接,22.04 产物能在更多旧发行版上跑 | |
| # (Debian 11 / Ubuntu 20.04 + 等)。 | |
| timeout-minutes: 180 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| ref: ${{ needs.prepare_metadata.outputs.release_branch }} | |
| # GitHub-hosted ubuntu runner 的 / 余量有限,而本 job 先后在同一磁盘产出 | |
| # release-lto(GUI/AppImage/deb/rpm/arch)与 release-cli(musl CLI)两份完整 | |
| # target,叠加 cargo registry / docker 镜像 / zig 工具链后会撑爆磁盘,musl CLI | |
| # 步骤报 "No space left on device"(见 run 27593938453)。先删掉与本构建无关的 | |
| # 预装工具链(Android SDK / .NET / GHC / CodeQL / Swift),腾出 ~25GB。 | |
| - name: Free up disk space | |
| shell: bash | |
| run: | | |
| sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc \ | |
| /usr/local/.ghcup /opt/hostedtoolcache/CodeQL /usr/share/swift || true | |
| df -h / | |
| - uses: ./.github/actions/prepare_environment | |
| with: | |
| target_os: linux | |
| is_self_hosted: false | |
| install_release_deps: true | |
| - name: Install extra dependencies for deb/rpm and build | |
| run: | | |
| sudo apt-get update | |
| # `rpm` 包提供 /usr/bin/rpmbuild,给后面的 RPM 打包步骤用。 | |
| sudo apt-get install -y libdbus-1-dev fakeroot rpm | |
| shell: bash | |
| - name: Ensure rust target is installed | |
| run: rustup target add x86_64-unknown-linux-gnu | |
| shell: bash | |
| - name: Check Linux release compile | |
| run: script/bundle --check-only --channel "$CHANNEL" --arch x86_64 --packages appimage,deb | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| - name: Install linuxdeploy | |
| # script/linux/install_linuxdeploy 不被 install_build_deps 调用,需手动跑; | |
| # 它把 linuxdeploy AppImage 放到 ~/.local/bin,加到 PATH 里。 | |
| run: | | |
| ./script/linux/install_linuxdeploy | |
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | |
| shell: bash | |
| - name: Build AppImage (unsigned) | |
| id: bundle_app | |
| run: script/bundle --channel "$CHANNEL" --arch x86_64 --packages appimage,deb | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| # ubuntu-22.04 默认有 libfuse2 但 24.04 没有;统一开 EXTRACT_AND_RUN | |
| # 让 linuxdeploy/appimagetool 不依赖 FUSE 内核模块,跨 runner 版本都稳。 | |
| APPIMAGE_EXTRACT_AND_RUN: 1 | |
| # RPM 包:复用上一步 release-lto 已经 strip 过的 `target/release-lto/zap-oss`, | |
| # 不重新 `cargo build`。`--skip-build` 让 `script/bundle` 跳过编译与 strip, | |
| # 直接进入 staging(`bundle_install` → 复制二进制 + resources)+ rpmbuild。 | |
| # 与 deb 同一台 ubuntu-22.04 runner 上跑,共享 host glibc 链接的产物; | |
| # 用 Fedora 26+ / RHEL 8+ 上的 RPM 4.13+ 安装(spec 用了 boolean dep 语法)。 | |
| # continue-on-error: 即便 rpmbuild 失败也不应阻塞 AppImage/deb 已经成功的发布。 | |
| - name: Build RPM package (reuse release-lto binary) | |
| continue-on-error: true | |
| run: script/bundle --skip-build --channel "$CHANNEL" --arch x86_64 --packages rpm | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| # Arch 包:复用上一步 release-lto 已经 strip 过的 `target/release-lto/zap-oss`, | |
| # 不重新 `cargo build` 主二进制 —— `--skip-build` 让 `script/bundle` 跳过编译与 strip, | |
| # 直接进入 staging(`bundle_install` → 复制二进制 + resources)+ makepkg。 | |
| # | |
| # 为什么放容器里:`makepkg` 是 Arch 独有,Ubuntu runner 没有。 | |
| # 容器里只装 Arch 自带的 `rust` 和 `cargo-about`: | |
| # - SKIP_SETTINGS_SCHEMA=1 后,不再跑 `cargo run --bin generate_settings_schema`, | |
| # 所以容器里 rustc 版本跟项目锁定版(1.92.x) 不一致也无所谓。 | |
| # - `cargo about generate` 只读 Cargo.lock 元数据生成第三方 license, | |
| # 不触发任何 Rust 代码编译。 | |
| # makepkg 拒绝 root 运行(EUID==0),必须切到非 root 用户。 | |
| # continue-on-error: Arch 工具链炸了不影响 AppImage/deb 发布。 | |
| - name: Build Arch package (reuse release-lto binary) | |
| continue-on-error: true | |
| run: | | |
| set -euo pipefail | |
| # 用 host runner 用户的 uid/gid 在容器里建 builder,免去 chown 整棵 | |
| # /work 与 ~/.cargo 的开销(makepkg 拒绝 root,但 uid != 0 即可, | |
| # 用什么名字、什么具体 uid 都行)。 | |
| HOST_UID=$(id -u) | |
| HOST_GID=$(id -g) | |
| # 注意:不要把 GITHUB_ACTIONS=true 透传进容器。 | |
| # script/bundle 看到该变量后会 `echo ... >> "$GITHUB_OUTPUT"`, | |
| # 而容器里没有 GITHUB_OUTPUT,redirect 到空字符串触发 `set -e` 退出, | |
| # Arch 包根本就构建不出来(见 run 26153630745)。 | |
| # 我们也不需要该步骤的 step outputs —— 它 continue-on-error, | |
| # packages_dir 由前面 AppImage 步骤的 bundle_app.outputs 提供。 | |
| docker run --rm \ | |
| -v "$PWD:/work" \ | |
| -v "$HOME/.cargo:/cargo-home" \ | |
| -w /work \ | |
| -e GIT_RELEASE_TAG="${{ needs.prepare_metadata.outputs.release_tag }}" \ | |
| -e SKIP_SETTINGS_SCHEMA=1 \ | |
| -e HOST_UID="$HOST_UID" \ | |
| -e HOST_GID="$HOST_GID" \ | |
| archlinux:latest bash -euxc ' | |
| # 预装 PKGBUILD `depends` 里的运行时依赖,避免 makepkg -s | |
| # 在容器内调 `sudo pacman -S` 装缺包(builder 没有免密 sudo, | |
| # 会因为读不到密码退出 8,Arch 包就此漏掉,见 run 26267606877)。 | |
| # `opengl-driver` 在官方仓库里不存在(NixOS 概念 / AUR 虚拟包), | |
| # 单独用 --assume-installed 让依赖检查跳过它。 | |
| pacman -Sy --noconfirm --needed \ | |
| base-devel git sudo rust cargo-about \ | |
| curl default-cursors fontconfig libegl libx11 libxcb \ | |
| libxcursor libxi libxkbcommon-x11 xdg-utils zlib && | |
| # 用 host uid/gid 建用户,挂进来的 /work 与 /cargo-home owner 就是它, | |
| # 不用 chown,直接 sudo -u 即可读写。 | |
| groupadd -g "$HOST_GID" builder 2>/dev/null || true | |
| useradd -u "$HOST_UID" -g "$HOST_GID" -m builder | |
| # 显式给 HOME=/home/builder,否则 `sudo -E` 会保留外层 HOME=/root, | |
| # 导致 `git config --global` 试图写 /root/.gitconfig 报 Permission denied。 | |
| sudo -u builder -E env \ | |
| HOME=/home/builder \ | |
| CARGO_HOME=/cargo-home \ | |
| PATH=/cargo-home/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ | |
| bash -c " | |
| git config --global --add safe.directory /work | |
| cd /work | |
| # 依赖已在外层 pacman 装好;告诉 makepkg `opengl-driver` | |
| # 视为已安装,避免它去 pacman -S 一个仓库里没有的包。 | |
| # 另外带 --noconfirm:容器里没透传 GITHUB_ACTIONS, | |
| # bundle_arch 里原生的那个分支不会生效。 | |
| MAKEPKG_EXTRA_ARGS='\''--noconfirm --assume-installed opengl-driver'\'' \ | |
| script/bundle --skip-build --channel oss --arch x86_64 --packages arch | |
| " | |
| ' | |
| shell: bash | |
| - name: Upload package artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: zap-linux-x86_64 | |
| # packages_dir 是 target/release-lto/bundle/linux,AppImage/deb/Arch 都落在这里 | |
| path: ${{ steps.bundle_app.outputs.packages_dir }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| # release-lto 产物(GUI/deb/rpm/arch)已由上一步 "Upload package artifacts" | |
| # 上传为 workflow artifact,本地不再需要;下面的 musl CLI 走独立的 release-cli | |
| # profile,删掉 release-lto 给它腾磁盘,避免 "No space left on device"。 | |
| - name: Reclaim disk before musl CLI build | |
| shell: bash | |
| run: | | |
| rm -rf target/release-lto | |
| df -h / | |
| # CLI/remote-server tarball 用静态 musl 链接,产物不依赖宿主 glibc, | |
| # 可在任意 Linux x86_64 主机(含 CentOS 7 / Amazon Linux 2 等旧 glibc | |
| # 以及 Alpine 等 musl 发行版)上运行。GUI AppImage/deb 仍走上面的 | |
| # glibc 链接构建,不受影响。 | |
| # | |
| # 用 `cargo zigbuild` 做 musl 交叉编译:zig 自带完整的 C/C++ musl | |
| # 工具链(`zig cc` / `zig c++`),不依赖宿主的 `musl-gcc` 或手写的 | |
| # `musl-g++` wrapper —— 历史上为 freetype-sys / harfbuzz-sys 等 *-sys | |
| # 依赖准备的「宿主 g++ + musl specs」hack 因此整条移除。 | |
| # 本地 dev 自动构建路径(`ssh_transport.rs`)也优先用 zigbuild,两边 | |
| # 工具链统一。 | |
| - name: Install zig + cargo-zigbuild for static musl CLI build | |
| run: | | |
| set -euo pipefail | |
| rustup target add x86_64-unknown-linux-musl | |
| # zig:用官方预编译 tarball,固定版本以保证构建可复现。 | |
| # 0.13.0 与 cargo-zigbuild >= 0.19 兼容。 | |
| ZIG_VERSION="0.13.0" | |
| ZIG_DIR="$HOME/.local/zig-${ZIG_VERSION}" | |
| if [ ! -x "${ZIG_DIR}/zig" ]; then | |
| mkdir -p "${ZIG_DIR}" | |
| curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-linux-x86_64-${ZIG_VERSION}.tar.xz" \ | |
| | tar -xJ -C "${ZIG_DIR}" --strip-components=1 | |
| fi | |
| echo "${ZIG_DIR}" >> "$GITHUB_PATH" | |
| # cargo-zigbuild:走 cargo install,首次安装在缓存里之后会复用。 | |
| cargo install --locked cargo-zigbuild --version ^0.19 | |
| shell: bash | |
| - name: Build CLI (static musl via zigbuild) | |
| id: bundle_cli | |
| run: | | |
| script/bundle --channel "$CHANNEL" --arch x86_64 --artifact cli --packages none \ | |
| --target x86_64-unknown-linux-musl | |
| shell: bash | |
| env: | |
| GIT_RELEASE_TAG: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| APPIMAGE_EXTRACT_AND_RUN: 1 | |
| # 让 script/linux/bundle 把 `cargo build` 切到 `cargo zigbuild`。 | |
| USE_ZIGBUILD: "true" | |
| # libc(musl)被 +crt-static 静态链接进二进制 —— 这是让产物摆脱 | |
| # 宿主 glibc 下限的关键。`libdbus-sys` 现在通过 keyring 的 | |
| # `vendored` feature 从源码内嵌编译(见 Cargo.toml),不再用 pkg-config | |
| # 探测宿主 `dbus-1`;`PKG_CONFIG_ALLOW_CROSS=1` 保留作兜底, | |
| # 万一某个新引入的 -sys crate 还在用 pkg-config 也不会卡。 | |
| PKG_CONFIG_ALLOW_CROSS: 1 | |
| - name: Package CLI tarball | |
| run: | | |
| cp "${{ steps.bundle_cli.outputs.executable_path }}" zap-oss | |
| tar czf zap-linux-x86_64.tar.gz \ | |
| zap-oss \ | |
| -C "$(dirname "${{ steps.bundle_cli.outputs.bundled_resources_dir }}")" resources | |
| shell: bash | |
| - name: Upload CLI artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: zap-cli-linux-x86_64 | |
| path: zap-linux-x86_64.tar.gz | |
| if-no-files-found: error | |
| retention-days: 7 | |
| publish_release: | |
| name: Publish GitHub Release | |
| runs-on: ubuntu-latest | |
| # 必须等所有平台都 build 成功才发布;任一失败 → 此 job 跳过 → 不会出现空 Release。 | |
| needs: | |
| - prepare_metadata | |
| - release_macos | |
| - release_windows | |
| - release_linux | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| # release-body artifact 是给 GitHub Release 描述用的,不是要挂到 Release 资产列表的产物。 | |
| # 提前从 dist/ 移到独立路径,避免 `files: dist/*` 把它当成 asset 上传。 | |
| - name: Extract release body from artifacts | |
| shell: bash | |
| run: | | |
| mv dist/release-body.md ./release-body.md | |
| echo "---- release-body.md ----" | |
| cat ./release-body.md | |
| - name: List downloaded files | |
| run: ls -lh dist | |
| shell: bash | |
| - name: Create GitHub release with all assets | |
| uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 | |
| with: | |
| name: ${{ needs.prepare_metadata.outputs.release_name }} | |
| tag_name: ${{ needs.prepare_metadata.outputs.release_tag }} | |
| body_path: ./release-body.md | |
| draft: false | |
| prerelease: false | |
| make_latest: "true" | |
| files: dist/* | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| # 发布成功后立刻删本次 run 的 workflow artifact,释放 Actions storage 配额。 | |
| # 安装包已经挂到 GitHub Release(独立存储,不占 Actions storage), | |
| # workflow artifact 只是 build job → publish job 的中间传递管道,留着没用。 | |
| # 仅在 Release 创建成功后执行(if: success()),失败保留 artifact 方便复盘。 | |
| - name: Delete workflow artifacts to free Actions storage | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| ids=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts" --jq '.artifacts[].id') | |
| for id in $ids; do | |
| echo "Deleting artifact $id" | |
| gh api -X DELETE "repos/${{ github.repository }}/actions/artifacts/$id" | |
| done | |
| shell: bash |