Skip to content

Migrate Windows codesigning to SignPath.io with unified build-sign-release pipeline#275

Draft
Hacksore with Copilot wants to merge 8 commits into
migrate/codesignfrom
copilot/sub-pr-253
Draft

Migrate Windows codesigning to SignPath.io with unified build-sign-release pipeline#275
Hacksore with Copilot wants to merge 8 commits into
migrate/codesignfrom
copilot/sub-pr-253

Conversation

Copilot AI commented May 8, 2026

Copy link
Copy Markdown

Replaces the old Windows codesigning flow (build → upload to draft release → download → sign → re-upload) with a linear pipeline where signing happens inside the build job. The release is created only after all builds succeed.

Pipeline structure

build-tauri (matrix: windows only for now)
  └─ all platforms: build → collect ALL artifacts into ./release-artifacts
  └─ windows only: extract .exe/.msi → upload unsigned → SignPath → replace with signed in ./release-artifacts
  └─ all platforms: upload {os}-release artifact
        ↓
create-release  (draft release created only after all builds succeed)
        ↓
upload-release  (downloads all *-release artifacts, uploads to draft release)

macOS and Linux matrix entries are commented out with a TODO: re-enable after Windows signing is verified e2e note and will be restored once the end-to-end signing flow is confirmed working.

Key changes

  • release.yaml — full pipeline rewrite:

    • Windows-only build-tauri matrix while signing is being validated (macOS/Linux commented out)
    • Triggers on pushes to both migrate/codesign and copilot/sub-pr-253 so the full pipeline can be observed on this branch without merging
    • Unified cross-platform artifact collection: a single "Collect release artifacts" step runs on all platforms via bash + node, copying every file from artifactPaths (including latest.json if generated by tauri-action) into ./release-artifacts. This is the single source of truth for artifact collection — no more separate PowerShell vs Python paths per OS.
    • Windows signing (signpath/github-action-submit-signing-request) extracts only .exe/.msi from ./release-artifacts, submits them to SignPath, then writes the signed files back in-place. All other files (.sig, .zip, latest.json) are left untouched.
    • A single "Upload {os} release artifacts" step runs for all platforms — no if: guards needed.
    • create-release now runs after all builds, eliminating the race condition in the previous design
    • New upload-release job uses actions/download-artifact@v4.1.3 (patched; previous @v4 floating tag was vulnerable to arbitrary file write via artifact extraction — CVE affecting >= 4.0.0, < 4.1.3)
    • Re-run safety: upload-release-artifacts.js lists existing release assets and deletes any matching name before uploading, so workflow re-runs on a reused draft release don't fail with already_exists
  • ci.yamlpull_request trigger disabled (only workflow_dispatch remains) while the Windows signing e2e flow is being validated; will be re-enabled after signing is confirmed working

  • scripts/actions/upload-release-artifacts.js — new script that uploads all files from ./release-artifacts/ to a release; deletes existing assets with the same name before uploading (upsert semantics); accumulates per-file errors and fails the workflow at the end rather than silently continuing; uses path.join() for safe path construction

@vercel

vercel Bot commented May 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
overlayed Ready Ready Preview, Comment May 10, 2026 5:58pm

Request Review

…job, then create release and upload

Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/604fd443-df2e-4ac5-a0e7-aba11888316b

Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com>
…fe file path construction

Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/604fd443-df2e-4ac5-a0e7-aba11888316b

Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com>
Copilot AI changed the title [WIP] Migrate to signpath.io Migrate Windows codesigning to SignPath.io with unified build-sign-release pipeline May 8, 2026
Copilot AI requested a review from Hacksore May 8, 2026 01:23
@Hacksore

Hacksore commented May 8, 2026

Copy link
Copy Markdown
Member

@copilot none of the CI actually ran it just has a ✅ and ran for less than 10s.

please make sure to only run the windows build for now so we can test singing e2e then after that's good we can expand the matrix back.

Copilot AI commented May 8, 2026

Copy link
Copy Markdown
Author

@copilot none of the CI actually ran it just has a ✅ and ran for less than 10s.

please make sure to only run the windows build for now so we can test singing e2e then after that's good we can exp...

Done in b659a7b — macOS and Linux are commented out in the matrix with a TODO: re-enable after Windows signing is verified e2e note. Only the Windows build will run now.

@Hacksore

Hacksore commented May 8, 2026

Copy link
Copy Markdown
Member

Oh we have another issue we have the paths filter logic making sure there are app changes but since we are only working on CI it wont run, maybe disable that as well so we can observe a build without app changes.

@copilot

Copilot AI commented May 8, 2026

Copy link
Copy Markdown
Author

Oh we have another issue we have the paths filter logic making sure there are app changes but since we are only working on CI it wont run, maybe disable that as well so we can observe a build without ...

Done in c2b670c — removed dorny/paths-filter and all if: steps.changes.outputs.desktop == 'true' guards from the build-tauri job in ci.yaml. Builds will now run unconditionally on every PR push regardless of whether app files changed.

@Hacksore

Hacksore commented May 8, 2026

Copy link
Copy Markdown
Member

@copilot TBH we don't even want the CI job running we wanna test release.yaml workflow for e2e codesign flow.

disable the CI jobs for this PR and focus on getting release.yaml to run the build ONLY for windows so we can test the full workflow for signing and release upload.

Copilot AI commented May 8, 2026

Copy link
Copy Markdown
Author

@copilot TBH we don't even want the CI job running we wanna test release.yaml workflow for e2e codesign flow.

disable the CI jobs for this PR and focus on getting release.yaml to run the build ONLY...

