From 9b75911bdd2581370f703dd2974ca79a0364e8b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:13:58 +0000 Subject: [PATCH 1/8] Initial plan From 6cf11d2cae8815d6f63ff34d8864a8302ce8b919 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:20:23 +0000 Subject: [PATCH 2/8] Refactor release pipeline: build all platforms, sign Windows in same 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> --- .github/workflows/ci.yaml | 4 +- .github/workflows/release.yaml | 152 ++++++++++++-------- scripts/actions/upload-release-artifacts.js | 50 +++++++ 3 files changed, 145 insertions(+), 61 deletions(-) create mode 100644 scripts/actions/upload-release-artifacts.js diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8f4ff619..36f86144 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,9 +1,7 @@ name: "CI" on: workflow_dispatch: - # NOTE: disable before merge - # FIXME: FYI - # pull_request: + pull_request: jobs: quality: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 413e2dc3..9655880b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -6,7 +6,6 @@ on: push: branches: # TODO: REMOVE ME BEFORE MERGE - # FIXME: fr fr ong pls remove - migrate/codesign concurrency: @@ -22,21 +21,21 @@ jobs: fail-fast: false matrix: settings: - # - host: macos-latest - # target: universal-apple-darwin - # toolchain: aarch64-apple-darwin,x86_64-apple-darwin - # bundles: app,dmg - # os: darwin + - host: macos-latest + target: universal-apple-darwin + toolchain: aarch64-apple-darwin,x86_64-apple-darwin + bundles: app,dmg + os: darwin - host: windows-latest target: x86_64-pc-windows-msvc toolchain: x86_64-pc-windows-msvc bundles: msi,nsis os: windows - # - host: ubuntu-latest - # target: x86_64-unknown-linux-gnu - # toolchain: x86_64-unknown-linux-gnu - # bundles: deb,appimage - # os: linux + - host: ubuntu-latest + target: x86_64-unknown-linux-gnu + toolchain: x86_64-unknown-linux-gnu + bundles: deb,appimage + os: linux env: APP_DIR: "apps/desktop" runs-on: ${{ matrix.settings.host }} @@ -78,76 +77,87 @@ jobs: VITE_AXIOM_TOKEN: "${{ secrets.VITE_AXIOM_TOKEN }}" VITE_SENTRY_AUTH_TOKEN: "${{ secrets.VITE_SENTRY_AUTH_TOKEN }}" with: - # NOTE: we only use this action to build the project bins for each platform - # because we need to do code signing for windows we will upload manually after the signing is completed projectPath: "${{ env.APP_DIR }}" args: --target ${{ matrix.settings.target }} --bundles ${{ matrix.settings.bundles }},updater - # TODO: figure out where the binary are in the fs from the above action - - name: Presign + + # Windows: collect unsigned binaries, sign them, then assemble final artifact + - name: Collect unsigned Windows binaries + if: matrix.settings.os == 'windows' + shell: pwsh run: | - # Create binaries directory if it doesn't exist New-Item -ItemType Directory -Force -Path "./binaries" - - # Parse artifactPaths to extract .exe and .msi files - $artifactPaths = '${{ steps.tauri.outputs.artifactPaths }}' - - # Parse as JSON array - $paths = $artifactPaths | ConvertFrom-Json - - # Extract .exe and .msi files (excluding .sig and .zip files) - $exeFiles = $paths | Where-Object { $_ -match '\.exe$' } | Where-Object { $_ -notmatch '\.(sig|zip)$' } - $msiFiles = $paths | Where-Object { $_ -match '\.msi$' } | Where-Object { $_ -notmatch '\.(sig|zip)$' } - - Write-Host "Found EXE files:" - $exeFiles | ForEach-Object { Write-Host " $_" } - - Write-Host "Found MSI files:" - $msiFiles | ForEach-Object { Write-Host " $_" } - - # Move the files to binaries folder - $exeFiles | ForEach-Object { - $fileName = Split-Path $_ -Leaf - Copy-Item $_ -Destination ".\binaries\$fileName" - } - - $msiFiles | ForEach-Object { + $paths = '${{ steps.tauri.outputs.artifactPaths }}' | ConvertFrom-Json + $toSign = $paths | Where-Object { $_ -match '\.(exe|msi)$' } | Where-Object { $_ -notmatch '\.(sig|zip)$' } + $toSign | ForEach-Object { $fileName = Split-Path $_ -Leaf Copy-Item $_ -Destination ".\binaries\$fileName" } + Get-ChildItem -Path ".\binaries" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } - # sha sum the files in binaries - Get-ChildItem -Path ".\binaries" -File -Recurse | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } - - - name: Upload Unsigned Windows Binaries + - name: Upload unsigned Windows binaries + if: matrix.settings.os == 'windows' id: upload-unsigned-artifact uses: actions/upload-artifact@v4 - with: + with: + name: windows-unsigned path: ./binaries - - name: Sign Windows Binaries + + - name: Sign Windows binaries + if: matrix.settings.os == 'windows' uses: signpath/github-action-submit-signing-request@v1.1 with: api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' organization-id: 'b2cc34a4-3b75-4753-82e4-b755351770ea' project-slug: 'overlayed' - # TODO: when we have the production signing policy update this + # TODO: switch to the production signing policy when available signing-policy-slug: 'test-signing' github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' wait-for-completion: true output-artifact-directory: 'binaries/signed' - - name: Postsign + + - name: Add updater files to Windows release artifact + if: matrix.settings.os == 'windows' + shell: pwsh run: | - # using powershell lets list out the sha sum of the signed binaries - Get-ChildItem -Path binaries/signed -File -Recurse | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } - - name: Upload signed windows binaries - uses: actions/github-script@v7 + $paths = '${{ steps.tauri.outputs.artifactPaths }}' | ConvertFrom-Json + $updaterFiles = $paths | Where-Object { $_ -match '\.(sig|zip)$' } + $updaterFiles | ForEach-Object { + $fileName = Split-Path $_ -Leaf + Copy-Item $_ -Destination ".\binaries\signed\$fileName" + } + Get-ChildItem -Path ".\binaries\signed" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } + + - name: Upload Windows release artifacts + if: matrix.settings.os == 'windows' + uses: actions/upload-artifact@v4 with: - script: | - const { script } = await import('${{ github.workspace }}/scripts/actions/upload-signed-bins.js'); - const id = "${{ needs.create-release.outputs.release_id }}"; - await script({ github, context }, id); + name: windows-release + path: ./binaries/signed + + # macOS and Linux: collect and upload all build artifacts + - name: Collect macOS/Linux artifacts + if: matrix.settings.os != 'windows' + shell: bash + run: | + mkdir -p ./artifacts + echo '${{ steps.tauri.outputs.artifactPaths }}' | python3 -c " + import json, sys, shutil, os + paths = json.load(sys.stdin) + for p in paths: + shutil.copy(p, './artifacts/' + os.path.basename(p)) + " + ls -la ./artifacts/ + + - name: Upload ${{ matrix.settings.os }} release artifacts + if: matrix.settings.os != 'windows' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.settings.os }}-release + path: ./artifacts + create-release: needs: build-tauri - name: Create or Update + name: Create Release permissions: contents: write runs-on: ubuntu-latest @@ -155,7 +165,7 @@ jobs: release_id: ${{ steps.create-release.outputs.result }} steps: - uses: actions/checkout@v4 - - name: setup node + - name: Setup node uses: actions/setup-node@v4 with: node-version: 20 @@ -169,3 +179,29 @@ jobs: const { script } = await import('${{ github.workspace }}/scripts/actions/create-release.js') return await script({ github, context }); + upload-release: + needs: create-release + name: Upload Release Artifacts + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Download all release artifacts + uses: actions/download-artifact@v4 + with: + pattern: '*-release' + path: ./release-artifacts + merge-multiple: true + - name: Upload artifacts to release + uses: actions/github-script@v7 + with: + script: | + const { script } = await import('${{ github.workspace }}/scripts/actions/upload-release-artifacts.js') + const id = "${{ needs.create-release.outputs.release_id }}"; + await script({ github, context }, id); + diff --git a/scripts/actions/upload-release-artifacts.js b/scripts/actions/upload-release-artifacts.js new file mode 100644 index 00000000..de07cb9a --- /dev/null +++ b/scripts/actions/upload-release-artifacts.js @@ -0,0 +1,50 @@ +import fs from "fs"; + +const RELEASE_ARTIFACTS_DIR = "./release-artifacts"; + +/** @param {import('@types/github-script').AsyncFunctionArguments} AsyncFunctionArguments */ +export const script = async ({ context, github }, releaseId) => { + console.log("📦 Uploading release artifacts for release id", releaseId); + console.log({ cwd: process.cwd() }); + + if (!fs.existsSync(RELEASE_ARTIFACTS_DIR)) { + console.log("No release artifacts found"); + return; + } + + const files = fs.readdirSync(RELEASE_ARTIFACTS_DIR); + console.log("Files to upload:", files); + + const errors = []; + + for (const file of files) { + const filePath = `${RELEASE_ARTIFACTS_DIR}/${file}`; + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + continue; + } + + const fileData = fs.readFileSync(filePath); + console.log("uploading asset", file, filePath); + + try { + const { data: uploadResponse } = await github.rest.repos.uploadReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: releaseId, + data: fileData, + name: file, + }); + + console.log("uploaded asset", uploadResponse.name, uploadResponse.id); + } catch (error) { + console.error("error uploading asset", file, error.message); + errors.push(`${file}: ${error.message}`); + } + } + + if (errors.length > 0) { + throw new Error(`Failed to upload ${errors.length} asset(s):\n${errors.join("\n")}`); + } +}; From b3502f261f21ac281a5aaa9c3bbb47e9b8ee7939 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:22:19 +0000 Subject: [PATCH 3/8] Fix: pin actions/download-artifact to v4.1.3 and use path.join for safe 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> --- .github/workflows/release.yaml | 2 +- scripts/actions/upload-release-artifacts.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9655880b..ad57f741 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -192,7 +192,7 @@ jobs: with: node-version: 20 - name: Download all release artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v4.1.3 with: pattern: '*-release' path: ./release-artifacts diff --git a/scripts/actions/upload-release-artifacts.js b/scripts/actions/upload-release-artifacts.js index de07cb9a..81db4bf0 100644 --- a/scripts/actions/upload-release-artifacts.js +++ b/scripts/actions/upload-release-artifacts.js @@ -1,4 +1,5 @@ import fs from "fs"; +import path from "path"; const RELEASE_ARTIFACTS_DIR = "./release-artifacts"; @@ -18,7 +19,7 @@ export const script = async ({ context, github }, releaseId) => { const errors = []; for (const file of files) { - const filePath = `${RELEASE_ARTIFACTS_DIR}/${file}`; + const filePath = path.join(RELEASE_ARTIFACTS_DIR, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { From b659a7b5ccb5faddb086a61a7ce0b36431be9550 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:39:55 +0000 Subject: [PATCH 4/8] Reduce matrix to Windows-only to test signing e2e Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/d78c6bd7-9817-4fce-bcde-64e5ce7a0e2e Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com> --- .github/workflows/release.yaml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ad57f741..2c58a233 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -21,21 +21,23 @@ jobs: fail-fast: false matrix: settings: - - host: macos-latest - target: universal-apple-darwin - toolchain: aarch64-apple-darwin,x86_64-apple-darwin - bundles: app,dmg - os: darwin + # TODO: re-enable after Windows signing is verified e2e + # - host: macos-latest + # target: universal-apple-darwin + # toolchain: aarch64-apple-darwin,x86_64-apple-darwin + # bundles: app,dmg + # os: darwin - host: windows-latest target: x86_64-pc-windows-msvc toolchain: x86_64-pc-windows-msvc bundles: msi,nsis os: windows - - host: ubuntu-latest - target: x86_64-unknown-linux-gnu - toolchain: x86_64-unknown-linux-gnu - bundles: deb,appimage - os: linux + # TODO: re-enable after Windows signing is verified e2e + # - host: ubuntu-latest + # target: x86_64-unknown-linux-gnu + # toolchain: x86_64-unknown-linux-gnu + # bundles: deb,appimage + # os: linux env: APP_DIR: "apps/desktop" runs-on: ${{ matrix.settings.host }} From c2b670cf7c731e2527f707c87e26a1dbb7faa4ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:44:49 +0000 Subject: [PATCH 5/8] Remove paths-filter from ci.yaml build-tauri so builds run on CI-only changes Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/0904acca-f47e-4e3a-99d6-ee205f9d5ec7 Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com> --- .github/workflows/ci.yaml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 36f86144..6a40bcc3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -84,28 +84,18 @@ jobs: runs-on: ${{ matrix.settings.host }} steps: - uses: actions/checkout@v4 - - uses: dorny/paths-filter@v3 - id: changes - with: - filters: | - desktop: - - 'apps/desktop/**' - name: Setup node - if: steps.changes.outputs.desktop == 'true' uses: actions/setup-node@v4 with: node-version: 20 - uses: pnpm/action-setup@v3 - if: steps.changes.outputs.desktop == 'true' with: version: 9 - name: Get pnpm store directory - if: steps.changes.outputs.desktop == 'true' shell: bash run: | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - uses: actions/cache@v4 - if: steps.changes.outputs.desktop == 'true' name: Setup pnpm cache with: path: ${{ env.STORE_PATH }} @@ -113,24 +103,20 @@ jobs: restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install Rust stable - if: steps.changes.outputs.desktop == 'true' uses: dtolnay/rust-toolchain@stable with: target: "${{ matrix.settings.toolchain }}" - uses: Swatinem/rust-cache@v2 - if: steps.changes.outputs.desktop == 'true' with: workspaces: "apps/desktop/src-tauri/target" - name: Install dependencies (ubuntu only) - if: matrix.settings.host == 'ubuntu-latest' && steps.changes.outputs.desktop == 'true' + if: matrix.settings.host == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - name: install frontend dependencies - if: steps.changes.outputs.desktop == 'true' run: pnpm install - uses: tauri-apps/tauri-action@dev - if: steps.changes.outputs.desktop == 'true' with: projectPath: apps/desktop args: --config "src-tauri/tauri.conf.ci.json" From 65ffcfdc52ce7315bde9758df0043f5486246a24 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 01:58:32 +0000 Subject: [PATCH 6/8] Disable CI pull_request trigger; add PR branch to release.yaml for e2e signing test Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/3c7804c9-5b2f-4354-b1d8-4d8c818620fb Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- .github/workflows/release.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6a40bcc3..7f181f63 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,7 +1,7 @@ name: "CI" on: + # TODO: re-enable pull_request trigger after Windows signing is verified e2e workflow_dispatch: - pull_request: jobs: quality: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2c58a233..48411222 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,6 +7,7 @@ on: branches: # TODO: REMOVE ME BEFORE MERGE - migrate/codesign + - copilot/sub-pr-253 concurrency: group: ${{ github.workflow }}-${{ github.ref }} From 9b12ecdc6496aa733b96050bb9be52a34c3aa2d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:13:05 +0000 Subject: [PATCH 7/8] upload-release-artifacts: delete existing assets before re-uploading (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> --- scripts/actions/upload-release-artifacts.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scripts/actions/upload-release-artifacts.js b/scripts/actions/upload-release-artifacts.js index 81db4bf0..a0233d8c 100644 --- a/scripts/actions/upload-release-artifacts.js +++ b/scripts/actions/upload-release-artifacts.js @@ -18,6 +18,15 @@ export const script = async ({ context, github }, releaseId) => { const errors = []; + // Fetch existing assets so we can replace them if a re-run uploads the same names + const { data: existingAssets } = await github.rest.repos.listReleaseAssets({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: releaseId, + per_page: 100, + }); + console.log("Existing assets:", existingAssets.map((a) => a.name)); + for (const file of files) { const filePath = path.join(RELEASE_ARTIFACTS_DIR, file); const stat = fs.statSync(filePath); @@ -30,6 +39,17 @@ export const script = async ({ context, github }, releaseId) => { console.log("uploading asset", file, filePath); try { + // Delete any existing asset with the same name so re-runs don't fail + const existingAsset = existingAssets.find((a) => a.name === file); + if (existingAsset) { + console.log("deleting existing asset", existingAsset.name, existingAsset.id); + await github.rest.repos.deleteReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + asset_id: existingAsset.id, + }); + } + const { data: uploadResponse } = await github.rest.repos.uploadReleaseAsset({ owner: context.repo.owner, repo: context.repo.repo, From 13d531337f3da5c7a2b10d9415de54d500973ac5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 May 2026 17:57:46 +0000 Subject: [PATCH 8/8] release.yaml: unified cross-platform artifact collection; fixes latest.json inclusion Agent-Logs-Url: https://github.com/overlayeddev/overlayed/sessions/6658cacb-6f3b-4925-87df-486df6c4be0d Co-authored-by: Hacksore <996134+Hacksore@users.noreply.github.com> --- .github/workflows/release.yaml | 79 ++++++++++++++++------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 48411222..bf3589ba 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -83,19 +83,37 @@ jobs: projectPath: "${{ env.APP_DIR }}" args: --target ${{ matrix.settings.target }} --bundles ${{ matrix.settings.bundles }},updater - # Windows: collect unsigned binaries, sign them, then assemble final artifact - - name: Collect unsigned Windows binaries + # Collect ALL Tauri artifacts (cross-platform, single source of truth) + - name: Collect release artifacts + shell: bash + env: + ARTIFACT_PATHS: ${{ steps.tauri.outputs.artifactPaths }} + run: | + mkdir -p ./release-artifacts + node -e " + const fs = require('fs'); + const path = require('path'); + const paths = JSON.parse(process.env.ARTIFACT_PATHS); + paths.forEach(p => { + const dest = path.join('./release-artifacts', path.basename(p)); + fs.copyFileSync(p, dest); + console.log('Collected:', path.basename(p)); + }); + " + + # Windows only: extract .exe/.msi for signing, sign, then replace in release-artifacts + - name: Extract Windows binaries for signing if: matrix.settings.os == 'windows' shell: pwsh run: | - New-Item -ItemType Directory -Force -Path "./binaries" - $paths = '${{ steps.tauri.outputs.artifactPaths }}' | ConvertFrom-Json - $toSign = $paths | Where-Object { $_ -match '\.(exe|msi)$' } | Where-Object { $_ -notmatch '\.(sig|zip)$' } - $toSign | ForEach-Object { - $fileName = Split-Path $_ -Leaf - Copy-Item $_ -Destination ".\binaries\$fileName" - } - Get-ChildItem -Path ".\binaries" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } + New-Item -ItemType Directory -Force -Path "./binaries-to-sign" + Get-ChildItem -Path "./release-artifacts" -File | + Where-Object { $_.Extension -in '.exe', '.msi' } | + ForEach-Object { + Copy-Item $_.FullName -Destination "./binaries-to-sign/$($_.Name)" + Write-Host "To sign: $($_.Name)" + } + Get-ChildItem -Path "./binaries-to-sign" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } - name: Upload unsigned Windows binaries if: matrix.settings.os == 'windows' @@ -103,7 +121,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: windows-unsigned - path: ./binaries + path: ./binaries-to-sign - name: Sign Windows binaries if: matrix.settings.os == 'windows' @@ -116,47 +134,24 @@ jobs: signing-policy-slug: 'test-signing' github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' wait-for-completion: true - output-artifact-directory: 'binaries/signed' + output-artifact-directory: 'binaries-signed' - - name: Add updater files to Windows release artifact + - name: Replace unsigned binaries with signed if: matrix.settings.os == 'windows' shell: pwsh run: | - $paths = '${{ steps.tauri.outputs.artifactPaths }}' | ConvertFrom-Json - $updaterFiles = $paths | Where-Object { $_ -match '\.(sig|zip)$' } - $updaterFiles | ForEach-Object { - $fileName = Split-Path $_ -Leaf - Copy-Item $_ -Destination ".\binaries\signed\$fileName" + Get-ChildItem -Path "./binaries-signed" -File | ForEach-Object { + Copy-Item $_.FullName -Destination "./release-artifacts/$($_.Name)" -Force + Write-Host "Replaced with signed: $($_.Name)" } - Get-ChildItem -Path ".\binaries\signed" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } - - - name: Upload Windows release artifacts - if: matrix.settings.os == 'windows' - uses: actions/upload-artifact@v4 - with: - name: windows-release - path: ./binaries/signed - - # macOS and Linux: collect and upload all build artifacts - - name: Collect macOS/Linux artifacts - if: matrix.settings.os != 'windows' - shell: bash - run: | - mkdir -p ./artifacts - echo '${{ steps.tauri.outputs.artifactPaths }}' | python3 -c " - import json, sys, shutil, os - paths = json.load(sys.stdin) - for p in paths: - shutil.copy(p, './artifacts/' + os.path.basename(p)) - " - ls -la ./artifacts/ + Get-ChildItem -Path "./release-artifacts" -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 } + # Upload release artifact — same step for all platforms (single source of truth) - name: Upload ${{ matrix.settings.os }} release artifacts - if: matrix.settings.os != 'windows' uses: actions/upload-artifact@v4 with: name: ${{ matrix.settings.os }}-release - path: ./artifacts + path: ./release-artifacts create-release: needs: build-tauri