Skip to content

Releases publish no installable package, only GitHub's source zip #14

Closed
3 of 3 issues completed
Closed

Description

@phmatray

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.conf sets PKGEXT='.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.14 here). Derive it with python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'.

Area

ci

Related: #9, #12

🧠 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.sh does. 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]
Loading

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.sh fetches at runtime — macarchy-touchbar curls the Material Symbols font from master at install time, unpinned. In a PKGBUILD it belongs in source=() with a real sha256sum, 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).
  • makepkg as root — refuses. The container step needs a build user.

Assumptions

  • The archlinux:base-devel image is x86_64-only, which is fine for arch=('any') packages: an any package 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

  1. A tagged release of macarchy-touchbar carries exactly one *.pkg.tar.* asset, and gh release view lists it.
  2. That asset installs with pacman -U on the target machine and puts macarchy-touchbar on PATH.
  3. The workflow runs on release publication only — never on a push or a PR.
  4. Re-running the workflow on the same release replaces the asset instead of failing.
  5. apple-glass, apple-glass-light and macarchy-install still 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 (pacman remote) hosting these packages — pacman -U on 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-aikit already 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

  1. added
    bugSomething isn't working
    priority: mediumThe default tier — worth doing, not urgent
    effort: largeCross-layer or phased — expect several commits
    area: cithe workflows and the hermetic test suites
    on Sep 4, 2026
  2. phmatray commented on Sep 4, 2026

    @phmatray
    ContributorAuthor

    First slice landed — the pattern is proven

    macarchy-touchbar v0.5.0 carries macarchy-touchbar-0.5.0-1-any.pkg.tar.zst (6.6 MB), built in CI from its tag. Verified against the downloaded artifact: pkgver matches 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:

    1. The packaging job lives inside release-please.yml, gated on release_created — never a workflow keyed on release: [published]. release-please creates the Release with GITHUB_TOKEN and GitHub raises no workflow run from a GITHUB_TOKEN event, so that trigger never fires and leaves no red run to notice.
    2. pkgver is rewritten from the tag by the job, not maintained by release-please's extra-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 a feat PR. Write the squash body on any multi-commit PR in this job.

  3. phmatray commented on Sep 5, 2026

    @phmatray
    ContributorAuthor

    Done — every code-bearing repo in the org publishes an installable package with each release, built from that release's own tag.

    repo release asset
    macarchy-touchbar v0.5.0 macarchy-touchbar-0.5.0-1-any.pkg.tar.zst
    macarchy-core v0.5.0 macarchy-core-0.5.0-1-any.pkg.tar.zst
    macos-dynamic-wallpaper v0.2.0 macos-dynamic-wallpaper-0.2.0-1-any.pkg.tar.zst
    omarchy-aikit v0.4.1 aikit-0.4.1-1-any.pkg.tar.zst
    jarvis v1.5.0 jarvis-1.5.0-1-any.pkg.tar.zst
    omarchy-aquarium v0.3.1 omarchy-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) and macarchy-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.

    1. release: [published] never fires. release-please creates the Release with GITHUB_TOKEN, and GitHub raises no workflow run from a GITHUB_TOKEN event. The job hangs off release_created in release-please's own workflow instead.
    2. extra-files cannot parse a PKGBUILD and stopped release PRs being built at all. pkgver is rewritten from the tag by the job, and grepped to confirm.
    3. GitHub's default squash body loses the top-level type. * feat: … bullets are parsed as nested commits: a feat PR proposed 0.4.1 with no Features section. Write the squash body.
    4. 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-touchbar and jarvis both resolved their data as one directory above their own code — the repo root in a checkout, /usr once 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 what install.sh copies.

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: cithe workflows and the hermetic test suitesbugSomething isn't workingeffort: largeCross-layer or phased — expect several commitspriority: mediumThe default tier — worth doing, not urgent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions