chore(ci): simplify workflows #128

Merged
charles merged 24 commits from ci/simplify-workflows into main 2026-04-13 19:41:13 +00:00
Collaborator

Summary

  • QA: remove pull_request trigger, keep push on all branches
  • Release: drop meson/nfpm/AppImage/deb/rpm/apk — build loom-gtk + loom-tui as tar.gz for x86_64 and aarch64
  • Flatpak: rewrite as manual-trigger workflow — build, GPG-sign, deploy to self-hosted repo at flatpak.jacquin.app via rsync

Test plan

  • Push a tag to verify release workflow produces 4 tarballs
  • Trigger Flatpak workflow manually, verify repo deploys to Caddy
  • Verify flatpak remote-add + flatpak install works from the self-hosted repo

🤖 Generated with Claude Code

## Summary - **QA**: remove `pull_request` trigger, keep push on all branches - **Release**: drop meson/nfpm/AppImage/deb/rpm/apk — build `loom-gtk` + `loom-tui` as `tar.gz` for x86_64 and aarch64 - **Flatpak**: rewrite as manual-trigger workflow — build, GPG-sign, deploy to self-hosted repo at `flatpak.jacquin.app` via rsync ## Test plan - [ ] Push a tag to verify release workflow produces 4 tarballs - [ ] Trigger Flatpak workflow manually, verify repo deploys to Caddy - [ ] Verify `flatpak remote-add` + `flatpak install` works from the self-hosted repo 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- QA: remove pull_request trigger, keep push on all branches
- Release: drop meson/nfpm/AppImage/deb/rpm/apk, build loom-gtk + loom-tui
  as tar.gz for x86_64 and aarch64
- Flatpak: rewrite as manual workflow — build, GPG-sign, deploy to
  self-hosted repo at flatpak.jacquin.app via rsync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): use ** glob to match branches with slashes
Some checks failed
QA / qa (push) Has been cancelled
cdb08be338
* does not match / in branch names, so ci/foo or tui/bar were skipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles left a comment

Review Summary

Solid simplification of the CI/CD workflows. Cutting out nfpm/AppImage/deb/rpm/apk is a big win. I've added inline comments for a few concerns that should be addressed before merge.

Key Issues

  1. QA trigger scope - branches: ["**"] on all pushes might be too aggressive
  2. GPG key handling - Potential "key already exists" error on reused runners
  3. SSH deployment - Static IP in secrets is brittle

See inline comments for details.

## Review Summary Solid simplification of the CI/CD workflows. Cutting out nfpm/AppImage/deb/rpm/apk is a big win. I've added inline comments for a few concerns that should be addressed before merge. ## Key Issues 1. **QA trigger scope** - `branches: ["**"]` on all pushes might be too aggressive 2. **GPG key handling** - Potential "key already exists" error on reused runners 3. **SSH deployment** - Static IP in secrets is brittle See inline comments for details.
@ -37,2 +35,2 @@
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
- name: Import GPG signing key
run: |
Owner

Potential race condition: if the runner cache contains an old GPG key, gpg --batch --import will fail with "key already exists".

Add --yes flag or check if key exists first:

gpg --batch --import --yes <<< "${{ secrets.FLATPAK_GPG_KEY }}"

Or check before importing:

if ! gpg --list-keys ${{ env.GPG_KEY_ID }} >/dev/null 2>&1; then
  gpg --batch --import <<< "${{ secrets.FLATPAK_GPG_KEY }}"
fi
Potential race condition: if the runner cache contains an old GPG key, `gpg --batch --import` will fail with "key already exists". Add `--yes` flag or check if key exists first: ```bash gpg --batch --import --yes <<< "${{ secrets.FLATPAK_GPG_KEY }}" ``` Or check before importing: ```bash if ! gpg --list-keys ${{ env.GPG_KEY_ID }} >/dev/null 2>&1; then gpg --batch --import <<< "${{ secrets.FLATPAK_GPG_KEY }}" fi ```
@ -58,0 +59,4 @@
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "${{ secrets.CI_SSH_KEY }}" > ~/.ssh/deploy
chmod 600 ~/.ssh/deploy
Owner

Consider using a hostname instead of static IP 192.168.1.240. If the Caddy server IP changes, you'll need to update secrets. A DNS entry like flatpak.jacquin.app would be more maintainable.

Example:

ssh-keyscan -H flatpak.jacquin.app >> ~/.ssh/known_hosts
rsync ... root@flatpak.jacquin.app:/srv/flatpak-repo/
Consider using a hostname instead of static IP `192.168.1.240`. If the Caddy server IP changes, you'll need to update secrets. A DNS entry like `flatpak.jacquin.app` would be more maintainable. Example: ```bash ssh-keyscan -H flatpak.jacquin.app >> ~/.ssh/known_hosts rsync ... root@flatpak.jacquin.app:/srv/flatpak-repo/
@ -2,9 +2,7 @@ name: QA
on:
push:
Owner

QA workflow currently runs on ALL pushes to ALL branches. This means untested feature branches trigger CI. Consider:

  • Keep pull_request trigger for PRs to main
  • OR add explicit exclusions like branches.ignore: ["**/experimental", "**/wip"]

What's your preference here?

QA workflow currently runs on ALL pushes to ALL branches. This means untested feature branches trigger CI. Consider: - Keep `pull_request` trigger for PRs to main - OR add explicit exclusions like `branches.ignore: ["**/experimental", "**/wip"]` What's your preference here?
Owner

looks good to me

looks good to me
@ -172,3 +113,1 @@
--cross-file /tmp/aarch64-cross.txt
meson compile -C builddir
DESTDIR=$PWD/install meson install -C builddir
run: cargo build --release --target aarch64-unknown-linux-gnu -p loom-gtk -p loom-tui
Owner

The OPENSSL_INCLUDE_DIR and OPENSSL_LIB_DIR environment variables are set for cross-compilation, but you're not linking OpenSSL directly (rustup handles it via cargo). These can be dropped to simplify the build matrix.

Check: what's the actual reason these are needed?

The `OPENSSL_INCLUDE_DIR` and `OPENSSL_LIB_DIR` environment variables are set for cross-compilation, but you're not linking OpenSSL directly (rustup handles it via cargo). These can be dropped to simplify the build matrix. Check: what's the actual reason these are needed?
Author
Collaborator

Addressed all review comments:

  1. QA trigger — added back pull_request: branches: [main], also fixed *** glob to match branches with / (e.g. ci/foo, tui/bar)
  2. OpenSSL env vars — keeping as-is. openssl-sys links OpenSSL natively; when cross-compiling for aarch64, headers/libs are in /usr/lib/aarch64-linux-gnu/ and /usr/include/aarch64-linux-gnu/, not the default search paths. Without the explicit vars, cargo build fails to find them.
  3. GPG import — added --yes flag to handle pre-existing keys on cached runners
  4. SSH hostname — switched from 192.168.1.240 to flatpak.jacquin.app (AdGuard resolves it)
Addressed all review comments: 1. **QA trigger** — added back `pull_request: branches: [main]`, also fixed `*` → `**` glob to match branches with `/` (e.g. `ci/foo`, `tui/bar`) 2. **OpenSSL env vars** — keeping as-is. `openssl-sys` links OpenSSL natively; when cross-compiling for aarch64, headers/libs are in `/usr/lib/aarch64-linux-gnu/` and `/usr/include/aarch64-linux-gnu/`, not the default search paths. Without the explicit vars, `cargo build` fails to find them. 3. **GPG import** — added `--yes` flag to handle pre-existing keys on cached runners 4. **SSH hostname** — switched from `192.168.1.240` to `flatpak.jacquin.app` (AdGuard resolves it)
fix(ci): address PR review feedback
Some checks failed
QA / qa (push) Successful in 33m1s
QA / qa (pull_request) Has been cancelled
b48a8068ff
- QA: restore pull_request trigger for PRs to main
- Flatpak: add --yes to GPG import for cached runners
- Flatpak: use flatpak.jacquin.app hostname instead of static IP

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): remove Meson build from QA pipeline
Some checks failed
QA / qa (push) Successful in 16m51s
QA / qa (pull_request) Has been cancelled
316dc4e9d0
fix(ci): only run QA on pull requests
All checks were successful
QA / qa (pull_request) Successful in 17m15s
070b3988ac
fix(ci): QA on push to main + PRs only, avoid double triggers
All checks were successful
QA / qa (pull_request) Successful in 16m59s
e7a776cb06
Push to feature branches no longer triggers QA directly — it runs
via the pull_request trigger when a PR is open.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor(ci): generic workflow steps backed by justfile recipes
Some checks failed
qa / qa (pull_request) Has been cancelled
fbe6de644b
Workflows now call just recipes instead of cargo directly:
- ci-setup: install toolchain + project deps (reads ARCH env var)
- ci-build: build release artifacts
- ci-package: tar.gz packaging
- fmt-check, clippy, test: QA steps

Workflow files are now project-agnostic — all project-specific
logic lives in the justfile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): QA lint step uses just lint (clippy + toml + markdown)
Some checks failed
qa / qa (pull_request) Has been cancelled
3d73eab407
Install rumdl and tombi in ci-setup so just lint works in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor: extract shared install-lint-tools recipe from setup and ci-setup
Some checks failed
qa / qa (pull_request) Has been cancelled
5862d6b6b8
Both dev setup and CI need rumdl + tombi. Extract into
install-lint-tools so neither duplicates the install logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
chore: remove local Flatpak dev recipes
Some checks failed
qa / qa (pull_request) Has been cancelled
9c8fbf385d
Flatpak builds are now CI-only (manual workflow trigger).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
chore: remove build-tui recipe (just build covers the full workspace)
Some checks failed
qa / qa (pull_request) Has been cancelled
01b457aa48
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat(ci): validate required justfile recipes before running
Some checks failed
qa / qa (pull_request) Failing after 17m12s
500271dab0
QA checks for: ci-setup, fmt-check, lint, test
Release checks for: ci-setup, ci-build, ci-package

Fails fast with a clear error if a project is missing a recipe.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor(ci): use shared ci-workflows reusable workflows
Some checks are pending
qa / qa (pull_request) Waiting to run
21e304dda0
qa.yml and release.yml now call forge_admin/ci-workflows@main.
All project-specific logic stays in the justfile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): add runs-on to caller jobs for Forgejo runner pickup
Some checks failed
qa / qa (pull_request) Failing after 0s
ab189cbc20
Forgejo reusable workflows need runs-on in the caller job,
otherwise the runner can't match labels and the job stays stuck
on "Waiting for a runner".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): remove runs-on from caller jobs (mutually exclusive with uses)
Some checks are pending
qa / qa (pull_request) Waiting to run
4bd9a5aecf
runs-on and uses cannot coexist on the same job. The reusable
workflow defines its own runs-on internally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
revert(ci): inline workflows — Forgejo doesn't support workflow_call yet
Some checks failed
qa / qa (pull_request) Failing after 17m21s
281fb7e293
Forgejo runner can't expand reusable workflows (empty runner labels,
job stuck on "Waiting"). Revert to inlined workflows backed by
justfile recipes. ci-workflows repo kept for future use.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): pin tombi binary download to avoid GitHub API rate-limit
Some checks failed
qa / qa (pull_request) Has been cancelled
32ce1c4cd3
The tombi install script queries GitHub API for the latest release tag,
which returns 401 from anonymous CI runner IPs. Use a direct binary
download from a pinned release instead, same pattern as just.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): download pre-built rumdl binary instead of cargo install
Some checks failed
qa / qa (pull_request) Has been cancelled
6c54e1438a
cargo install rumdl compiled from source (~14 min). Use the pre-built
x86_64-unknown-linux-musl binary from GitHub releases instead, same
pattern as just and tombi.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor(ci): use shared ci-base image, drop per-job tool installs
Some checks failed
qa / qa (pull_request) Has been cancelled
0f1864fb12
Switch all workflow jobs from debian:trixie to the shared ci-base image
at forge.jacquin.app/charles/ci-base:latest which has nodejs, just,
tombi, and rumdl pre-baked. This eliminates ~20s of tool downloads and
14+ min of cargo install per job.

install-lint-tools now skips tools already in PATH so ci-setup is
effectively a no-op for lint tools when running in the ci-base image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): remove install-lint-tools from ci-setup
Some checks failed
qa / qa (pull_request) Has been cancelled
5af9cd2d43
Lint tools (rumdl, tombi) are pre-baked in the ci-base image.
No need to download them during ci-setup anymore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor(ci): simplify ci-setup — base tools and Rust are in ci-base image
Some checks failed
qa / qa (pull_request) Failing after 1m34s
72f78f74fd
Remove build-essential, git, pkg-config, curl, ca-certificates installs
(provided by ci-base image). Replace curl rustup.rs with rustup target
add for cross-compile. x86_64 builds need no Rust setup at all now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): add cargo to GITHUB_PATH — runner doesn't inherit Docker ENV
Some checks failed
qa / qa (pull_request) Failing after 1m30s
06160753f6
Forgejo's Docker runner doesn't propagate ENV PATH from the container
image to subsequent workflow steps. Explicitly register /usr/local/cargo/bin
via GITHUB_PATH so cargo/rustup/clippy are found in fmt-check, lint, test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): remove GITHUB_PATH hack — cargo symlinked in ci-base image
Some checks failed
qa / qa (pull_request) Failing after 1m31s
9322f947c5
The ci-base image now symlinks /usr/local/cargo/bin/* into
/usr/local/bin/ which is always on PATH. No need for GITHUB_PATH.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fix(ci): pin ci-base image to v1 tag to force runner pull
All checks were successful
qa / qa (pull_request) Successful in 25m31s
2126d36acc
The runner caches :latest and doesn't re-pull. Using a pinned version
tag forces the runner to pull the new image with cargo symlinked
into /usr/local/bin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles referenced this pull request from a commit 2026-04-13 19:41:15 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/loom!128
No description provided.