Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/cd-debian13.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ on:
description: 'Set version manually (e.g. 1.2.3)'
required: false
default: ''
push:
tags:
- '*'
# 测试期注释:velopack CD 联调的测试 tag 不触发 Debian 打包,恢复时取消注释
# push:
# tags:
# - '*'

jobs:
debian13-build:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/cd-fedora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ on:
description: 'Set version manually (e.g. 1.2.3)'
required: false
default: ''
push:
tags:
- '*'
# 测试期注释:velopack CD 联调的测试 tag 不触发 Fedora 打包,恢复时取消注释
# push:
# tags:
# - '*'

jobs:
fedora-build:
Expand Down
216 changes: 203 additions & 13 deletions .github/workflows/cd_on_macos_arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ jobs:
os: [macos-14]
arch: [arm64]
runs-on: ${{ matrix.os }}
timeout-minutes: 45
# Windows CD 为 45 分钟;mac 侧多出 vpk 签名 + notarytool 公证等待
# (package.scm 时代公证单独给了 60 分钟超时),放宽到 60。
timeout-minutes: 60
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: xmake-io/github-action-setup-xmake@v1
Expand All @@ -27,30 +29,218 @@ jobs:
actions-cache-folder: '.xmake-cache'
- name: xmake repo --update
run: xmake repo --update
- name: Config and build goldfish
# Noto 字体(与 Windows CD 相同来源):原由 package.scm 内部下载,
# DMG 流程移除后必须在此落位,install 才会收进 .app 的 Resources。
- name: Noto fonts
run: |
xmake config -m release -a ${{ matrix.arch }} -vD --loro=yes --yes
xmake build goldfish-bin
ls -la TeXmacs/plugins/goldfish/bin/ || echo "goldfish bin dir not found"
- name: Package with Goldfish
mkdir -p TeXmacs/fonts/opentype/noto
cd TeXmacs/fonts/opentype/noto
curl -fsSLO https://github.com/XmacsLabs/mogan/releases/download/v1.2.9.7/NotoSansCJK-Bold.ttc
curl -fsSLO https://github.com/XmacsLabs/mogan/releases/download/v1.2.9.7/NotoSansCJK-Regular.ttc
curl -fsSLO https://github.com/XmacsLabs/mogan/releases/download/v1.2.9.7/NotoSerifCJK-Bold.ttc
curl -fsSLO https://github.com/XmacsLabs/mogan/releases/download/v1.2.9.7/NotoSerifCJK-Regular.ttc
- name: config
run: xmake config -m release -a ${{ matrix.arch }} -vD --loro=yes --yes
- name: build
run: xmake build -vD stem
- name: install
run: xmake install -vD stem
# vpk 1.2.0 的 apphost 需要 .NET 10 runtime;macos-14 arm64 镜像自带的
# dotnet 版本较旧且不在 apphost 默认搜索路径(首跑实测 You must install
# .NET)。setup-dotnet 显式装 .NET 10 并设置 DOTNET_ROOT。
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install vpk
shell: pwsh
run: |
dotnet tool install -g vpk --version 1.2.0
# pwsh 在 Unix 无 USERPROFILE,用 HOME
Add-Content -Path $env:GITHUB_PATH -Value "$($env:HOME)/.dotnet/tools"
# Apple 签名/公证 setup(mac 独有;Windows 的正式签名在 SafeNet 签名机
# 事后完成,mac 未签名 pkg 会被 Gatekeeper 直接拦截,故在 CI 内完成)。
# keychain 命令序列照搬 packages/macos/package.scm 的 setup-keychain;
# 身份名动态解析后经 VPK_SIGN_* 环境变量注入 pack_velopack.lua(见
# tools/release/pack_velopack.lua 的 mac 签名参数透传),stage 侧检测到
# VPK_SIGN_APP_IDENTITY 即跳过 ad-hoc、交给 vpk 深签。
- name: Setup Apple signing
env:
APPLE_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_CERTIFICATE_P12 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
chmod +x TeXmacs/plugins/goldfish/bin/goldfish
TeXmacs/plugins/goldfish/bin/goldfish packages/macos/package.scm
- name: Upload
set -e
KEYCHAIN="$HOME/Library/Keychains/mogan-signing.keychain-db"
KEYCHAIN_PASS="$(openssl rand -base64 32)"
CERT=/tmp/mogan_cert.p12
printf '%s' "$APPLE_CERTIFICATE_P12_BASE64" | base64 -D -o "$CERT"
security delete-keychain "$KEYCHAIN" 2>/dev/null || true
security create-keychain -p "$KEYCHAIN_PASS" "$KEYCHAIN"
security set-keychain-settings -lut 21600 "$KEYCHAIN"
security unlock-keychain -p "$KEYCHAIN_PASS" "$KEYCHAIN"
security import "$CERT" -P "$APPLE_CERTIFICATE_PASSWORD" -k "$KEYCHAIN" -T /usr/bin/codesign ||
security import "$CERT" -P "$APPLE_CERTIFICATE_PASSWORD" -k "$KEYCHAIN"
curl -fsSL -o /tmp/apple_devid_ca.cer https://www.apple.com/certificateauthority/DeveloperIDCA.cer
curl -fsSL -o /tmp/apple_devid_ca_g2.cer https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer
security add-certificates -k "$KEYCHAIN" /tmp/apple_devid_ca.cer /tmp/apple_devid_ca_g2.cer
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASS" "$KEYCHAIN"
LOGIN_KC="$HOME/Library/Keychains/login.keychain-db"
if [ -f "$LOGIN_KC" ]; then
security list-keychains -d user -s "$KEYCHAIN" "$LOGIN_KC" /Library/Keychains/System.keychain
else
security list-keychains -d user -s "$KEYCHAIN" /Library/Keychains/System.keychain
fi
security default-keychain -s "$KEYCHAIN"
# notarytool 凭据 profile(App Store Connect API key,同 package.scm)
KEY_DIR="$HOME/.appstoreconnect/private_keys"
mkdir -p "$KEY_DIR"
API_KEY="$KEY_DIR/AuthKey_${APPLE_API_KEY_ID}.p8"
printf '%s' "$APPLE_API_KEY_P8" | base64 -D -o "$API_KEY"
chmod 600 "$API_KEY"
xcrun notarytool store-credentials mogan-notary \
--key "$API_KEY" --key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_ISSUER_ID" --keychain "$KEYCHAIN"
# 身份名动态解析(P12 里证书的完整主题名因续期而变,不硬编码)
APP_IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" |
sed -n 's/.*"\(Developer ID Application:[^"]*\)".*/\1/p' | head -1)"
INSTALL_IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" |
sed -n 's/.*"\(Developer ID Installer:[^"]*\)".*/\1/p' | head -1)"
if [ -n "$APP_IDENTITY" ]; then
echo "VPK_SIGN_APP_IDENTITY=$APP_IDENTITY" >> "$GITHUB_ENV"
else
echo "::error::keychain 中未找到 Developer ID Application 证书"
exit 1
fi
# P12 可能只含 Application 证书;缺 Installer 时 vpk 跳过 .pkg 签名并
# 告警(app 仍签名),属可接受降级
if [ -n "$INSTALL_IDENTITY" ]; then
echo "VPK_SIGN_INSTALL_IDENTITY=$INSTALL_IDENTITY" >> "$GITHUB_ENV"
echo "INSTALL_IDENTITY=$INSTALL_IDENTITY"
else
echo "INSTALL_IDENTITY=(未找到 Developer ID Installer,pkg 将不签名)"
fi
echo "VPK_NOTARY_PROFILE=mogan-notary" >> "$GITHUB_ENV"
echo "VPK_KEYCHAIN=$KEYCHAIN" >> "$GITHUB_ENV"
echo "APP_IDENTITY=$APP_IDENTITY"
- name: Stage Velopack
run: xmake l tools/release/stage_velopack.lua
# 从 GitHub Release 拉取上一版本的发布压缩包作为各通道的 delta 基线:
# 逻辑与 Windows CD 一致(列 100 个 release、排除 draft 与当前 tag、
# beta 必查 + 无 -rc 才查 stable、stable 只认非 rc release、同版本跳过、
# 解 zip 取该通道 full 包拷入 build/velopack_release_<channel>/)。
# 与 Windows 的两处差异:
# 1) zip 匹配模式带 -osx-arm64 平台段——同一 release 上还有 Windows 的
# mogan-release-*-win-x64-<channel>.zip,nupkg 是平台专属的,不带
# 平台段会抓错平台基线;
# 2) 不做裸 nupkg 回退——Windows 的该回退对应其过渡期历史,mac 沿用
# 会抓到 Windows 的旧 full 包。
# 某通道首次发布(GitHub 上尚无 mac 归档 zip)时跳过属正常:没有基线
# 时 pack 只出 full 包,是合法状态。
# GITHUB_TOKEN 不会自动注入为环境变量,必须显式传入 secrets.GITHUB_TOKEN;
# 为空时回退为公开仓库的匿名访问。
- name: Fetch delta baselines from GitHub Release
shell: pwsh
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$headers = @{
Accept = "application/vnd.github+json"
"User-Agent" = "mogan-cd"
}
if ($env:GITHUB_TOKEN) {
$headers["Authorization"] = "Bearer $($env:GITHUB_TOKEN)"
}
$releases = Invoke-RestMethod -Headers $headers `
-Uri "https://api.github.com/repos/${{ github.repository }}/releases?per_page=100"
$releases = $releases |
Where-Object { -not $_.draft -and $_.tag_name -ne $env:GITHUB_REF_NAME }
# 本次要打的通道:beta 必打;stable 仅 tag 不含 -rc 时打
# (tag 名由 bump-version 流水线产生,-rc 与否即通道信息,无需透传)。
$tag = "${{ github.ref_name }}"
$channels = @("beta")
if ($tag -notmatch '-rc') { $channels += "stable" }
$vars = Get-Content xmake/vars.lua -Raw
$currentVer = [regex]::Match($vars, 'XMACS_VERSION\s*=\s*"([^"]+)"').Groups[1].Value
foreach ($channel in $channels) {
Write-Host "== 通道 $channel:查找 delta 基线 =="
foreach ($release in $releases) {
# stable 基线只认非 rc tag 的 release(rc release 无 stable 包)
if ($channel -eq "stable" -and $release.tag_name -match '-rc') {
continue
}
Remove-Item build/velopack_baseline -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path build/velopack_baseline -Force | Out-Null
# 按平台 + 通道名匹配 zip(分开上传的格式,名带平台与通道后缀,
# 只下载目标通道的归档,避免拉取无关平台的 1.5GB 包)
$zipPattern = "mogan-release-*-osx-arm64-$channel.zip"
$zip = $release.assets |
Where-Object { $_.name -like $zipPattern } |
Select-Object -First 1
if (-not $zip) { continue }
/usr/bin/curl -fsSL "$($zip.browser_download_url)" -o build/velopack_baseline.zip
Expand-Archive -Path build/velopack_baseline.zip `
-DestinationPath build/velopack_baseline -Force
$full = Get-ChildItem build/velopack_baseline -Filter "*-$channel-full.nupkg" |
Select-Object -First 1
if (-not $full) { continue }
$baselineVer = $full.Name -replace '^Mogan-', '' `
-replace "-$channel-full\.nupkg$", ''
if ($baselineVer -eq $currentVer) {
Write-Host "基线版本与当前版本相同($baselineVer),跳过(重跑同一版本)"
break
}
$outDir = "build/velopack_release_$channel"
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
Copy-Item $full.FullName $outDir/
Write-Host "已就位 $channel delta 基线: $($full.Name)"
break
}
}
# vpk pack 在 outputDir 存在上一版本(上一步拉取的 full 包)时自动生成
# delta 增量包;首次发布无上一版本,只有全量包。beta/stable 各用独立
# 输出目录(vpk 把 outputDir 当 channel 累积目录,混用会互相干扰),
# 产物文件名带 channel 后缀,最后合并进同一 release 归档。
- name: Pack Velopack (beta)
env:
VPK_CHANNEL: beta
VPK_OUTPUT_DIR: build/velopack_release_beta
run: xmake l tools/release/pack_velopack.lua
- name: Pack Velopack (stable)
if: ${{ !contains(github.ref_name, '-rc') }}
env:
VPK_CHANNEL: stable
VPK_OUTPUT_DIR: build/velopack_release_stable
run: xmake l tools/release/pack_velopack.lua
# 每个通道各自打一个 zip(Release 资产与下游 delta 基线按通道取用):
# 文件名带平台与通道后缀 mogan-release-<ver>-osx-arm64-<channel>.zip,
# 命名规则与 Windows CD 的 win-x64 归档一致。
- name: Create release archive
shell: pwsh
run: |
$vars = Get-Content xmake/vars.lua -Raw
$ver = [regex]::Match($vars, 'XMACS_VERSION\s*=\s*"([^"]+)"').Groups[1].Value
$dirs = Get-ChildItem build -Directory -Filter 'velopack_release_*' |
Sort-Object Name
foreach ($d in $dirs) {
$channel = $d.Name -replace '^velopack_release_', ''
$archive = "build/mogan-release-$ver-osx-arm64-$channel.zip"
Compress-Archive -Path "$($d.FullName)/*" -DestinationPath $archive `
-CompressionLevel Optimal -Force
Get-Item $archive | Select-Object Name, Length
}
- name: Upload
uses: actions/upload-artifact@v4
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
with:
path: build/*.dmg
path: |
build/velopack_release_*/*
build/mogan-release-*.zip
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
files: build/*.dmg
files: build/mogan-release-*.zip
19 changes: 11 additions & 8 deletions .github/workflows/cd_research_on_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ jobs:
# stable full。所有发布都标了 prerelease,releases/latest 接口拿不到,
# 这里列出最近 100 个 release,排除 draft 和当前 tag(重跑同一 tag 时
# 避免把自己当基线),按通道各自向后遍历,wget 下载对应通道的 zip。
# 压缩包分两种:新版每通道各一个 zip(mogan-release-<ver>-win-x64-
# <channel>.zip,按通道名只下载目标通道的归档);旧版是全部通道合并的
# 单一 zip(无通道后缀,兼容回退)。解压拣出对应通道的 full 包
# 压缩包分两种:新版每平台每通道各一个 zip(mogan-release-<ver>-
# <platform>-<channel>.zip,按平台与通道名匹配归档——mac CD 会向同一
# release 上传 osx-arm64 归档,nupkg 是平台专属的,不带平台段会抓错
# 基线);旧版是全部通道合并的单一 zip(无通道后缀,仅 Windows 时代
# 存在,兼容回退)。解压拣出对应通道的 full 包
# (stable 需逐个 release 尝试:rc tag 的 zip 里没有 stable 包,自然
# 跳过)。某通道首次发布或 GitHub 上尚无压缩包时跳过属正常(没有基线
# 时 pack 只出 full 包,是合法状态)。
Expand Down Expand Up @@ -116,16 +118,17 @@ jobs:
}
Remove-Item build/velopack_baseline -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path build/velopack_baseline -Force | Out-Null
# 优先按通道名匹配 zip(分开上传的新格式,名带通道后缀,
# 只下载目标通道的归档,避免拉取无关通道的 1.5GB 包);找不到
# 再回退旧合并 zip(无通道后缀,内含全部通道的包)。
$zipPattern = if ($channel -eq "beta") { '*beta*.zip' } else { '*stable*.zip' }
# 按平台 + 通道名匹配 zip(分开上传的新格式,名带平台与通道
# 后缀,只下载目标通道的归档,避免拉取无关通道/平台的 1.5GB
# 包);找不到再回退旧合并 zip(无通道后缀、仅 Windows 时代
# 存在,内含全部通道的包)。
$zipPattern = "mogan-release-*-win-x64-$channel.zip"
$zip = $release.assets |
Where-Object { $_.name -like $zipPattern } |
Select-Object -First 1
if (-not $zip) {
$zip = $release.assets |
Where-Object { $_.name -like 'mogan-release-*.zip' } |
Where-Object { $_.name -like 'mogan-release-*-win-x64.zip' } |
Select-Object -First 1
}
if ($zip) {
Expand Down
40 changes: 35 additions & 5 deletions 3rdparty/velopack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,39 @@

许可证:MIT(见上游仓库 LICENSE)。

当前仅 vendor Windows x64 资产:
- `include/Velopack.h`、`include/Velopack.hpp`:官方 C/C++ 头文件(C++ 为 C API 的薄封装)。
- `lib/velopack_libc_win_x64_msvc.dll`:动态库本体。
- `lib/velopack_libc_win_x64_msvc.dll.lib`:MSVC 导入库。
当前 vendor 的资产:

macOS / Linux / Windows arm64 等资产后续按平台补充(zip 内其余文件未 vendor)。
- Windows x64:
- `include/Velopack.h`、`include/Velopack.hpp`:官方 C/C++ 头文件(C++ 为 C API 的薄封装)。
- `lib/velopack_libc_win_x64_msvc.dll`:动态库本体。
- `lib/velopack_libc_win_x64_msvc.dll.lib`:MSVC 导入库。
- macOS(universal x86_64 + arm64):
- `lib/libvelopack_libc.dylib`:来自 zip 内 `lib/velopack_libc_osx.dylib`,经下述三步
预处理后按 `lib` 前缀命名(见「macOS 预处理」)。`lib-static/` 下的 `.a` 未 vendor:
dylib 已预链 Rust 依赖,免去手动补 framework/link 参数。

Linux / Windows arm64 等资产后续按平台补充(zip 内其余文件未 vendor)。

## macOS 预处理

上游 dylib 直接链接会产生两个问题,vendor 时已做如下处理(复现命令):

1. 上游 install id 是 CI 构建机的绝对路径(`/Users/runner/work/...`),直接链接会把
该路径写进可执行文件的依赖表,运行时找不到库。改名 + 重写 id 为 `@rpath/`:
```bash
mv libvelopack_libc_osx.dylib libvelopack_libc.dylib # lib 前缀使 -lvelopack_libc 可解析
install_name_tool -id @rpath/libvelopack_libc.dylib libvelopack_libc.dylib
```
加载名必须与磁盘文件名一致(loader 按 install id 的文件名在各 rpath 目录查找),
故 id 带 lib 前缀,不能对齐 Windows 的无前缀 `velopack_libc.dll`。
2. `install_name_tool` 改 id 会使原有 linker-signed 签名失效,arm64 上签名损坏的
dylib 会被 AMFI 拒载,必须 ad-hoc 重签:
```bash
codesign --force --sign - --timestamp=none libvelopack_libc.dylib
```

注意:与 Windows 的改名时机不同——Windows 在安装期把 DLL 改名为
`velopack_libc.dll`(见 `xmake/targets/stem.lua`),macOS 因链接期/运行期文件名
必须与磁盘文件一致,只能在 vendor 时改好提交。

dylib 的 `LC_BUILD_VERSION` minos 为 11.0,低于应用自身要求,无兼容性约束。
Binary file added 3rdparty/velopack/lib/libvelopack_libc.dylib
Binary file not shown.
2 changes: 1 addition & 1 deletion TeXmacs/progs/texmacs/menus/preferences-widgets.scm
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@
) ;list
;; 更新通道(Stable/Beta 单选 combo):真实存储单值 update-channel,
;; 写值经 set-field 特例路由到 updater-switch-channel 的两次确认。
;; 仅 Velopack 更新器平台(Windows 安装版)显示。
;; 仅 Velopack 更新器平台(Windows / macOS arm64 安装版)显示。
(if (use-plugin-updater?)
(list (list (pref-update-channel)
"Update channel"
Expand Down
Loading
Loading