chore: prep v0.5.3 release

This commit is contained in:
2026-03-08 22:08:46 -07:00
parent 7b5ab3294d
commit 2e59c21078
9 changed files with 249 additions and 121 deletions

View File

@@ -10,7 +10,6 @@ concurrency:
cancel-in-progress: false
permissions:
actions: read
contents: write
jobs:
@@ -220,27 +219,6 @@ jobs:
restore-keys: |
${{ runner.os }}-bun-
- name: Validate Windows signing secrets
shell: bash
run: |
missing=0
for name in SIGNPATH_API_TOKEN SIGNPATH_ORGANIZATION_ID SIGNPATH_PROJECT_SLUG SIGNPATH_SIGNING_POLICY_SLUG SIGNPATH_ARTIFACT_CONFIGURATION_SLUG; do
if [ -z "${!name}" ]; then
echo "Missing required secret: $name"
missing=1
fi
done
if [ "$missing" -ne 0 ]; then
echo "Set the SignPath Windows signing secrets and rerun."
exit 1
fi
env:
SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
SIGNPATH_ORGANIZATION_ID: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
SIGNPATH_PROJECT_SLUG: ${{ secrets.SIGNPATH_PROJECT_SLUG }}
SIGNPATH_SIGNING_POLICY_SLUG: ${{ secrets.SIGNPATH_SIGNING_POLICY_SLUG }}
SIGNPATH_ARTIFACT_CONFIGURATION_SLUG: ${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}
- name: Install dependencies
run: bun install --frozen-lockfile
@@ -252,99 +230,17 @@ jobs:
bun run build
- name: Build unsigned Windows artifacts
run: bun run build:win
run: bun run build:win:unsigned
- name: Upload unsigned Windows artifact for SignPath
id: upload-unsigned-windows-artifact
- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: unsigned-windows
name: windows
path: |
release/*.exe
release/*.zip
if-no-files-found: error
- name: Submit Windows signing request (attempt 1)
id: signpath-sign-attempt-1
continue-on-error: true
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
project-slug: ${{ secrets.SIGNPATH_PROJECT_SLUG }}
signing-policy-slug: ${{ secrets.SIGNPATH_SIGNING_POLICY_SLUG }}
artifact-configuration-slug: ${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}
github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: signed-windows-attempt-1
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Submit Windows signing request (attempt 2)
id: signpath-sign-attempt-2
if: steps.signpath-sign-attempt-1.outcome == 'failure'
continue-on-error: true
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
project-slug: ${{ secrets.SIGNPATH_PROJECT_SLUG }}
signing-policy-slug: ${{ secrets.SIGNPATH_SIGNING_POLICY_SLUG }}
artifact-configuration-slug: ${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}
github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: signed-windows-attempt-2
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Submit Windows signing request (attempt 3)
id: signpath-sign-attempt-3
if: steps.signpath-sign-attempt-1.outcome == 'failure' && steps.signpath-sign-attempt-2.outcome == 'failure'
continue-on-error: true
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
project-slug: ${{ secrets.SIGNPATH_PROJECT_SLUG }}
signing-policy-slug: ${{ secrets.SIGNPATH_SIGNING_POLICY_SLUG }}
artifact-configuration-slug: ${{ secrets.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}
github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: signed-windows-attempt-3
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Fail when all SignPath signing attempts fail
if: steps.signpath-sign-attempt-1.outcome == 'failure' && steps.signpath-sign-attempt-2.outcome == 'failure' && steps.signpath-sign-attempt-3.outcome == 'failure'
shell: bash
run: |
echo "All SignPath signing attempts failed; rerun the workflow when SignPath is healthy."
exit 1
- name: Upload signed Windows artifacts (attempt 1)
if: steps.signpath-sign-attempt-1.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: windows
path: |
signed-windows-attempt-1/*.exe
signed-windows-attempt-1/*.zip
- name: Upload signed Windows artifacts (attempt 2)
if: steps.signpath-sign-attempt-2.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: windows
path: |
signed-windows-attempt-2/*.exe
signed-windows-attempt-2/*.zip
- name: Upload signed Windows artifacts (attempt 3)
if: steps.signpath-sign-attempt-3.outcome == 'success'
uses: actions/upload-artifact@v4
with:
name: windows
path: |
signed-windows-attempt-3/*.exe
signed-windows-attempt-3/*.zip
release:
needs: [build-linux, build-macos, build-windows]
runs-on: ubuntu-latest

View File

@@ -1,5 +1,11 @@
# Changelog
## v0.5.3 (2026-03-09)
### Changed
- Release: Publish unsigned Windows `.exe` and `.zip` artifacts directly from release CI instead of routing them through SignPath.
- Release: Added `bun run build:win:unsigned` for explicit local unsigned Windows packaging.
## v0.5.2 (2026-03-09)
### Internal

View File

@@ -0,0 +1,62 @@
---
id: TASK-138
title: Publish unsigned Windows release artifacts and add local unsigned build script
status: Done
assignee:
- codex
created_date: '2026-03-09 00:00'
updated_date: '2026-03-09 00:00'
labels:
- release
- windows
dependencies: []
references:
- .github/workflows/release.yml
- package.json
- src/release-workflow.test.ts
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Stop the tag-driven release workflow from depending on SignPath and publish unsigned Windows `.exe` and `.zip` artifacts directly. Add an explicit local `build:win:unsigned` script without changing the existing `build:win` command.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Windows release CI builds unsigned artifacts without requiring SignPath secrets.
- [x] #2 The Windows release job uploads `release/*.exe` and `release/*.zip` directly as the `windows` artifact.
- [x] #3 The repo exposes a local `build:win:unsigned` script for explicit unsigned Windows packaging.
- [x] #4 Regression coverage fails if the workflow reintroduces SignPath submission or drops the unsigned script.
<!-- AC:END -->
## Implementation Plan
<!-- SECTION:PLAN:BEGIN -->
1. Update workflow regression tests to assert unsigned Windows release behavior and the new local script.
2. Patch `package.json` to add `build:win:unsigned`.
3. Patch `.github/workflows/release.yml` to build unsigned Windows artifacts and upload them directly.
4. Add the release changelog fragment and run focused verification.
<!-- SECTION:PLAN:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Removed the Windows SignPath secret validation and submission steps from `.github/workflows/release.yml`. The Windows release job now runs `bun run build:win:unsigned` and uploads `release/*.exe` and `release/*.zip` directly as the `windows` artifact consumed by the release job.
Added `scripts/build-win-unsigned.mjs` plus the `build:win:unsigned` package script. The wrapper clears Windows code-signing environment variables and disables identity auto-discovery before invoking `electron-builder`, so release CI stays unsigned even if signing credentials are configured elsewhere.
Updated `src/release-workflow.test.ts` to assert the unsigned workflow contract and added the release changelog fragment in `changes/unsigned-windows-release-builds.md`.
<!-- SECTION:NOTES:END -->
## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Windows release CI now publishes unsigned artifacts directly and no longer depends on SignPath. Local developers also have an explicit `bun run build:win:unsigned` path for unsigned packaging without changing the existing `build:win` command.
Verification:
- `bun test src/release-workflow.test.ts`
- `bun run typecheck`
- `node --check scripts/build-win-unsigned.mjs`
<!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -0,0 +1,57 @@
---
id: TASK-139
title: Cut patch release v0.5.3 for unsigned Windows release builds
status: Done
assignee:
- codex
created_date: '2026-03-09 00:00'
updated_date: '2026-03-09 00:00'
labels:
- release
- patch
dependencies:
- TASK-138
references:
- package.json
- CHANGELOG.md
- release/release-notes.md
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Publish a patch release from the unsigned Windows release-build change by bumping the app version, generating committed changelog artifacts for `v0.5.3`, and pushing the release-prep commit.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Repository version metadata is updated to `0.5.3`.
- [x] #2 `CHANGELOG.md` and `release/release-notes.md` contain the committed `v0.5.3` section and consumed fragments are removed.
- [x] #3 New `v0.5.3` release-prep commit is pushed to `origin/main`.
<!-- AC:END -->
## Implementation Plan
<!-- SECTION:PLAN:BEGIN -->
1. Bump `package.json` from `0.5.2` to `0.5.3`.
2. Run `bun run changelog:build` so committed changelog artifacts match the new patch version.
3. Run changelog/typecheck/test verification.
4. Commit the release-prep change set and push `main`.
<!-- SECTION:PLAN:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Bumped `package.json` from `0.5.2` to `0.5.3`, ran `bun run changelog:build`, and committed the generated release artifacts. That prepended the `v0.5.3` section to `CHANGELOG.md`, regenerated `release/release-notes.md`, and removed the consumed `changes/unsigned-windows-release-builds.md` fragment.
Verification before push: `bun run changelog:lint`, `bun run changelog:check --version 0.5.3`, `bun run typecheck`, and `bun run test:fast`.
<!-- SECTION:NOTES:END -->
## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Prepared patch release `v0.5.3` so the unsigned Windows release-build change is captured in committed release metadata on `main`. Version metadata, changelog output, and release notes are aligned with the new patch version.
Validation: `bun run changelog:lint`, `bun run changelog:check --version 0.5.3`, `bun run typecheck`, `bun run test:fast`.
<!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -0,0 +1,77 @@
# Unsigned Windows Release Builds Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Publish unsigned Windows release artifacts in GitHub Actions while adding an explicit local `build:win:unsigned` script.
**Architecture:** Keep Windows packaging on `electron-builder`, but stop the release workflow from routing artifacts through SignPath. The Windows release job will build unsigned artifacts and upload them directly under the existing `windows` artifact name so the downstream release job stays stable. Local developer behavior remains unchanged except for a new explicit unsigned build script.
**Tech Stack:** GitHub Actions, Bun, Electron Builder, Node test runner
---
### Task 1: Track the workflow contract change
**Files:**
- Create: `backlog/tasks/task-138 - Publish-unsigned-Windows-release-artifacts-and-add-local-unsigned-build-script.md`
- Create: `changes/unsigned-windows-release-builds.md`
**Step 1: Write the backlog task + changelog fragment**
Document the scope: unsigned Windows release CI, new local unsigned script, no SignPath dependency.
**Step 2: Review file formatting**
Run: `sed -n '1,220p' backlog/tasks/task-138\ -\ Publish-unsigned-Windows-release-artifacts-and-add-local-unsigned-build-script.md && sed -n '1,80p' changes/unsigned-windows-release-builds.md`
Expected: task metadata matches existing backlog files; changelog fragment matches `changes/README.md` format.
### Task 2: Write failing workflow regression tests
**Files:**
- Modify: `src/release-workflow.test.ts`
**Step 1: Write the failing test**
Replace SignPath-specific workflow assertions with assertions for:
- unsigned Windows artifacts built via `bun run build:win:unsigned`
- direct `windows` artifact upload from `release/*.exe` and `release/*.zip`
- no SignPath action references
- package scripts include `build:win:unsigned`
**Step 2: Run test to verify it fails**
Run: `bun test src/release-workflow.test.ts`
Expected: FAIL because the current workflow still validates SignPath secrets and submits signing requests.
### Task 3: Patch package scripts and release workflow
**Files:**
- Modify: `package.json`
- Modify: `.github/workflows/release.yml`
**Step 1: Write minimal implementation**
- add `build:win:unsigned` that clears Windows signing env and disables auto discovery before invoking `electron-builder --win nsis zip --publish never`
- change the Windows release job to remove SignPath secret validation/submission
- build Windows artifacts with `bun run build:win:unsigned`
- upload `release/*.exe` and `release/*.zip` directly as `windows`
**Step 2: Run tests to verify they pass**
Run: `bun test src/release-workflow.test.ts`
Expected: PASS
### Task 4: Run focused verification
**Files:**
- Modify: none
**Step 1: Run focused checks**
Run: `bun test src/release-workflow.test.ts && bun run typecheck`
Expected: all green
**Step 2: Spot-check diff**
Run: `git --no-pager diff -- .github/workflows/release.yml package.json src/release-workflow.test.ts changes/unsigned-windows-release-builds.md backlog/tasks/task-138\ -\ Publish-unsigned-Windows-release-artifacts-and-add-local-unsigned-build-script.md docs/plans/2026-03-09-unsigned-windows-release-builds.md`
Expected: only scoped unsigned-Windows workflow/script/docs changes

View File

@@ -1,6 +1,6 @@
{
"name": "subminer",
"version": "0.5.2",
"version": "0.5.3",
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
"packageManager": "bun@1.3.5",
"main": "dist/main-entry.js",
@@ -60,7 +60,8 @@
"build:mac": "bun run build && electron-builder --mac dmg zip --publish never",
"build:mac:unsigned": "bun run build && env -u APPLE_ID -u APPLE_APP_SPECIFIC_PASSWORD -u APPLE_TEAM_ID -u CSC_LINK -u CSC_KEY_PASSWORD CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac dmg zip --publish never",
"build:mac:zip": "bun run build && electron-builder --mac zip --publish never",
"build:win": "bun run build && electron-builder --win nsis zip --publish never"
"build:win": "bun run build && electron-builder --win nsis zip --publish never",
"build:win:unsigned": "bun run build && node scripts/build-win-unsigned.mjs"
},
"keywords": [
"anki",

View File

@@ -1,6 +1,7 @@
## Highlights
### Internal
- Release: Pinned the Windows SignPath submission workflow to an explicit artifact-configuration slug instead of relying on the SignPath project's default configuration.
### Changed
- Release: Publish unsigned Windows `.exe` and `.zip` artifacts directly from release CI instead of routing them through SignPath.
- Release: Added `bun run build:win:unsigned` for explicit local unsigned Windows packaging.
## Installation

View File

@@ -0,0 +1,30 @@
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
const env = { ...process.env };
for (const name of [
'CSC_LINK',
'CSC_KEY_PASSWORD',
'WIN_CSC_LINK',
'WIN_CSC_KEY_PASSWORD',
'CSC_NAME',
'WIN_CSC_NAME',
]) {
delete env[name];
}
env.CSC_IDENTITY_AUTO_DISCOVERY = 'false';
const electronBuilderCli = fileURLToPath(new URL('../node_modules/electron-builder/out/cli/cli.js', import.meta.url));
const result = spawnSync(process.execPath, [electronBuilderCli, '--win', 'nsis', 'zip', '--publish', 'never'], {
stdio: 'inherit',
env,
});
if (result.error) {
throw result.error;
}
process.exit(result.status ?? 1);

View File

@@ -38,18 +38,16 @@ test('release package scripts disable implicit electron-builder publishing', ()
assert.match(packageJson.scripts['build:appimage'] ?? '', /--publish never/);
assert.match(packageJson.scripts['build:mac'] ?? '', /--publish never/);
assert.match(packageJson.scripts['build:win'] ?? '', /--publish never/);
assert.match(packageJson.scripts['build:win:unsigned'] ?? '', /build-win-unsigned\.mjs/);
});
test('windows release workflow retries SignPath submission and fails only after exhausting attempts', () => {
assert.match(releaseWorkflow, /Submit Windows signing request \(attempt 1\)/);
assert.match(releaseWorkflow, /Submit Windows signing request \(attempt 2\)/);
assert.match(releaseWorkflow, /Submit Windows signing request \(attempt 3\)/);
assert.match(releaseWorkflow, /All SignPath signing attempts failed; rerun the workflow when SignPath is healthy\./);
});
test('windows release workflow pins the SignPath artifact configuration slug explicitly', () => {
assert.match(releaseWorkflow, /SIGNPATH_ARTIFACT_CONFIGURATION_SLUG/);
assert.match(releaseWorkflow, /artifact-configuration-slug: \$\{\{ secrets\.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG \}\}/);
test('windows release workflow publishes unsigned artifacts directly without SignPath', () => {
assert.match(releaseWorkflow, /Build unsigned Windows artifacts/);
assert.match(releaseWorkflow, /run: bun run build:win:unsigned/);
assert.match(releaseWorkflow, /name: windows/);
assert.match(releaseWorkflow, /path: \|\n\s+release\/\*\.exe\n\s+release\/\*\.zip/);
assert.ok(!releaseWorkflow.includes('signpath/github-action-submit-signing-request'));
assert.ok(!releaseWorkflow.includes('SIGNPATH_'));
});
test('Makefile routes Windows install-plugin setup through bun and documents Windows builds', () => {