* ci: fix desktop build cache ownership * build: centralize native release artifact validation Reuse package command execution and npm artifact paths. Share release identity and target metadata, consume explicit Tauri artifact outputs, and reject incomplete or mixed-run artifact sets before draft publication. * refactor: use release package aliases across directories * ci: coordinate verified native and npm releases Build shared frontend inputs once and keep native targets parallel. Bind their complete artifact set to immutable source and workflow revisions, verify updater signatures and attestations, and replace draft assets only after preflight and verified npm publication. * test: group native release tests by domain
255 lines
8.9 KiB
YAML
255 lines
8.9 KiB
YAML
name: Build
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: Existing stable release tag to rebuild without moving it (vX.Y.Z).
|
|
required: true
|
|
type: string
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: release-${{ inputs.tag || github.ref_name }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
WORKFLOW_COMMIT: ${{ github.workflow_sha }}
|
|
|
|
jobs:
|
|
plan:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
outputs:
|
|
tag: ${{ steps.release.outputs.tag }}
|
|
version: ${{ steps.release.outputs.version }}
|
|
source: ${{ steps.release.outputs.source }}
|
|
matrix: ${{ steps.release.outputs.matrix }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ github.workflow_sha }}
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-bun
|
|
- id: release
|
|
name: Resolve immutable source and native matrix
|
|
env:
|
|
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
|
run: bun tools/release-packages/src/native/resolve.ts
|
|
|
|
frontend:
|
|
needs: plan
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
outputs:
|
|
sha256: ${{ steps.frontend.outputs.sha256 }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ needs.plan.outputs.source }}
|
|
persist-credentials: false
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ github.workflow_sha }}
|
|
path: .pipeline
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.x
|
|
- uses: ./.pipeline/.github/actions/setup-bun
|
|
with:
|
|
cache-scope: desktop
|
|
- name: Install pinned workflow tooling
|
|
run: bun install --cwd .pipeline --frozen-lockfile
|
|
- name: Build shared desktop frontend and package outputs
|
|
run: |
|
|
bun run generate:icons --target desktop
|
|
bun run generate:tauri-menu
|
|
bun run build
|
|
- name: Prepare and validate npm tarballs
|
|
run: |
|
|
bun .pipeline/tools/release-packages/src/cli.ts prepare
|
|
bun .pipeline/tools/release-packages/src/cli.ts pack
|
|
- name: Extract exact release notes
|
|
env:
|
|
RELEASE_VERSION: ${{ needs.plan.outputs.version }}
|
|
run: bun .pipeline/tools/release-packages/src/extract-release-notes.ts "$RELEASE_VERSION" release-notes.md
|
|
- name: Archive platform-independent native inputs
|
|
id: frontend
|
|
run: |
|
|
tar -cf frontend.tar dist desktop/icons desktop/generated
|
|
echo "sha256=$(sha256sum frontend.tar | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
|
|
- uses: actions/upload-artifact@v7
|
|
with:
|
|
name: release-frontend
|
|
path: |
|
|
frontend.tar
|
|
release-notes.md
|
|
if-no-files-found: error
|
|
compression-level: 0
|
|
- uses: actions/upload-artifact@v7
|
|
with:
|
|
name: release-npm
|
|
path: .npm-packages/*.tgz
|
|
include-hidden-files: true
|
|
if-no-files-found: error
|
|
compression-level: 0
|
|
|
|
native:
|
|
needs: [plan, frontend]
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.plan.outputs.matrix) }}
|
|
runs-on: ${{ matrix.platform }}
|
|
timeout-minutes: 40
|
|
env:
|
|
RELEASE_TAG: ${{ needs.plan.outputs.tag }}
|
|
SOURCE_COMMIT: ${{ needs.plan.outputs.source }}
|
|
FRONTEND_SHA256: ${{ needs.frontend.outputs.sha256 }}
|
|
RELEASE_TARGET: ${{ matrix.target }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ needs.plan.outputs.source }}
|
|
persist-credentials: false
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ github.workflow_sha }}
|
|
path: .pipeline
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.x
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: desktop -> target
|
|
key: ${{ matrix.target }}
|
|
- name: Install native dependencies on Linux
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
|
- uses: ./.pipeline/.github/actions/setup-bun
|
|
with:
|
|
cache-scope: desktop
|
|
cache-save: ${{ matrix.saveBunCache && runner.os != 'Linux' }}
|
|
- name: Install pinned workflow tooling
|
|
run: bun install --cwd .pipeline --frozen-lockfile
|
|
- uses: actions/download-artifact@v8
|
|
with:
|
|
name: release-frontend
|
|
- name: Verify shared inputs and disable only the redundant build hook
|
|
run: bun .pipeline/tools/release-packages/src/native/frontend.ts
|
|
- name: Extract shared frontend, icons and menu
|
|
run: tar -xf frontend.tar
|
|
- name: Verify Node and Tauri startup
|
|
timeout-minutes: 1
|
|
run: |
|
|
node --version
|
|
node node_modules/@tauri-apps/cli/tauri.js --version
|
|
- name: Build and sign native bundles (no release uploads)
|
|
id: tauri
|
|
timeout-minutes: 30
|
|
uses: tauri-apps/tauri-action@v0
|
|
env:
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || '' }}
|
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
with:
|
|
tauriScript: node node_modules/@tauri-apps/cli/tauri.js
|
|
args: --target ${{ matrix.target }} --config "${{ github.workspace }}/release-build-config.json" --verbose
|
|
retryAttempts: 0
|
|
- name: Collect only reported bundles and signatures
|
|
env:
|
|
TAURI_ARTIFACT_PATHS: ${{ steps.tauri.outputs.artifactPaths }}
|
|
run: bun .pipeline/tools/release-packages/src/native/collect.ts
|
|
- uses: actions/upload-artifact@v7
|
|
with:
|
|
name: native-${{ matrix.target }}
|
|
path: native-output/*
|
|
if-no-files-found: error
|
|
compression-level: 0
|
|
|
|
publish:
|
|
needs: [plan, frontend, native]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
attestations: write
|
|
env:
|
|
RELEASE_TAG: ${{ needs.plan.outputs.tag }}
|
|
SOURCE_COMMIT: ${{ needs.plan.outputs.source }}
|
|
FRONTEND_SHA256: ${{ needs.frontend.outputs.sha256 }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ needs.plan.outputs.source }}
|
|
persist-credentials: false
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ github.workflow_sha }}
|
|
path: .pipeline
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24.x
|
|
registry-url: https://registry.npmjs.org/
|
|
- uses: ./.pipeline/.github/actions/setup-bun
|
|
with:
|
|
cache-scope: desktop
|
|
cache-save: 'false'
|
|
- name: Install pinned workflow tooling
|
|
run: bun install --cwd .pipeline --frozen-lockfile
|
|
- uses: actions/download-artifact@v8
|
|
with:
|
|
name: release-frontend
|
|
- uses: actions/download-artifact@v8
|
|
with:
|
|
name: release-npm
|
|
path: .npm-packages
|
|
- uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: native-*
|
|
path: native-artifacts
|
|
- name: Install signature verifier
|
|
run: sudo apt-get update && sudo apt-get install -y minisign
|
|
- name: Verify all targets, digests and updater signatures
|
|
run: bun .pipeline/tools/release-packages/src/native/assemble.ts
|
|
- name: Refuse published releases or moved tags
|
|
run: bun .pipeline/tools/release-packages/src/native/publish.ts check
|
|
- name: Attest the complete binary set and source/workflow manifest
|
|
id: provenance
|
|
uses: actions/attest@v4
|
|
with:
|
|
subject-path: release-output/*
|
|
- name: Verify attestations against the pinned workflow
|
|
env:
|
|
ATTESTATION_BUNDLE: ${{ steps.provenance.outputs.bundle-path }}
|
|
run: |
|
|
for artifact in release-output/*; do
|
|
gh attestation verify "$artifact" --bundle "$ATTESTATION_BUNDLE" \
|
|
--repo "$GITHUB_REPOSITORY" \
|
|
--signer-workflow "$GITHUB_REPOSITORY/.github/workflows/build.yml" \
|
|
--signer-digest "$WORKFLOW_COMMIT" --deny-self-hosted-runners
|
|
done
|
|
- name: Publish verified npm artifacts with provenance
|
|
run: bun .pipeline/tools/release-packages/src/cli.ts publish
|
|
- name: Replace and verify the entire draft asset set
|
|
run: bun .pipeline/tools/release-packages/src/native/publish.ts upload
|