Commit Graph
123 Commits
Author SHA1 Message Date
Dylan M. Taylor fd88e26a87 feat(gate): support caller setup commands (#224) 2026-11-12 21:51:38 -05:00
FredApps 804f702057 fix(sonar): surface archived Rust test failures after analysis (#222)
* fix(sonar): report archived Rust test failures after scanning

* test(sonar): cover shard status production and document result semantics
2026-11-12 23:38:33 +01:00
FredApps 293de72429 release.yml: a FreeBSD cache a later release can restore, with the aarch64 cross output (#216)
The release FreeBSD jobs keyed their Cargo cache on toJSON(inputs), and
contributors-artifact is contributor-snapshot-<run id>-<attempt>, so every run
wrote an entry no other run could restore: on 11 Nov every release built FreeBSD
cold. The key now holds only the inputs that change the FreeBSD build (app name,
architecture, craft-fonts ref, FreeBSD release); dry-run is left out too, so a dry
run warms the cache a release restores. A test makes every new input pick a side.

The aarch64 job cross-compiles, and Cargo writes that output to
target/aarch64-unknown-freebsd/release, which the cache action never saved: only
the host build scripts in target/release were kept. The action takes the triple as
a new target input and saves and restores that directory too.
2026-11-12 07:25:29 +01:00
FredApps 17eb0f0717 release.yml: build Windows arm64 natively on the windows-11-arm runner (#215) 2026-11-12 07:25:20 +01:00
FredApps 3951f6df01 sonarcloud: merge each shard's profiles before the scan downloads them (#210)
Each coverage shard now merges its own raw profiles into one sparse
.profdata with the archive toolchain's llvm-profdata and uploads only
that. The scan job merges the shard profiles instead of downloading
every raw profile beside the test archive, which on 11 Nov 2026 filled
the runner for vectorcraft (four ~7 GB zipped profraw artifacts).

A raw profile llvm-profdata cannot read, such as one cut short by a
test process that crashed while writing it (lightcraft, 11 Nov 2026),
now fails its shard with an error naming the file, instead of being
uploaded and failing the scan's merge.

Single-shard callers keep the cargo llvm-cov path unchanged.
2026-11-11 19:55:14 -05:00
FredApps 840a417e3d Release: scripts/cut_release.py cuts a release from green main without a bump pull request (#207)
* Release: scripts/cut_release.py cuts a release from green main without a bump pull request

On 11 Nov 2026 the release of 14 apps took most of the day. A large part went to version-bump pull
requests that changed only version strings yet waited on the full CI of a pull request (1-2 h of
FreeBSD, sharded SonarCloud coverage), and to rerunning it. The script commits the bump on the
newest main commit whose CI passed, merges it into release (which starts release.yml), opens the
same bump for main as its own pull request, and with --publish publishes the draft once the run
passed and has assets. Tests cover the bump: workspace and path-dependency versions, only the
workspace's own Cargo.lock entries, CRLF files, the repository hook.

* cut_release: review fixes

- A trailing comment after the workspace version stays; the value alone is replaced.
- Cargo.lock: only the workspace members' entries (cargo metadata --no-deps) change, not a local
  path dependency outside the workspace that shares the version.
- Cargo.lock is checked with a resolving cargo metadata --locked, on the bump, on release after
  the merge and on the sync branch; --no-deps never compared it with path dependency versions.
- --publish refuses a draft with fewer assets than the last release (a skipped build job leaves
  the run green), unless --allow-fewer-assets.
- The sync PR never moves main backwards: versions compare as numbers, and a main at or past the
  release gets none.
- A failed auto-merge says so, with the PR to merge by hand.
- Arguments that reach git or gh are checked first (owner/name, version, commit hash, workflow,
  title), so none can be read as an option. git, gh and cargo are required up front.

* Release: scripts/release_train.py releases many apps at once with cut_release.py

Every app in parallel, a log per app, and one summary line each (published, pushed, or stopped
and why); one app stopping doesn't stop the rest. Tested on figcraft and soundcraft with
--dry-run (both done in under a minute).

* tests: release_train options before -- in the test

* release_train: only owner/name repos and known cut_release.py options reach the subprocess
2026-11-11 23:02:43 +01:00
FredApps 603045e42d release.yml: a dry-run input builds and checks without releasing (#208)
* release.yml: a dry-run input builds and checks without releasing

For a nightly run on main that finds release-only breakage before release day. On 11 Nov 2026
gridcraft's riscv64 build, materialcraft's private-repo FreeBSD jobs, wordcraft's Print job and
the riscv64 apt mirrors each surfaced only during the release, one fix PR and release run at a
time. With dry-run: no job enters the release environment (no signing secrets; the environment
admits only the release branch), the macOS job and the draft are skipped, and the Flatpak OCI
layouts are not pushed to GHCR or Docker Hub.

* tests: the Flatpak OCI push and the release environment also stay out of a dry run
2026-11-11 22:46:06 +01:00
Dylan M. Taylor 15058dc71e ci: use StepSecurity's maintained actions (#206)
* ci: use StepSecurity's maintained actions

Each third-party action that StepSecurity publishes a secure drop-in
replacement for now uses that replacement, pinned to a commit with its
version as a comment. Versions follow what we used: the newest
StepSecurity release in the same major, or the closest major they
publish. dtolnay/rust-toolchain refs that named a toolchain (stable,
nightly, 1.76) become the replacement's `toolchain` input.

* tests: find the FreeBSD VM, SonarCloud scan and install-action steps by their StepSecurity names
2026-11-11 14:55:40 -05:00
Dylan M. Taylor 693c8dd084 sonarcloud: honour each repository's own sonar.cpd.exclusions (#205)
* sonarcloud: honour each repository's own sonar.cpd.exclusions

* sonarcloud: read sonar.cpd.exclusions with properties syntax and allow the ? wildcard
2026-11-11 14:42:26 -05:00
FredApps 5d42870ead apt: wait for cloud-init before rewriting the sources (#204)
During the ubuntu.com outage, cloud-init's apt_configure module (once per
instance, at boot) spent two 10-second DNS timeouts looking for a mirror
and then wrote ubuntu.sources from its template, after the job had
started. On those VMs configure-apt-mirrors had already pointed the
sources at its list: apt-get update fetched every index for that list,
cloud-init put the image's mirror list back, and apt-get install found
no indexes for it, so no Ubuntu package had a candidate (materialcraft's
Flatpak x86_64 job, the FreeBSD tests job on 26.04). A repro on 12
runners failed on 8, every round, and a file watcher caught cloud-init's
write landing mid-update.

wait-for-cloud-init.sh runs `cloud-init status --wait` (at most 300 s,
never failing the job) before configure-apt-mirrors and
install-riscv64-cross's select-mirrors.sh touch anything.
2026-11-11 17:57:29 +01:00
FredApps 3f541b8904 install-riscv64-cross: fall back to mirrors outside ubuntu.com (#202)
The release builds' Linux riscv64 job read amd64 from archive and
security.ubuntu.com and riscv64 from ports.ubuntu.com only. With no
ubuntu.com name resolving on the runners, apt spent 3m20s on failed
lookups and then found no libc6-dev:riscv64, so every app's release
failed there.

select-mirrors.sh now chooses one pair of mirrors for both architectures:
Ubuntu's own, then dotsrc (it carries both trees), then kernel.org with
TU Chemnitz's ports. It takes the first pair whose amd64 and riscv64
InRelease files answer for every suite with the same Date (Ubuntu signs
one Release for archive and ports), so Multi-Arch: same packages still
match. The image's own Ubuntu sources are disabled in that job: they
only added a second, lagging snapshot and, during the outage, the stall.

The riscv64 job runs Harden-Runner in audit mode, so release.yml needs
no allowlist change.
2026-11-11 17:01:34 +01:00
Dylan M. Taylor 3d49e352fa apt: stop SRV lookups; give the FreeBSD VM host the fallback mirrors (#200)
Harden-Runner blocked apt's SRV lookups (_https._tcp.mirrors.edge.kernel.org,
_https._tcp.mirrors.dotsrc.org): the allow lists name the hosts, not their
SRV records. configure-apt-mirrors now sets Acquire::EnableSrvRecords false;
apt connects to the hosts directly either way.

The FreeBSD workflow's VM action apt-installs QEMU on the host, which failed
during the ubuntu.com outage (sudo exit 100) and reached packages.microsoft.com.
Run configure-apt-mirrors first and drop the image's Microsoft source, which
the job never installs from.
2026-11-11 10:26:48 -05:00
FredApps d97dcd6dcf apt: fall back to mirrors outside ubuntu.com when it is down (#199)
On 11 Nov 2026 no ubuntu.com name resolved on the runners for about
half an hour. The images' mirror list (azure.archive, archive and
security.ubuntu.com) sits entirely in that zone, so every retry spent
its five minutes on 20-second lookups of the same dead names and the
SonarCloud archive builds failed with "downloading the packages failed
3 times".

configure-apt-mirrors points the image's Ubuntu sources at
/etc/apt/craft-apt-mirrors.txt: the image's mirrors in the image's
order, then mirrors.edge.kernel.org and mirrors.dotsrc.org (arm:
mirrors.dotsrc.org and ftp.tu-chemnitz.de). Each mirror is checked
first, in parallel; those that do not serve this release's InRelease
move to the end. install-apt-packages runs it before every network
attempt, and the plain apt-get steps (Flatpak, release, packaging lint,
RPM signing, Linux deps, FreeBSD test) run it before apt-get update.
Block-mode Harden-Runner lists allow the new hosts.
2026-11-11 16:21:03 +01:00
Dylan M. Taylor 644a5d76b9 ci: harden workflows with credential isolation, template injection defenses, and dependabot cooldown (#191)
* ci: harden workflows with credential isolation, template injection defenses, and dependabot cooldown

- Add persist-credentials: false across all actions/checkout invocations
- Eliminate template injection by mapping matrix and input variables to env: in freebsd.yml, release.yml, and sonarcloud.yml
- Add 7-day cooldown to dependabot.yml to protect against supply-chain compromise of recently published releases
- Update test suite to validate hardened environment mappings

* ci: allow static.crates.io and registry endpoints in gate and windows-arm64 runners
2026-11-10 18:07:38 -05:00
FredApps 567530acb5 Merge branch 'main' into sonar/docker-build-job-permissions 2026-11-10 18:23:14 +01:00
Dylan M. Taylor 5a43790c93 ci: replace anchore/sbom-action with step-security/sbom-action
Switch to the StepSecurity-maintained secure drop-in replacement
pinned to v0.24.2 (28bb7d0d2869c9ab0e5571c93591747945819d39).
2026-11-10 08:26:20 -05:00
Dylan M. Taylor 529d68aa05 test: account for Harden-Runner step in workflow assertions
Update unit test step inspections and unpacks to locate steps by name/action
or ignore the leading Harden-Runner security step.
2026-11-10 08:26:20 -05:00
FredApps 1a6c6c0dd5 fix(docker-build): scope packages: write to the pushing jobs 2026-11-10 11:10:27 +01:00
Dylan M. Taylor fd14193f06 fix(docker-build): set up Buildx before registry logins (#181) 2026-11-08 20:16:57 -05:00
Dylan M. Taylor c9f7255114 chore(docker-build): remove DigitalOcean Container Registry support (#180) 2026-11-08 20:10:10 -05:00
Dylan M. Taylor a5eda472ea feat(docker-build): support Docker Hub registry alongside DOCR and GHCR (#179) 2026-11-08 19:33:37 -05:00
Dylan M. Taylor 3b3ea7ed62 feat(release): dual-push Flatpak OCI layouts to Docker Hub (#178)
* feat(release): dual-push Flatpak OCI layouts to Docker Hub

* fix(release): derive Docker Hub repo name from REGISTRY
2026-11-08 19:11:04 -05:00
FredApps 4b23a68072 fix(packaging-lint): retry transient actionlint downloads (#176)
Bound archive and checksum download retries, including refused connections, while retaining HTTPS and SHA-256 validation. Report missing checksum entries using an exact archive filename lookup. Add nine real-curl regression tests for recovery, permanent failures, retry bounds and checksum validation.
2026-11-08 14:16:10 +01:00
FredApps 8fb29161c2 fix(sonar): reduce sharded coverage disk usage (#174)
* fix(sonar): bound sharded coverage disk usage

* test(signing): detect restricted GPG agent sockets
2026-11-08 14:15:27 +01:00
Dylan M. Taylor 3e2ac193fd feat: drop Windows 32-bit builds (#163)
Drops i686-pc-windows-msvc (x86) builds from the Windows release matrix, retaining 64-bit x64 and arm64 targets.
2026-11-06 21:27:06 -05:00
Dylan M. Taylor 2f46576245 feat: allow uploading assets to an existing published release (#164) (#165)
Add allow-published (default false) to draft-release. When true, draft-release
permits uploading assets to an existing published release without failing or
attempting to convert it to a draft with --draft.
2026-11-06 20:40:48 -05:00
Dylan M. Taylor aa106c86ee feat: allow additional Arch runtime dependencies (#161) 2026-11-06 19:33:10 -05:00
Dylan M. Taylor 489222f309 feat: optionally retain existing draft release assets (#160) 2026-11-06 19:24:50 -05:00
Dylan M. Taylor dd3d987521 feat: allow a custom draft release tag prefix (#159) 2026-11-06 16:06:01 -05:00
nnaannooandnnaannoo 13f3c2c99b release.yml: export each app's build variables from its env.sh, so a new app needs no change here (#148)
* release.yml: export each app's build variables from its env.sh, not a list

Eight release jobs set <APP>_VERSION, <APP>_BUILD_DATE and <APP>_BUILD_SHA for
every app by name (298 lines), and the FreeBSD VM step listed them all again,
so every new app meant editing this workflow. materialcraft and texturecraft
were never added: their packaging reads MATERIALCRAFT_* and TEXTURECRAFT_*,
so their release builds got no release version, date or commit, and a
dispatched run with a version override packaged them under Cargo.toml's.

actions/export-app-build-env reads the prefix the app's packaging/env.sh (or
packaging/common.sh) already declares in VERSION="${<PREFIX>_VERSION:-...}",
falling back to app-name in capitals, and writes the three variables to
GITHUB_ENV; its names output feeds the FreeBSD VM's envs. Each job runs it
right after checkout. On all 17 apps' env.sh it finds the prefix the old
list used.

Tests run the script on sample env.sh files and check release.yml sets no
app's variable by name, so the list can't come back.

* Export the build variables after the contributor snapshot, which must follow the checkout

test_contributor_refresh requires each build job to load the contributor snapshot directly after checkout, so the export step goes after it when a job has one. Also fix the line-break test passing a variable twice.

---------

Co-authored-by: nnaannoo <n4nosaur@gmail.com>
2026-11-06 07:36:30 -05:00
FredAppsandCursor 70fc5d4964 Check that AGENTS.md copies the shared house rules.
The writer and the checker share one normalization. A rewritten digest does not make an edit pass, an intact older copy warns only when main has moved on, and a source that cannot be read is reported as could not check.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-06 11:34:30 +01:00
nnaannooandKristian Myram 4d1066685f Add git-sources.yml: the shared "Git dependencies come from storytold" check (#147)
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>
2026-11-05 09:13:01 -05:00
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
f8dc631547 Add setup-windows-signing: the shared Authenticode signing script (#144)
* Add the setup-windows-signing action: the shared Authenticode signing script

Every app carries its own packaging/windows/sign.ps1 and the copies have drifted: four lack the
Trusted Signing client SHA-256 pin. The action exports the maintained script, parameterized by
product name and URL, for package.ps1 to call; it rejects line breaks that could inject
environment variables, and refuses an unset product name. The script reads file names literally.
Tests run it against a stand-in signtool.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fTnVxnXTv2MBW6uj2PPyU

* Test that an unset product name gets the clear message, not a null-method error

PowerShell echoes the failing source line, so the message alone passed on the old code too.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fTnVxnXTv2MBW6uj2PPyU

* Refuse a non-x64 signtool for Azure Trusted Signing

The Azure branch loads the x64 Azure.CodeSigning.Dlib.dll, but SIGNTOOL or
PATH can name an x86 or ARM64 signtool.exe, which cannot load it. Read the
PE machine type of the chosen signtool and fail with a clear message before
downloading the client. A file that is not a PE image is left alone.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Kristian Myram <kmy@oresundsbron.com>
2026-11-05 09:10:10 -05:00
nnaannooandClaude Sonnet 5.5 7ae2c64a8a Add import-macos-certificate: the shared macOS signing certificate import (#140)
* Add shared macOS certificate import and Windows signing script actions

Every app carries its own packaging/macos/import-cert.sh and packaging/windows/sign.ps1, and the
copies have drifted: four apps lack the Trusted Signing client SHA-256 pin and eight still write the
signing certificate to a predictable temporary path.

- import-macos-certificate: the hardened import (private mktemp -d directory, keychain removed on
  failure), self-contained, with identity/keychain outputs.
- setup-windows-signing: exports the shared sign.ps1, parameterized by product name and URL, for
  package.ps1 to call; rejects line breaks that could inject environment variables.
- Tests run both scripts against stand-ins for security, openssl and signtool.

Existing callers are unchanged; apps adopt the actions one at a time.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Signing scripts: read file names literally, refuse an unset product name clearly

sign.ps1 resolved its file arguments with Resolve-Path, which treats [ and ] as wildcards, so a
file such as 'App [x64].msi' failed. setup-windows-signing called .Trim() on an unset product
name, a null-valued method call, instead of its own message. Tests for both.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fTnVxnXTv2MBW6uj2PPyU

* Split the signing PR: keep only the macOS certificate import here

The Windows signing action moves to its own branch and PR. The tests, README text and bullet for
each action now live with that action, with separate README headings so the two PRs merge
independently.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fTnVxnXTv2MBW6uj2PPyU

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 09:08:39 -05:00
FredApps bb16e4122a gate.yml: optional gate-timeout-minutes stops a hung gate with a process list and a clear error (#143)
CI green; CodeRabbit rate-limited with no findings; 0 review threads.
2026-11-05 11:27:56 +01:00
FredApps 0755fd19c7 Add changed-paths.yml: run a job only when its paths change or a label asks (#142)
* 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
2026-11-05 11:12:34 +01:00
Dylan M. Taylor ea2cae4a03 Match the SonarCloud token fallback the scan actually uses (#139) 2026-11-04 17:59:19 -05:00
FredAppsandClaude Opus 5.5 e09a018c65 Build model titles only from each provider's known words
Anyone can commit under an agent email, so a free-form Git name such as
"Private Person <noreply@anthropic.com>" became a published model title,
which the apps would ship in their About windows. Each provider now lists
the words a model title may use. A name with any other word credits the
agent's default model and repeats none of it; versions are bounded too.

Across the co-author trailers in the 13 apps' history, 18,099 keep their
model row and 7 unusual names now fall back to the default. Also pin that
the PR lookup reads the merge commit rather than the PR head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 13:49:44 +01:00
FredAppsandClaude Opus 5.5 c2e0e404ab Batch PR lookups gently and ignore bot PR openers
effectcraft's 4,000-commit history made 50-commit association queries time
out on GitHub, so batches are smaller and a failed batch is retried once.
GraphQL names bot openers without the [bot] suffix, which turned dependabot
into a person; only User accounts now count as PR openers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:38:06 +01:00
FredAppsandClaude Opus 5.5 fbfdcb1b5e Credit AI agents as models and verify merge-commit and carried PRs
GitHub links agent trailers such as noreply@anthropic.com to the claude and
codex accounts, so they appeared as the top human contributors. Agents are now
recognized by exact Git email or GitHub account, never by name, and credited
only in the snapshot's models (About > Models), including commits an agent
authored itself. Bots are no longer listed as people. Model and version are
read from the agent's Git name, covering every provider the apps' history
uses.

Commits merged with a merge commit or rebase never equal a PR's merge commit,
so self-added names lost verification and unlinked commits lost their author.
GitHub's commit-to-PR association now supplies the opener of the one merged PR
containing the commit. An integration PR opened by a writer that carries the
person's own linked commit also verifies their entry.

Against the shipped snapshots of effectcraft, pdfcraft, photocraft and
lightcraft at their recorded heads, no person loses a row, a name or a commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:30:28 +01:00
Kristian Myram ed26e3cd27 Harden contributor consent identities and preference preflight 2026-11-03 12:53:38 +00:00
Kristian Myram 4b2457cec2 Merge main and resolve workflow test trigger conflicts 2026-11-03 12:30:26 +00:00
Dylan M. Taylor 1304973f86 Keep development builds off stable OCI tags 2026-11-03 00:01:47 -05:00
Dylan M. Taylor 67cc91cfd1 Test release signing branch and rollout gates 2026-11-03 00:01:15 -05:00
Dylan M. Taylor f76b6b82d2 Fix Linux signing rollout and review findings 2026-11-03 00:00:15 -05:00
Dylan M. Taylor c351cb5b3e Merge pull request #128 from dylanmtaylor/feat/flatpak-bundle-oci-repo-url
feat(flatpak): make bundle installs update from the ArtCraft OCI repository
2026-11-02 23:56:41 -05:00
Dylan M. Taylor 4da08b882e Merge pull request #98 from g1obalworlds/ci/run-tests-for-every-tested-file
ci: run the unit tests when any workflow or action they cover changes
2026-11-02 22:29:15 -05:00
Dylan M. Taylor 08d40594f5 Merge pull request #97 from g1obalworlds/fix/arch-prerelease-version
arch-package: keep a prerelease version instead of packaging it as 0.0.0
2026-11-02 22:29:08 -05:00
Dylan M. Taylor 2851baf0c0 Merge pull request #130 from storytold/fix/sec-arch-metainfo-read
fix(arch-package): read AppStream metainfo only as a bounded regular file inside staging
2026-11-02 22:29:02 -05:00