From 1c91a4906c0347d602330beeed594a28b8438c39 Mon Sep 17 00:00:00 2001 From: Kalvin Chau Date: Wed, 12 Aug 2026 19:09:01 -0700 Subject: [PATCH 1/5] fix(ci): bootstrap windows release build install the pinned node and pnpm toolchain used by the unsigned windows build. reuse its managed goose cargo cache and extend the release job timeout to 240 minutes. --- .github/workflows/release.yml | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96cd020d8..118a5b697 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -267,7 +267,7 @@ jobs: needs: setup if: needs.setup.outputs.staged_windows_assets_ready != 'true' runs-on: windows-latest - timeout-minutes: 120 + timeout-minutes: 240 permissions: contents: write id-token: write @@ -300,14 +300,35 @@ jobs: with: tool: just@1.40.0 - - name: Require updater public key + - name: Install pinned Node + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: 24.10.0 + + - name: Install pinned pnpm shell: pwsh run: | - if ([string]::IsNullOrWhiteSpace($env:BERD_UPDATER_PUBLIC_KEY)) { throw 'BERD_UPDATER_PUBLIC_KEY repository secret is required' } + $ErrorActionPreference = 'Stop' + corepack enable + corepack prepare pnpm@10.33.0 --activate + if ((pnpm --version) -ne '10.33.0') { throw 'pnpm 10.33.0 was not activated' } + + - name: Resolve managed Goose Cargo target + shell: pwsh + run: | + $target = Join-Path $env:LOCALAPPDATA 'berd-dev\cargo-target' + "GOOSE_DEV_CARGO_TARGET_DIR=$target" >> $env:GITHUB_ENV + + - name: Cache managed Goose Cargo target + uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + with: + path: ${{ env.GOOSE_DEV_CARGO_TARGET_DIR }} + key: goose-cargo-${{ runner.os }}-rust-1.94.1-${{ hashFiles('goose-backend.lock.json') }} - - name: Set up Windows build dependencies + - name: Require updater public key shell: pwsh - run: just setup-windows release + run: | + if ([string]::IsNullOrWhiteSpace($env:BERD_UPDATER_PUBLIC_KEY)) { throw 'BERD_UPDATER_PUBLIC_KEY repository secret is required' } - name: Generate updater-enabled Tauri configuration shell: pwsh From 06ad80d4714fd3aebbe40550dbd8cbbd215120d2 Mon Sep 17 00:00:00 2001 From: Kalvin Chau Date: Wed, 12 Aug 2026 19:15:11 -0700 Subject: [PATCH 2/5] fix(release): recover tagged builds from main load recovery workflow changes from main while checking out the requested immutable tag. serialize push and recovery runs against the same tag key. --- .github/workflows/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 118a5b697..103cf81df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: inputs: tag: - description: Existing immutable v tag to recover; select this same tag as the run ref + description: Existing immutable v tag to recover; run from main required: true type: string @@ -18,7 +18,7 @@ permissions: # incomplete platform payload before rebuilding it, so concurrent runs for the # same immutable tag would otherwise race against each other's uploads. concurrency: - group: berd-release-${{ github.ref }} + group: berd-release-${{ inputs.tag || github.ref_name }} cancel-in-progress: false env: @@ -47,7 +47,7 @@ jobs: - name: Check out requested immutable ref uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: - ref: ${{ github.ref }} + ref: ${{ inputs.tag || github.ref }} fetch-depth: 0 persist-credentials: false @@ -70,8 +70,8 @@ jobs: echo "::error::Expected an existing v tag without build metadata; got '$TAG'" exit 1 } - if [[ "$EVENT_NAME" == "workflow_dispatch" && "${GITHUB_REF:-}" != "refs/tags/$TAG" ]]; then - echo "::error::Recovery dispatch must run from refs/tags/$TAG; got '${GITHUB_REF:-}'" + if [[ "$EVENT_NAME" == "workflow_dispatch" && "${GITHUB_REF:-}" != "refs/heads/main" ]]; then + echo "::error::Recovery dispatch must use the workflow from main; got '${GITHUB_REF:-}'" exit 1 fi echo "tag=$TAG" >> "$GITHUB_OUTPUT" From b518f475a8057b08c6106a79d85d273e470b690d Mon Sep 17 00:00:00 2001 From: Kalvin Chau Date: Wed, 12 Aug 2026 19:16:56 -0700 Subject: [PATCH 3/5] fix(release): disable build caches prevent release artifacts from consuming github actions cache state. --- .github/workflows/release.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 103cf81df..064be4363 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -304,6 +304,7 @@ jobs: uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 with: node-version: 24.10.0 + package-manager-cache: false - name: Install pinned pnpm shell: pwsh @@ -313,18 +314,6 @@ jobs: corepack prepare pnpm@10.33.0 --activate if ((pnpm --version) -ne '10.33.0') { throw 'pnpm 10.33.0 was not activated' } - - name: Resolve managed Goose Cargo target - shell: pwsh - run: | - $target = Join-Path $env:LOCALAPPDATA 'berd-dev\cargo-target' - "GOOSE_DEV_CARGO_TARGET_DIR=$target" >> $env:GITHUB_ENV - - - name: Cache managed Goose Cargo target - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 - with: - path: ${{ env.GOOSE_DEV_CARGO_TARGET_DIR }} - key: goose-cargo-${{ runner.os }}-rust-1.94.1-${{ hashFiles('goose-backend.lock.json') }} - - name: Require updater public key shell: pwsh run: | From 60c6bd534f6006be60ce36f9b117a7a345d80279 Mon Sep 17 00:00:00 2001 From: Kalvin Chau Date: Wed, 12 Aug 2026 19:22:13 -0700 Subject: [PATCH 4/5] test: update release workflow assertions cover the windows bundle entrypoint and tag-keyed recovery concurrency used by the updated release workflow. --- scripts/release/tests/release-scripts.test.mjs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/release/tests/release-scripts.test.mjs b/scripts/release/tests/release-scripts.test.mjs index eea7fb7b2..37ed33f5c 100644 --- a/scripts/release/tests/release-scripts.test.mjs +++ b/scripts/release/tests/release-scripts.test.mjs @@ -88,7 +88,7 @@ describe("managed Goose build profile", () => { '$gooseBuildProfile = if ($Debug) { "debug" } else { "release" }', ); expect(bundle).toContain("$env:GOOSE_BUILD_PROFILE = $gooseBuildProfile"); - expect(workflow).toContain("run: just setup-windows release"); + expect(workflow).toContain("just bundle-windows nsis"); expect(windowsSetup).toContain( '[ValidateSet("debug", "release")][string]$GooseBuildProfile = "debug"', ); @@ -754,7 +754,9 @@ describe("desktop release workflow platform gate", () => { expect(workflow).not.toContain(`${expressionStart} env.asset_dir }}`); expect(workflow).not.toContain("release delete-asset"); expect(workflow).toContain("release-reconcile-assets"); - expect(workflow).toContain("group: berd-release-$" + "{{ github.ref }}"); + expect(workflow).toContain( + "group: berd-release-$" + "{{ inputs.tag || github.ref_name }}", + ); expect(workflow).toContain("pnpm install --frozen-lockfile"); expect(workflow).toContain("release-write-provenance"); expect(workflow).not.toContain("jq -n"); From c2aba5a6f83268144d65743d9d671e266424506b Mon Sep 17 00:00:00 2001 From: Kalvin Chau Date: Wed, 12 Aug 2026 19:45:13 -0700 Subject: [PATCH 5/5] fix(release): verify encoded updater signatures remove plaintext minisign envelope checks that reject tauri cli base64 output. rely on the existing cryptographic verifier for linux and windows updater archives. --- scripts/release/package-signed-updater-linux.sh | 4 ---- scripts/release/package-signed-updater-windows.sh | 4 ---- 2 files changed, 8 deletions(-) diff --git a/scripts/release/package-signed-updater-linux.sh b/scripts/release/package-signed-updater-linux.sh index 93ea9c447..e926640ea 100755 --- a/scripts/release/package-signed-updater-linux.sh +++ b/scripts/release/package-signed-updater-linux.sh @@ -58,10 +58,6 @@ tar -tzf "$OUTPUT_DIR/$ARCHIVE_NAME" | grep -Fxq "$APPIMAGE_NAME" ) SIGNATURE="$OUTPUT_DIR/$ARCHIVE_NAME.sig" [[ -s "$SIGNATURE" ]] || { release_error "tauri signer produced no $SIGNATURE"; exit 1; } -grep -Fq "untrusted comment: signature from minisign secret key" "$SIGNATURE" || { - release_error "tauri signer produced an invalid minisign envelope" - exit 1 -} "$REPO_ROOT/scripts/release/verify-updater-signature.sh" \ "$OUTPUT_DIR/$ARCHIVE_NAME" "$SIGNATURE" "$BERD_UPDATER_PUBLIC_KEY" unset TAURI_SIGNING_PRIVATE_KEY TAURI_SIGNING_PRIVATE_KEY_PASSWORD diff --git a/scripts/release/package-signed-updater-windows.sh b/scripts/release/package-signed-updater-windows.sh index 7541b01bf..ea90a2660 100755 --- a/scripts/release/package-signed-updater-windows.sh +++ b/scripts/release/package-signed-updater-windows.sh @@ -115,10 +115,6 @@ if [[ ! -s "$SIGNATURE" ]]; then release_error "tauri signer produced no $SIGNATURE" exit 1 fi -if ! grep -Fq "untrusted comment: signature from minisign secret key" "$SIGNATURE"; then - release_error "tauri signer produced an invalid minisign envelope" - exit 1 -fi "$REPO_ROOT/scripts/release/verify-updater-signature.sh" \ "$ARCHIVE" "$SIGNATURE" "$BERD_UPDATER_PUBLIC_KEY" unset TAURI_SIGNING_PRIVATE_KEY TAURI_SIGNING_PRIVATE_KEY_PASSWORD