Moonarch configures the Sweet-cursors theme in six places — greeter
(moongreet.toml, niri-greeter.kdl) and desktop (niri config.kdl, GTK 3/4
settings.ini) — but never declared the package that ships the theme.
On a fresh install the cursor theme was absent system-wide, so Niri and
GTK fell back to the default cursor; it only worked where sweet-cursors
happened to be present (e.g. installed into a user home).
sweet-cursors-git provides 'sweet-cursors'; listing it ensures the theme
is installed system-wide for both the greeter user and the desktop user.
The blanket WantedBy-symlink loop installed a global-scope link for
wlsunset, which meant `systemctl --user disable` (the waybar nightlight
toggle's mechanism) could never persist — systemd warned about exactly
this scope mismatch on every disable. Filter survived reboots even when
the user turned it off.
PKGBUILD now skips wlsunset; moonarch.install drops the legacy symlink
on upgrade. pkgrel bumped so installed systems pick up the fix.
Pre-bump to match moonarch HEAD ahead of push so pkgver-bot detects
"already up to date" and skips a redundant build trigger. Without
this, pushing moonarch first would push another pkgver-bump commit
here and re-trigger build-and-publish a second time.
The udev rule for charge_control_end_threshold permissions has been
removed in moonarch (commit 952776c). The toggle now dispatches a
pkexec helper instead. PKGBUILD no longer needs to install the rule.
The pkgver bump in this PKGBUILD will be picked up automatically by
pkgver-bot on the next moonarch push.
Run 107's clear loop on sweet-cursors deleted the just-uploaded moongreet-git versions. Track per-package "just built" version and skip it in the DELETE loop. Add .type=="arch" jq filter as defense-in-depth.
Run 108 hit a verified global OOM (constraint=CONSTRAINT_NONE) when cargo -j2 ran two parallel rustc workers on a host with 1.6 GiB available. -j1 halves the peak. 4 GiB swapfile added on host as additional buffer; this changes the build pipeline as the second layer.
Run 106 hung the host before I/O caps were in place. act_runner now has 30 MB/s + 500 IOPS hard limits via blkio_config; this commit retriggers the build that failed mid-compile.
Local AUR/older builds outsort the registry versions on pacman vercmp:
- sweet-cursors-git: paru-built r445 (Gigas002/Sweet#cursors) > registry
r1 (our snapshot fork). Snapshot stays frozen by design.
- moongreet-git: pre-rollback 0.10.0 > current 0.8.6 (upstream tag
history continued at 0.8.4–0.8.6 on top of an earlier 0.10.0 line).
epoch=1 on both, pkgrel bumped to retrigger CI. Also extends .gitignore
to cover the remaining makepkg bare-clone dirs (moongreet, moonlock,
moonset, sshfs_connect) that weren't listed before.
Initial sshfsc-git build (run #150, 2026-04-19) failed with
'go: command not found' — at that point the workflow did not yet
install makedepends. Workflow now reads makedepends from PKGBUILD
and installs them via pacman before makepkg, so a fresh trigger
should succeed.
Install mpv.conf straight to /etc/mpv/mpv.conf in package(), remove
the /usr/share/moonarch/mpv/ staging and the post_install copy.
modernz.conf is no longer shipped — overrides moved into mpv.conf
via script-opts-append.
Stages defaults/etc/mpv/ to /usr/share/moonarch/mpv/ and copies
mpv.conf + modernz.conf into /etc/mpv/ on install. modernz.conf
deliberately overwrites the AUR default from mpv-modernz-git.
pkgrel bumped to 11.
The compose mount `./runner-cargo-target:/cache/target` already
persists the target dir. Set CARGO_HOME to a subdir of that mount so
the downloaded-crates index + git cache survive too — otherwise every
build re-fetches every dep. No server-side compose change needed.
The previous CARGO_BUILD_JOBS=1 + nice + ionice throttling rested on an
assumed OOM diagnosis for run 86 (2026-04-23) that was never confirmed
via dmesg/journalctl. Build times tripled for no verified reason.
Remove the throttle; if a real OOM is captured in the future, re-add
limits with actual evidence.
The act_runner exports CARGO_TARGET_DIR=/cache/target for cache
persistence, but the three Rust-app PKGBUILDs hardcoded
target/release/<bin>. Run 87 compiled 8 min then failed at
install stage. Use ${CARGO_TARGET_DIR:-target} so both CI and
local makepkg work.
Parallel Rust builds have OOM-killed the Gitea host twice
(2026-04-20, 2026-04-23 run 86). Force CARGO_BUILD_JOBS=1,
MAKEFLAGS=-j1, and wrap makepkg with nice+ionice so the
act_runner can't drown the shared host.
moongreet/moonlock/moonset link against gtk4 headers at build time.
The CI workflow runs `makepkg -sfd` and only installs makedepends
explicitly — with gtk4 listed only in depends, the build container
had no cairo.pc / gtk4.pc and cairo-sys-rs failed to find the
system library. Add gtk4, gtk4-layer-shell, pkgconf (plus
gtk-session-lock + pam for moonlock) to makedepends.
This previously only worked because repeated `makepkg -s` runs
left the libs installed in the act_runner container filesystem.
Recreating the runner today exposed the latent gap.
Ships config/polkit/50-moongreet-power.rules (new in moongreet v0.8.3)
to /usr/share/polkit-1/rules.d/ so the greeter user can reboot and
power off without authentication.
Reset pkgrel to 1 — the pkgver bump to 0.8.3 will be picked up by
pkgver-bot after the moongreet tag is pushed.
Promote moongreet-git/moonlock-git/moonset-git and ~30 Arch-repo
essentials (networkmanager, bluez, wlsunset, xwayland-satellite,
file-manager stack, portals, zsh plugins, CLI tools, neovim, git,
ufw, fwupd, etc.) from optdepends (or absent) to hard depends.
Previously a fresh `paru -S moonarch-git` installed the configs but
none of the packages they depend on, producing a non-functional
Moonarch — no greeter, no lockscreen, no launcher, no network stack.
AUR packages cannot be hard depends (pacman cannot resolve AUR),
so they remain in moonarch's packages/aur.txt and post-install.sh
pulls them explicitly. optdepends trimmed to real extras —
docker, rustup (for dev), waterfox.
The moonarch.install hook used to ensure /etc/paru.conf had Mode = arp
and a [moonarch-pkgbuilds] section. Both exist to let paru resolve
moonarch packages from a PKGBUILD repo — a second mechanism parallel
to the Arch registry, redundant now that the registry DB is stable.
Hook now strips the legacy config on next upgrade. Bump pkgrel so every
installed system picks up the cleanup.
README now describes the Gitea Arch registry path as the canonical
install/update mechanism — the paru --pkgbuilds fallback is no longer
advertised to users. Adds troubleshooting for missing updates (check
the repo DB directly) and file conflicts.
DECISIONS.md records why the build-and-publish workflow now wipes all
existing versions before upload, and why three packages had to be
re-registered manually.
Gitea's Arch registry doesn't regenerate the repo DB on pkgver change —
old entries linger as zombies (e.g. moonarch-git r99 stuck in moonarch.db
even though only r105 exists as a package). List all versions of each
built package and DELETE them before the upload so the DB gets rebuilt
cleanly. Bump moonarch-git pkgrel to force a rebuild and exercise the fix.
curl -sf was silencing upload errors: r105 was 'Published' six times
in a row but never landed in the registry. Capture the HTTP status
and abort on non-2xx so the run goes red and the response body shows
up in the log.
moonarch-git's runtime depends include AUR-only packages (stasis,
auto-cpufreq, ttf-ubuntusans-nerd) that plain pacman cannot resolve,
so `makepkg -s` fails with "Could not resolve all dependencies" —
even though those runtime deps aren't needed to build the package.
Extract makedepends from PKGBUILD, install them targeted (cargo/go
for Rust and Go packages; empty for moonarch-git), then run makepkg
with -d so it skips the full dep check. Rust packages still get their
compiler, moonarch-git builds without needing the AUR world.
PKGBUILDs with options=('debug') produce a main + -debug split pair.
The previous `ls -t | head -1` only uploaded one, and which one won
was mtime-dependent. Loop over all *.pkg.tar.zst and parse pkgname
per file (so -debug gets its own registry entry).
Previous -Syu triggered a full system upgrade inside the runner
container, which together with the concurrent Rust build saturated
the shared host and took Gitea down. -Sy just refreshes the package
DB, which is all makepkg -s actually needs to resolve current deps.
Runner container has a cached pacman DB that lists package versions
already rotated off the mirrors, causing 404s when makepkg -s tries
to pull makedepends (gtk4, mesa, llvm-libs). Sync the DB first.
makepkg -sfd skipped dependency checks, preventing `-s` from pulling
in rust/cargo (moonlock/moongreet/moonset) and go (sshfsc). Builds
failed with `cargo: command not found`. Remove `-d`; `-s` now installs
makedepends via pacman before the build.
Walker theme files at /etc/xdg/walker/themes/moonarch/ were deployed
manually before the package owned them, causing pacman file conflicts
on upgrade. pre_upgrade hook now removes untracked files so pacman
can take ownership cleanly.
Add udev rule and systemd service to PKGBUILD. Create /var/lib/moonarch
state directory and enable batsaver restore service on laptops in the
post-install hook.
2026-04-08 09:59:09 +02:00
19 changed files with 611 additions and 153 deletions
- **Why**: `moonlock-git`/`moongreet-git`/`moonset-git`/`sshfsc-git` carried the `-git` suffix (Arch convention: VCS package, user builds HEAD locally) but the registry ships pre-built binaries — the user never builds. The suffix lied about what is distributed. corsairctl already did it right: no suffix, build from a versioned git tag (`#tag=v$pkgver`) — the official-Arch-repo model (versioned source, built centrally, distributed as binary).
- **Tradeoffs**: A `-bin` style (project CI builds the binary, PKGBUILD installs only a release asset) was considered but rejected: it needs new build infra in each project repo, whereas tag-build is the smallest change to the existing two-stage CI and corsairctl already proves the pattern. The build stays in CI (no OOM-relevant change). Downside: per-package `update-pkgver` now reads the latest tag instead of `git describe`.
- **How**: In moonarch-pkgbuilds, `git mv <name>-git <name>`; PKGBUILD drops `pkgver()`, sets fixed `pkgver` = latest tag, `source=...#tag=v$pkgver`, `pkgname` without suffix, `pkgrel=1`, plus `replaces=('<name>-git')` + `conflicts=('<name>-git')` for clean client migration on `pacman -Syu`. moongreet keeps `epoch=1` (2026-04-28 rollback) and its install hook. corsairctl added as-is (already tag-style). `moonarch-git``depends` updated to the new names (pkgrel 12 → 13). Per-project `update-pkgver.yaml` switched to tag-trigger + `git describe --tags --abbrev=0`. Old `-git` registry versions deleted manually (the name change defeats the auto zombie-cleanup). Scope: `sshfsc` deferred (only tag v0.1.0, HEAD 11 commits ahead — needs a fresh tag first); `sweet-cursors` stays `-git` (no version tags upstream).
## 2026-05-04 – moonarch-git: skip wlsunset in global enable loop
- **Who**: Dominik, ClaudeCode
- **Why**: PKGBUILD's blanket loop over `defaults/etc/systemd/user/*.service` created `/etc/systemd/user/graphical-session.target.wants/wlsunset.service` — a global-scope symlink. The waybar nightlight toggle calls `systemctl --user disable wlsunset`, which only touches user-scope symlinks; the global one persists, so the filter came back on every reboot. Fix coordinates with moonarch repo (post-install.sh and CLAUDE.md updates) — see `moonarch/DECISIONS.md` 2026-05-04 entry.
- **Tradeoffs**: A whitelist of services-to-enable (instead of blacklist) would be cleaner long-term, but the project ships exactly one toggle-able user service today; a `skip_enable` array reads more clearly against the existing loop. `pre_upgrade()` cleanup is conservative: removes only the wlsunset wants-symlink, leaves the unit file itself.
- **How**: PKGBUILD `package()` — symlink loop now consults `skip_enable=("wlsunset.service")` and skips matching basenames. `moonarch.install``pre_upgrade()` — deletes pre-existing `/etc/systemd/user/graphical-session.target.wants/wlsunset.service` so installed systems migrate cleanly. `pkgrel` bumped 11 → 12 so existing installs see the fix on next `pacman -Syu`; otherwise the registry would carry a same-versioned package and clients would skip the upgrade.
## 2026-04-28 – Bump epoch on moongreet-git after upstream version rollback
- **Who**: Dominik, ClaudeCode
- **Why**: `pacman -Syu` warned that local `moongreet-git 0.10.0.r0.gce9f219-3` is "newer" than the moonarch registry's `0.8.6.r0.gb9b6f50-1`. Cause: `greetd-moongreet` upstream was tagged `v0.9.0` and `v0.10.0` early on, then the tag history continued with `v0.8.4` → `v0.8.5` → `v0.8.6` patches on top — a deliberate downgrade of the version line. `pkgver()` uses `git describe --long --tags`, which now returns `0.8.6.r0.gb9b6f50` at HEAD, but any system that built moongreet before the tag rollback still has the higher-sorting `0.10.0` installed. Without an epoch bump, those systems will never accept the registry's 0.8.x as an upgrade.
- **Tradeoffs**: Re-tagging upstream to leapfrog past v0.10.0 (e.g. v0.11.0) would also resolve the mismatch and avoid the epoch — but it would create a fake version that doesn't reflect the actual feature scope, and we'd be permanently chasing the v0.10.0 ghost on every future bump. Epoch is the canonical pacman mechanism for exactly this situation; one-time cost, no upstream lie.
- **How**: `epoch=1` added to `moongreet-git/PKGBUILD`, `pkgrel` bumped 3 → 4 to retrigger CI.
## 2026-04-28 – Bump epoch on sweet-cursors-git to overrule AUR-built local installs
- **Who**: Dominik, ClaudeCode
- **Why**: `pacman -Syu` warned that local `sweet-cursors-git r445.1d92ac7-1` is "newer" than the moonarch registry's `r1.4b49c35-2`. Cause: our Gitea fork (`nevaforget/Sweet-cursors`) is a one-shot snapshot of `EliverLara/Sweet`'s `kde/cursors/Sweet-cursors/` from 2025-09-28 with a single `init` commit, so `pkgver()` always evaluates to `r1`. The local r445 came from the AUR package by `Gigas002` (source: `github.com/Gigas002/Sweet#cursors`, 445 commits, actively maintained, last cursor change 2026-03-02). Without an epoch bump, vercmp would flag the registry as a downgrade on every system that ever installed via paru/AUR.
- **Tradeoffs**: Switching the PKGBUILD source to `Gigas002/Sweet#cursors` would track upstream and avoid the version mismatch entirely, but requires `inkscape` + `xorg-xcursorgen` makedeps and a non-trivial SVG-compile build step in CI. Cursor changes upstream are minimal in practice (one fix in 6 months), so the maintenance value is low. Keeping the snapshot keeps the build trivial and the source tiny — at the cost of being permanently frozen at the September 2025 state. Documented in the fork's README.
- **How**: `epoch=1` added to `sweet-cursors-git/PKGBUILD`, `pkgrel` bumped 2 → 3 to retrigger CI. Added `README.md` to the `nevaforget/Sweet-cursors` Gitea repo explaining the snapshot rationale and pointing to `Gigas002/Sweet` for users who want a maintained variant.
- **Why**: The act_runner container sets `CARGO_TARGET_DIR=/cache/target` (for cross-build cache persistence), but `moongreet-git`/`moonlock-git`/`moonset-git``package()` hardcoded `target/release/<bin>`. Run 87 compiled for 8 min and then failed at `install: cannot stat 'target/release/moongreet'` because the binary actually lived in `/cache/target/release/`. Silent until today because earlier builds pre-date the env var.
- **Tradeoffs**: None meaningful — the fallback `${CARGO_TARGET_DIR:-target}` preserves local `makepkg` builds (no env var → still reads from `./target/`).
- **How**: Patched `install -Dm755` in all three Rust-app PKGBUILDs to use `"${CARGO_TARGET_DIR:-target}/release/<bin>"`.
## 2026-04-23 – Single-threaded, low-priority build in CI to keep the Gitea host alive
- **Who**: Dominik, ClaudeCode
- **Why**: The act_runner container shares CPU/RAM/I/O with the Gitea host (network-host mode, no resource limits). Parallel Rust builds OOM-kill or thrash the host: run 86 (2026-04-23, moongreet-git 0.8.3.r1) stopped mid-compile at `Compiling gio v0.22.2` with no error, and gitea HTTPS was unreachable for ~11 min. Same pattern on 2026-04-20. Runner-side resource limits would be better, but require host-side config changes; a pipeline-side fix is portable and low-risk.
- **Tradeoffs**: Builds are slower — single-threaded cargo compile of a moon* project takes ~2–3× as long. `nice -n 19` + `ionice -c 3` further delay the build when the host is busy, but that's the point. Slow build beats downed host.
- **How**: `build-and-publish.yaml` exports `CARGO_BUILD_JOBS=1` and `MAKEFLAGS=-j1` before `makepkg`, and wraps `makepkg` with `nice -n 19 ionice -c 3`. Affects every package build in the matrix.
## 2026-04-21 – moonarch-git becomes a full meta-package (hard deps on all Arch-repo essentials + own registry siblings)
- **Who**: Dominik, ClaudeCode
- **Why**: `moonarch-git` listed `moongreet-git`/`moonlock-git`/`moonset-git` only as `optdepends` and omitted most Arch-repo essentials (wlsunset, networkmanager, bluez, xwayland-satellite, file-manager stack, zsh plugins, CLI tools, …) entirely — they lived only in `packages/official.txt`. `paru -S moonarch-git` on a fresh system therefore produced a desktop with no greeter, no lockscreen, no power menu, no nightlight, no network manager, no portals — a non-functional Moonarch. Split source of truth between PKGBUILD deps and txt files caused continuous drift (e.g. walker-bin was missing from both).
- **Tradeoffs**: `moonarch-git` is now chunky — installing it pulls ~60 packages (vs ~20 before). Acceptable because this is exactly what every Moonarch system needs; a leaner package just shifted the install work to imperative scripts that silently failed. AUR packages cannot be hard `depends=` (pacman can't resolve AUR), so they stay in `packages/aur.txt` and post-install.sh pulls them explicitly. `optdepends=` was slashed to real extras (docker, rustup for dev, waterfox) — no more mirroring of aur.txt there.
- **How**: Added to `depends=`: moongreet-git, moonlock-git, moonset-git, xwayland-satellite, libnotify, foot-terminfo, wlsunset, nwg-look, awww, libpulse, gst-plugin-pipewire, networkmanager + nm-applet + nm-openvpn + openvpn, bluez, gvfs + gvfs-{dnssd,mtp,smb}, udisks2, ntfs-3g, xdg-desktop-portal-{gnome,gtk}, qt6-5compat, zsh-{autosuggestions,syntax-highlighting}, bat, btop, eza, fastfetch, fd, fzf, lazygit, ripgrep, neovim, git, fwupd, ufw. Removed from `optdepends=`: all Moonarch ecosystem packages (now hard deps), all AUR packages (post-install.sh pulls from aur.txt), and already-depended Arch-repo packages. `pkgrel` bumped 9 → 10.
## 2026-04-20 – Registry is the only install path; drop paru --pkgbuilds
- **Who**: Dominik, ClaudeCode
- **Why**: Two parallel mechanisms for finding moonarch packages (the Arch registry via `[moonarch]` in `pacman.conf`, and paru's PKGBUILD-repo via `[moonarch-pkgbuilds]` in `paru.conf`) created ambiguous state: `paru -S` resolves from whichever has a matching version first, and diagnostics have to account for both. With the registry DB now stable (see zombie fix below), the PKGBUILD-repo path is redundant.
- **Tradeoffs**: No more local-build fallback when the registry is broken — but when the registry is broken, the real fix is to repair it, not to mask the problem with a second mechanism. Existing systems need their `/etc/paru.conf` cleaned once (hook handles that on next moonarch-git upgrade).
- **How**: `moonarch.install` post_install now deletes `Mode = arp` and the `[moonarch-pkgbuilds]` section from `/etc/paru.conf` instead of writing them. `moonarch/scripts/post-install.sh` and `transform.sh` no longer configure paru.conf or call `paru -Syu --pkgbuilds`; they run `pacman -Sy` + `paru -S moonarch-git` (registry only).
## 2026-04-20 – CI wipes all package versions before upload to kill DB zombies
- **Who**: Dominik, ClaudeCode
- **Why**: `paru -Syu` stopped offering `moonarch-git` updates after the r99 → r105 pkgver bump. Root cause: Gitea's Arch registry updates `moonarch.db` incrementally on upload, but does not evict old entries when a pkgver changes. `r99` lingered in the DB as a zombie — file already 404, but desc/sig still present — so clients saw `r99` as "latest" and never got `r105`. Not a one-off: every future pkgver bump would repeat the issue.
- **Tradeoffs**: Delete-before-upload adds an HTTP round-trip per package and requires `read:package` on the registry token (`write:package` was already there for upload). Alternative was an admin-side DB scrub per zombie — unscalable and hostile to the user.
- **How**: `build-and-publish.yaml` now lists every existing version of each built package via `GET /api/v1/packages/{owner}?type=arch&q={name}` and `DELETE`s them before the upload loop. jq installed on the runner as a dependency of the listing parser. The per-upload `DELETE` of the exact new version was removed (redundant).
## 2026-04-20 – Register moongreet/moonset/sweet-cursors in the Arch registry
- **Who**: Dominik, ClaudeCode
- **Why**: These three packages were missing entirely from the registry — their last pkgver-bumps landed before the `build-and-publish` CI fixes (makedepends install, source-based PKGBUILD parse, multi-artifact upload). Without a new PKGBUILD change, the workflow never re-triggered, so they stayed absent.
- **Tradeoffs**: Bumping `pkgrel` manually is a one-shot push. Alternative (wait for the next real upstream change) would have left packages uninstallable indefinitely.
- **How**: Bumped `pkgrel` in each PKGBUILD, single commit, triggered the `build-and-publish` workflow.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.