Skip to content

Commit 32c99b5

Browse files
authored
Recover release workflow (#14)
1 parent 307944f commit 32c99b5

9 files changed

Lines changed: 102 additions & 40 deletions

File tree

.github/workflows/release.yml

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,13 @@ jobs:
8888
retention-days: 7
8989

9090
build:
91-
name: Build signed ${{ matrix.name }} installer
91+
name: Build ${{ matrix.name }} installer
9292
needs: validate
9393
runs-on: ${{ matrix.os }}
9494
timeout-minutes: 60
95+
env:
96+
WINDOWS_SIGNING_AVAILABLE: ${{ secrets.WINDOWS_CERTIFICATE != '' && secrets.WINDOWS_CERTIFICATE_PASSWORD != '' }}
97+
APPLE_SIGNING_AVAILABLE: ${{ secrets.APPLE_CERTIFICATE != '' && secrets.APPLE_CERTIFICATE_PASSWORD != '' && secrets.APPLE_SIGNING_IDENTITY != '' && secrets.APPLE_ID != '' && secrets.APPLE_PASSWORD != '' && secrets.APPLE_TEAM_ID != '' }}
9598
strategy:
9699
fail-fast: false
97100
matrix:
@@ -126,7 +129,8 @@ jobs:
126129
patchelf \
127130
libudev-dev \
128131
dbus-x11 \
129-
xvfb
132+
xvfb \
133+
webkit2gtk-driver
130134
131135
- name: Setup pnpm
132136
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5
@@ -147,7 +151,7 @@ jobs:
147151
run: pnpm install --frozen-lockfile
148152

149153
- name: Import Windows signing certificate
150-
if: runner.os == 'Windows'
154+
if: runner.os == 'Windows' && env.WINDOWS_SIGNING_AVAILABLE == 'true'
151155
shell: pwsh
152156
env:
153157
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -165,7 +169,7 @@ jobs:
165169
"WINDOWS_CERTIFICATE_THUMBPRINT=$($cert.Thumbprint)" >> $env:GITHUB_ENV
166170
167171
- name: Verify Apple signing and notarization secrets
168-
if: runner.os == 'macOS'
172+
if: runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE == 'true'
169173
shell: bash
170174
env:
171175
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
@@ -180,23 +184,34 @@ jobs:
180184
test -n "${!name}" || { echo "$name is required" >&2; exit 1; }
181185
done
182186
183-
- name: Build signed Windows NSIS installer
187+
- name: Report unsigned platform fallback
188+
if: >-
189+
(runner.os == 'Windows' && env.WINDOWS_SIGNING_AVAILABLE != 'true') ||
190+
(runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE != 'true')
191+
shell: bash
192+
run: echo "::warning::Platform signing secrets are not configured; this installer will be explicitly marked unsigned."
193+
194+
- name: Build Windows NSIS installer
184195
if: runner.os == 'Windows'
185196
shell: pwsh
186197
run: |
187-
$config = @{
188-
bundle = @{
189-
windows = @{
190-
certificateThumbprint = $env:WINDOWS_CERTIFICATE_THUMBPRINT
191-
digestAlgorithm = 'sha256'
192-
timestampUrl = 'http://timestamp.digicert.com'
198+
if ($env:WINDOWS_SIGNING_AVAILABLE -eq 'true') {
199+
$config = @{
200+
bundle = @{
201+
windows = @{
202+
certificateThumbprint = $env:WINDOWS_CERTIFICATE_THUMBPRINT
203+
digestAlgorithm = 'sha256'
204+
timestampUrl = 'http://timestamp.digicert.com'
205+
}
193206
}
194-
}
195-
} | ConvertTo-Json -Compress -Depth 5
196-
pnpm tauri:build --target ${{ matrix.target }} --bundles nsis --config $config
207+
} | ConvertTo-Json -Compress -Depth 5
208+
pnpm tauri:build --target ${{ matrix.target }} --bundles nsis --config $config
209+
} else {
210+
pnpm tauri:build --target ${{ matrix.target }} --bundles nsis
211+
}
197212
198213
- name: Build signed and notarized macOS DMG
199-
if: runner.os == 'macOS'
214+
if: runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE == 'true'
200215
env:
201216
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
202217
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -206,6 +221,10 @@ jobs:
206221
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
207222
run: pnpm tauri:build --target ${{ matrix.target }} --bundles dmg
208223

224+
- name: Build unsigned macOS DMG
225+
if: runner.os == 'macOS' && env.APPLE_SIGNING_AVAILABLE != 'true'
226+
run: pnpm tauri:build --target ${{ matrix.target }} --bundles dmg
227+
209228
- name: Build Linux AppImage and deb installers
210229
if: runner.os == 'Linux'
211230
run: pnpm tauri:build --target ${{ matrix.target }} --bundles appimage,deb
@@ -229,8 +248,15 @@ jobs:
229248
New-Item -ItemType Directory -Force release-assets | Out-Null
230249
$installers = Get-ChildItem 'target/${{ matrix.target }}/release/bundle/nsis/*.exe'
231250
if ($installers.Count -ne 1) { throw "expected one NSIS installer, found $($installers.Count)" }
232-
$signature = Get-AuthenticodeSignature $installers[0].FullName
233-
if ($signature.Status -ne 'Valid') { throw "invalid Authenticode signature: $($signature.Status)" }
251+
if ($env:WINDOWS_SIGNING_AVAILABLE -eq 'true') {
252+
$signature = Get-AuthenticodeSignature $installers[0].FullName
253+
if ($signature.Status -ne 'Valid') { throw "invalid Authenticode signature: $($signature.Status)" }
254+
'- Windows NSIS: Authenticode signed and verified.' |
255+
Set-Content release-assets/windows-signing-status.txt
256+
} else {
257+
'- Windows NSIS: unsigned (signing secrets were not configured).' |
258+
Set-Content release-assets/windows-signing-status.txt
259+
}
234260
235261
$installRoot = Join-Path $env:RUNNER_TEMP 'bbcom-smoke'
236262
Start-Process -FilePath $installers[0].FullName -ArgumentList '/S', "/D=$installRoot" -Wait
@@ -261,8 +287,16 @@ jobs:
261287
dmg=(target/${{ matrix.target }}/release/bundle/dmg/*.dmg)
262288
test "${#app[@]}" -eq 1
263289
test "${#dmg[@]}" -eq 1
264-
codesign --verify --deep --strict --verbose=2 "${app[0]}"
265-
xcrun stapler validate "${dmg[0]}"
290+
mkdir -p release-assets
291+
if [[ "$APPLE_SIGNING_AVAILABLE" == 'true' ]]; then
292+
codesign --verify --deep --strict --verbose=2 "${app[0]}"
293+
xcrun stapler validate "${dmg[0]}"
294+
echo '- macOS DMG: Developer ID signed and notarized.' \
295+
> release-assets/macos-signing-status.txt
296+
else
297+
echo '- macOS DMG: unsigned and not notarized (signing secrets were not configured).' \
298+
> release-assets/macos-signing-status.txt
299+
fi
266300
267301
mount_dir="$RUNNER_TEMP/bbcom-dmg"
268302
install_dir="$RUNNER_TEMP/bbcom-smoke-applications"
@@ -309,7 +343,6 @@ jobs:
309343
test ! -e "$installed_app"
310344
hdiutil detach "$mount_dir"
311345
rm -rf "$mount_dir"
312-
mkdir -p release-assets
313346
cp "${dmg[0]}" release-assets/
314347
315348
- name: Verify, launch, and uninstall Linux installers
@@ -350,6 +383,8 @@ jobs:
350383
test "$(dpkg-query -W -f='${db:Status-Status}' "$package" 2>/dev/null || true)" != installed
351384
mkdir -p release-assets
352385
cp "${appimage[0]}" "${deb[0]}" release-assets/
386+
echo '- Linux AppImage/deb: Sigstore keyless bundles are attached by the release job.' \
387+
> release-assets/linux-signing-status.txt
353388
354389
- name: Upload installer
355390
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
@@ -387,11 +422,13 @@ jobs:
387422
appimage=(release/*.AppImage)
388423
deb=(release/*.deb)
389424
sbom=(release/*.cdx.json)
425+
signing_status=(release/*-signing-status.txt)
390426
test "${#nsis[@]}" -eq 1
391427
test "${#dmg[@]}" -eq 1
392428
test "${#appimage[@]}" -eq 1
393429
test "${#deb[@]}" -eq 1
394430
test "${#sbom[@]}" -eq 1
431+
test "${#signing_status[@]}" -eq 3
395432
test -f release/frontend-licenses.json
396433
test -f release/rust-licenses.json
397434
@@ -410,17 +447,24 @@ jobs:
410447
run: |
411448
(
412449
cd release
450+
checksum_tmp="../SHA256SUMS.tmp"
413451
find . -maxdepth 1 -type f ! -name SHA256SUMS -print0 \
414452
| sort -z \
415453
| xargs -0 sha256sum \
416-
| sed 's# \./# #' > SHA256SUMS
454+
| sed 's# \./# #' > "$checksum_tmp"
455+
mv "$checksum_tmp" SHA256SUMS
417456
)
418457
version="${GITHUB_REF_NAME#v}"
419458
awk -v heading="## [$version]" '
420459
index($0, heading) == 1 { found=1; next }
421460
found && /^## \[/ { exit }
422461
found { print }
423462
' CHANGELOG.md > release-notes.md
463+
{
464+
echo
465+
echo '## Artifact signing status'
466+
cat release/*-signing-status.txt
467+
} >> release-notes.md
424468
test -s release-notes.md
425469
426470
- name: Attest release artifacts

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to bbcom are documented here. The format is based on
55

66
## [Unreleased]
77

8+
## [0.7.1] - 2026-07-11
9+
10+
### Release workflow recovery
11+
12+
- Installed the WebKit WebDriver required by Tauri's native Linux smoke test.
13+
- Made Windows Authenticode and Apple signing/notarization conditional on the
14+
complete platform secret set, while retaining unsigned installer builds when
15+
those credentials are unavailable.
16+
- Added per-platform signing-status manifests to release assets and draft notes
17+
so unsigned fallbacks are explicit and auditable. Linux installers continue
18+
to receive Sigstore keyless bundles and GitHub provenance attestations.
19+
820
## [0.7.0] - 2026-07-11
921

1022
### Z.ai client API migration

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ sessions, checksums, OS credential storage, and bounded AI client calls.
5353
with model validation, request limits/cancellation, role-separated prompts,
5454
and risk classification.
5555
- **Desktop polish** with dark/light themes, English/Chinese UI catalogs,
56-
persisted settings, keyboard shortcuts, and signed installer releases.
56+
persisted settings, keyboard shortcuts, and installer releases with explicit
57+
per-platform signing status.
5758

5859
## Screenshots
5960

@@ -249,11 +250,12 @@ commit, it rejects unstaged or non-ignored untracked files. Do not use
249250
`--no-verify` to bypass it.
250251

251252
GitHub Actions is intentionally release-only: it runs after an exact
252-
`vX.Y.Z` tag and performs signed, three-platform release assembly and smoke
253-
verification rather than repeating local PR checks.
253+
`vX.Y.Z` tag and performs three-platform release assembly and smoke verification
254+
rather than repeating local PR checks. Windows and macOS platform signing is
255+
enabled when the corresponding complete secret set is configured.
254256

255-
Tags matching `vX.Y.Z` produce a draft release containing signed Windows NSIS
256-
and notarized macOS arm64 DMG installers, Linux AppImage/deb packages,
257+
Tags matching `vX.Y.Z` produce a draft release containing Windows NSIS, macOS
258+
arm64 DMG, Linux AppImage/deb packages, explicit signing-status manifests,
257259
SHA-256 checksums, a CycloneDX SBOM, license inventories, Sigstore bundles, and
258260
GitHub build provenance. No automatic updater is shipped in v0.5.0.
259261

README.zh-CN.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
- **AI 助手**:Linux/BusyBox 命令生成与串口日志分析,包含模型校验、
4848
请求限制/取消、角色隔离提示词和风险分级。
4949
- **桌面体验**:深色/浅色主题、中英文界面、本地设置持久化、快捷键
50-
和签名安装包发布
50+
和带明确平台签名状态的安装包发布
5151

5252
## 截图
5353

@@ -236,12 +236,13 @@ P0 覆盖率、browser mock E2E、架构检查、审计、Rust fmt/Clippy/test/l
236236
`cargo-llvm-cov``cargo-audit` 版本。为确保校验对象正是将要提交的 index,
237237
hook 会拒绝未暂存或非忽略的未跟踪文件;请勿使用 `--no-verify` 绕过它。
238238

239-
GitHub Actions 仅承担 release:精确 `vX.Y.Z` 标签触发后执行三平台签名打包与
240-
smoke 验证,不再重复运行本地 PR 检查。
239+
GitHub Actions 仅承担 release:精确 `vX.Y.Z` 标签触发后执行三平台打包与
240+
smoke 验证,不再重复运行本地 PR 检查。Windows 与 macOS 在完整签名 Secret
241+
已经配置时启用平台签名。
241242

242-
`vX.Y.Z` 标签会生成草稿 release,其中包含已签名 Windows NSIS、已签名并
243-
公证的 macOS arm64 DMG、Linux AppImage/deb、SHA-256、CycloneDX SBOM、
244-
许可证清单、Sigstore bundle 和 GitHub 构建来源证明。v0.5.0 不提供自动更新器。
243+
`vX.Y.Z` 标签会生成草稿 release,其中包含 Windows NSIS、macOS arm64 DMG、
244+
Linux AppImage/deb、明确的签名状态清单、SHA-256、CycloneDX SBOM、许可证
245+
清单、Sigstore bundle 和 GitHub 构建来源证明。v0.5.0 不提供自动更新器。
245246

246247
`pnpm install` 会自动安装 hook。提交 PR 前,如本次提交尚未运行门禁,请手动
247248
执行同一命令:

RELEASING.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
configuration must match it and the local quality gate must pass before tagging.
66

77
Only an exact `vX.Y.Z` tag whose commit is on protected `master` can start the
8-
release workflow. It creates a draft release after all three signed installer
9-
builds, checksums, SBOM, license inventories, Sigstore bundles, and provenance
10-
attestations are present. Publish the draft only after the platform smoke tests
11-
have been reviewed.
8+
release workflow. It creates a draft release after all three installer builds,
9+
checksums, SBOM, license inventories, Sigstore bundles, and provenance
10+
attestations are present. Windows Authenticode signing and Apple Developer ID
11+
signing/notarization are applied when their complete secret sets are configured;
12+
otherwise the draft and attached status manifests explicitly mark those
13+
installers unsigned. Publish the draft only after the platform smoke tests and
14+
signing-status manifests have been reviewed.
1215

1316
No updater metadata is produced or published.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "bbcom",
33
"private": true,
4-
"version": "0.7.0",
4+
"version": "0.7.1",
55
"type": "module",
66
"packageManager": "pnpm@11.11.0",
77
"engines": {

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bbcom"
3-
version = "0.7.0"
3+
version = "0.7.1"
44
description = "Serial Port Assistant"
55
edition = "2024"
66
rust-version = "1.97"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2.0.0",
33
"productName": "bbcom",
4-
"version": "0.7.0",
4+
"version": "0.7.1",
55
"identifier": "com.bbcom.app",
66
"build": {
77
"beforeDevCommand": "pnpm dev",

0 commit comments

Comments
 (0)