GitHub's Ubuntu mirror is sometimes slow: a FilmCraft CI run spent 5 min 42 s downloading
21 MB of build dependencies (storytold/filmcraft#2860), and FigCraft's apt step took 4 to 9
minutes in two of eight runs (craft-common-actions#60). The action points apt's archive
directory at a cached folder, so a run with a warm cache downloads only the package lists.
* fix(release): give riscv64 packages the glibc floor of their runner
The riscv64 job builds on ubuntu-24.04, so its GUI binaries need GLIBC_2.39,
but the apps' nfpm.yaml declares the 2.35 floor of the other Linux jobs.
Ubuntu 22.04 can't host the cross build: jammy's ncurses security update was
never built for riscv64, so libtinfo6 can't match across architectures.
Export GLIBC_FLOOR=2.39 on the riscv64 job for each app's package.sh and
nfpm.yaml to declare. Refs #44.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* docs(release): say GLIBC_FLOOR reaches the packages only through the app's nfpm.yaml
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci(release): cross-compile FreeBSD aarch64 in the x86_64 VM
The FreeBSD release job built aarch64 in an emulated aarch64 guest, which
ran into the 300-minute limit for most apps, so aarch64 was dropped from
releases (#39). #49 fixed the same problem in freebsd.yml by cross-compiling
in the KVM-accelerated x86_64 guest; this ports that setup to release.yml.
The release VM is now always x86_64. For aarch64 it pins the quarterly
package branch, installs lang/rust and runs the same "Set up the aarch64
cross toolchain" step as freebsd.yml; a test keeps the two copies identical.
The build step sets the version before loading the cross environment, so
xtask still builds for the guest. The built-in packager reads binaries from
target/<triple>/release, and the job fails if an archive does not match the
matrix architecture.
aarch64 stays opt-in through the new freebsd-architectures input (default
'["x86_64"]'): each app's package.sh still reads target/release and names
its archive after uname -m, so it must honor CARGO_BUILD_TARGET first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci(release): reject unsupported FreeBSD architectures before the VM starts
The guest is always x86_64 and only aarch64 is cross-compiled, so any other
freebsd-architectures value would build x86_64 binaries and the fallback
packager would label them with that value. Check matrix.arch on the host
first and fail for anything but x86_64 and aarch64.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
An app's craft-i18n.rev switches craft-i18n on. checkout-craft-i18n reads
it (trimmed: Windows checks it out with CRLF), checks out that SHA and sets
CRAFT_I18N_DIR and CRAFT_I18N_REQUIRED=1 for every build job in release.yml,
freebsd.yml and windows-arm64.yml; the FreeBSD guests export them too.
The i18n-gate workflow runs cargo test --workspace i18n_gate with
CRAFT_I18N_GATE=1 and fails if no test ran. Release packaging needs it,
skip-i18n-gate skips it on workflow_dispatch only, and freebsd.yml runs it
on pull requests that touch craft-i18n.rev. Without the pin file every
step is a no-op and the gate succeeds.
Claude-Session: https://claude.ai/code/session_01B5qjdPbdcyPMikAqXxAAdW
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The VM's shell is root, and root is never refused a file: a test that
locks a file and expects "permission denied" fails, and a permission bug
root would hide goes unseen. Default and custom tests now run as
craft-test through su; the build and packaging stay root.
Human-reviewed, AI-assisted, nobody's mailbox harmed.
The aarch64 leg booted an emulated aarch64 guest, which compiles about 23
times slower than the KVM-accelerated x86_64 one, so it ran into the
300-minute limit in every caller (#33). GitHub's Arm runners cannot help:
none of them exposes nested virtualization.
Both legs now boot an x86_64 guest. The aarch64 leg pins the quarterly
package branch, installs lang/rust, copies the aarch64 standard library from
the aarch64 lang/rust package of the same version, builds an arm64 sysroot
from base.txz and the GUI library packages, and builds the workspace with
CARGO_BUILD_TARGET=aarch64-unknown-freebsd through base clang and lld. Stable
Rust, no -Zbuild-std.
The cross leg compiles every target, including the tests, but cannot run them
or package.sh, which builds for the guest's own architecture.
GitHub does not expose repository secrets (including SONAR_TOKEN) to pull
requests opened from forks. Because the reusable sonarcloud.yml declared
SONAR_TOKEN as a required secret and sonar-scan.yml called it with
`secrets: inherit` on every pull_request, fork PRs failed immediately with:
Error when evaluating 'secrets' ... Secret SONAR_TOKEN is required, but not
provided while calling.
This made every fork PR show a failing "SonarCloud Scan" check unrelated to the
PR's contents. (The separate SonarCloud GitHub App check, "SonarCloud Code
Analysis", is unaffected and continues to run.)
Fixes:
- Gate the caller job so it only runs on pushes to main and on same-repo PRs;
fork PRs now report a neutral skipped status instead of a hard failure.
- Make SONAR_TOKEN optional in the reusable workflow and guard the scan step on
the token being present, so a missing token never fails the workflow.
Verified with actionlint.
Fixes an accidental overwrite where the reusable workflow_call definition was
replaced by a caller stub. The reusable workflow lives at sonarcloud.yml; this
repo's own scan now runs via sonar-scan.yml calling the local reusable workflow.
Calls storytold/craft-common-actions/.github/workflows/sonarcloud.yml@main
with secrets: inherit. Adds SonarCloud badge to README where missing and
removes the redundant sonar-project.properties (config now passed by the
reusable workflow).
Reusable workflow_call entrypoint for SonarCloud analysis across craft repos.
Consumer repos call it via storytold/craft-common-actions/.github/workflows/sonarcloud.yml@main.
Derives project key as storytold_<repo> unless project-key input is provided.
release.yml and freebsd.yml default craft-fonts-ref to craft-fonts main
(bfcbf71: Japanese, Chinese, Arabic, Thai, Georgian), so one bump here
reaches every app's next release; an app sets the input only to pin
another commit. A test checks the two defaults agree and that every
release job that checks out craft-fonts builds with CRAFT_FONTS_REQUIRED=1.
Refs storytold/craft-libs#197
The emulated aarch64 VM takes over 5 hours for most apps, so the job is
cancelled at the limit. GitHub's ARM64 runners have no KVM, so they do not
help. Releases ship FreeBSD x86_64 only until #39 is fixed.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#35 matched <app-name>-<version>-linux-<arch>.tar.gz exactly. craft-launcher
passes app-name craft-launcher but ships artcraft-launcher-*, so its 0.6.1
Arch and Flatpak jobs found nothing. Match *-<version>-linux-<arch>.tar.gz,
skip -cli- and -server- companion tarballs, and require exactly one.
Co-authored-by: Brandon Thomas <brandon@storyteller.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(release): pick the app's own Linux tarball by exact name
The Arch and Flatpak jobs globbed *-linux-<arch>.tar.gz. PDFCraft also ships
pdfcraft-cli-<ver>-linux-<arch>.tar.gz, so Arch saw two tarballs and failed,
and Flatpak aarch64 took the CLI tarball (no bin/pdfcraft). Select
<app-name>-<version>-linux-<arch>.tar.gz instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(release): pass tarball name parts through step env
Review (CodeRabbit, CWE-78): app-name is a free-form reusable-workflow
input, and interpolating it into run: puts caller text into the shell
source. The Flatpak and Arch steps now read APP_NAME, RELEASE_VERSION
and ARCH from env.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <brandon@storyteller.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
aarch64-unknown-freebsd is a tier-3 Rust target, so rustup publishes no
toolchain for it: since the multiarch matrix (#17), every FreeBSD aarch64
job stopped in `prepare` with "installer for platform
'aarch64-unknown-freebsd' not found". The aarch64 leg now installs
FreeBSD's lang/rust package (1.98.1 on FreeBSD 15) and x86_64 keeps
rustup; `$HOME/.cargo/env`, which only rustup writes, is sourced only
when present. Applied to both freebsd.yml and release.yml.
Tests check that each architecture picks its installer and that the run
step works without a rustup environment; both fail on the previous
workflows.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(release): build Arch Linux package (.pkg.tar.zst) via makepkg from release tarball
* fix(arch-package): fix PKGBUILD provides quotes, add podman fallback and e2e test
The desktop release jobs check out storytold/craft-fonts at craft-fonts-ref and build with CRAFT_FONTS_DIR. The web job never did, so an app's web build could not embed any of its fonts.
This adds a boolean input, web-craft-fonts, defaulting to false. When it's true and craft-fonts-ref is set, the web job checks out craft-fonts and runs packaging/web/package.sh with CRAFT_FONTS_DIR and CRAFT_FONTS_REQUIRED=1.
Co-authored-by: kulveersingh <kulveer.singh@gmail.com>
- macOS and Windows jobs fail on refs/heads/release when their signing secrets
are empty, instead of letting the app's packaging warn and ship unsigned.
A caller that doesn't list a secret name gets it empty, even though the value
is in its release environment: craft-launcher 0.3.1 built unsigned Windows
MSIs this way.
- linux-riscv64 calls package.sh --formats "deb rpm tar". Every app's
package.sh splits formats on spaces, so deb,rpm,tar matched nothing and the
job failed with an empty dist/release.
- README caller example lists the secrets instead of secrets: inherit.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
dtolnay/rust-toolchain derives the toolchain from the ref it is called at
(@stable, @1.90). Pinned to a commit SHA, that ref carries no toolchain, so
the action fails with "'toolchain' is a required input". This broke the
Windows ARM64 workflow on every craft app's main (e.g. storytold/wordcraft
run on 860f4ca) and would break the macOS, Windows, Linux, web and riscv64
release jobs the same way. Pass toolchain: stable at every call site.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>