Files
craft-common-actions/.github/workflows/release.yml
T
nnaannooandKristian Myram 6b66469bba Push the Flatpak OCI tags in the release workflow, not the app's script (#146)
The release job ran each app's packaging/linux/flatpak-oci.sh --push. Most
apps still carry the copy from before scripts/scaffold-flatpak-oci.sh learnt
to guard the stable tag, and it moves stable-<arch> on every push, so a
prerelease or a test run dispatched from any branch became what stable-<arch>
clients install. 15 of the 17 apps carry that copy.

Call the script without --push, which only builds the layout in every copy,
and push from the workflow: <version>-<arch> on every non-PR run, and
stable-<arch> only for a stable version built from the release branch, the
rule the scaffold template already uses. No app needs to change.

Co-authored-by: Kristian Myram <kmy@oresundsbron.com>
2026-11-05 09:12:05 -05:00

1369 lines
65 KiB
YAML

name: "Release"
on:
workflow_call:
inputs:
app-name:
description: "Application repository name (e.g. photocraft, cadcraft)"
type: string
required: true
app-title:
description: "Application display name (e.g. PhotoCraft, CADCraft)"
type: string
required: true
craft-fonts-ref:
# The suite's craft-fonts pin. Bump it here, in freebsd.yml and in gate.yml together.
description: "Git ref for storytold/craft-fonts embedded font assets. Defaults to the suite's pin; override it only for an app that needs another commit. Desktop builds run with CRAFT_FONTS_DIR and CRAFT_FONTS_REQUIRED=1 either way"
type: string
required: false
default: "bfcbf714e45a3ea8e98f88ab2b7971372a576414"
web-craft-fonts:
description: "Build the web release with craft-fonts too (CRAFT_FONTS_DIR); needs craft-fonts-ref. Off by default: each app's build.rs picks which fonts its web build embeds"
type: boolean
required: false
default: false
version:
description: "Version override for a test run (empty: read from Cargo.toml)"
type: string
required: false
default: ""
contributors-artifact:
description: "Optional contributor snapshot artifact from refresh-contributors.yml in this workflow run; installed before every source build"
type: string
required: false
default: ""
has-web:
description: "Whether to build the WebAssembly (wasm) release"
type: boolean
required: false
default: true
has-riscv64:
description: "Whether to build the Linux riscv64 release"
type: boolean
required: false
default: true
has-freebsd:
description: "Whether to build the FreeBSD release"
type: boolean
required: false
default: true
has-arch:
description: "Whether to build the Arch Linux package (.pkg.tar.zst) via makepkg"
type: boolean
required: false
default: true
wix-version:
description: "Version of WiX tool to install"
type: string
required: false
default: "5.0.2"
nfpm-version:
description: "Version of nfpm tool to install"
type: string
required: false
default: "2.47.0"
trunk-version:
description: "Version of trunk tool to install"
type: string
required: false
default: "0.21.14"
freebsd-release:
description: "FreeBSD OS version to run in VM"
type: string
required: false
default: "15.1-STABLE"
freebsd-architectures:
# aarch64 is cross-compiled in the x86_64 VM, so packaging/freebsd/package.sh must build
# with CARGO_BUILD_TARGET and name its archive after it, not after uname -m (#39).
description: 'JSON array of FreeBSD release architectures; packaging/freebsd/package.sh must honor CARGO_BUILD_TARGET for each listed architecture'
type: string
required: false
default: '["x86_64","aarch64"]'
has-server:
description: "Whether to build and release the headless Linux server"
type: boolean
required: false
default: false
secrets:
APPLE_CERTIFICATE:
required: false
APPLE_CERTIFICATE_PASSWORD:
required: false
KEYCHAIN_PASSWORD:
required: false
APPLE_ID:
required: false
APPLE_PASSWORD:
required: false
APPLE_TEAM_ID:
required: false
WINDOWS_CERTIFICATE:
required: false
WINDOWS_CERTIFICATE_PASSWORD:
required: false
AZURE_TENANT_ID:
required: false
AZURE_CLIENT_ID:
required: false
AZURE_CLIENT_SECRET:
required: false
AZURE_SIGNING_ENDPOINT:
required: false
AZURE_SIGNING_ACCOUNT:
required: false
AZURE_CERT_PROFILE:
required: false
# ASCII-armored OpenPGP secret key without a passphrase (a signing subkey is enough). It signs
# every Linux package format, the Flatpak bundle's commit and OCI image, and SHA256SUMS.txt.
LINUX_SIGNING_KEY:
required: false
outputs:
version:
description: "Resolved release version without a leading v"
value: ${{ jobs.version.outputs.version }}
prerelease:
description: "Whether the resolved version is a prerelease"
value: ${{ jobs.version.outputs.prerelease }}
permissions:
contents: read
jobs:
# Fails fast before any build: git dependencies must come from github.com/storytold, and the
# lock file must not declare source replacement, patches or path overrides that could silently
# swap one. Lives here (not in each app's release.yml) so every craftapp gets the gate at @main.
# Every build job needs `version`, so these builds are gated transitively.
git-sources:
name: Git dependencies come from storytold
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Git dependencies come from storytold
run: |
set -euo pipefail
test -f Cargo.lock || { echo "Cargo.lock is missing"; exit 1; }
# Source replacement, patches and path overrides in cargo config never show up
# in Cargo.lock. Parsed rather than grepped: TOML has many spellings of one key.
# Cargo still reads the legacy .cargo/config.
python3 - <<'PY'
import os, sys, tomllib
for path in (".cargo/config", ".cargo/config.toml"):
if not os.path.exists(path):
continue
config = tomllib.load(open(path, "rb"))
replaced = [name for name, source in config.get("source", {}).items()
if isinstance(source, dict) and "replace-with" in source]
if replaced or "patch" in config or "paths" in config:
print(f"{path} replaces, patches or overrides a source")
sys.exit(1)
PY
# Fails when Cargo.lock is out of date with the manifests.
cargo metadata --locked --format-version 1 > /dev/null
python3 - <<'PY'
import sys, tomllib
lock = tomllib.load(open("Cargo.lock", "rb"))
bad = sorted({p["source"] for p in lock.get("package", [])
if p.get("source", "").startswith("git+")
and not p["source"].startswith("git+https://github.com/storytold/")})
if bad:
print("Git dependencies outside github.com/storytold:", *bad, sep="\n")
sys.exit(1)
PY
version:
timeout-minutes: 10
name: version
needs: git-sources
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.version }}
date: ${{ steps.v.outputs.date }}
prerelease: ${{ steps.v.outputs.prerelease }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: v
name: Resolve version
uses: storytold/craft-common-actions/actions/resolve-version@main
with:
input-version: ${{ inputs.version }}
app-title: ${{ inputs.app-title }}
macos:
timeout-minutes: 90
name: macOS universal
needs: [version]
runs-on: macos-15-xlarge
environment: release
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
# A signed job reads only the secrets the caller lists in its `secrets:` block; values come
# from the repo's `release` environment. An unlisted name is empty, and the app's packaging
# would then warn and ship unsigned, so on the release branch fail here instead.
- name: Require signing secrets on the release branch
if: github.ref == 'refs/heads/release'
shell: bash
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
missing=""
for name in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD KEYCHAIN_PASSWORD APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID; do
[ -n "${!name}" ] || missing="$missing $name"
done
if [ -n "$missing" ]; then
echo "::error::macOS release builds must be signed and notarized, but these secrets are empty:$missing. List them in the caller's secrets: block and set them in the repo's release environment."
exit 1
fi
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-fonts
if: inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
targets: aarch64-apple-darwin, x86_64-apple-darwin
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-macos-universal
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$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 }}
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
run: packaging/macos/package.sh --arch universal
- name: Verify signatures and notarization
if: hashFiles('packaging/macos/verify.sh') != ''
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
for attempt in 1 2 3 4; do
if packaging/macos/verify.sh --arch universal; then
exit 0
fi
if [ "$attempt" -eq 4 ]; then
exit 1
fi
echo "macOS verification failed (attempt $attempt of 4); retrying in 20 seconds" >&2
sleep 20
done
- name: Note missing macOS verification
if: github.ref == 'refs/heads/release' && hashFiles('packaging/macos/verify.sh') == ''
run: echo "::warning::packaging/macos/verify.sh is missing, so this release was not checked for a signature or notarization ticket."
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
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:
timeout-minutes: 90
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 }
- { arch: arm64, target: aarch64-pc-windows-msvc }
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
# See the macOS job: unlisted secrets are empty, and the build would ship unsigned.
# Signing needs either the PFX pair or all six Azure Trusted Signing values.
- name: Require signing secrets on the release branch
if: github.ref == 'refs/heads/release'
shell: bash
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: |
if [ -n "$WINDOWS_CERTIFICATE" ] && [ -n "$WINDOWS_CERTIFICATE_PASSWORD" ]; then exit 0; fi
missing=""
for name in AZURE_TENANT_ID AZURE_CLIENT_ID AZURE_CLIENT_SECRET AZURE_SIGNING_ENDPOINT AZURE_SIGNING_ACCOUNT AZURE_CERT_PROFILE; do
[ -n "${!name}" ] || missing="$missing $name"
done
if [ -n "$missing" ]; then
echo "::error::Windows release builds must be signed, but there is no WINDOWS_CERTIFICATE pair and these Azure Trusted Signing secrets are empty:$missing. List them in the caller's secrets: block and set them in the repo's release environment."
exit 1
fi
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-fonts
if: inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-windows-${{ matrix.arch }}
- name: Apply version override
if: inputs.version != ''
shell: bash
run: cargo xtask version set "$VERSION"
- name: Install WiX
uses: storytold/craft-common-actions/actions/install-wix@main
with:
wix-version: ${{ inputs.wix-version }}
- 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 }}
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
run: ./packaging/windows/package.ps1 -Arch ${{ matrix.arch }}
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-windows-${{ matrix.arch }}
path: dist/release/*
if-no-files-found: error
linux:
timeout-minutes: 90
name: Linux ${{ matrix.arch }}
needs: [version]
# The signing key lives in the release environment, as it does for the macOS, Windows and
# flatpak jobs; without this the Linux packages are built unsigned.
environment: release
runs-on: ${{ matrix.runner }}
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:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-fonts
if: inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- uses: storytold/craft-common-actions/actions/install-linux-deps@main
with:
deb-arch: ${{ matrix.deb }}
nfpm-version: ${{ inputs.nfpm-version }}
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-linux-${{ matrix.arch }}
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$VERSION"
- name: Build and package (AppImage, deb, rpm, tar.gz)
env:
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
run: packaging/linux/package.sh
- name: Import the Linux signing key
if: github.ref == 'refs/heads/release'
id: linux_signing
uses: storytold/craft-common-actions/actions/import-signing-key@main
with:
key: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Sign the RPM packages
if: steps.linux_signing.outputs.enabled == 'true'
uses: storytold/craft-common-actions/actions/sign-rpms@main
with:
path: dist/release
- name: Check the packages
run: |
dpkg-deb --info dist/release/*.deb || true
dpkg-deb --contents dist/release/*.deb | grep -E 'usr/bin/|metainfo|applications' || true
for appimage in dist/release/*.AppImage; do
if [ -f "$appimage" ]; then
chmod +x "$appimage"
APPIMAGE_EXTRACT_AND_RUN=1 "$appimage" --version || true
fi
done
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-linux-${{ matrix.arch }}
path: dist/release/*
if-no-files-found: error
flatpak:
timeout-minutes: 90
name: Flatpak ${{ matrix.arch }}
needs: [version, linux]
runs-on: ${{ matrix.runner }}
# LINUX_SIGNING_KEY comes from the repo's release environment, as the macOS secrets do.
environment: release
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
- { arch: x86_64, runner: ubuntu-24.04 }
- { arch: aarch64, runner: ubuntu-24.04-arm }
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
OCI_SIGNATURES_READY: ${{ vars.LINUX_OCI_SIGNATURES_READY }}
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-linux-${{ matrix.arch }}
path: dist/linux
- name: Install flatpak-builder
run: |
sudo apt-get update
# elfutils is only a Recommends of flatpak-builder, but flatpak-builder runs its eu-strip
# on every module it builds with debuginfo, such as the apps' cups-client.
sudo apt-get install -y --no-install-recommends flatpak flatpak-builder elfutils librsvg2-common skopeo
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Import the Linux signing key
if: github.ref == 'refs/heads/release'
# flatpak-bundle.sh signs the commit and embeds the public key when SIGNING_FPR is set.
uses: storytold/craft-common-actions/actions/import-signing-key@main
with:
key: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Build the Flatpak bundle
id: flatpak_bundle
env:
RELEASE_VERSION: ${{ needs.version.outputs.version }}
ARCH: ${{ matrix.arch }}
run: |
shopt -s nullglob
# The app's own tarball: <file-prefix>-<version>-linux-<arch>.tar.gz. The file prefix can
# differ from app-name (craft-launcher ships artcraft-launcher-*), and CLI or server
# tarballs (pdfcraft-cli-*, figcraft-server-*) sit beside it.
tarballs=()
for f in dist/linux/*-"${RELEASE_VERSION}"-linux-"${ARCH}".tar.gz; do
case "${f##*/}" in *-cli-*|*-server-*) ;; *) tarballs+=("$f") ;; esac
done
if [ "${#tarballs[@]}" -ne 1 ]; then
echo "::error::expected one app tarball for ${RELEASE_VERSION} in release-linux-${ARCH}, found ${#tarballs[@]}: ${tarballs[*]}"
exit 1
fi
tarball="${tarballs[0]}"
packaging/linux/flatpak-bundle.sh "$tarball"
printf 'tarball=%s\n' "$tarball" >> "$GITHUB_OUTPUT"
- name: Publish Flatpak OCI layout to GHCR
if: github.event_name != 'pull_request'
env:
RELEASE_VERSION: ${{ needs.version.outputs.version }}
ARCH: ${{ matrix.arch }}
REGISTRY: ghcr.io/${{ github.repository }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARBALL: ${{ steps.flatpak_bundle.outputs.tarball }}
run: |
if [ -x packaging/linux/flatpak-oci.sh ]; then
REGISTRY="${REGISTRY,,}"
creds="${GITHUB_ACTOR:-storytold}:$GITHUB_TOKEN"
# The app's script only builds the layout; the tags are pushed here. Older copies of
# flatpak-oci.sh move stable-<arch> on every --push, so a prerelease or a test run
# from any branch would become what stable-<arch> clients install.
packaging/linux/flatpak-oci.sh "$TARBALL"
base="$(basename "$TARBALL" .tar.gz)"
layout="dist/release/$base-oci"
if [ ! -d "$layout" ]; then
echo "::error::packaging/linux/flatpak-oci.sh did not write the OCI layout $layout"
exit 1
fi
echo "==> Pushing to $REGISTRY:$RELEASE_VERSION-$ARCH"
skopeo copy --format oci --dest-creds "$creds" "oci:$layout" "docker://$REGISTRY:$RELEASE_VERSION-$ARCH"
# Only a stable version built from the release branch may move the stable tag.
if [[ "$RELEASE_VERSION" != *-* && "$GITHUB_REF" == refs/heads/release ]]; then
echo "==> Pushing to $REGISTRY:stable-$ARCH"
skopeo copy --format oci --dest-creds "$creds" "oci:$layout" "docker://$REGISTRY:stable-$ARCH"
else
echo "Leaving $REGISTRY:stable-$ARCH unchanged: $RELEASE_VERSION from $GITHUB_REF is not a stable release-branch build"
fi
# The pushed manifest, byte for byte: the release job signs its digest for Flatpak's
# signature lookaside, and the release keeps it so the digest can be checked.
skopeo inspect --raw --creds "$creds" \
"docker://$REGISTRY:$RELEASE_VERSION-$ARCH" >"dist/release/$base.oci-manifest.json"
fi
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-flatpak-${{ matrix.arch }}
path: |
dist/release/*.flatpak
dist/release/*.oci-manifest.json
if-no-files-found: error
arch:
name: Arch Linux ${{ matrix.arch }}
if: inputs.has-arch
needs: [version, linux]
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
arch: [x86_64, aarch64]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-linux-${{ matrix.arch }}
path: dist/linux
- name: Find the release tarball
id: tarball
env:
RELEASE_VERSION: ${{ needs.version.outputs.version }}
ARCH: ${{ matrix.arch }}
run: |
shopt -s nullglob
# The app's own tarball: <file-prefix>-<version>-linux-<arch>.tar.gz. The file prefix can
# differ from app-name (craft-launcher ships artcraft-launcher-*), and CLI or server
# tarballs (pdfcraft-cli-*, figcraft-server-*) sit beside it.
tarballs=()
for f in dist/linux/*-"${RELEASE_VERSION}"-linux-"${ARCH}".tar.gz; do
case "${f##*/}" in *-cli-*|*-server-*) ;; *) tarballs+=("$f") ;; esac
done
if [ "${#tarballs[@]}" -ne 1 ]; then
echo "::error::expected one app tarball for ${RELEASE_VERSION} in release-linux-${ARCH}, found ${#tarballs[@]}: ${tarballs[*]}"
exit 1
fi
tarball="${tarballs[0]}"
echo "path=$tarball" >>"$GITHUB_OUTPUT"
- uses: storytold/craft-common-actions/actions/arch-package@main
with:
tarball: ${{ steps.tarball.outputs.path }}
arch: ${{ matrix.arch }}
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-arch-${{ matrix.arch }}
path: dist/release/*.pkg.tar.zst
if-no-files-found: error
freebsd:
name: FreeBSD ${{ matrix.arch }}
if: inputs.has-freebsd
needs: [version]
runs-on: ubuntu-latest
timeout-minutes: 300
strategy:
fail-fast: false
matrix:
# aarch64 is in the default freebsd-architectures; callers can narrow it (#39).
arch: ${{ fromJSON(inputs.freebsd-architectures) }}
env:
APP_NAME: ${{ inputs.app-name }}
CARGO_HOME: /var/tmp/craft-cargo
CARGO_TARGET_DIR: /var/tmp/craft-target
CARGO_BUILD_JOBS: 4
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
- name: Check the FreeBSD architecture
env:
ARCH: ${{ matrix.arch }}
run: |
# The guest is always x86_64 and only aarch64 is cross-compiled: any other value
# would build x86_64 binaries and package them under its own name.
case "$ARCH" in
x86_64 | aarch64) ;;
*)
echo "::error::unsupported FreeBSD architecture '$ARCH' in freebsd-architectures; use x86_64 or aarch64"
exit 1
;;
esac
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-fonts
if: inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- name: Start the FreeBSD VM
uses: vmactions/freebsd-vm@c46abacb49f09938ca4e1702d15d836285d694cc # v1.5.9
with:
release: ${{ inputs.freebsd-release == '15.1-STABLE' && '15.1' || inputs.freebsd-release }}
# Always an x86_64 guest, which KVM accelerates: aarch64 is cross-compiled in it,
# because an emulated aarch64 guest takes over 5 hours for most apps (#39).
usesh: true
cpu: 4
mem: 12288
copyback: false
envs: "APP_NAME CARGO_HOME CARGO_TARGET_DIR CARGO_INCREMENTAL CARGO_BUILD_JOBS VERSION BUILD_DATE BUILD_SHA INPUT_VERSION CADCRAFT_VERSION CADCRAFT_BUILD_DATE CADCRAFT_BUILD_SHA ARTCRAFT_LAUNCHER_VERSION ARTCRAFT_LAUNCHER_BUILD_DATE ARTCRAFT_LAUNCHER_BUILD_SHA DECKCRAFT_VERSION DECKCRAFT_BUILD_DATE DECKCRAFT_BUILD_SHA DESIGNCRAFT_VERSION DESIGNCRAFT_BUILD_DATE DESIGNCRAFT_BUILD_SHA EFFECTCRAFT_VERSION EFFECTCRAFT_BUILD_DATE EFFECTCRAFT_BUILD_SHA FILMCRAFT_VERSION FILMCRAFT_BUILD_DATE FILMCRAFT_BUILD_SHA GRIDCRAFT_VERSION GRIDCRAFT_BUILD_DATE GRIDCRAFT_BUILD_SHA LIGHTCRAFT_VERSION LIGHTCRAFT_BUILD_DATE LIGHTCRAFT_BUILD_SHA PDFCRAFT_VERSION PDFCRAFT_BUILD_DATE PDFCRAFT_BUILD_SHA PHOTOCRAFT_VERSION PHOTOCRAFT_BUILD_DATE PHOTOCRAFT_BUILD_SHA SOUNDCRAFT_VERSION SOUNDCRAFT_BUILD_DATE SOUNDCRAFT_BUILD_SHA VECTORCRAFT_VERSION VECTORCRAFT_BUILD_DATE VECTORCRAFT_BUILD_SHA WORDCRAFT_VERSION WORDCRAFT_BUILD_DATE WORDCRAFT_BUILD_SHA FIGCRAFT_VERSION FIGCRAFT_BUILD_DATE FIGCRAFT_BUILD_SHA"
prepare: |
# Keep rustup/proxies outside the Cargo data cache.
unset CARGO_HOME CARGO_TARGET_DIR
if [ "${{ matrix.arch }}" = aarch64 ]; then
# The host compiler and the aarch64 standard library come from the amd64 and
# aarch64 lang/rust packages, which must be the same build. "latest" can build
# them days apart; the quarterly branch keeps them in step.
mkdir -p /usr/local/etc/pkg/repos
printf 'FreeBSD-ports: { url: "https://pkg.FreeBSD.org/${ABI}/quarterly" }\n' > /usr/local/etc/pkg/repos/FreeBSD.conf
pkg update -f -q
fi
pkg install -y bash git curl pkgconf cmake python3 libxkbcommon wayland libX11 libXcursor libXrandr libXi libxcb mesa-libs vulkan-loader gtk3 fontconfig freetype2 alsa-lib
# aarch64-unknown-freebsd is a tier-3 Rust target: rustup publishes no toolchain
# or standard library for it ("installer for platform not found"), so use
# FreeBSD's lang/rust package.
if [ "${{ matrix.arch }}" = aarch64 ]; then
pkg install -y rust
else
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
fi
# Keep this step identical to the one in freebsd.yml; tests/test_freebsd.py checks it.
- name: Set up the aarch64 cross toolchain
if: matrix.arch == 'aarch64'
shell: freebsd {0}
run: |
set -eu
# Stable Rust, no -Zbuild-std: the aarch64 standard library is copied from FreeBSD's
# aarch64 lang/rust package, and C code links with base clang and lld against an
# arm64 sysroot (base.txz plus the libraries the prepare step installs).
target=aarch64-unknown-freebsd
X=/var/tmp/craft-cross
S=$X/sysroot
mkdir -p "$X/db" "$X/cache" "$S"
release=$(freebsd-version -u | sed 's/-p[0-9]*$//')
P="-o ABI=FreeBSD:${release%%.*}:aarch64 -o OSVERSION=$(uname -U) -o PKG_DBDIR=$X/db -o PKG_CACHEDIR=$X/cache -o IGNORE_OSVERSION=yes"
pkg $P update -q
host=$(pkg query %v rust)
cross=$(pkg $P rquery %v rust)
if [ "$host" != "$cross" ]; then
echo "error: lang/rust is $host for amd64 but $cross for aarch64; the standard library must match the compiler" >&2
exit 1
fi
pkg $P fetch -y -q rust
# pkg links each name-version.pkg to its hashed file.
tar -xf "$X/cache/rust-$cross.pkg" -C "$X" --include "*usr/local/lib/rustlib/$target/*"
cp -R "$X/usr/local/lib/rustlib/$target" /usr/local/lib/rustlib/
base=https://download.freebsd.org/releases/arm64/aarch64/$release
fetch -q -o "$X/MANIFEST" "$base/MANIFEST"
fetch -q -o "$X/base.txz" "$base/base.txz"
if [ "$(awk '$1 == "base.txz" { print $2 }' "$X/MANIFEST")" != "$(sha256 -q "$X/base.txz")" ]; then
echo "error: arm64 base.txz does not match its MANIFEST" >&2
exit 1
fi
tar -xf "$X/base.txz" -C "$S" ./lib ./usr/lib ./usr/include ./usr/libdata
# The libraries the prepare step installs; the build tools and fonts stay host-only.
pkg $P fetch -y -q -d libxkbcommon wayland libX11 libXcursor libXrandr libXi libxcb mesa-libs vulkan-loader gtk3 fontconfig freetype2 alsa-lib
for p in "$X"/cache/*.pkg; do
[ ! -L "$p" ] || continue
case "$p" in */rust-*) continue ;; esac
tar -xf "$p" -C "$S" --exclude '+*'
done
for tool in cc c++; do
printf '#!/bin/sh\nexec %s --target=%s%s --sysroot=%s -fuse-ld=lld -I%s/usr/local/include -L%s/usr/local/lib -Wl,-rpath-link,%s/usr/local/lib "$@"\n' \
"$tool" "$target" "${release%%-*}" "$S" "$S" "$S" "$S" > "$X/$tool"
chmod +x "$X/$tool"
done
cat > "$X/env" <<EOF
export CARGO_BUILD_TARGET=$target
export CARGO_TARGET_AARCH64_UNKNOWN_FREEBSD_LINKER=$X/cc
export CC_aarch64_unknown_freebsd=$X/cc CXX_aarch64_unknown_freebsd=$X/c++ AR_aarch64_unknown_freebsd=/usr/bin/ar
export PKG_CONFIG_ALLOW_CROSS=1 PKG_CONFIG_SYSROOT_DIR=$S PKG_CONFIG_LIBDIR=$S/usr/local/libdata/pkgconfig:$S/usr/libdata/pkgconfig
EOF
rustc --print target-libdir --target "$target"
- name: Restore FreeBSD release Cargo cache
id: cargo-cache
continue-on-error: true
timeout-minutes: 10
uses: storytold/craft-common-actions/actions/freebsd-cargo-cache@main
with:
profile: release
configuration: ${{ toJSON(inputs) }}
source-hash: ${{ hashFiles('**/Cargo.lock', '**/Cargo.toml', '**/build.rs', '.cargo/**', 'rust-toolchain*', 'packaging/**', '.github/workflows/release.yml') }}
- name: Build and package
shell: freebsd {0}
run: |
set -eu
# Only rustup writes this; the lang/rust package installs into /usr/local/bin.
[ ! -f "$HOME/.cargo/env" ] || . "$HOME/.cargo/env"
# A failed restore may leave partial files. Rebuild from an empty cache.
if [ "${{ steps.cargo-cache.outcome }}" = failure ]; then
rm -rf /var/tmp/craft-target /var/tmp/craft-cargo/registry /var/tmp/craft-cargo/git
fi
git config --global --add safe.directory "*"
# Before the cross environment: xtask has to run on the guest.
if [ -n "$INPUT_VERSION" ]; then cargo xtask version set "$VERSION" || cargo run -q -p xtask -- version set "$VERSION"; fi
# Written by "Set up the aarch64 cross toolchain": cargo then builds for aarch64.
[ ! -f /var/tmp/craft-cross/env ] || . /var/tmp/craft-cross/env
# Cargo puts a cross build's binaries under target/<triple>/release.
rel="${CARGO_BUILD_TARGET:+$CARGO_BUILD_TARGET/}release"
export CRAFT_FONTS_DIR="$PWD/craft-fonts" CRAFT_FONTS_REQUIRED=1
if [ -f craft-i18n.rev ]; then export CRAFT_I18N_DIR="$PWD/craft-i18n" CRAFT_I18N_REQUIRED=1; fi
if [ -f packaging/freebsd/package.sh ]; then
bash packaging/freebsd/package.sh
else
set -- -p "$APP_NAME"
if cargo metadata --format-version 1 --no-deps | python3 -c 'import json, sys; sys.exit(not any(p["name"] == sys.argv[1] for p in json.load(sys.stdin)["packages"]))' "$APP_NAME-cli"; then
set -- "$@" -p "$APP_NAME-cli"
fi
cargo build --release --locked "$@"
name="$APP_NAME-$VERSION-freebsd-${{ matrix.arch }}"
mkdir -p "dist/release/$name"
cp "target/$rel/$APP_NAME" "dist/release/$name/" 2>/dev/null || cp "/var/tmp/craft-target/$rel/$APP_NAME" "dist/release/$name/"
if [ -f "target/$rel/$APP_NAME-cli" ]; then
cp "target/$rel/$APP_NAME-cli" "dist/release/$name/"
elif [ -f "/var/tmp/craft-target/$rel/$APP_NAME-cli" ]; then
cp "/var/tmp/craft-target/$rel/$APP_NAME-cli" "dist/release/$name/"
fi
cp README.md LICENSE-MIT LICENSE-APACHE NOTICE ATTRIBUTION.md "dist/release/$name/" 2>/dev/null || true
if [ -f "packaging/linux/ai.storyteller.$APP_NAME.desktop" ]; then
cp "packaging/linux/ai.storyteller.$APP_NAME.desktop" "dist/release/$name/"
fi
mkdir -p "dist/release/$name/icons"
cp -R assets/app-icon/hicolor "dist/release/$name/icons/" 2>/dev/null || true
tar -C dist/release -czf "dist/release/$name.tar.gz" "$name"
rm -rf "dist/release/$name"
fi
# The guest is x86_64 either way: a package.sh that names its archive after uname -m
# instead of CARGO_BUILD_TARGET would ship an x86_64-labelled aarch64 build, or worse.
found=
for archive in dist/release/*-freebsd-*.tar.gz; do
[ -f "$archive" ] || continue
case "$archive" in
*-freebsd-${{ matrix.arch }}.tar.gz) found=1 ;;
*)
echo "error: $archive is not a FreeBSD ${{ matrix.arch }} archive; packaging/freebsd/package.sh must honor CARGO_BUILD_TARGET" >&2
exit 1
;;
esac
done
if [ -z "$found" ]; then
echo "error: no FreeBSD ${{ matrix.arch }} archive was produced" >&2
exit 1
fi
- name: Copy release archives from the VM
run: |
mkdir -p dist/release
rsync -a --timeout=1800 --rsync-path='env PATH=/usr/local/bin:/usr/bin:/bin rsync' \
-e 'ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=60 -o ConnectTimeout=120' \
"freebsd:$GITHUB_WORKSPACE/dist/release/" dist/release/
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-freebsd-${{ matrix.arch }}
path: dist/release/*
if-no-files-found: error
- name: Save FreeBSD release Cargo cache
if: github.event_name != 'pull_request' && github.event_name != 'pull_request_target' && steps.cargo-cache.outputs.key != '' && steps.cargo-cache.outputs.cache-hit != 'true'
continue-on-error: true
timeout-minutes: 10
uses: storytold/craft-common-actions/actions/freebsd-cargo-cache@main
with:
phase: save
profile: release
configuration: ${{ toJSON(inputs) }}
source-hash: ${{ hashFiles('**/Cargo.lock', '**/Cargo.toml', '**/build.rs', '.cargo/**', 'rust-toolchain*', 'packaging/**', '.github/workflows/release.yml') }}
key: ${{ steps.cargo-cache.outputs.key }}
web:
timeout-minutes: 90
name: Web (wasm)
if: inputs.has-web
needs: [version]
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-web
- uses: storytold/craft-common-actions/actions/install-trunk@main
with:
trunk-version: ${{ inputs.trunk-version }}
- name: Check out craft-fonts
if: inputs.web-craft-fonts && inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$VERSION"
- name: Build and zip
if: ${{ !(inputs.web-craft-fonts && inputs.craft-fonts-ref != '') }}
run: packaging/web/package.sh
- name: Build and zip (with craft-fonts)
if: inputs.web-craft-fonts && inputs.craft-fonts-ref != ''
env:
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
run: packaging/web/package.sh
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-web
path: dist/release/*
if-no-files-found: error
linux-riscv64:
timeout-minutes: 90
name: Linux riscv64
if: inputs.has-riscv64
needs: [version]
environment: release
# Not 22.04 like the other Linux jobs: Ubuntu never built jammy's ncurses security update for
# riscv64, so the amd64 and riscv64 libtinfo6 can't match and the cross deps don't install (#44).
runs-on: ubuntu-24.04
env:
# Built on 24.04, the binaries need GLIBC_2.39. The deb and rpm declare it only where the
# app's nfpm.yaml reads ${GLIBC_FLOOR}; an app still hard-coding 2.35 keeps declaring 2.35.
GLIBC_FLOOR: "2.39"
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
CADCRAFT_VERSION: ${{ needs.version.outputs.version }}
CADCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
CADCRAFT_BUILD_SHA: ${{ github.sha }}
ARTCRAFT_LAUNCHER_VERSION: ${{ needs.version.outputs.version }}
ARTCRAFT_LAUNCHER_BUILD_DATE: ${{ needs.version.outputs.date }}
ARTCRAFT_LAUNCHER_BUILD_SHA: ${{ github.sha }}
DECKCRAFT_VERSION: ${{ needs.version.outputs.version }}
DECKCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DECKCRAFT_BUILD_SHA: ${{ github.sha }}
DESIGNCRAFT_VERSION: ${{ needs.version.outputs.version }}
DESIGNCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
DESIGNCRAFT_BUILD_SHA: ${{ github.sha }}
EFFECTCRAFT_VERSION: ${{ needs.version.outputs.version }}
EFFECTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
EFFECTCRAFT_BUILD_SHA: ${{ github.sha }}
FILMCRAFT_VERSION: ${{ needs.version.outputs.version }}
FILMCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FILMCRAFT_BUILD_SHA: ${{ github.sha }}
GRIDCRAFT_VERSION: ${{ needs.version.outputs.version }}
GRIDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
GRIDCRAFT_BUILD_SHA: ${{ github.sha }}
LIGHTCRAFT_VERSION: ${{ needs.version.outputs.version }}
LIGHTCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
LIGHTCRAFT_BUILD_SHA: ${{ github.sha }}
PDFCRAFT_VERSION: ${{ needs.version.outputs.version }}
PDFCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PDFCRAFT_BUILD_SHA: ${{ github.sha }}
PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }}
PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
PHOTOCRAFT_BUILD_SHA: ${{ github.sha }}
SOUNDCRAFT_VERSION: ${{ needs.version.outputs.version }}
SOUNDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
SOUNDCRAFT_BUILD_SHA: ${{ github.sha }}
VECTORCRAFT_VERSION: ${{ needs.version.outputs.version }}
VECTORCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
VECTORCRAFT_BUILD_SHA: ${{ github.sha }}
WORDCRAFT_VERSION: ${{ needs.version.outputs.version }}
WORDCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
WORDCRAFT_BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
INPUT_VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-fonts
if: inputs.craft-fonts-ref != ''
uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main
with:
ref: ${{ inputs.craft-fonts-ref }}
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
targets: riscv64gc-unknown-linux-gnu
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-linux-riscv64
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$VERSION"
- uses: storytold/craft-common-actions/actions/install-riscv64-cross@main
- name: Install nfpm (SHA256-verified)
uses: storytold/craft-common-actions/actions/install-nfpm@main
with:
nfpm-version: ${{ inputs.nfpm-version }}
deb-arch: amd64
- name: Build and package (deb, rpm, tar.gz)
env:
CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts
CRAFT_FONTS_REQUIRED: "1"
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
PKG_CONFIG_SYSROOT_DIR: /
PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig:/usr/share/pkgconfig
PKG_CONFIG_ALLOW_CROSS: "1"
CROSS_ARCH: riscv64
CROSS_TARGET: riscv64gc-unknown-linux-gnu
CROSS_COMPILE: riscv64-linux-gnu-
EMULATOR: qemu-riscv64
QEMU_LD_PREFIX: /usr/riscv64-linux-gnu
run: packaging/linux/package.sh --formats "deb rpm tar"
- name: Import the Linux signing key
if: github.ref == 'refs/heads/release'
id: linux_signing
uses: storytold/craft-common-actions/actions/import-signing-key@main
with:
key: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Sign the RPM packages
if: steps.linux_signing.outputs.enabled == 'true'
uses: storytold/craft-common-actions/actions/sign-rpms@main
with:
path: dist/release
- name: Check the packages
run: |
dpkg-deb --info dist/release/*-linux-riscv64.deb 2>/dev/null || true
dpkg-deb --contents dist/release/*-linux-riscv64.deb 2>/dev/null | grep -E 'usr/bin/|metainfo|applications' || true
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-linux-riscv64
path: dist/release/*
if-no-files-found: error
server:
timeout-minutes: 90
name: Server Linux ${{ matrix.arch }}
if: inputs.has-server
needs: [version]
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { arch: x86_64, runner: ubuntu-22.04 }
- { arch: aarch64, runner: ubuntu-22.04-arm }
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
VERSION: ${{ needs.version.outputs.version }}
BUILD_DATE: ${{ needs.version.outputs.date }}
BUILD_SHA: ${{ github.sha }}
FIGCRAFT_VERSION: ${{ needs.version.outputs.version }}
FIGCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }}
FIGCRAFT_BUILD_SHA: ${{ github.sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Load refreshed contributor credits
if: inputs.contributors-artifact != ''
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ inputs.contributors-artifact }}
path: contributors
- name: Check out craft-i18n
uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # v1
with:
toolchain: stable
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
with:
key: release-server-${{ matrix.arch }}
- name: Apply version override
if: inputs.version != ''
run: cargo xtask version set "$VERSION" || cargo run --locked -q -p xtask -- version set "$VERSION" || true
- name: Build and package (tar.gz)
run: packaging/server/package.sh
- name: Check the archive
shell: bash
env:
APP_NAME: ${{ inputs.app-name }}
run: |
tar -tzf "dist/release/$APP_NAME-server-$VERSION-linux-${{ matrix.arch }}.tar.gz" || true
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-server-linux-${{ matrix.arch }}
path: dist/release/*.tar.gz
if-no-files-found: error
release:
timeout-minutes: 10
name: Draft GitHub Release
if: "!cancelled() && !contains(needs.*.result, 'failure')"
needs: [version, macos, windows, linux, linux-riscv64, flatpak, arch, freebsd, web, server]
runs-on: ubuntu-latest
environment: release
permissions:
contents: write
steps:
- uses: storytold/craft-common-actions/actions/draft-release@main
with:
version: ${{ needs.version.outputs.version }}
app-title: ${{ inputs.app-title }}
prerelease: ${{ needs.version.outputs.prerelease }}
github-token: ${{ secrets.GITHUB_TOKEN }}
signing-key: ${{ github.ref == 'refs/heads/release' && secrets.LINUX_SIGNING_KEY || '' }}