Commit Graph
37 Commits
Author SHA1 Message Date
Marcelo Alcantara ea7738975a omarchy-settings-dev: ship the full set on aarch64 for runtime-profile sources
#638 gave omarchy-settings this and -dev was never ported, so edge, the only
channel aarch64 machines are qualified for, still stripped zram, oomd, zswap,
the sysctl tuning and USB autosuspend there: on Snapdragon, migration
1790328426 installs zram-generator, finds no dev-zram0.swap and completes
without zram. A source with default/settings-runtime-profile now gets the same
files, backup and optdepends on aarch64 as on x86_64, Thunderbolt drop-in
included, and its HOOKS files ship as they are. Older sources, including the
current quattro pin, keep today's aarch64 package. The platform guard and its
detector check stay aarch64-only (#691, #694). The keyboard backlight unit
first-run enables ships whenever the source has it, as in omarchy-settings.

tests/settings-runtime-profile.sh now runs both recipes. pkgrel 5 so the
recipe change builds; the payload from the current pin is unchanged.
2026-09-28 21:28:47 +10:00
eee77d5a38 voxtype-bin: update to 1.1.0 (#640)
* voxtype-bin: update to 1.1.0

Ship the signed 1.1.0 release assets, baseline and ARM binaries, and the complete Quickshell and OSD style trees. Add OpenVINO optional dependencies from #526 and select the baseline binary automatically on pre-AVX2 hosts.

* voxtype-bin: bump pkgrel past the published 1.1.0-1

voxtype-bin 1.1.0-1 is already published to edge, rc and stable from master's upstream sync. This branch changes that package's contents (baseline binary, OSD styles and recipes, the install hook, OpenVINO optdepends) without changing its version, so publish.yml would call it already published and skip it, and publish-artifact refuses different bytes under an existing filename. pacman would not offer it as an upgrade either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* voxtype-bin: list accelerator optdepends for x86_64 only

makepkg appends optdepends_$CARCH to optdepends rather than replacing it, so optdepends_aarch64 did not drop the Vulkan, CUDA, ROCm and MIGraphX entries on aarch64: it listed all sixteen shared ones and then eleven of them a second time. The accelerator runtimes move to optdepends_x86_64 beside the OpenVINO ones, and the aarch64 array goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* voxtype-bin: move pre-AVX2 hosts to the baseline build on upgrade

The baseline pick in _set_default_backend only runs when no backend was saved, which is a fresh install. Every release before 1.1.0 gave a CPU without AVX2 voxtype-avx2, and pre_upgrade saves that path, so post_upgrade restored the build the host cannot run and the machines the baseline binary exists for never reached it. A saved AVX2 or AVX-512 build whose instruction set the CPU lacks is now picked again; GPU and ONNX choices are left alone.

tests/voxtype-bin-install.sh covers the fresh-install pick and the upgrade cases, and runs with the other self-tests. It borrows the hook's fixed /tmp/.voxtype-backend-upgrade, so it refuses to start when anything is already there, a dangling symlink included: CI runs it as root, and writing through a planted link would land outside the test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

* tests: keep voxtype-bin-install's upgrade state out of /tmp

The test borrowed the hook's /tmp/.voxtype-backend-upgrade and checked it was free only once, so a real voxtype-bin upgrade writing its state during the run could have that state overwritten or deleted, and the hook would then lose the user's backend. The test now redefines the sourced _preserve_or_set_backend with the path moved into its own directory, and fails outright if the hook stops using that path rather than passing without reading it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

* tests: never parse voxtype-bin-install's temp path as code

The redefined _preserve_or_set_backend went through eval with the mktemp path pasted in, so a TMPDIR holding shell syntax -- a directory named $HOME, or $(...) -- was expanded or run when the function was called. It now carries a reference to $SAVED, which expands to the path only at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>

---------

Co-authored-by: Spencer Bull <spencer@omarchy.org>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>
2026-09-27 23:55:23 -05:00
Marcelo Alcantara c2c3f0a4ed omarchy-settings: ship the platform guard on aarch64 only
No platform package is built for x86_64, so an x86 machine has nothing to
guard. The check that 00-omarchy-hooks.conf has its detector copy follows it:
without the copy, x86_64 keeps the busybox line it would have anyway, and
leaving the check unscoped would fail every x86_64 build from a source that
asks omarchy-hw-platform. Taken from #691, which keeps the -dev recipe.
2026-09-28 13:41:10 +10:00
Marcelo Alcantara 2fecfe548e Check the exact network-only sysctl an older source's aarch64 package ships 2026-09-28 13:31:31 +10:00
Marcelo Alcantara e0eb841a2e omarchy-settings: ship the full set on aarch64 for runtime-profile sources
A source with default/settings-runtime-profile decides at runtime which
platform-specific files apply, so its aarch64 package now gets the same files,
backup and optdepends as x86_64: the Thunderbolt request and the memory stack
stay, and its HOOKS files ship as they are. The check that a Mac's asahi line
survives still runs on every aarch64 build. Older sources, including the pinned
v4.0.4, keep #380's aarch64 package: Thunderbolt removed, the HOOKS line guarded
for asahi, the memory stack stripped. The keyboard backlight unit first-run
enables ships whenever the source has it.

pkgrel 4 so the recipe change builds: edge already holds 4.0.4-3 on both
architectures. The payload built from v4.0.4 is unchanged.
2026-09-28 13:17:22 +10:00
Ryan Hughes 547a54d097 Merge pull request #621 from jacob-vincent-mink/bump/omawake-openvino-optdepends
Package Omaspeak 0.1.0 and Omawake 0.1.1 with OpenVINO 2026.4 options
2026-09-27 21:30:03 -04:00
Marcelo Alcantara 6eb4ad1a85 Merge pull request #380 from jdvmi00/spark/aarch64-settings-boot-dropins
omarchy-settings: keep the Limine and mkinitcpio drop-ins on aarch64
2026-09-28 11:29:04 +10:00
Ryan Hughes 31b10abd75 Merge pull request #663 from omacom/ci/sync-pr-churn
Keep sync PRs building across bot pushes
2026-09-27 20:07:45 -04:00
Marcelo Alcantara caac8448be omarchy-settings: pass #13362's platform-aware hooks through on aarch64
omacom/omarchy#13362 sets HOOKS per platform inside 00-omarchy-hooks.conf,
with no column-0 HOOKS= line, so the aarch64 build failed on it; settings-dev
tracks quattro automatically and would break as soon as it lands. Wrap only a
single-line HOOKS=(...), refuse any other column-0 HOOKS=, then source the
shipped files onto a Mac line and a stock line: the Mac line must come through
unchanged and the stock one must not. Back up 00-omarchy-hooks.conf when it
ships, and refuse it without the omarchy-hw-platform copy it asks.

The test now uses the real v4.0.4 hooks file, #13362's two files and
omarchy-mac-boot's 90-94 fragments, and covers upgrades over a hand-restored
file.
2026-09-28 07:53:14 +10:00
Marcelo Alcantara 919b084b93 Merge remote-tracking branch 'upstream/master' into spark/aarch64-settings-boot-dropins 2026-09-28 07:42:17 +10:00
Ryan Hughes 7fe542cde7 Keep branch syncs together and simplify tracker setup 2026-09-27 12:39:53 -04:00
Ryan Hughes d87686ca4f Track upstream branches as pinned releases on an unattended lane
Since publishing moved to CI on merge, a package whose PKGBUILD never
changes while its source moves was never rebuilt: omarchy-dev and
omarchy-settings-dev followed quattro through "#branch=" and a pkgver()
function, and nothing in this repository changed when quattro did. The
host timers that used to notice are off, so edge fell days behind.

The rule now: no git source without a commit or tag pin
(tests/pinned-sources.sh, run in CI). A package that has to follow a
branch declares a git_branch upstream watch, and the pin moves through
the same PR/build/publish path as every other version bump.

Watch (helpers/upstream-watch.py)
  git_branch gains tag_pattern: the newest release tag in the pinned
  commit's own history, exposed as {tag}/{version}/{distance}, so a
  branch build is versioned <tag>.r<n>.g<sha>, above the release it
  follows and below the next one. One blobless clone per branch per
  run, shared by every package on it. min_release_age selects the
  newest commit older than the window, so a push burst builds once.

Lane (helpers/package-metadata.sh, bin/sync-upstream --lane)
  "auto_merge": true moves a package from the reviewed 6-hourly sync
  PR to the unattended lane. Packages pinned from the same branch move
  together: a failure on one restores the others and fails the group,
  so the dev pair can never ship from two quattro commits.

Tracker (.github/workflows/track-branches.yml)
  Every two hours: pin, open one PR with a GitHub App token, enable
  auto-merge. Branch protection still gates the merge on result,
  self-tests and build-isolation. A tip that fails to build stays an
  open red PR until the next tick supersedes it. The App is required:
  a PR opened with GITHUB_TOKEN has its checks held for approval and
  its auto-merge would not fire publish.yml.

The reviewed workflows (sync-upstream, sync-rebuilds) open their PRs
with the same App so their builds start without a maintainer clicking
"Approve workflows to run"; without the App they fall back to
GITHUB_TOKEN and behave as before.

Recipes
  The dev pair pins _commit and a real sha256sum, keeps the OMARCHY_SRC
  override, and drops pkgver(). Its r-number stays the branch's total
  commit count because the published history used it and pacman must
  never see the version go down. omasnap-git is new: omacom/omasnap
  main, versioned <tag>.r<distance>.g<sha>, provides/conflicts omasnap.
2026-09-27 12:39:53 -04:00
Jim Martin 21f3c4a8c4 omarchy-settings: keep the Mac initramfs hooks on aarch64
Apple Silicon Macs install the aarch64 package too, and an unconditional
HOOKS= line would replace their asahi hooks. Apply Omarchy's HOOKS line only
when the incoming hooks lack asahi, in whichever drop-in carries it, and
rebuild omarchy-settings (4.0.4-3) so existing installs get the fix.
2026-09-27 09:08:49 -05:00
Ryan Hughes 4aca3bdbc7 Keep sync PRs building across bot pushes
Three things kept the upstream sync PR (#589) from ever finishing a build:

Scoped dispatches wiped the shared PR. A workflow_dispatch with `packages`
regenerates only those packages from master, and pushing that to
auto/sync-upstream replaced 38 pending updates with one. Scoped runs now
push to their own auto/sync-{upstream,rebuilds}-<packages> branch and PR;
scheduled runs keep the shared branch.

build-approved stopped working after the first bot push. A GITHUB_TOKEN
push creates pull_request runs held for approval but no pull_request_target
run, so approve-pr.yml never saw it: its last run on the branch was the
label itself (2026-09-25T19:26), and each of the next four syncs sat at
action_required. The sync workflows now release the held runs for the
commit they just pushed, from a separate job holding actions: write, and
only for their own bot-authored, same-repo PR while build-approved is on
it.

Each approved push cancelled the in-flight build. Approving the 21:43
sync's build cancelled the label-triggered one still queued on strata and
schist-bin. On auto/sync-* branches a new build now waits for the running
one instead, then reuses its artifacts. The approval script no longer
waits for a lone approved build to start before releasing tests, which a
queued build would have turned into a timeout.
2026-09-26 20:01:17 -04:00
Jim Martin 9d05b3fb06 Merge remote-tracking branch 'upstream/master' into spark/aarch64-settings-boot-dropins 2026-09-26 17:38:24 -05:00
Ryan Hughes d9748c6a15 Merge current package defaults into clipboard fix 2026-09-25 15:35:16 -04:00
Marcelo Alcantara baf6df3e80 limine-mkinitcpio-hook 1.39.0-2: Apple Silicon activation gate on aarch64
On aarch64 the Limine hooks and the mkinitcpio wrapper run through
limine-apple-gate. Only an Apple Silicon Mac (device tree "apple,")
behaves differently: Limine's kernel and removal hooks wait until
Omarchy activates Limine (/var/lib/omarchy/limine.enabled and
/etc/default/limine), mkinitcpio's own kernel hook keeps /boot current
before and after activation, Limine's EFI deploy hook is left to
omarchy-mac-boot, and the wrapper is plain mkinitcpio. Skipped hooks
drain the socket pacman streams targets over.

x86_64 packages exactly what 1.39.0-1 did; generic aarch64 and
Snapdragon keep upstream behaviour.
2026-09-25 18:20:07 +10:00
Jacob Mink b44166a9bc Package Omaspeak 0.1.0 and Omawake 0.1.1 2026-09-24 16:22:18 -05:00
Jacob Mink a1549d8724 Allow later Oma package revisions in removal test 2026-09-24 14:53:32 -05:00
Jim Martin 19976635bc Merge remote-tracking branch 'upstream/master' into spark/aarch64-settings-boot-dropins
# Conflicts:
#	.github/workflows/test.yml
2026-09-22 18:35:30 -05:00
Ryan Hughes 4b60e4cd95 Merge pull request #551 from omacom/ci/daily-builder-images
Publish tested daily package builder images
2026-09-20 13:49:44 -07:00
Ryan Hughes 451280ace1 artifact-helpers: survive bash -e
`restore=$(shopt -p nullglob)` exits 1 when nullglob is off, which it is
in the workflow shell. Under the `bash -e` that GitHub runs steps with,
that ended "Pack artifact" before tar ran: every job on #512 and #550
built fine and then failed with nothing in the log but the command.

The self-test never saw it because `pack_packages ... || fail` suppresses
errexit. Enumerate package files with a loop instead of toggling shell
options, and add a test that calls both helpers under `bash -e` exactly
as the workflows do; it fails against the old helper.
2026-09-20 16:42:24 -04:00
Ryan Hughes 124b067694 Carry PR build artifacts inside a tar so epoch package names survive
actions/upload-artifact rejects any path containing ':', and makepkg names
a package with an epoch `name-1:ver-rel-arch.pkg.tar.zst`. Every PR that
built such a package (cursor-cli in the sync PRs, omasnap once it gained an
epoch) failed at "Upload artifact" after a successful build, and publish
then rebuilt from scratch on merge.

The files now ride inside packages.tar for the artifact hop and come back
out with makepkg's names untouched: pacman clients and bin/publish-artifact
both require the filename to match PKGINFO, and the channels already carry
these names. publish.yml still accepts bare pre-packing artifacts until the
7-day retention drains them.

helpers/artifact-helpers.sh holds both halves; tests/artifact-helpers.sh
covers the round trip and runs with the other self-tests.
2026-09-20 15:52:02 -04:00
Ryan Hughes ad328b725d Build and test daily package builder images 2026-09-20 15:36:18 -04:00
Ryan Hughes 158133f15a Keep unapproved PR builds pending instead of failing 2026-09-20 02:31:44 -04:00
Ryan Hughes 3628915c5d Make build-approved release pending PR workflows 2026-09-20 02:11:34 -04:00
fbfbda4eca Package Omawake 0.0.3 and Omaspeak 0.0.3 with service-removal cleanup hooks (#503)
* Package Omawake 0.0.3 and Omaspeak 0.0.2

Bump both -bin packages to the model-support roadmap delivery:

Omawake 0.0.3:
- W02-W05 setup/activation/cache gates audited and closed
- W07 pinned catalog URL health checks and import diagnostics
- W08 Moonshine Small/Medium benchmarked; both deferred (Tiny default)
- W09 Spanish wake profile (multilingual Whisper Base INT8, es)
- W10 connection-owned playback pauses (HoldPause)

Omaspeak 0.0.2:
- S09 Kokoro 82M: Kokoro-capable packaged provider (supertonic;kokoro_tts)
  with espeak-ng-data.bin shipped beside the executable, 54 named voices
- S10 catalog URL checks, Spanish speech profile, consistent status shape
- S07 streaming deferred at the current pin

Upstream: omawake v0.0.3, omaspeak v0.0.2 (aarch64 + x86_64 verified on
promaxgb10-d666 CUDA and local NPU installs).

* omaspeak-bin: install espeak-ng-data.bin beside the packaged library

* omaspeak-bin: bump to 0.0.3-rc.1 (catalog-managed eSpeak data)

- The tarball no longer ships espeak-ng-data.bin: the Kokoro catalog row
  pins the data package as a model asset (downloaded/verified/installed
  into the model directory with the GGUF), so the core package ships no
  model data at all.
- Both arch checksums taken from the v0.0.3-rc.1 SHA256SUMS.txt.

* omaspeak-bin: finalize at 0.0.3

* Stop setup-created Oma services before pacman removes their binaries

* Drop stale release-verification fixtures from the branch

These were swept in by git add -A during the version bumps: packaged
copies of old releases (0.0.1 tarballs and extracted trees, ~80 MB)
belong to the local verification workflow, not to the package repo.
The consolidated upstream PR should carry only the package changes,
hooks and the removal regression suite.

* Update removal-test fixture versions to the packaged finals

* Ask systemd to reset only an Oma unit that actually failed

The removal helper reset the failed state of every unit it stopped, but
systemd accepts ResetFailed for a unit that is in the failed state alone.
For any other state it answers that the unit is not loaded and exits
non-zero, and because the helper runs under errexit while the hook aborts
on failure, a healthy unit then aborted the whole transaction:

  (2/2) Stop and remove omaspeak user services before package removal
  Failed to reset failed state of unit omaspeak.service: Unit omaspeak.service not loaded.
  :: Could not clean up omaspeak for jacob; removal aborted.

That is the ordinary case, as the packaged service ships disabled and an
enabled one is commonly stopped rather than failed. Read the active state
after the stop and ask for the reset only where it applies, so a failed
unit still loses its failed state along with its rate and restart counters
while a clean unit no longer fails the removal. A reset that a reachable
manager still refuses stays fatal.

Model the rule in the removal suite, where reset-failed now follows the
active state the way a real manager does, and cover both outcomes: an
inactive unit must not be asked for, a failed one must be reset between
the stop and the disable, and a refused reset must still fail the hook.

* Keep removal cleanup faithful to how systemd reads configuration

Both defects from the review of e025111 sat in the shared package-remove
helper, so both packages were affected the same way.

An offline user's drop-in was recognised by grep '^ExecStart=', while the
configuration parser throws away the whitespace around an assignment
(parse_line() strips the line and both halves of the assignment).  A drop-in
naming a development build as

  ExecStart =
  ExecStart = /home/alice/build/omawake daemon

therefore went unmatched, and the helper cleared away the generated base unit
beside with its enablement links, right behind a service that was never meant
to be the package's.  Match an assignment the way the parser accepts one.  The
gate that decides whether a unit file is the generated one stays strict on
purpose: only the exact generated shape is ever deleted.

systemctl show-environment also prints every value the way a shell would read
it, through shell_maybe_quote(SHELL_ESCAPE_POSIX), so an XDG_CONFIG_HOME with a
space arrives as $'/home/alice/custom config'.  The XDG_CONFIG_HOME=/* case saw
neither form and kept the home's .config directory quietly, leaving the unit in
the directory the manager really reads pointing at the removed binary.  Decode
that quoting character by character, without letting the text become shell
syntax, and refuse a value that is neither a plain path nor a closed $'...'
quote rather than delete what would have to be guessed at.  A value that is not
an absolute path stays the fallback it is in systemd itself.

The fixtures now hand the helper the very text a manager prints, quoted by a
mirror of that printer, and cover a quoted path with a space, an apostrophe and
a backslash, an unreadable quoted value, a relative one, and each spacing of an
offline override.  Verified with the removal suite, 15 tests; the eight new
assertions fail against the helper as it was.  The other suites were not run
here, as they reach for the network.

pkgrel 3 -> 4 and the helper's checksum, in both recipes.
Reported-by: spencerbull

* Decode systemd control escapes during service removal

systemctl C-escapes control bytes in show-environment output. Rejecting those valid values aborted package removal for every user, even when the affected account had no Oma service. Decode the printer’s named and octal escapes without evaluating shell syntax or stripping trailing newlines, and cover the real printer format in the fixtures.

Co-Authored-By: GPT-6 XHigh <noreply@openai.com>

---------

Co-authored-by: Spencer Bull <spencer@omarchy.org>
Co-authored-by: GPT-6 XHigh <noreply@openai.com>
2026-09-18 20:32:11 -05:00
Ryan Hughes 537c377fa5 Build PRs on ephemeral droplets; publish merged packages from CI
Every pull request now builds the package directories it touches on
ephemeral DigitalOcean droplets, and every merge to master publishes the
resulting artifacts into the channels each package belongs to. The
repository host's timers become the fallback rather than the pipeline.

Build (.github/workflows/build-pr.yml)
  One job per package per architecture, always against edge. The artifact
  is labelled with the package directory's git tree hash. Tooling (bin/,
  helpers/, build/) is checked out from the base branch; the PR supplies
  only pkgbuilds/, so a PR can change what is built, never how. Builds
  run only for trusted authors: collaborators, .github/VOUCHED.td, or a
  PR carrying the build-approved label. A single required check, result,
  aggregates the matrix.

Publish (.github/workflows/publish.yml, bin/publish-artifact)
  One job per merge. It collects the PR artifacts for the merged tree,
  builds anything that has none, then walks each channel/architecture
  slot once: pull that database, repo-add every package that belongs in
  it, upload packages, signatures, then the database. A published
  filename is immutable; identical bytes under an existing name only
  gain a database entry, different bytes are refused. Fast-ring packages
  reach edge, rc and stable in the same run from the same file.

Matrix (bin/build-matrix)
  Package x architecture, with the channels the artifact ships to,
  decided by package_builds_for_mirror so CI and the host agree.
  arch=any packages build once and land in every architecture database.

Builder (build/build.sh, bin/build, build/Dockerfile)
  With no local published tree, plan against and resolve from the public
  channel over HTTPS. PACKAGER is set to Omarchy. rclone is in the image.

Runners (ci/)
  A controller droplet polls GitHub with curl and creates one g5 droplet
  per queued job from cloud-init, deleting them when off or over-age.
  Builders carry QEMU with credential support for aarch64. Operator SSH
  keys come from GitHub. tests/controller.sh and tests/publish-artifact.sh
  cover the decisions against fixtures and real makepkg output.

Tests run on pull requests only; branch protection requires result,
self-tests and build-isolation with up-to-date branches.
2026-09-18 11:25:32 -04:00
Basti b422d37fa2 Drop privileges when seeding Dell haptic config (#497)
The root-run package hook changed ownership of paths below a
user-controlled home directory. A config symlink could redirect chown to
an arbitrary root-owned file during installation or upgrade.

Run the config writer as the target desktop user and remove the privileged
ownership changes. This also prevents the missing-config path from writing
through a user-controlled pathname as root. Add regression coverage and
bump the package release.

Reported-by: piratemoo (Esther) <22439214+piratemoo@users.noreply.github.com>
Link: https://github.com/piratemoo/Arbitrary-File-Ownership-Change-via-Symlink-LPE
2026-09-18 15:24:41 +02:00
Ryan Hughes 1f025695d5 Build t3code-bin for aarch64 2026-09-17 13:35:33 -04:00
Birk Skyum 16b1a730f6 Run boot settings regression explicitly from tests 2026-09-16 20:54:59 +02:00
Ryan Hughes 9d5c3eea19 Skip retained published archives when planning builds 2026-09-15 00:13:57 -04:00
Ryan Hughes b34de5c29e Replace scheduled AUR imports with direct upstream watches 2026-09-14 21:15:17 -04:00
Ryan Hughes d96b950901 Publish completed packages when a peer build fails 2026-09-14 02:30:11 -04:00
Ryan Hughes 0022e278c6 Respect tmux clipboard policy and preserve empty reads 2026-09-13 19:48:41 -04:00
David Heinemeier Hansson c095aa4ccc Keep remote clipboard paste fast and cover provider transports 2026-09-13 17:46:10 +02:00
Ryan Hughes fc3226ff94 Build each package in an isolated container 2026-09-08 22:49:08 -04:00