mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 12:38:58 -06:00
The release workflow gains a FreeBSD x86_64 job: packaging/freebsd/package.sh builds in the same pinned FreeBSD VM and writes a /usr/local-style tar.gz (app, CLI, desktop entry, MIME type, AppStream metadata, icons, licences). README and CLAUDE.md list FreeBSD now that its CI job builds PrintCraft and passes all 688 tests on FreeBSD 14.3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
324 lines
12 KiB
YAML
324 lines
12 KiB
YAML
# Release pipeline: every push to `release` builds signed installers for every platform and
|
|
# creates or updates the draft GitHub Release "PrintCraft v<version>". See docs/releasing.md.
|
|
#
|
|
# All jobs run in the `release` environment (restricted to the `release` branch), which holds
|
|
# the signing secrets. Every secret is optional: missing ones produce unsigned artifacts and a
|
|
# warning, never a failed build.
|
|
name: Release
|
|
|
|
on:
|
|
push:
|
|
branches: [release]
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Version override for a test run, e.g. 0.2.0-rc.1 (empty: Cargo.toml)"
|
|
type: string
|
|
default: ""
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: release-${{ github.ref }}
|
|
# Never cancel a run mid-notarization or mid-upload; a newer push waits its turn.
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
CARGO_INCREMENTAL: 0
|
|
RUST_BACKTRACE: 1
|
|
PRINTCRAFT_BUILD_SHA: ${{ github.sha }}
|
|
INPUT_VERSION: ${{ inputs.version }}
|
|
|
|
jobs:
|
|
version:
|
|
name: version
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
outputs:
|
|
version: ${{ steps.v.outputs.version }}
|
|
date: ${{ steps.v.outputs.date }}
|
|
prerelease: ${{ steps.v.outputs.prerelease }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- id: v
|
|
name: Resolve version
|
|
run: |
|
|
. packaging/env.sh
|
|
v="${INPUT_VERSION#v}"
|
|
v="${v:-$VERSION}"
|
|
if ! printf '%s' "$v" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then
|
|
echo "::error::'$v' is not a version like 1.2.3 or 1.2.3-rc.1"
|
|
exit 1
|
|
fi
|
|
case "$v" in *-*) pre=true ;; *) pre=false ;; esac
|
|
{
|
|
echo "version=$v"
|
|
echo "date=$(date -u +%Y-%m-%d)"
|
|
echo "prerelease=$pre"
|
|
} >>"$GITHUB_OUTPUT"
|
|
echo "### PrintCraft v$v (\`${GITHUB_SHA::9}\`)" >>"$GITHUB_STEP_SUMMARY"
|
|
|
|
macos:
|
|
name: macOS universal
|
|
needs: version
|
|
runs-on: macos-15
|
|
environment: release
|
|
env:
|
|
PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: aarch64-apple-darwin, x86_64-apple-darwin
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: release-macos-universal
|
|
- name: Apply version override
|
|
if: inputs.version != ''
|
|
run: cargo xtask version set "$PRINTCRAFT_VERSION"
|
|
- name: Import signing certificate
|
|
env:
|
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
|
run: packaging/macos/import-cert.sh
|
|
- name: Build, sign, notarize
|
|
env:
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
run: packaging/macos/package.sh --arch universal
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-macos
|
|
path: dist/release/*
|
|
if-no-files-found: error
|
|
- name: Remove temporary keychain
|
|
if: always()
|
|
run: |
|
|
if [ -n "${MACOS_KEYCHAIN:-}" ]; then security delete-keychain "$MACOS_KEYCHAIN" || true; fi
|
|
|
|
windows:
|
|
name: Windows ${{ matrix.arch }}
|
|
needs: version
|
|
runs-on: windows-latest
|
|
environment: release
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- { arch: x64, target: x86_64-pc-windows-msvc }
|
|
- { arch: x86, target: i686-pc-windows-msvc }
|
|
env:
|
|
PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: release-windows-${{ matrix.arch }}
|
|
- name: Apply version override
|
|
if: inputs.version != ''
|
|
shell: bash
|
|
run: cargo xtask version set "$PRINTCRAFT_VERSION"
|
|
- name: Install WiX
|
|
shell: pwsh
|
|
run: dotnet tool install --global wix --version 5.0.2
|
|
- name: Build, sign, package
|
|
shell: pwsh
|
|
env:
|
|
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
|
|
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
|
|
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
|
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
|
|
AZURE_SIGNING_ENDPOINT: ${{ secrets.AZURE_SIGNING_ENDPOINT }}
|
|
AZURE_SIGNING_ACCOUNT: ${{ secrets.AZURE_SIGNING_ACCOUNT }}
|
|
AZURE_CERT_PROFILE: ${{ secrets.AZURE_CERT_PROFILE }}
|
|
run: ./packaging/windows/package.ps1 -Arch ${{ matrix.arch }}
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-windows-${{ matrix.arch }}
|
|
path: dist/release/*
|
|
if-no-files-found: error
|
|
|
|
linux:
|
|
name: Linux ${{ matrix.arch }}
|
|
needs: version
|
|
# The oldest GitHub-hosted image, so the binaries only need glibc >= 2.35 (Ubuntu 22.04+,
|
|
# Debian 12+, Fedora 36+, RHEL 10). See docs/releasing.md.
|
|
runs-on: ${{ matrix.runner }}
|
|
environment: release
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- { arch: x86_64, runner: ubuntu-22.04, deb: amd64 }
|
|
- { arch: aarch64, runner: ubuntu-22.04-arm, deb: arm64 }
|
|
env:
|
|
PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
NFPM_VERSION: 2.47.0
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Install build and packaging tools
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends \
|
|
libxkbcommon-dev libwayland-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev \
|
|
desktop-file-utils appstream python3-yaml
|
|
curl -fsSL -o "$RUNNER_TEMP/nfpm.deb" \
|
|
"https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_${{ matrix.deb }}.deb"
|
|
sudo dpkg -i "$RUNNER_TEMP/nfpm.deb"
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: release-linux-${{ matrix.arch }}
|
|
- name: Apply version override
|
|
if: inputs.version != ''
|
|
run: cargo xtask version set "$PRINTCRAFT_VERSION"
|
|
- name: Build and package (AppImage, deb, rpm, tar.gz)
|
|
run: packaging/linux/package.sh
|
|
- name: Check the packages
|
|
run: |
|
|
dpkg-deb --info dist/release/*.deb
|
|
dpkg-deb --contents dist/release/*.deb | grep -E 'usr/bin/printcraft$|metainfo|applications'
|
|
ldd target/release/printcraft
|
|
python3 -c "import yaml; m = yaml.safe_load(open('packaging/linux/flatpak/ai.storyteller.printcraft.yml')); assert m['id'] == 'ai.storyteller.printcraft'"
|
|
for appimage in dist/release/*.AppImage; do
|
|
chmod +x "$appimage"
|
|
APPIMAGE_EXTRACT_AND_RUN=1 "$appimage" --version
|
|
done
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-linux-${{ matrix.arch }}
|
|
path: dist/release/*
|
|
if-no-files-found: error
|
|
|
|
freebsd:
|
|
name: FreeBSD x86_64
|
|
needs: version
|
|
# GitHub has no FreeBSD runners: build in a FreeBSD VM (see .github/workflows/freebsd.yml).
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
timeout-minutes: 180
|
|
env:
|
|
PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
VERSION_OVERRIDE: ${{ inputs.version }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Build and package in a FreeBSD VM (tar.gz)
|
|
# vmactions/freebsd-vm v1.5.9, pinned by commit (it runs our build).
|
|
uses: vmactions/freebsd-vm@c46abacb49f09938ca4e1702d15d836285d694cc
|
|
with:
|
|
release: "14.3"
|
|
usesh: true
|
|
mem: 12288
|
|
envs: "PRINTCRAFT_VERSION PRINTCRAFT_BUILD_DATE VERSION_OVERRIDE"
|
|
prepare: |
|
|
pkg install -y bash curl git cmake pkgconf llvm19 perl5 \
|
|
libxkbcommon wayland libX11 libXrandr libXi libXcursor mesa-libs gtk3
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
|
|
run: |
|
|
set -e
|
|
. "$HOME/.cargo/env"
|
|
git config --global --add safe.directory "$PWD"
|
|
export LIBCLANG_PATH=/usr/local/llvm19/lib CARGO_BUILD_JOBS=4
|
|
if [ -n "$VERSION_OVERRIDE" ]; then cargo xtask version set "$PRINTCRAFT_VERSION"; fi
|
|
packaging/freebsd/package.sh
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-freebsd-x86_64
|
|
path: dist/release/*
|
|
if-no-files-found: error
|
|
|
|
web:
|
|
name: Web (wasm)
|
|
needs: version
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
env:
|
|
PRINTCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PRINTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
TRUNK_VERSION: 0.21.14
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: wasm32-unknown-unknown
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: release-web
|
|
- name: Install trunk
|
|
run: |
|
|
curl -fsSL "https://github.com/trunk-rs/trunk/releases/download/v${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz" \
|
|
| tar -xz -C "$HOME/.cargo/bin" trunk
|
|
trunk --version
|
|
- name: Apply version override
|
|
if: inputs.version != ''
|
|
run: cargo xtask version set "$PRINTCRAFT_VERSION"
|
|
- name: Build and zip
|
|
run: packaging/web/package.sh
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-web
|
|
path: dist/release/*
|
|
if-no-files-found: error
|
|
|
|
release:
|
|
name: Draft GitHub Release
|
|
needs: [version, macos, windows, linux, freebsd, web]
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
permissions:
|
|
contents: write
|
|
env:
|
|
VERSION: ${{ needs.version.outputs.version }}
|
|
PRERELEASE: ${{ needs.version.outputs.prerelease }}
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
GH_REPO: ${{ github.repository }}
|
|
steps:
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
pattern: release-*
|
|
path: artifacts
|
|
merge-multiple: true
|
|
- name: Checksums
|
|
working-directory: artifacts
|
|
run: |
|
|
sha256sum -- * | tee SHA256SUMS.txt
|
|
- name: Create or update the draft release
|
|
working-directory: artifacts
|
|
run: |
|
|
tag="v$VERSION"
|
|
title="PrintCraft v$VERSION"
|
|
pre=()
|
|
if [ "$PRERELEASE" = true ]; then pre=(--prerelease); fi
|
|
if draft="$(gh release view "$tag" --json isDraft --jq .isDraft 2>/dev/null)"; then
|
|
if [ "$draft" != "true" ]; then
|
|
echo "::error::Release $tag is already published. Bump the version (cargo xtask version set) before pushing to release."
|
|
exit 1
|
|
fi
|
|
echo "Updating draft $tag: replacing its assets"
|
|
gh release view "$tag" --json assets --jq '.assets[].name' | while read -r asset; do
|
|
gh release delete-asset "$tag" "$asset" --yes
|
|
done
|
|
gh release edit "$tag" --draft --title "$title" --target "$GITHUB_SHA" --prerelease="$PRERELEASE"
|
|
gh release upload "$tag" --clobber -- *
|
|
else
|
|
echo "Creating draft $tag"
|
|
gh release create "$tag" --draft --title "$title" --target "$GITHUB_SHA" --generate-notes "${pre[@]}" -- *
|
|
fi
|
|
{
|
|
echo "Draft release **$title** at \`${GITHUB_SHA::9}\`:"
|
|
echo
|
|
sed 's/^/ /' SHA256SUMS.txt
|
|
} >>"$GITHUB_STEP_SUMMARY"
|