mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-25 02:17:30 -06:00
* Flatpak single-file bundle as a release artifact (#140) packaging/linux/flatpak/ai.storyteller.photocraft.bundle.yml repackages the release's Linux tarball (no Rust build, no network) on the freedesktop 26.08 runtime; packaging/linux/flatpak-bundle.sh builds it with flatpak-builder and flatpak build-bundle and smoke-tests it. release.yml gains a Flatpak job per arch that feeds the draft release and SHA256SUMS. The Flathub manifest moves to 26.08 with the same documented finish-args (portals + Pictures/Documents), and packaging-lint checks the two manifests agree. Font scanning also looks in /run/host/fonts and /run/host/user-fonts so host fonts show up in the sandbox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Docs: installing the Flatpak bundle (#140) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Flatpak job: install the SVG pixbuf loader for appstream compose Without librsvg2-common (absent on the x86_64 runner image) the host's appstreamcli compose fails with file-read-error on the scalable icon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * release.yml: the Flatpak job runs without the release environment It only repackages the Linux job's tarball and signs nothing, so it doesn't need (and shouldn't hold) the signing secrets while running third-party tooling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- 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 "PhotoCraft 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
|
|
PHOTOCRAFT_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 "### PhotoCraft v$v (\`${GITHUB_SHA::9}\`)" >>"$GITHUB_STEP_SUMMARY"
|
|
|
|
macos:
|
|
name: macOS universal
|
|
needs: version
|
|
runs-on: macos-15
|
|
environment: release
|
|
env:
|
|
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PHOTOCRAFT_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 "$PHOTOCRAFT_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:
|
|
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PHOTOCRAFT_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 "$PHOTOCRAFT_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:
|
|
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PHOTOCRAFT_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 "$PHOTOCRAFT_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/photocraft$|metainfo|applications'
|
|
ldd target/release/photocraft
|
|
python3 -c "import yaml; m = yaml.safe_load(open('packaging/linux/flatpak/ai.storyteller.photocraft.yml')); assert m['id'] == 'ai.storyteller.photocraft'"
|
|
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
|
|
|
|
flatpak:
|
|
name: Flatpak ${{ matrix.arch }}
|
|
needs: [version, linux]
|
|
# Repackages the Linux job's tarball (the same binaries as the AppImage/deb/rpm); no Rust
|
|
# build here. 24.04 for a newer flatpak-builder (1.4) than 22.04 ships.
|
|
runs-on: ${{ matrix.runner }}
|
|
# No `environment: release`: this job signs nothing, so it gets no release secrets.
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- { arch: x86_64, runner: ubuntu-24.04 }
|
|
- { arch: aarch64, runner: ubuntu-24.04-arm }
|
|
env:
|
|
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/download-artifact@v4
|
|
with:
|
|
name: release-linux-${{ matrix.arch }}
|
|
path: dist/linux
|
|
- name: Install flatpak-builder
|
|
run: |
|
|
sudo apt-get update
|
|
# librsvg2-common: the SVG pixbuf loader. flatpak-builder runs the host's
|
|
# `appstreamcli compose`, which renders the scalable icon and fails without it.
|
|
sudo apt-get install -y --no-install-recommends flatpak flatpak-builder librsvg2-common
|
|
# Ubuntu 24.04's AppArmor blocks the unprivileged user namespaces bubblewrap needs.
|
|
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
|
- name: Build the Flatpak bundle
|
|
run: packaging/linux/flatpak-bundle.sh "dist/linux/photocraft-$PHOTOCRAFT_VERSION-linux-${{ matrix.arch }}.tar.gz"
|
|
- uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-flatpak-${{ matrix.arch }}
|
|
path: dist/release/*.flatpak
|
|
if-no-files-found: error
|
|
|
|
web:
|
|
name: Web (wasm)
|
|
needs: version
|
|
runs-on: ubuntu-latest
|
|
environment: release
|
|
env:
|
|
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
PHOTOCRAFT_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 "$PHOTOCRAFT_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, flatpak, 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="PhotoCraft 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"
|