Repository navigation
Releases publish no installable package, only GitHub's source zip #14
Description
Problem
Every release in this org carries zero assets. gh release view v0.3.1 -R macarchy/macarchy-install --json assets returns an empty list; the only downloads are the source zip/tar.gz GitHub attaches automatically to any tag. So "install macarchy" means: clone a repo, run install.sh, and hope the tag you cloned is the one you wanted.
Every one of these repos targets Arch on Asahi. The native artifact is an Arch package, and the org already contains a PKGBUILD — omarchy-aikit/PKGBUILD — which nothing builds and no workflow publishes.
Proposed solution
Each release publishes an installable .pkg.tar.zst built from its own tag, attached to the GitHub Release.
This is already proven to work. Built locally on the target hardware (aarch64 Asahi, makepkg 7.1.0) from macarchy-touchbar v0.4.0's release tarball:
macarchy-touchbar-0.4.0-1-any.pkg.tar.xz 36 KB
usr/bin/macarchy-touchbar
usr/lib/modules-load.d/macarchy-touchbar.conf
usr/lib/systemd/user/macarchy-touchbar.service
usr/lib/udev/rules.d/70-macarchy-touchbar.rules
usr/lib/python3.14/site-packages/macarchy_touchbar/…
Two facts that fell out of that proof and constrain the design:
- Don't hardcode the package extension. This machine's
/etc/makepkg.confsetsPKGEXT='.pkg.tar.xz'; a stock container defaults to.zst. The upload step must glob, not assume. - Don't hardcode
site-packages. The path carries the interpreter version (python3.14here). Derive it withpython -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'.
Area
ci
🧠 Brainstorm
Problem / context
The distribution model today is documented in macarchy-touchbar/.github/workflows/release-please.yml: "there is no publish job on purpose: this repository is installed straight from its git checkout (install.sh symlinks bin/… into ~/.local/bin), so the tag IS the artifact." That was a deliberate choice and it is what the request now overturns — reasonably, because "the tag is the artifact" only serves someone who already has the repo cloned.
omarchy-aikit/PKGBUILD is the existing precedent, and it is a -git package: pkgname=aikit-git, source=(git+https://…), a pkgver() that runs git describe. It builds HEAD, not a release. Useful as a shape to copy — its package() mirrors install.sh file by file, which is exactly the mapping each repo needs — but its versioning is the opposite of what this issue wants.
No ADRs in this repo (docs/adr/ absent; the profile records none), so nothing to check the approach against.
Approaches
A. Attach a .tar.gz of the tree to each release. Nearly free. Also nearly worthless: GitHub already attaches the source archive, so this adds a second copy of the same bytes under a different name. Rejected — it satisfies the letter of "produce an artifact" and none of its point.
B. Publish to the AUR. The idiomatic Arch channel, and it would make paru -S macarchy-touchbar work. But it is a different distribution channel, not a release asset: the AUR hosts a PKGBUILD, not a built package, and the request is specifically that a release carry something. It also adds an out-of-band credential and a second place versions can drift. Worth doing later; it does not answer this.
C. Build a .pkg.tar.zst in CI on tag, attach it to the release. (recommended) The artifact is installable with pacman -U, it is versioned by the tag that produced it, and it lives exactly where the request says it is missing. Proven above on real hardware.
Recommendation
C, rolled out in three slices rather than nine repos at once — one repo proven end to end, then the mechanical repeat, then the one repo that is genuinely different because it compiles.
B is explicitly deferred, not rejected: once C exists, an AUR PKGBUILD that points at the release tarball is a small follow-on, and it is the right second step. It is out of scope here.
📋 Spec
Goal
Every release of a code-bearing macarchy repo carries a .pkg.tar.zst built from that tag, installable with pacman -U.
Scope
The five repos whose install.sh installs executables, plus the one that compiles:
| Repo | arch | note |
|---|---|---|
macarchy-touchbar |
any |
the proof case; needs the Material Symbols font in source=() |
macarchy-core |
any |
many scripts + udev + systemd |
macos-dynamic-wallpaper |
any |
one script + timer |
omarchy-aikit |
any |
has a PKGBUILD already — convert from -git to tag-based |
jarvis |
any |
its only C is vendored numpy inside a venv, so not a compiled package |
omarchy-aquarium |
aarch64 |
genuinely compiles src/*.c; needs an aarch64 Arch container |
Non-goals
apple-glass/apple-glass-light— themes, not programs. Where an Omarchy theme belongs system-wide is a separate question this issue does not answer.macarchy-install— it is the bootstrap you run before you have anything; packaging it inverts its own model.- AUR publication. The right second step, deliberately out of scope (brainstorm B).
- Changing what
install.shdoes. The package is an additional channel; the git-checkout install keeps working.
Design
flowchart LR
A[release-please merges<br/>the release PR] --> B[tag vX.Y.Z + GitHub Release]
B --> C{arch}
C -->|any| D[archlinux:base-devel<br/>on ubuntu-latest]
C -->|aarch64| E[Arch ARM container<br/>on ubuntu-24.04-arm]
D --> F[makepkg --nodeps]
E --> F
F --> G[gh release upload<br/>glob the built file]
The job triggers on the Release being published, so it runs exactly once per version and cannot fire on a branch. makepkg runs as a non-root user (it refuses to run as root), builds with --nodeps (the container has no aarch64 dependency tree and the package's depends are a runtime contract, not a build one), and the upload globs *.pkg.tar.* rather than naming an extension.
Each repo's package() mirrors its own install.sh file for file — that mapping, not the workflow, is the per-repo work.
Edge cases
- A file
install.shfetches at runtime —macarchy-touchbarcurls the Material Symbols font frommasterat install time, unpinned. In a PKGBUILD it belongs insource=()with a realsha256sum, which is strictly better than what happens today. - A release that predates the workflow gets no asset. Acceptable; the next one does.
- A re-run of the job must not fail on an asset that already exists (
gh release upload --clobber). makepkgas root — refuses. The container step needs a build user.
Assumptions
- The
archlinux:base-develimage is x86_64-only, which is fine forarch=('any')packages: ananypackage is architecture-independent by construction. Verified only by reasoning, not by a build — the first slice proves it in CI or discovers otherwise. - An aarch64 Arch container is available for the aquarium slice. Unverified; that slice's first task is to establish it.
Acceptance criteria
- A tagged release of
macarchy-touchbarcarries exactly one*.pkg.tar.*asset, andgh release viewlists it. - That asset installs with
pacman -Uon the target machine and putsmacarchy-touchbaronPATH. - The workflow runs on release publication only — never on a push or a PR.
- Re-running the workflow on the same release replaces the asset instead of failing.
apple-glass,apple-glass-lightandmacarchy-installstill publish releases with no package, and nothing in their workflows changed.
Testing decisions
Seams under test: the built package's file list (tar -tf), and the release's asset list from gh release view --json assets. Both are observable without reading the workflow.
Prior art: macarchy-install/tests/clean-machine.sh — the existing pattern of proving an install by observing the result rather than the script.
A good test here: a tar -tf assertion that the package contains the same paths install.sh installs, so the two channels cannot drift apart silently.
Out of scope
- AUR publication, and any signing of the produced packages.
- A repository (
pacmanremote) hosting these packages —pacman -Uon a downloaded file is the target.
Destination
Every code-bearing repo in the org publishes an installable Arch package with each release, built from that release's own tag.
Notes
- Proven locally before filing:
macarchy-touchbar-0.4.0-1-any.pkg.tar.xz, 36 KB, correct layout. omarchy-aikitalready has a PKGBUILD to convert rather than write.
Decisions so far
- Arch packages, not tarballs — a second copy of GitHub's source zip is not an artifact (brainstorm A).
- AUR is the right second step and is deliberately not this issue (brainstorm B).
Not yet ticketed
- An AUR PKGBUILD per package, pointing at the release tarball.
- Whether Omarchy themes have a meaningful system-wide install at all.
Out of scope
apple-glass/apple-glass-light— themes, not programs.macarchy-install— the bootstrap runs before anything is installed.- AUR publication and package signing.
Activity
phmatray commentedon Sep 4, 2026
First slice landed — the pattern is proven
macarchy-touchbarv0.5.0 carriesmacarchy-touchbar-0.5.0-1-any.pkg.tar.zst(6.6 MB), built in CI from its tag. Verified against the downloaded artifact:pkgvermatches the tag,arch = any,ExecStart=/usr/bin/…, codepoints inside so the install needs no network. #16.Two design decisions the slice settled, both binding on #17 and #18:
release-please.yml, gated onrelease_created— never a workflow keyed onrelease: [published]. release-please creates the Release withGITHUB_TOKENand GitHub raises no workflow run from aGITHUB_TOKENevent, so that trigger never fires and leaves no red run to notice.pkgveris rewritten from the tag by the job, not maintained by release-please'sextra-files— which could not parse a PKGBUILD and stopped release PRs being built at all.And one process lesson: GitHub's default squash body (
* feat: …bullets) makes release-please drop the top-level type. It proposed 0.4.1 with no Features section for afeatPR. Write the squash body on any multi-commit PR in this job.phmatray commentedon Sep 5, 2026
Done — every code-bearing repo in the org publishes an installable package with each release, built from that release's own tag.
macarchy-touchbarmacarchy-touchbar-0.5.0-1-any.pkg.tar.zstmacarchy-coremacarchy-core-0.5.0-1-any.pkg.tar.zstmacos-dynamic-wallpapermacos-dynamic-wallpaper-0.2.0-1-any.pkg.tar.zstomarchy-aikitaikit-0.4.1-1-any.pkg.tar.zstjarvisjarvis-1.5.0-1-any.pkg.tar.zstomarchy-aquariumomarchy-aquarium-0.3.1-1-**aarch64**.pkg.tar.**xz**#16 · #17 · #18. Out of scope as filed and still out:
apple-glass,apple-glass-light(themes, not programs) andmacarchy-install(the bootstrap runs before anything is installed).Four failures that would each have shipped silence
Every one produced a release with no package and, except the last, no red run anywhere to notice.
release: [published]never fires. release-please creates the Release withGITHUB_TOKEN, and GitHub raises no workflow run from aGITHUB_TOKENevent. The job hangs offrelease_createdin release-please's own workflow instead.extra-filescannot parse a PKGBUILD and stopped release PRs being built at all.pkgveris rewritten from the tag by the job, and grepped to confirm.* feat: …bullets are parsed as nested commits: afeatPR proposed 0.4.1 with no Features section. Write the squash body.check()and pacman's sandbox fail in containers —aikit's selftest needs an environment it cannot have there, and pacman 7's Landlock confinement is not permitted in the ARM image. Both were fixed narrowly, in the one repo each affects.Two design facts worth keeping
A PKGBUILD is rarely just packaging. Two of six repos could not be packaged without a code change first:
macarchy-touchbarandjarvisboth resolved their data as one directory above their own code — the repo root in a checkout,/usronce installed. Both would have produced artifacts that install cleanly and then fail to start. Both were caught by reading how the program finds its files, not by reading whatinstall.shcopies.macarchy-core's package is honestly partial and says so. Most of what it installs is user configuration pacman may not write; those pieces ship as templates with a scriptlet naming every destination. A package that looked complete and was not would have been worse than none.Next, deliberately not now
An AUR PKGBUILD per package pointing at these release tarballs — the right second step, and named as out of scope when this was filed.