Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
255 lines
9 KiB
YAML
255 lines
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/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/release-packages/src/cli.ts prepare
|
|
bun .pipeline/tools/release/release-packages/src/cli.ts pack
|
|
- name: Extract exact release notes
|
|
env:
|
|
RELEASE_VERSION: ${{ needs.plan.outputs.version }}
|
|
run: bun .pipeline/tools/release/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/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/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/release-packages/src/native/assemble.ts
|
|
- name: Refuse published releases or moved tags
|
|
run: bun .pipeline/tools/release/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/release-packages/src/cli.ts publish
|
|
- name: Replace and verify the entire draft asset set
|
|
run: bun .pipeline/tools/release/release-packages/src/native/publish.ts upload
|