Eight apps paste the same 25-line job into ci.yml, nix.yml or release.yml (ten
copies): Cargo.lock exists and is up to date, no .cargo/config(.toml)
replaces, patches or overrides a source, and every git dependency comes from
github.com/storytold. Apps' workflows are meant to only call workflows here.
actions/check-git-sources holds the check as a tested script, and
git-sources.yml runs it on a credential-less checkout, so an app swaps its
job for one `uses:` line and keeps `needs: git-sources`. It reports every
problem rather than the first, as GitHub error annotations, and treats
unreadable TOML as a failure. On all 18 apps' current Cargo.lock and Cargo
config it agrees with the inline copy.
Co-authored-by: Kristian Myram <kmy@oresundsbron.com>
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>
* Add changed-paths.yml: run a job only when its paths change or a label asks
* changed-paths: read paths NUL-separated, keep the reason on one line; README: what the checkout holds
A new optional LINUX_SIGNING_KEY secret (an unprotected OpenPGP signing subkey, from the
release environment) signs each Linux format the way its tools check it:
- rpm: embedded signature (rpmsign), for `rpm -K` and dnf/zypper gpgcheck
- deb: embedded _gpgorigin member (debsigs) and a detached .asc
- Arch: <file>.sig, which pacman looks for
- AppImage, tar.gz, zsync: detached .asc
- Flatpak bundle: signed commit and embedded public key (flatpak-bundle.sh, via the
scaffold's new step 4), so `flatpak install` verifies it, plus a detached .asc
- Flatpak OCI image: a containers/image signature for ghcr.io/<repo>@<digest>, which Flatpak
checks from its signature lookaside; the flatpak job records the pushed manifest for it
- SHA256SUMS.txt.asc over every release asset, and release-signing-key.asc
The draft-release action signs before computing checksums (embedded signatures change the rpm
and deb files) and verifies every signature against the exported public key. The new
import-signing-key action is shared by the flatpak and release jobs and refuses a key that
needs a passphrase. Without the secret, releases are published unsigned with a warning.
v2.87.29 knows nextest only up to 0.9.148, so every gate and coverage run that installs the
pinned cargo-nextest@0.9.150 fell back to cargo-binstall@latest: an unpinned download, then a
binstall of nextest. v2.87.33 is the oldest release whose manifest has 0.9.150; the releases
since v2.87.29 change only tool manifests.
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Calls with nothing to install from apt (a Windows-only check, a wasm build) had to pass a package
list the gate would ignore or install for nothing. packages now defaults to empty, and the apt step
runs only on Linux legs that name packages. The README describes such second gate calls, with
their own command and cache-version, instead of keeping web builds in the app's own workflow:
the apps' CI rules now allow only calls to shared workflows (#118).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pull requests that touch Windows packaging saved their own windows-arm64-package cache (about
0.7 GB), visible only to that pull request. Every app repository is at the 10 GB cache limit,
so each one evicted a cache main's gate restores. The nightly run on main still saves it.
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
flatpak-builder only Recommends elfutils, which --no-install-recommends skips. Apps whose
manifests now build cups-client from source (gridcraft, designcraft, wordcraft, pdfcraft) fail
in the Flatpak job with: Failed to execute child process "eu-strip".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
App repos' .github/workflows/ should only call craft-common-actions at @main, so CI
is the same across the Craft apps. gate.yml and the README said app-only jobs
(fuzzing, corpora, web builds, Windows installer probes) stay in the caller; they
now belong here as shared workflows or inputs, and move without being dropped.
* ci(release): build FreeBSD aarch64 archives by default
app packaging/freebsd/package.sh scripts now honor CARGO_BUILD_TARGET, so
aarch64 is no longer opt-in: freebsd-architectures defaults to
'["x86_64","aarch64"]'. Callers can still narrow it to x86_64 only.
* docs(readme): FreeBSD aarch64 is in the default freebsd-architectures
The aarch64 job uses FreeBSD's quarterly packages, which since 2026-10-28 have no `cmake` meta-package, only `cmake-core`. `pkg install cmake` failed and stopped every app's release build. `cmake-core` is in both the quarterly and latest sets.
test-freebsd.yml is the only workflow that runs tests/, but its path filter
still lists the FreeBSD-era files. A change to sonarcloud.yml,
supply-chain.yml, nix.yml, ast-grep.yml, or to actions such as arch-package,
resolve-version, ast-grep or checkout-craft-fonts ran none of their tests:
#86 (sonarcloud.yml and the README) and #90 (sonarcloud.yml) merged without
test_sonarcloud.py running. Match every workflow, action and test file, and
test that the filter does, with GitHub's glob rules.
cargo llvm-cov adds its own exclusions to --ignore-filename-regex: tests/,
examples/ and benches/ directories and tests.rs / *_tests.rs files. The
sharded merge (the default since #87) calls llvm-cov export directly with
only (vendor|xtask)/, so integration tests and src/**/tests.rs reached
lcov.info as almost fully covered source, and coverage moved when a caller
switched between shards: 1 and the default. Put those exclusions in the
shared regex; the unsharded run already applies them.
The attest job has no checkout, so `gh release upload` had no git remote to
find the repository from and failed with "not a git repository" after the
attestations were already published. Pass GH_REPO, as draft-release does.
* Provision coverage fonts for archive builds and test runners
* Keep coverage fonts optional unless a pin is requested
* Pin nested actions used by coverage jobs
* Export the font path only after a requested checkout
* Measure optional Python tooling coverage in Sonar
* ci: restore craft-common-actions tracking main
* ci: share Python coverage configuration with XML reporting
* sonarcloud: optionally shard Rust coverage across parallel nextest partitions
* sonarcloud: default coverage to four shards
* sonarcloud: build the instrumented archive once and shard tests from it
* sonarcloud: skip sharded scan steps when the plan job produces no shards
* sonarcloud: validate shard count, pin the archive's toolchain, merge only test binaries