Repository navigation
Roll the package pattern out to the four other any-arch repos #17
Description
Part of #14 — Releases publish no installable package, only GitHub's source zip.
Blocked by: Prove the release-package pattern on macarchy-touchbar (#16)
Problem
Four more repos install executables from a git checkout and publish no package: macarchy-core, macos-dynamic-wallpaper, omarchy-aikit and jarvis. Once #C1 has proven the pattern on one repo, this is the mechanical repeat — but mechanical is not trivial: each package() has to mirror that repo's own install.sh, and omarchy-aikit already carries a PKGBUILD that must be converted rather than written.
Proposed solution
The #C1 workflow, copied per repo, with a PKGBUILD written from each install.sh.
| Repo | what its install.sh lands |
note |
|---|---|---|
macarchy-core |
~12 scripts, hooks, udev rule, 2 units + timers, shell plugins | the biggest mapping |
macos-dynamic-wallpaper |
one script, a unit + timer, a theme hook | smallest |
omarchy-aikit |
bin/*, share/*, omarchy fragments, 2 units |
convert its -git PKGBUILD to tag-based |
jarvis |
CLI, plugin, units, Piper voices, models | the voices/models are large and fetched — decide ship-vs-depend |
Area
ci
📋 Spec
Goal
Each of the four repos publishes an installable .pkg.tar.zst on release.
Design
One PKGBUILD + one package.yml per repo, both copied from #16's proven pair. The only per-repo work is package() and depends.
omarchy-aikit is the exception worth naming: its existing aikit-git PKGBUILD builds HEAD via git describe. It becomes a tag-based aikit package, keeping its check() (bin/aikit-selftest) and its aikit.install post-install note. Both cannot be provides/conflicts peers by accident — the -git variant is retired, not kept alongside.
jarvis needs a decision this issue must not defer silently: its Piper voices and wake models are large binaries fetched by install.sh. Shipping them makes a fat package; depending on a fetch makes a package that needs the network. Default taken: keep them out of the package and have the post-install note say to run jarvis setup — a voice assistant that cannot reach the network has bigger problems than a missing package.
Acceptance criteria
- Each of the four repos' next release carries exactly one
*.pkg.tar.*asset. tar -tfon each shows the same destinations that repo'sinstall.shwrites.omarchy-aikitpublishesaikit, notaikit-git, and no release carries both.jarvis's package installs without network access; its post-install note names the setup step that needs one.- No repo's
install.shchanged behaviour.
Testing decisions
Seams under test: the built package's file list (tar -tf) and the release's asset list.
Prior art: #16's own PKGBUILD-vs-install.sh test, copied per repo.
A good test here: the same drift test as #C1 — every path install.sh writes has a counterpart in package().
Out of scope
apple-glass,apple-glass-light,macarchy-install(see Releases publish no installable package, only GitHub's source zip #14's Out of scope).omarchy-aquarium— it compiles, and is its own slice.
🛠️ Implementation plan
For agentic workers: execute this plan task-by-task with
implement-issue(subagent-per-task for broad plans, inline for small ones). Steps use checkbox (- [ ]) syntax for tracking.
Goal: four more repos publish packages, using #16's proven pair.
Architecture: one PKGBUILD + one workflow per repo; each repo's own test suite.
Tech stack: bash, makepkg 7, GitHub Actions, archlinux:base-devel.
Seams under test: the built package's file list (tar -tf) and the release's asset list.
Global constraints
- Copy Prove the release-package pattern on macarchy-touchbar #16's workflow verbatim; only
package()anddependsare per-repo. - Never hardcode
PKGEXTorsite-packages. - Conventional Commit PR title decides the release bump; commits below use
feat. - Commit trailer:
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>.
Task 1: macos-dynamic-wallpaper — the smallest mapping first
Files: create PKGBUILD, .github/workflows/package.yml; test tests/test_pkgbuild.py.
Interfaces: arch=('any'); package() lands bin/macos-dynamic-wallpaper, the unit and the timer.
- Step 1: Write the failing drift test (seam: PKGBUILD text vs
install.sh's destinations). - Step 2: Run it → FAIL.
- Step 3: Write the PKGBUILD; build it locally with
makepkg -f --nodepsandtar -tfthe result. - Step 4: Copy Prove the release-package pattern on macarchy-touchbar #16's
package.yml; assert the trigger is release-only. - Step 5: Re-run the suite → PASS.
- Step 6: Commit:
feat(pkg): publish an installable package on release.
Task 2: macarchy-core — the biggest mapping
Files: create PKGBUILD, .github/workflows/package.yml; test tests/test_pkgbuild.sh.
Interfaces: arch=('any'); scripts to /usr/bin, udev to /usr/lib/udev/rules.d, units to /usr/lib/systemd/user, shell plugins to /usr/share/macarchy-core/shell-plugins.
- Step 1: Write the failing drift test over
install.sh's destinations. - Step 2: Run → FAIL.
- Step 3: Write the PKGBUILD; build and
tar -tfit. Decide where the shell plugins belong system-wide and say so in a comment. - Step 4: Copy
package.yml; assert release-only. - Step 5: Re-run → PASS.
- Step 6: Commit:
feat(pkg): publish an installable package on release.
Task 3: omarchy-aikit — convert the existing -git PKGBUILD
Files: modify PKGBUILD; create .github/workflows/package.yml; test tests/test_pkgbuild.sh.
Interfaces: pkgname=aikit sourced from the release tarball; pkgver() removed; check() and aikit.install kept.
- Step 1: Write the failing test — assert
pkgnameisaikit,sourceis the tarball, and nopkgver()remains. - Step 2: Run → FAIL.
- Step 3: Convert it. Retire the
-gitvariant rather than leaving both. - Step 4: Build locally; confirm
check()still runsbin/aikit-selftest. - Step 5: Copy
package.yml; assert release-only. - Step 6: Re-run → PASS.
- Step 7: Commit:
feat(pkg): publish a tag-based package instead of the -git PKGBUILD.
Task 4: jarvis — package the program, not the voices
Files: create PKGBUILD, jarvis.install, .github/workflows/package.yml; test tests/test_pkgbuild.sh.
Interfaces: arch=('any'); CLI, plugin, units. Voices and models excluded; jarvis.install names the setup step.
- Step 1: Write the failing test — assert no voice or model file appears in
package(), and that the post-install note names the setup step. - Step 2: Run → FAIL.
- Step 3: Write the PKGBUILD and
jarvis.install; build andtar -tf; confirm the package is small and network-free. - Step 4: Copy
package.yml; assert release-only. - Step 5: Re-run → PASS.
- Step 6: Commit:
feat(pkg): publish an installable package on release. - Step 7: Record the four results on Releases publish no installable package, only GitHub's source zip #14's
## Decisions so far.
Activity
feat(pkg): publish an installable package on every release (#6)
feat(pkg): publish an installable package on every release (#14)
feat(pkg): publish a tag-based package instead of the -git PKGBUILD (#11
feat(pkg): publish an installable package on every release (#5)
phmatray commentedon Sep 5, 2026
Done — all four repos publish an installable package, verified on their live releases:
macos-dynamic-wallpapermacos-dynamic-wallpaper-0.2.0-1-any.pkg.tar.zstmacarchy-coremacarchy-core-0.5.0-1-any.pkg.tar.zstomarchy-aikitaikit-0.4.1-1-any.pkg.tar.zstjarvisjarvis-1.5.0-1-any.pkg.tar.zstmacarchy/macos-dynamic-wallpaper#6 · macarchy/macarchy-core#14 · macarchy/omarchy-aikit#11 and #13 · macarchy/jarvis#5
The mechanical repeat was not mechanical
macarchy-coreis not a full install, and says so. Most of what itsinstall.shlands is user configuration pacman may not write. The commands, units and udev rule go system-wide; the theme hooks, shell plugins,macarchy-keys.luaand starter configs ship as templates under/usr/sharewith a scriptlet naming every destination. Shipping something that looks complete and is not would have been worse than no package.jarviscould not be packaged as-is either — the same defect asmacarchy-touchbar, found again in a second repo.JARVIS_DIRwas one directory above the script: the repo root in a checkout,/usronce packaged, and 41 uses of it would have pointed nowhere. My first marker for the search wasprompts/, which turned out to be generated, not versioned — caught by running it, not by reading it.omarchy-aikitpublished v0.4.0 with no package. Itscheck()runsbin/aikit-selftest, which needs tmux, sqlite, gh and a session: in a build container 40 of 61 checks fail for want of an environment, not of correctness.--nocheckin the container only; the selftest is still its own gate inci.yml. Backfilled v0.4.0 through thepackage_tagdispatch input — which is the first time that escape hatch was used, and it worked.The squash-body lesson held. All four release PRs came back as minor bumps with a Features section, because the bodies were written by hand instead of taking GitHub's
* feat: …bullets.Fixed in passing
jarvis/install.sh:29still calledmacarchy-dfr reload— a name retired earlier today. Behind its|| trueit had been doing nothing silently, which is exactly the failure that made the Touch Bar mascot vanish for an hour in #9.