Skip to content

Add CI gate and auto-merge workflow (warren-ready) - #37

Merged
arest merged 3 commits into
mainfrom
chore/warren-ready
Sep 16, 2026
Merged

arest merged 3 commits into
mainfrom
chore/warren-ready

Conversation

@arest

@arest arest commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Integrates the warren project-setup checklist into this repo.

Why CI comes first

The checklist assumes the repo already has a PR CI workflow. It doesn't — there was no .github/ directory at all, and no workflow anywhere in history. Enabling auto-merge without CI would mean owner PRs merge immediately and unverified, so this PR adds the gate and the auto-merge flow together.

What's added

.github/workflows/ci.yml

The required check. Single non-matrix job with id and name ci, so the branch-protection context is exactly ci.

  • Add-on metadata (.github/scripts/validate_addon.py) — required HA keys, known arch values, options ↔ schema symmetry, ports ↔ ports_description symmetry, map entry format, slug matches the add-on directory, and version matches the latest CHANGELOG.md heading.

  • Init scripts — bash -n plus shellcheck --severity=error.

  • Build — linux/amd64 image with GitHub Actions layer cache.

  • Smoke test (.github/scripts/smoke_test.sh) — boots the image under its real /init and asserts:

    • cupsd scheduler running, web UI 200 on loopback, declared HEALTHCHECK healthy
    • compiled filters present and executable: rastertokpsl, raster2dymolw, raster2dymolm, rastertogutenprint.5.3
    • vendored PPD sets intact (25 Dymo, 6 Kyocera)
    • avahi-daemon running for AirPrint
    • generated cupsd.conf still allows @LOCAL + the RFC1918/fe80::/10/fd00::/8 ranges, is not allow-all, and still authorises Cancel-Job inside a Policy
    • a LAN client container gets HTTP 200 on /, /printers/ and /admin

    These target the regressions from AirPrint, cancel-job auth, and IPv6 web UI (1.3.2) #35 (IPv6 web UI 403, Cancel-Job Unauthorized) and 1.3.1 (missing Gutenprint PPDs).

.github/workflows/auto-merge.yml

Verbatim from the checklist. Squash auto-merge on non-draft PRs authored by github.repository_owner only, using a GitHub App installation token so the merge commit still triggers downstream workflows.

⚠️ Manual step required — step 2 of the checklist

auto-merge.yml will fail red until the GitHub App credentials exist. That failure is the intended signal (the checklist: "A revoked key or an uninstalled app turns that job red before the merge queue can stall silently"). It is not a required check, so it does not block this PR.

Create the App (Settings → Developer settings → GitHub Apps → New GitHub App): Contents Read and write, Pull requests Read and write, webhook off, installed on this repo only. Then:

gh variable set AUTO_MERGE_APP_ID --repo arest/cups-addon --body '<app id>'
gh secret set AUTO_MERGE_APP_PRIVATE_KEY --repo arest/cups-addon < path/to/key.pem

Repo settings (applied alongside this PR)

  • allow_auto_merge=true
  • delete_branch_on_merge=true
  • branch protection on main requiring the ci check (targets checklist step 5: keep the required status check, no review requirement)

Local verification

  • validate_addon.py passes, and catches injected faults (bad arch, version/CHANGELOG drift, options/schema mismatch, orphan ports_description entry)
  • image builds locally and boots; smoke test reports 22 passed, 0 failed
  • smoke test reports 0 passed, 16 failed and exits 1 against alpine:latest, so it cannot pass spuriously
  • shellcheck --severity=error clean on the init script and the smoke test

Wire up the repo so warren PRs auto-merge once CI passes, per
docs/project-setup.md.

The repo had no CI at all, so auto-merge would have had nothing to wait
on and every owner PR would have merged unverified. Two workflows:

- auto-merge.yml: verbatim from the warren checklist. Enables squash
  auto-merge on non-draft PRs authored by the repo owner only, using a
  GitHub App installation token so the merge commit still triggers
  downstream workflows.
- ci.yml: the gate it waits on. Validates add-on metadata (required HA
  keys, known arch values, options/schema and ports/description
  symmetry, version vs CHANGELOG), shellchecks the cont-init script,
  builds the amd64 image, then boots it and smoke-tests it.

The smoke test asserts the things that have actually broken here:
compiled filters (rastertokpsl, raster2dymolw/m, rastertogutenprint)
and vendored PPDs are present, avahi is up for AirPrint, the generated
cupsd.conf keeps the LAN/IPv6 ACLs and is not allow-all, Cancel-Job is
authorised in a Policy, and a LAN client gets 200 on the web UI.

The job id and name are both `ci` so the branch-protection required
check context is exactly `ci`.
CI caught this on the first run: the s6 init shebang
(`#!/usr/bin/with-contenv bash`) is not one ShellCheck recognizes, so
SC1008 fired as an error before any real check ran.
The avahi assertion sampled the process once, which is racy:
avahi-daemon is started with --daemonize, which always returns 0 even
if the child exits shortly after (e.g. when D-Bus was not usable yet).
Poll for it like we do for cupsd, assert the control socket too, and
dump container logs / process list / runtime sockets whenever the smoke
test fails so CI output explains itself.
@arest
arest merged commit 9366c33 into main Sep 16, 2026
2 of 3 checks passed
@arest
arest deleted the chore/warren-ready branch September 16, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant