Compare commits
16
Commits
ci/build-client
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4794bed2cf | ||
|
|
e6070f91ee | ||
|
|
26731958ea | ||
|
|
de7263569c | ||
|
|
c9ce7b64ef | ||
|
|
f3b09ca9a6 | ||
|
|
1cccc1aa00 | ||
|
|
f0538fa233 | ||
|
|
47ef7c63dd | ||
|
|
b74c6654e5 | ||
|
|
ac3d639d6b | ||
|
|
2ed16ff88d | ||
|
|
6f83ebbe3c | ||
|
|
4667d94c45 | ||
|
|
76b96cc374 | ||
|
|
03f7279b53 |
@@ -0,0 +1,16 @@
|
||||
# actionlint 配置。
|
||||
#
|
||||
# 这个仓库的 CI 跑在 Gitea 上,但 actionlint 用的是 GitHub 的规则,所以有一条
|
||||
# 政策性的误报要忽略掉:
|
||||
#
|
||||
# the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions
|
||||
#
|
||||
# 它对 GitHub 是成立的(v3 声明的 node16 运行时 GitHub 已经不再执行),但我们是
|
||||
# Gitea:Gitea 的 runner 用自己的 node 跑 JS action,v3 能正常把产物传上去;反过来
|
||||
# v4 在 Gitea 上**根本跑不了** —— v4 里的 @actions/artifact 会拒绝非 github.com
|
||||
# 的服务器(GHESNotSupportedError,原文见 .github/workflows/build-client.yml 文件头
|
||||
# 第 3 条,那是 2026-10-15 第一次真实运行的日志里抄下来的)。
|
||||
paths:
|
||||
.github/workflows/*.yml:
|
||||
ignore:
|
||||
- 'the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions'
|
||||
+191
-108
@@ -2,41 +2,94 @@
|
||||
#
|
||||
# 产物都挂在这次运行下面(Actions 页面直接下载),保留 14 天:
|
||||
# Linux x64 deb + AppImage cam-desktop_<版本>_amd64.deb / .AppImage ← 默认每次编
|
||||
# Windows x64 NSIS 安装包 cam-desktop_<版本>_x64-setup.exe ← 有 runner 才编
|
||||
# macOS 通用 .app + .dmg arm64 与 x86_64 合成一个包 ← 有 runner 才编
|
||||
# Windows x64 NSIS 安装包 cam-desktop_<版本>_x64-setup.exe ← 默认每次编
|
||||
# macOS 通用 .app + .dmg arm64 与 x86_64 合成一个包 ← 还没有机器,手动勾选才编
|
||||
#
|
||||
# ── 触发 ─────────────────────────────────────────────────────────────────────
|
||||
# * push 到 main/master —— 只认 desktop/、protocol/ 与本文件的改动,改固件不会
|
||||
# 白占 runner
|
||||
# * 打 v* tag、开 PR
|
||||
# * 手动 Run workflow:逐个平台勾选,不进 paths 过滤("就想编一次"走它)
|
||||
# Windows 与 macOS 两个 job 目前默认不跑,原因与打开方式见下面第 1 条。
|
||||
# 平台开关一律看勾选框(理由见下面第 4 条)。
|
||||
#
|
||||
# ── 跑在 Gitea 上要先对上的两件事 ────────────────────────────────────────────
|
||||
# 1. runner 标签是注册 runner 时自己起的名字,猜不到,所以三个 job 都写成
|
||||
# "仓库变量优先、常见标签兜底":
|
||||
# runs-on: ${{ vars.RUNNER_LINUX || 'ubuntu-latest' }}
|
||||
# 标签对不上时 job 是**排队**而不是报错 —— 排队会一直占着这次运行不结束,
|
||||
# 所以第一次跑之前先看一眼 runner 页面上那几行标签。
|
||||
# 所以上线新平台前先看一眼 runner 页面上那几行标签。
|
||||
#
|
||||
# 本仓库目前只有 Linux 的两个 runner 标签(ubuntu-latest / ubuntu-24.04 /
|
||||
# ubuntu-22.04),所以**默认只跑 Linux**:Windows 与 macOS 两个 job 要等
|
||||
# 仓库变量 ENABLE_WINDOWS / ENABLE_MACOS 设成 true 才会跑(手动 Run workflow
|
||||
# 时另看勾选框),机器的标签则用 RUNNER_WINDOWS / RUNNER_MACOS 指过去。
|
||||
# 等那两台机器上的 runner 注册好再打开,否则每次 push 都会多出两个永远排队的
|
||||
# job。
|
||||
# 2026-10-15 实测在线的(括号里是它们自己声明的标签):
|
||||
# * simba-runner-01 (ubuntu-latest / ubuntu-24.04 / ubuntu-22.04)
|
||||
# * windows-runner-01 (windows-latest / windows-2025 / windows-2022)
|
||||
# * macOS:还没有
|
||||
# 所以 Windows 默认就跑;macOS 的 job 写成"手动勾选才跑"。
|
||||
#
|
||||
# 为什么不能拿 Linux runner 交叉编出来:
|
||||
# * Windows:Rust 侧用 mingw 交叉编还能出个裸 exe,但 tauri 的 NSIS 打包器
|
||||
# 本身只能在 Windows 上跑,出不了安装包;
|
||||
# * macOS:要 Apple SDK 与 codesign/lipo,只能在 macOS 上编。
|
||||
# 所以这两个平台的 job 留着是为了"机器到位那天直接开",不是摆设。
|
||||
# 那两台机器上要预装好:Windows 的 MSVC Build Tools(link.exe)、macOS 的
|
||||
# Xcode Command Line Tools,以及 rustup(dtolnay/rust-toolchain 靠它装工具链)。
|
||||
# Linux 的 job 通常跑在容器里,所以没装 rustup 也没关系 —— 见下面那步兜底。
|
||||
# Windows runner 上要预装好 MSVC Build Tools(link.exe)、WebView2 运行时与
|
||||
# rustup(dtolnay/rust-toolchain 靠它装工具链);macOS 上要 Xcode Command Line
|
||||
# Tools + rustup。Linux 的 job 通常跑在容器里,没装 rustup 也没关系 —— 见兜底那步。
|
||||
# 2. 这个文件放在 .github/workflows/ 下就够:Gitea 的 [actions] WORKFLOW_DIRS
|
||||
# 默认值就是 [".gitea/workflows", ".github/workflows"](源码里的默认值,且
|
||||
# .yml 与 .yaml 都认),所以两个目录都是原生支持的,不用挪。
|
||||
# 3. 两处"GitHub 能跑、Gitea 上不行"的地方,都是 2026-10-15 第一次真实运行的
|
||||
# 日志里钉出来的:
|
||||
# * 传产物用 upload-artifact@v3,**不能用 v4**。v4 里的 @actions/artifact 会
|
||||
# 拒绝非 github.com 的服务器,日志原文:
|
||||
# GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+
|
||||
# and download-artifact@v4+ are not currently supported on GHES
|
||||
# Gitea 实现的是 v3 那套接口(ACTIONS_RUNTIME_URL),所以 v3 能传上去。
|
||||
# * 一个缓存都没开。这台实例的缓存服务在 job 容器里连不上,日志原文:
|
||||
# Failed to restore: getCacheEntry failed: connect ETIMEDOUT 172.18.0.2:37315
|
||||
# setup-node 的 cache 每次要干等 4 分 39 秒才放弃(两个 job 各一次)。
|
||||
# 等缓存能从容器访问到了再加回来,写法就是:
|
||||
# setup-node 的 with 里加:cache: pnpm / cache-dependency-path: desktop/pnpm-lock.yaml
|
||||
# 各 job 里加:
|
||||
# - uses: actions/cache@v4
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry/index
|
||||
# ~/.cargo/registry/cache
|
||||
# ~/.cargo/git/db
|
||||
# key: ${{ runner.os }}-cargo-registry-${{ hashFiles('protocol/Cargo.lock', 'desktop/core/Cargo.lock', 'desktop/src-tauri/Cargo.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cargo-registry-
|
||||
# 4. 平台开关只用 github.event.inputs,**不用仓库变量**。2026-10-15 那次 Windows# runner 明明在线、job 也确实派给了它(它自己的日志里写着
|
||||
# "Runner labels: windows-latest, windows-2025, windows-2022"),产物却一直是
|
||||
# skipped —— 卡在 job 级 if 的 `vars.ENABLE_WINDOWS == 'true'` 上:Gitea 的
|
||||
# runner 在 job 级 if 里拿不到(或拿不对)vars 上下文,而这个条件写反的代价是
|
||||
# "静悄悄不编",最难发现。同一份文件里 `github.event.inputs.linux != 'false'`
|
||||
# 这个形式在 runner 日志里能看到正常求值(evaluating expression '...' evaluated
|
||||
# to 'true'),所以平台开关统一成这种:
|
||||
# * Linux / Windows:`github.event.inputs.<平台> != 'false'` → 默认跑,
|
||||
# 手动触发时取消勾选就不跑
|
||||
# * macOS:`github.event.inputs.macos == 'true'` → 默认不跑,等有机器了改成
|
||||
# 上一种形式即可
|
||||
# runs-on 里的 vars(RUNNER_*)不受影响,标签不匹配时用那个覆盖。
|
||||
# 5. Windows runner 的 job 跑在**低完整性**上(实测 Mandatory Label\Low Mandatory
|
||||
# Level, S-1-16-4096),而 Windows 不允许低完整性往中完整性写:用户目录
|
||||
# (~/.rustup、~/.cargo、%TEMP%、%LOCALAPPDATA%)统统 Access denied (os error 5)
|
||||
# —— ACL 是干净的(SYSTEM / Administrators / 本人 全 F,没有任何 Deny),拦它的是
|
||||
# 完整性级别,所以"放宽权限"一点用都没有。表现是一串看着毫不相干的错误:
|
||||
# * Git Bash 的 mktemp 写 /tmp 被拒(它的 /tmp 跟着 TEMP 走;TEMP 不可写时退回
|
||||
# <Git 安装目录>\tmp,那个目录普通权限进不去);
|
||||
# * rustup: could not create temp file C:\Users\admin\.rustup\tmp\xxx_file
|
||||
# 处置:Windows job 把能重定向的都指到 runner 自己的工作目录
|
||||
# (C:\Users\admin\runner\windows\cache,job 内写探测实测可写)——
|
||||
# RUSTUP_HOME / CARGO_HOME / npm_config_cache / npm_config_store_dir /
|
||||
# RUNNER_TOOL_CACHE / LOCALAPPDATA / APPDATA,加上 TEMP/TMP/TMPDIR、
|
||||
# pnpm/action-setup 的 dest,以及 **USERPROFILE**。
|
||||
# 最后这个是被 pnpm 逼出来的:它的 store 操作锁不在 store-dir 下面,也不看
|
||||
# LOCALAPPDATA,而是按 <USERPROFILE>\AppData\Local\pnpm-store-operation-locks
|
||||
# 算 —— 只把 LOCALAPPDATA 指走它照样去开原来的路径(报错原文见 run 8 的日志),
|
||||
# 把 USERPROFILE 指走它才跟着走(本机实测:探针 profile 下立刻出现
|
||||
# all-stores.lock)。
|
||||
# 想从根上解决:让 gitea-runner 以**中完整性**启动(在普通终端里跑
|
||||
# run-runner.ps1,而不是从被沙箱化的低完整性 shell 里拉起来),那样这些重定向
|
||||
# 就都可以撤掉。这台机器上 runner 由计划任务 GiteaRunner-Windows(admin /
|
||||
# Limited)拉起,但进程链上的完整性已经落到了 Low。
|
||||
#
|
||||
# ── 三个平台都显式写 --target,这不是啰嗦 ────────────────────────────────────
|
||||
# desktop/.cargo/config.toml 里钉着 `target = "aarch64-apple-darwin"`(本机开发用;
|
||||
@@ -80,18 +133,18 @@ on:
|
||||
- ".github/workflows/build-client.yml"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
# Linux 的 runner 有,默认勾上;另两个平台目前没有 runner,默认不勾 ——
|
||||
# 勾了而没有对应 runner,那个 job 会一直排队。
|
||||
# Linux 与 Windows 的 runner 都在线,默认勾上;macOS 还没有机器,默认不勾
|
||||
# (勾了会一直排队)。开关为什么不用仓库变量见文件头第 4 条。
|
||||
linux:
|
||||
description: "构建 Linux(deb + AppImage)"
|
||||
type: boolean
|
||||
default: true
|
||||
windows:
|
||||
description: "构建 Windows(NSIS 安装包)——需要 Windows runner"
|
||||
description: "构建 Windows(NSIS 安装包)"
|
||||
type: boolean
|
||||
default: false
|
||||
default: true
|
||||
macos:
|
||||
description: "构建 macOS(通用 dmg)——需要 macOS runner"
|
||||
description: "构建 macOS(通用 dmg)——还没有 macOS runner,勾了会排队"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -148,7 +201,8 @@ jobs:
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
fi
|
||||
|
||||
# pnpm 必须在 setup-node 之前:setup-node 的 cache: pnpm 要用它算 store 路径。
|
||||
# pnpm 装在 setup-node 之前:这一步只靠 runner 镜像里自带的 node(实测
|
||||
# /opt/hostedtoolcache 里有 24.x),而下面的 pnpm install 要用它。
|
||||
- name: 装 pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
@@ -158,8 +212,6 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: pnpm
|
||||
cache-dependency-path: desktop/pnpm-lock.yaml
|
||||
|
||||
- name: 前端依赖(严格按 lock 装)
|
||||
working-directory: desktop
|
||||
@@ -178,21 +230,6 @@ jobs:
|
||||
with:
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
|
||||
# 只缓存 registry(crate 源码),不缓存 target/:自建 runner 的容器每次都是
|
||||
# 干净的,几 GB 的 target 缓存拉下来的时间常常比重新编译还长,磁盘也扛不住。
|
||||
# 缓存服务在不同 Gitea 版本上差异较大,所以失败不让它拖垮构建。
|
||||
- name: cargo 缓存
|
||||
uses: actions/cache@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('protocol/Cargo.lock', 'desktop/core/Cargo.lock', 'desktop/src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
# protocol 没有自己的 rust-toolchain.toml,会被根目录那个 `esp` 接住,
|
||||
# 所以这里必须 +stable 显式指定。
|
||||
- name: protocol 单元测试(15)
|
||||
@@ -272,25 +309,11 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: pnpm
|
||||
cache-dependency-path: desktop/pnpm-lock.yaml
|
||||
|
||||
- name: 前端依赖(严格按 lock 装)
|
||||
working-directory: desktop
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: cargo 缓存
|
||||
uses: actions/cache@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('protocol/Cargo.lock', 'desktop/core/Cargo.lock', 'desktop/src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
# 上面 apt 装了 ffmpeg,所以 recording.rs 里那几条"真的起 ffmpeg 并读回帧数"
|
||||
# 的测试不会走 has_ffmpeg() 的跳过分支,是真的在验。
|
||||
# 如果这台 runner 上它们长期不稳定,删掉这一步即可 —— 它们不在守门 job 里,
|
||||
@@ -305,7 +328,7 @@ jobs:
|
||||
run: pnpm tauri build --target ${{ env.TARGET }} --bundles deb,appimage
|
||||
|
||||
- name: 上传产物
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cam-desktop-linux-x64
|
||||
# 一个都没找到就报错:产物路径写错却"构建成功"是最难发现的一种失败。
|
||||
@@ -321,65 +344,143 @@ jobs:
|
||||
windows:
|
||||
name: Windows x64(NSIS 安装包)
|
||||
needs: checks
|
||||
# 默认不跑:本仓库目前没有 Windows runner,跑了只会一直排队。有了机器之后
|
||||
# 在仓库变量里加 ENABLE_WINDOWS=true 就会跟着每次 push 自动跑;手动触发时
|
||||
# 勾 "构建 Windows" 也能单独跑一次。标签用 RUNNER_WINDOWS 指。
|
||||
if: >-
|
||||
${{
|
||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.windows == 'true')
|
||||
|| (github.event_name != 'workflow_dispatch' && vars.ENABLE_WINDOWS == 'true')
|
||||
}}
|
||||
# 自建 Windows runner 上要有 MSVC Build Tools(tauri 的 Rust 侧要 link.exe)、
|
||||
# WebView2 运行时(装了包的应用要它才能起窗口;打包本身不需要)与 rustup。
|
||||
# 默认就跑:windows-runner-01 在线(自报标签 windows-latest)。
|
||||
# 开关用 inputs 而不是仓库变量的原因见文件头第 4 条 —— 这个坑正是它踩出来的。
|
||||
if: ${{ github.event.inputs.windows != 'false' }}
|
||||
# 这台机器上要预装:MSVC Build Tools(tauri 的 Rust 侧要 link.exe)、WebView2
|
||||
# 运行时(装了包的应用要它才能起窗口;打包本身不需要)与 rustup。
|
||||
runs-on: ${{ vars.RUNNER_WINDOWS || 'windows-latest' }}
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
TARGET: x86_64-pc-windows-msvc
|
||||
CARGO_BUILD_TARGET: x86_64-pc-windows-msvc
|
||||
# 见文件头第 5 条:这台 runner 的 job 跑在**低完整性**(Low Mandatory Level,
|
||||
# S-1-16-4096)上,而 Windows 不允许低完整性往中完整性写 —— 用户目录全中招:
|
||||
# ~/.rustup、~/.cargo、%TEMP%、%LOCALAPPDATA% 下新建任何东西都是
|
||||
# "Access denied (os error 5)",ACL 再宽松也没用(没有 Deny ACE,是完整性
|
||||
# 级别拦的)。所以 CI 用到的每个"家目录"都挪到 runner 自己的工作目录下,
|
||||
# 那几处在 job 内的写探测里实测可写。换一台 Windows runner 时改这几行。
|
||||
RUSTUP_HOME: C:\Users\admin\runner\windows\cache\ci-rustup
|
||||
CARGO_HOME: C:\Users\admin\runner\windows\cache\ci-cargo
|
||||
# LOCALAPPDATA/APPDATA 也得改:pnpm 12 的 store 锁与 cache/state 都挂在
|
||||
# %LOCALAPPDATA% 下(报错原文:pnpm-store-operation-locks\all-stores.lock:
|
||||
# 拒绝访问),tauri 打包时下载的 NSIS 也放这儿。本机实测:把 LOCALAPPDATA
|
||||
# 指到可写目录后,pnpm 会在那里建 pnpm-cache / pnpm-state,install 正常。
|
||||
LOCALAPPDATA: C:\Users\admin\runner\windows\cache\ci-localappdata
|
||||
APPDATA: C:\Users\admin\runner\windows\cache\ci-appdata
|
||||
npm_config_cache: C:\Users\admin\runner\windows\cache\ci-npm
|
||||
RUNNER_TOOL_CACHE: C:\Users\admin\runner\windows\cache\ci-toolcache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# 宿主模式的 Windows runner 上,PATH 里的 `bash` 是 C:\Windows\System32\bash.exe
|
||||
# —— WSL 的启动器,而 WSL 在 runner 账户下起不来,报 E_ACCESSDENIED(日志里是
|
||||
# 一串 GBK 被当 UTF-8 解出来的乱码 + https://github.com/microsoft/WSL/issues)。
|
||||
# 于是任何 `shell: bash` 的步骤、以及用 bash 写的 composite action
|
||||
# (dtolnay/rust-toolchain 就是),都会在 0 秒内失败。
|
||||
# Git for Windows 自带 bash,把它的 bin 前置到 PATH —— GITHUB_PATH 的语义就是
|
||||
# **前置**插入,所以它会盖过 System32 那个 —— 后面这些步骤才跑得起来。
|
||||
#
|
||||
# 换掉 bash 之后还有第二个坑:这个 job 的环境里 TEMP/TMP 是空的,而 Git Bash 的
|
||||
# /tmp 是从 TEMP 推出来的;没有 TEMP 它会退回 <Git 安装目录>\tmp
|
||||
# (C:\Program Files\Git\tmp),那个目录普通权限写不进去,于是 dtolnay 里那句
|
||||
# log=$(mktemp) 直接挂掉:
|
||||
# mktemp: failed to create file via template '/tmp/tmp.XXXXXXXXXX': Permission denied
|
||||
# 所以顺手给 job 指定一个自己建的可写目录(workspace 的同级 ci-tmp)。
|
||||
# 两个坑都是 2026-10-15 真跑 Windows job 时踩出来的,本地按这样改完后
|
||||
# mktemp、rustup toolchain install、rustup target add 全部正常。
|
||||
- name: 让 bash 指向 Git for Windows,并给 job 一个可写的临时目录
|
||||
shell: pwsh
|
||||
run: |
|
||||
if (-not $env:GITHUB_PATH) { throw '这个 runner 没提供 GITHUB_PATH,没法给后续步骤改 PATH' }
|
||||
if (-not $env:GITHUB_ENV) { throw '这个 runner 没提供 GITHUB_ENV,没法给后续步骤加变量' }
|
||||
if (-not $env:GITHUB_WORKSPACE) { throw '这个 runner 没提供 GITHUB_WORKSPACE' }
|
||||
|
||||
$gitBash = 'C:\Program Files\Git\bin'
|
||||
if (-not (Test-Path (Join-Path $gitBash 'bash.exe'))) {
|
||||
throw "找不到 $gitBash\bash.exe:这台机器上没装 Git for Windows,bash 会落到 WSL 上"
|
||||
}
|
||||
Add-Content -Path $env:GITHUB_PATH -Value $gitBash -Encoding ascii
|
||||
|
||||
$tmpRoot = Join-Path (Split-Path -Parent $env:GITHUB_WORKSPACE) 'ci-tmp'
|
||||
New-Item -ItemType Directory -Force -Path $tmpRoot | Out-Null
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "TEMP=$tmpRoot" -Encoding ascii
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "TMP=$tmpRoot" -Encoding ascii
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "TMPDIR=$($tmpRoot -replace '\\', '/')" -Encoding ascii
|
||||
|
||||
# 第三个坑:pnpm 的 store 操作锁是按 <USERPROFILE>\AppData\Local\
|
||||
# pnpm-store-operation-locks 算的 —— 实测只把 LOCALAPPDATA 指走它不跟,
|
||||
# 只把 USERPROFILE 指走它就跟着走(换完 USERPROFILE 后探针目录里立刻出现
|
||||
# all-stores.lock)。所以 USERPROFILE 也得指到能写的地方,并且先把
|
||||
# AppData\Local、AppData\Roaming 建好。
|
||||
$profileRoot = Join-Path (Split-Path -Parent $env:GITHUB_WORKSPACE) 'ci-profile'
|
||||
New-Item -ItemType Directory -Force -Path (Join-Path $profileRoot 'AppData\Local'), (Join-Path $profileRoot 'AppData\Roaming') | Out-Null
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "USERPROFILE=$profileRoot" -Encoding ascii
|
||||
|
||||
"bash = $(Join-Path $gitBash 'bash.exe')"
|
||||
"TEMP/TMP/TMPDIR = $tmpRoot"
|
||||
"USERPROFILE = $profileRoot"
|
||||
|
||||
- name: 装 Rust(stable)
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: x86_64-pc-windows-msvc
|
||||
|
||||
- name: 装 pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
|
||||
- name: 装 Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: pnpm
|
||||
cache-dependency-path: desktop/pnpm-lock.yaml
|
||||
|
||||
# 这里**不用** pnpm/action-setup:它装的是 standalone 的 pnpm 二进制,而那个
|
||||
# 二进制在这台 runner 的低完整性沙箱里走到"把包装进 virtual store"时必崩:
|
||||
# thread '<unknown>' (6716) has overflowed its stack
|
||||
# corepack 拉下来的是同一个二进制(也崩),所以改成用 npm 装 JS 版 pnpm ——
|
||||
# 它跑在 node 上,是另一条代码路径。装到 node 自己的目录里(RUNNER_TOOL_CACHE
|
||||
# 已经指到可写位置,见 job env)。
|
||||
- name: 装 pnpm(npm 装 JS 版,绕开 standalone 二进制)
|
||||
shell: pwsh
|
||||
run: |
|
||||
# 前面几次尝试在 node 目录里留下过 pnpm/pnpx 的影子文件,npm 会以
|
||||
# EEXIST 拒绝覆盖,先清掉(node 目录在 RUNNER_TOOL_CACHE 下,可写)。
|
||||
$nodeDir = Split-Path (Get-Command node).Source
|
||||
foreach ($n in 'pnpm', 'pnpx', 'pnpm.cmd', 'pnpx.cmd', 'pnpm.ps1', 'pnpx.ps1') {
|
||||
Remove-Item (Join-Path $nodeDir $n) -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
npm install -g pnpm@12.8.1
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm 装 pnpm 失败(exit $LASTEXITCODE)" }
|
||||
"pnpm = $((Get-Command pnpm).Source)"
|
||||
pnpm --version
|
||||
|
||||
- name: 前端依赖(严格按 lock 装)
|
||||
working-directory: desktop
|
||||
run: pnpm install --frozen-lockfile
|
||||
shell: pwsh
|
||||
# 这台 runner 的 job 跑在低完整性沙箱里(见文件头第 5 条),standalone 的
|
||||
# pnpm 到"把包装进 virtual store"那一步会直接栈溢出:
|
||||
# thread '<unknown>' (6716) has overflowed its stack
|
||||
# (store 已经在可写目录、也改成 copy 导入了,仍然复现;同样的命令在普通
|
||||
# Medium 会话里跑得好好的。)所以先试 standalone,崩了就退回 corepack:
|
||||
# 让 node 去跑 pnpm 的 JS 实现,绕开那个二进制。
|
||||
run: |
|
||||
$pnpmArgs = @('install', '--frozen-lockfile',
|
||||
'--store-dir', 'C:\Users\admin\runner\windows\cache\ps',
|
||||
'--package-import-method=copy', '--reporter=append-only')
|
||||
pnpm @pnpmArgs
|
||||
if ($LASTEXITCODE -eq 0) { exit 0 }
|
||||
"::warning::standalone pnpm 失败(exit $LASTEXITCODE),改用 corepack + node 跑 pnpm"
|
||||
corepack enable
|
||||
corepack prepare pnpm@12.8.1 --activate
|
||||
pnpm @pnpmArgs
|
||||
exit $LASTEXITCODE
|
||||
|
||||
- name: cargo 缓存
|
||||
uses: actions/cache@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('protocol/Cargo.lock', 'desktop/core/Cargo.lock', 'desktop/src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
# nsis 是纯安装包,不需要 WiX;tauri 会自己把 NSIS 下到用户缓存里,所以
|
||||
# 这台 runner 要能访问 GitHub(离线环境改成 --bundles msi 也一样要下 WiX)。
|
||||
# nsis 是纯安装包,不需要 WiX;tauri 会自己把 NSIS 下到用户缓存里(这个缓存
|
||||
# 也跟着 LOCALAPPDATA 走,见上面 job env),所以这台 runner 要能访问 GitHub
|
||||
# (离线环境改成 --bundles msi 也一样要下 WiX)。
|
||||
- name: 打包(tauri build)
|
||||
working-directory: desktop
|
||||
run: pnpm tauri build --target ${{ env.TARGET }} --bundles nsis
|
||||
|
||||
- name: 上传产物
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cam-desktop-windows-x64
|
||||
if-no-files-found: error
|
||||
@@ -393,14 +494,10 @@ jobs:
|
||||
macos:
|
||||
name: macOS 通用(.app + .dmg)
|
||||
needs: checks
|
||||
# 同 Windows:默认不跑,有机器之后设仓库变量 ENABLE_MACOS=true,标签用
|
||||
# RUNNER_MACOS 指。
|
||||
if: >-
|
||||
${{
|
||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.macos == 'true')
|
||||
|| (github.event_name != 'workflow_dispatch' && vars.ENABLE_MACOS == 'true')
|
||||
}}
|
||||
# 自建 macOS runner 上要有 Xcode Command Line Tools(链接要它)与 rustup。
|
||||
# 还没有 macOS runner,所以只有"手动触发 + 勾上"才跑;等机器注册好,把这一行
|
||||
# 换成 `github.event.inputs.macos != 'false'` 就变成默认跑(同 Windows)。
|
||||
if: ${{ github.event.inputs.macos == 'true' }}
|
||||
# 那台机器上要有 Xcode Command Line Tools(链接要它)与 rustup。
|
||||
runs-on: ${{ vars.RUNNER_MACOS || 'macos-latest' }}
|
||||
timeout-minutes: 150
|
||||
env:
|
||||
@@ -426,25 +523,11 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: pnpm
|
||||
cache-dependency-path: desktop/pnpm-lock.yaml
|
||||
|
||||
- name: 前端依赖(严格按 lock 装)
|
||||
working-directory: desktop
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: cargo 缓存
|
||||
uses: actions/cache@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('protocol/Cargo.lock', 'desktop/core/Cargo.lock', 'desktop/src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
# 只想要当前架构、想省一半编译时间的话,把 --target 换成 aarch64-apple-darwin
|
||||
# (Apple Silicon 的 runner)并去掉上面 targets 里的 x86_64 即可。
|
||||
- name: 打包(tauri build)
|
||||
@@ -454,7 +537,7 @@ jobs:
|
||||
# 第二行是兜底:不同 tauri-cli 版本给通用包放的目录略有差异,宁可多写一行,
|
||||
# 也不要上传时静默少东西。(注意 path 是块标量,里面写 # 是路径不是注释。)
|
||||
- name: 上传产物
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cam-desktop-macos-universal
|
||||
if-no-files-found: error
|
||||
|
||||
Reference in New Issue
Block a user