Done in 65ffcfd:

  • ci.yaml: removed the pull_request trigger (only workflow_dispatch remains) so CI won't run on this PR
  • release.yaml: added copilot/sub-pr-253 to the push branches list so the Windows-only release/signing pipeline fires on every push to this branch

@Hacksore

Copy link
Copy Markdown
Member

@copilot here is the output from the release job.

📦 Uploading release artifacts for release id 176254267
{ cwd: '/home/runner/work/overlayed/overlayed' }
Files to upload: [
  'Overlayed_0.6.2_x64-setup.exe',
  'Overlayed_0.6.2_x64-setup.exe.sig',
  'Overlayed_0.6.2_x64-setup.nsis.zip',
  'Overlayed_0.6.2_x64-setup.nsis.zip.sig',
  'Overlayed_0.6.2_x64_en-US.msi',
  'Overlayed_0.6.2_x64_en-US.msi.sig',
  'Overlayed_0.6.2_x64_en-US.msi.zip',
  'Overlayed_0.6.2_x64_en-US.msi.zip.sig'
]
uploading asset Overlayed_0.6.2_x64-setup.exe release-artifacts/Overlayed_0.6.2_x64-setup.exe
error uploading asset Overlayed_0.6.2_x64-setup.exe Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64-setup.exe.sig release-artifacts/Overlayed_0.6.2_x64-setup.exe.sig
error uploading asset Overlayed_0.6.2_x64-setup.exe.sig Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64-setup.nsis.zip release-artifacts/Overlayed_0.6.2_x64-setup.nsis.zip
error uploading asset Overlayed_0.6.2_x64-setup.nsis.zip Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64-setup.nsis.zip.sig release-artifacts/Overlayed_0.6.2_x64-setup.nsis.zip.sig
error uploading asset Overlayed_0.6.2_x64-setup.nsis.zip.sig Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64_en-US.msi release-artifacts/Overlayed_0.6.2_x64_en-US.msi
error uploading asset Overlayed_0.6.2_x64_en-US.msi Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64_en-US.msi.sig release-artifacts/Overlayed_0.6.2_x64_en-US.msi.sig
error uploading asset Overlayed_0.6.2_x64_en-US.msi.sig Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64_en-US.msi.zip release-artifacts/Overlayed_0.6.2_x64_en-US.msi.zip
error uploading asset Overlayed_0.6.2_x64_en-US.msi.zip Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
uploading asset Overlayed_0.6.2_x64_en-US.msi.zip.sig release-artifacts/Overlayed_0.6.2_x64_en-US.msi.zip.sig
error uploading asset Overlayed_0.6.2_x64_en-US.msi.zip.sig Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Error: Failed to upload 8 asset(s):
Overlayed_0.6.2_x64-setup.exe: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.exe.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.nsis.zip: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.nsis.zip.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.zip: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.zip.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
    at script (file:///home/runner/work/overlayed/overlayed/scripts/actions/upload-release-artifacts.js:49:11)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async eval (eval at callAsyncFunction (/home/runner/work/_actions/actions/github-script/v7/dist/index.js:36187:16), <anonymous>:5:1)
    at async main (/home/runner/work/_actions/actions/github-script/v7/dist/index.js:36285:20)
Error: Unhandled error: Error: Failed to upload 8 asset(s):
Overlayed_0.6.2_x64-setup.exe: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.exe.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.nsis.zip: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64-setup.nsis.zip.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.zip: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}
Overlayed_0.6.2_x64_en-US.msi.zip.sig: Validation Failed: {"resource":"ReleaseAsset","code":"already_exists","field":"name"}

…(fix already_exists)

Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/d474a418-4d3d-465f-90c5-f44d7da1e4c3

Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com>

Copilot AI commented May 10, 2026

Copy link
Copy Markdown
Author

@copilot here is the output from the release job.

...

Fixed in 9b12ecd. The already_exists errors happen because create-release reuses the existing draft release on re-runs, which already has assets from the previous run.

upload-release-artifacts.js now fetches the list of existing assets on the release before uploading. If an asset with the same name is already there, it deletes it first, then uploads the new (signed) version.

@Hacksore

Copy link
Copy Markdown
Member

@copilot this is great and all but is there a way to make the code in release.yaml reusable cross-platform so there is only one source of truth?

also i don't see the latest.json for the tauri auto updating being uploaded?

Copilot AI commented May 10, 2026

Copy link
Copy Markdown
Author

@copilot this is great and all but is there a way to make the code in release.yaml reusable cross-platform so there is only one source of truth?

also i don't see the latest.json for the tauri aut...

Done in 13d5313. Both addressed:

Cross-platform reusability: The per-platform duplication is gone. There are now exactly two shared steps — "Collect release artifacts" and "Upload {os} release artifacts" — that run identically on Windows, macOS, and Linux. Between them, the Windows-only signing steps (extract → SignPath → replace) are sandwiched in. No more separate powershell vs python3 collection paths.

The collect step uses node (already installed) via bash (available on all runners including Windows via Git Bash), reading paths from an env var to avoid any shell-quoting issues with the JSON:

- name: Collect release artifacts
  shell: bash
  env:
    ARTIFACT_PATHS: ${{ steps.tauri.outputs.artifactPaths }}
  run: |
    mkdir -p ./release-artifacts
    node -e "...copy all paths into ./release-artifacts..."

latest.json: The previous Windows approach explicitly filtered to only .sig/.zip files, which would have dropped any latest.json tauri-action generates. Now the collect step copies all files from artifactPaths into ./release-artifacts first. The signing steps only extract/replace .exe/.msi files, leaving everything else (including latest.json) untouched in ./release-artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants