Merge pull request #277 from maralcbr/omacom/aarch64-host-pipeline
Make aarch64 a first-class architecture in the scheduled pipeline
This commit is contained in:
49 files changed
+2155
-522
No files matched your search
@@ -27,6 +27,7 @@ jobs:
|
||||
set -euo pipefail
|
||||
pacman -Syu --noconfirm jq
|
||||
./bin/sync-upstream self-test
|
||||
./bin/sync-rebuilds --self-test
|
||||
./bin/omarchy-pkgs self-test
|
||||
./bin/omarchy-release self-test
|
||||
'
|
||||
@@ -1,3 +1,4 @@
|
||||
.firecrawl/
|
||||
src/
|
||||
logs/
|
||||
build-output/
|
||||
|
||||
@@ -30,18 +30,57 @@ The filesystem no longer encodes release policy. Instead:
|
||||
## Prerequisites
|
||||
### aarch64 Builds (Optional)
|
||||
|
||||
To build ARM64 packages on x86_64, enable QEMU emulation:
|
||||
The repository host builds every architecture it publishes on the same
|
||||
machine. A foreign architecture runs under QEMU user emulation, which
|
||||
`bin/build` checks by actually running a container for the target platform.
|
||||
Rootful Docker registers QEMU on first use. Rootless Podman uses the host's
|
||||
registration and prints the one-time Arch setup commands when it is missing or
|
||||
lacks the credential flag required by `sudo` inside the builder:
|
||||
|
||||
```bash
|
||||
# Run after each reboot
|
||||
docker run --privileged --rm tonistiigi/binfmt --install arm64
|
||||
|
||||
# Verify
|
||||
docker run --rm --platform linux/arm64 alpine:latest uname -m
|
||||
podman run --rm --platform linux/arm64 docker.io/library/alpine:latest uname -m
|
||||
# Should output: aarch64
|
||||
```
|
||||
|
||||
**Note**: aarch64 builds use QEMU and slower than native x86_64 builds.
|
||||
**Note**: emulated builds are much slower than native ones.
|
||||
|
||||
### Published architectures
|
||||
|
||||
`helpers/paths.sh` names the architectures this repository publishes:
|
||||
|
||||
```bash
|
||||
PUBLISHED_ARCHES="${OMARCHY_ARCHES:-x86_64}"
|
||||
```
|
||||
|
||||
That list drives the whole scheduled pipeline. `check-versions` compares
|
||||
PKGBUILDs against each architecture's channel databases and writes one queue
|
||||
file per channel and architecture (`.sync-needed-<channel>-<arch>`);
|
||||
`auto-release <channel>` works through the queues one architecture at a
|
||||
time, each with its own backoff (`.build-failed-<channel>-<arch>`), so a
|
||||
failing build on one architecture never holds up the other; and the release
|
||||
train advances channels with `--arch all`: it takes one host-wide lock and
|
||||
verifies every architecture's source database before moving any of them. The
|
||||
first entry is the reference architecture the release train observes channels
|
||||
through. A remote sync failure can still leave a promotion temporarily partial;
|
||||
rerunning the same advance completes it safely.
|
||||
|
||||
Adding an architecture to the scheduled pipeline is therefore one checked-in
|
||||
change to that list: the next `check-versions` tick queues everything the new
|
||||
architecture lacks, and the next `auto-release` tick starts building it. A
|
||||
checked-in list also means the rebuild workflow and release host cannot drift
|
||||
onto different architecture sets. For a one-off run, override it directly:
|
||||
|
||||
```bash
|
||||
OMARCHY_ARCHES=x86_64 bin/check-versions
|
||||
OMARCHY_ARCHES=aarch64 bin/check-versions
|
||||
OMARCHY_ARCHES="x86_64 aarch64" bin/check-versions
|
||||
```
|
||||
|
||||
The builder image bootstraps
|
||||
`omarchy-keyring` from the x86_64 tree for every architecture, so the first
|
||||
build of a new architecture does not depend on a repository that only it can
|
||||
create.
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -300,7 +339,8 @@ bin/sync-upstream openai-codex-desktop # Update specific packages
|
||||
|
||||
Some vendors publish a release feed of their own that is faster and more precise
|
||||
than the AUR packaging of it. Those packages are `source: local` — Omarchy owns
|
||||
the PKGBUILD — and declare where releases come from in one of two ways.
|
||||
the PKGBUILD — and declare where releases come from either as data or, for an
|
||||
unusual feed, a small hook.
|
||||
|
||||
A vendor shipping tagged GitHub releases is pure data, declared as `upstream`
|
||||
in `.omarchy/package.json` with no code at all:
|
||||
@@ -322,6 +362,32 @@ digest GitHub's release API reports for every asset — see
|
||||
`pkgbuilds/schist-bin/.omarchy/package.json`. Either way the artifacts
|
||||
themselves are never downloaded.
|
||||
|
||||
An architecture may map to an ordered array when its PKGBUILD downloads more
|
||||
than one release asset. Small versioned files outside the release assets can be
|
||||
listed under `sources` and are downloaded and hashed when a new version appears:
|
||||
|
||||
```json
|
||||
"upstream": {
|
||||
"github": "owner/project",
|
||||
"digests": true,
|
||||
"assets": {
|
||||
"x86_64": ["tool-{pkgver}-x86_64", "tool-{pkgver}-x86_64.asc"],
|
||||
"aarch64": ["tool-{pkgver}-aarch64", "tool-{pkgver}-aarch64.asc"]
|
||||
},
|
||||
"sources": {
|
||||
"any": ["https://raw.githubusercontent.com/owner/project/{tag}/LICENSE"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asset and source keys must be disjoint because each key maps to one PKGBUILD
|
||||
checksum array (`any` means the unsuffixed `sha256sums`).
|
||||
|
||||
Repositories whose historical releases use incompatible tag schemes may set
|
||||
`"latest_only": true`. The provider then considers only the newest stable
|
||||
GitHub release, while retaining all validation for that release. A quarantine
|
||||
will wait for that release to age instead of falling back to an older one.
|
||||
|
||||
`{tag}` and `{pkgver}` interpolate into asset names; a leading `v` on the tag is
|
||||
stripped for `pkgver`; drafts and prereleases are ignored. Only the 100 most
|
||||
recent releases are considered. The provider fails closed on anything it cannot
|
||||
@@ -364,14 +430,33 @@ the tarball named by the selected dist-tag:
|
||||
|
||||
`dist_tag` defaults to `latest`. The registry's publication timestamp is
|
||||
carried into the provider result, so `min_release_age` works for npm packages.
|
||||
Exactly one of `github`, `git_tags`, or `npm` may appear in a declaration.
|
||||
|
||||
A vendor with a plain-text Debian `Packages` index can use it to discover the
|
||||
newest exact package version, then hash immutable source URLs:
|
||||
|
||||
```json
|
||||
"upstream": {
|
||||
"debian": "https://example.com/debian/dists/stable/main/binary-amd64/Packages",
|
||||
"package": "example-app",
|
||||
"sources": {
|
||||
"x86_64": ["https://example.com/tool-{pkgver}-x64.tar.gz"],
|
||||
"aarch64": ["https://example.com/tool-{pkgver}-arm64.tar.gz"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This deliberately accepts only Debian versions that are already valid Arch
|
||||
`pkgver` values. Feeds needing epoch, revision, or filename translation retain
|
||||
a hook. Exactly one of `github`, `git_tags`, `npm`, or `debian` may appear in a
|
||||
declaration.
|
||||
|
||||
A timestamped provider may also declare `"min_release_age": "24h"`
|
||||
(`s`/`m`/`h`/`d` suffix or bare seconds) to quarantine fresh releases until
|
||||
maintainers have had time to pull a bad or compromised one. GitHub Releases and
|
||||
npm provide publication times; raw git tags do not, so combining `git_tags`
|
||||
with this policy fails closed. The newest release that has cleared the window
|
||||
ships, so a fast release cadence cannot starve updates. The window is enforced
|
||||
npm provide publication times; raw git tags and Debian Packages indexes do not,
|
||||
so combining either with this policy fails closed. The newest release that has
|
||||
cleared the window ships, so a fast release cadence cannot starve updates. The
|
||||
window is enforced
|
||||
centrally: whatever reports the release must prove its age via `published_at`,
|
||||
or the sync fails. A maintainer deliberately shipping inside the window runs
|
||||
`BYPASS_MIN_RELEASE_AGE=1 bin/sync-upstream <package>` locally and merges the
|
||||
@@ -424,7 +509,12 @@ A package names those dependencies in `.omarchy/package.json`:
|
||||
{ "source": "aur", "sync": false, "rebuild_on": ["qt6-base", "qt6-declarative", "qt6-wayland"] }
|
||||
```
|
||||
|
||||
`bin/sync-rebuilds` reads each named package's version from the official repositories and compares it to `rebuilt_against`, the record of what the checked-in pkgrel was last bumped for. pkgrel is bumped unless every name in `rebuild_on` is recorded and still matches, so a name the record does not carry reads as changed rather than going unexamined forever. Opting a package in therefore buys one rebuild: what its published build actually linked against is not knowable from here, and a record written without a rebuild would certify a build nobody checked.
|
||||
`bin/sync-rebuilds` reads each named package's version from the official
|
||||
repositories for every published architecture the package supports and compares
|
||||
it to `rebuilt_against`. Records are kept per architecture because Arch and
|
||||
Arch Linux ARM can carry different dependency versions. pkgrel is bumped once
|
||||
when any recorded version moves; that one source revision is then rebuilt by
|
||||
each architecture's normal queue.
|
||||
|
||||
The bump is the point of the command, and it has to land in git rather than in the builder. A rebuild that reuses the published version string produces a package pacman will never offer anyone, so merely unlocking the build gate would ship nothing. Bumping pkgrel needs no other change: `bin/check-versions` and the builder both already rebuild when pkgrel moves.
|
||||
|
||||
@@ -432,9 +522,12 @@ For an AUR-synced package the bump is expressed as the dotted Omarchy pkgrel suf
|
||||
|
||||
The bumped version is checked against the published one as well as the checked-in one, and refused when pacman would not order it higher. The checked-in version is not the floor; what a user already has is, and a checkout that has fallen behind the repository can otherwise be bumped to something that loses to the package it means to replace. That check is skipped with a warning when the published database cannot be read.
|
||||
|
||||
Versions are read from the local pacman database, so this runs on Arch or in an Arch container against a synced database. Only `core`, `extra` and `multilib` count: a Qt release sitting in testing or kde-unstable is not what the builder will link against, and rebuilding for it would ship a package built against the wrong ABI. The workflow points that database at `mirror.omarchy.org`, the mirror the x86_64 builder itself uses, because a mirror running ahead of the builder would record a version the build never linked against and nothing re-fires once the record matches.
|
||||
|
||||
aarch64 is not covered. Those builds resolve Qt from Arch Linux ARM, which can lag Arch, so one record cannot describe both architectures. Only x86_64 is published today, so nothing currently ships from the untracked side; if ARM publishing starts, `rebuilt_against` has to become per-architecture before this can be trusted there.
|
||||
x86_64 versions are read from the local pacman database, so the workflow runs
|
||||
in an Arch container pointed at `mirror.omarchy.org`, the same mirror as the
|
||||
x86_64 builder. aarch64 versions are read directly from the live Arch Linux ARM
|
||||
repository database, which is also what the ARM builder uses. Testing and
|
||||
staging repositories do not count. A legacy flat `rebuilt_against` record is
|
||||
read as x86_64 and is migrated naturally the next time a rebuild is needed.
|
||||
|
||||
### Other
|
||||
|
||||
@@ -632,7 +725,7 @@ Minimal examples:
|
||||
Fields:
|
||||
|
||||
- `source`: `aur` or `local`. A `local` package can still follow an upstream release, either declaratively via `upstream` or with an `.omarchy/upstream.sh` hook.
|
||||
- `upstream`: optional for `local` packages whose vendor ships tagged GitHub releases. `{ "github": "owner/repo", "checksums": "SHASUMS256.txt", "assets": { "<arch>": "name-{tag}.tar.xz" } }`, or `"digests": true` in place of `checksums` to use the release API's per-asset digests — see [Sync Upstream Releases](#sync-upstream-releases). Mutually exclusive with `.omarchy/upstream.sh`.
|
||||
- `upstream`: optional for `local` packages following GitHub releases, git tags, npm dist-tags, or a Debian `Packages` index. GitHub architecture assets may be a string or an ordered array, and can be combined with disjoint versioned `sources` — see [Sync Upstream Releases](#sync-upstream-releases). Mutually exclusive with `.omarchy/upstream.sh`.
|
||||
- `min_release_age`: optional quarantine for upstream releases (`"24h"`, `"2d"`, or bare seconds). The newest release older than the window ships; anything younger waits, and a release whose age cannot be proven fails the sync. Bypass deliberately with `BYPASS_MIN_RELEASE_AGE=1 bin/sync-upstream <package>`.
|
||||
- `sync`: optional for AUR packages; defaults to `true`. Set `false` for AUR-origin packages that Omarchy maintains manually.
|
||||
- `aur`: optional AUR package name when it differs from the local package directory, usually for split packages.
|
||||
@@ -642,7 +735,7 @@ Fields:
|
||||
- `skip_build`: optional boolean; defaults to `false`. Set `true` to exclude a package from scheduled version checks and unscoped builds. The package can still be built explicitly with `bin/repo release --package <name>`.
|
||||
- `pkgrel`: optional Omarchy pkgrel suffix for a version-pinned rebuild bump. This emits `<aur pkgrel>.<suffix>` instead of replacing AUR's pkgrel. `offset` can be used only when preserving monotonic upgrades from old absolute pkgrel bumps. The metadata is removed automatically when AUR sync changes `pkgver`; the current package version is read from the checked-in PKGBUILD, so the version is not duplicated in JSON.
|
||||
- `rebuild_on`: optional array of package names this package links against closely enough that it must be rebuilt when they change, independent of its own source. Read by `bin/sync-rebuilds`.
|
||||
- `rebuilt_against`: written by `bin/sync-rebuilds`. Records the version of each `rebuild_on` package that the current pkgrel was bumped for.
|
||||
- `rebuilt_against`: written by `bin/sync-rebuilds`. Maps each published architecture to the versions of its `rebuild_on` packages that the current pkgrel was bumped for.
|
||||
- `upstream_commit`: set by `bin/sync-aur` for AUR packages. Used by `bin/package-worktree` to recreate the exact raw AUR package that Omarchy last synced.
|
||||
|
||||
### Build Matrix
|
||||
@@ -737,10 +830,15 @@ bin/repo release --package my-package
|
||||
- Mirrors: mirror.omarchy.org, rackspace, pkgbuild.com
|
||||
|
||||
### aarch64
|
||||
- QEMU emulation required on x86_64 hosts (slower)
|
||||
- Uses Arch Linux ARM repositories
|
||||
- Built on the repository host like x86_64; under QEMU when the host is x86_64
|
||||
- On an ARM host, package builds and the signing/database utility containers
|
||||
run natively; only an explicitly requested x86_64 package build is emulated
|
||||
- Uses Arch Linux ARM repositories through the same HTTPS mirror for every
|
||||
channel (Arch Linux ARM publishes no dated snapshots to pin a channel's base)
|
||||
- Additional repos: `[alarm]`, `[aur]`
|
||||
- Same workflow, just add `--arch aarch64`
|
||||
- Same workflow, just add `--arch aarch64`; the scheduled pipeline runs it
|
||||
automatically once `aarch64` is in `PUBLISHED_ARCHES`
|
||||
- Packages whose `arch=()` lacks `aarch64` are skipped, not failed
|
||||
|
||||
### Building for Both Architectures
|
||||
|
||||
@@ -791,8 +889,8 @@ The repository includes GitHub workflows and systemd services for automated rele
|
||||
All four units run **every 5 minutes**, staggered by a minute each, so a push
|
||||
reaches the mirror in minutes rather than hours:
|
||||
|
||||
1. **check-versions** (`*:0/5`): Pulls latest from git, compares PKGBUILD versions to published versions, creates state files if builds are needed
|
||||
2. **auto-release-edge** (`*:1/5`): If a state file exists, builds all edge packages that need updates
|
||||
1. **check-versions** (`*:0/5`): Pulls latest from git, compares PKGBUILD versions to published versions for every published architecture, creates one state file per channel and architecture if builds are needed
|
||||
2. **auto-release-edge** (`*:1/5`): For each published architecture with a state file, builds all edge packages that need updates
|
||||
3. **auto-release-rc** (`*:2/5`): Builds fast-ring packages for rc, from the main checkout like the other two — natively in the rc image, not copied from another channel. The pinned release pair is built separately by `omarchy-release rc` in the `rc` branch worktree
|
||||
4. **auto-release-stable** (`*:3/5`): If a state file exists, builds `release_ring=fast` packages for stable and replicates them to rc
|
||||
|
||||
@@ -806,10 +904,11 @@ That cadence is only safe because of three guards:
|
||||
an operator expects. `check-versions` takes it too — its `git pull` would
|
||||
otherwise swap PKGBUILDs out from under a running build.
|
||||
- **Backoff on failure.** A failed release records the attempt in
|
||||
`.build-failed-<channel>` and backs off exponentially — 10m, 20m, 40m, up to
|
||||
`.build-failed-<channel>-<arch>` and backs off exponentially — 10m, 20m, 40m, up to
|
||||
a 6h ceiling — instead of rebuilding the same broken tree every 5 minutes.
|
||||
**Any new commit clears the backoff immediately**, since a push is the most
|
||||
likely fix. Clear it by hand with `rm /root/.state/.build-failed-<channel>`.
|
||||
likely fix. Clear it by hand with
|
||||
`rm /root/.state/.build-failed-<channel>-<arch>`.
|
||||
- **Quiet when idle.** With nothing queued a tick exits without output, so the
|
||||
journal shows the runs that mattered rather than 288 no-ops a day.
|
||||
|
||||
@@ -862,10 +961,14 @@ bin/repo timers --local # inspect this machine instead
|
||||
```
|
||||
|
||||
State files are stored in `/root/.state/`:
|
||||
- `.sync-needed-<channel>` — the packages queued for that channel, one per
|
||||
line; the release run reads them to name what it is building
|
||||
- `.build-failed-<channel>` — consecutive failure count, timestamp, and the
|
||||
commit it failed on (drives the backoff; removing it forces a retry)
|
||||
- `.sync-needed-<channel>-<arch>` — the packages queued for that channel and
|
||||
architecture, one per line; the release run reads them to name what it is
|
||||
building
|
||||
- `.build-failed-<channel>-<arch>` — consecutive failure count, timestamp, and
|
||||
the commit it failed on (drives the backoff; removing it forces a retry)
|
||||
|
||||
Legacy files without the architecture suffix are consumed once as x86_64
|
||||
state, so upgrading the host does not lose an in-flight build.
|
||||
|
||||
### Schedule (America/New_York)
|
||||
|
||||
|
||||
+51
-3
@@ -25,6 +25,22 @@ SKIP_PROD_CHECK=false
|
||||
FAST_RING_ONLY=false
|
||||
BOOTSTRAP=false
|
||||
PACKAGES=""
|
||||
ALL_ARCHES=false
|
||||
|
||||
# Kept for --arch all, which re-invokes this script per architecture with the
|
||||
# other arguments unchanged (minus the --arch all pair itself).
|
||||
ORIGINAL_ARGS=()
|
||||
arch_option=false
|
||||
for arg in "$@"; do
|
||||
if [[ "$arch_option" == true ]]; then
|
||||
[[ "$arg" != "all" ]] && ORIGINAL_ARGS+=("--arch" "$arg")
|
||||
arch_option=false
|
||||
elif [[ "$arg" == "--arch" ]]; then
|
||||
arch_option=true
|
||||
else
|
||||
ORIGINAL_ARGS+=("$arg")
|
||||
fi
|
||||
done
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 --from <channel> --to <channel> [OPTIONS]"
|
||||
@@ -36,7 +52,8 @@ usage() {
|
||||
echo " or --bootstrap (one-time initial seed)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --arch <arch> Target architecture (x86_64 or aarch64, default: x86_64)"
|
||||
echo " --arch <arch>|all Target architecture (x86_64 or aarch64, default: x86_64);"
|
||||
echo " all = every published architecture, one after another"
|
||||
echo " --package <names...> Advance only the named package(s)"
|
||||
echo " --fast-ring Restrict to fast-ring packages (stable -> rc parity copy)"
|
||||
echo " --bootstrap One-time stable -> rc seed before forward-only enforcement"
|
||||
@@ -65,8 +82,14 @@ while [[ $# -gt 0 ]]; do
|
||||
shift 2
|
||||
;;
|
||||
--arch)
|
||||
ARCH="$2"
|
||||
update_arch_paths
|
||||
if [[ "$2" == "all" ]]; then
|
||||
ALL_ARCHES=true
|
||||
ARCH=all
|
||||
else
|
||||
require_valid_arch "$2"
|
||||
ARCH="$2"
|
||||
update_arch_paths
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
--package)
|
||||
@@ -134,6 +157,31 @@ case "$FROM->$TO" in
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$ALL_ARCHES" == true ]]; then
|
||||
# Hold one lock across the whole operation so a timer cannot mutate a
|
||||
# channel between architectures. Check every source database before moving
|
||||
# the first one; a failed sync can still require an idempotent retry, but a
|
||||
# missing architecture never creates a knowingly partial advance.
|
||||
if [[ "$DRY_RUN" != true ]]; then
|
||||
acquire_release_lock || exit 1
|
||||
fi
|
||||
|
||||
ARCHES=$(published_arches)
|
||||
for arch in $ARCHES; do
|
||||
source_db="$REPO_ROOT/$FROM/$arch/omarchy.db.tar.zst"
|
||||
if [[ ! -f "$source_db" ]]; then
|
||||
print_error "Source database not found: $source_db"
|
||||
echo "Nothing has been published to the $FROM channel for $arch."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for arch in $ARCHES; do
|
||||
"$0" --arch "$arch" "${ORIGINAL_ARGS[@]}" || exit $?
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SOURCE_DIR="$REPO_ROOT/$FROM/$ARCH"
|
||||
TARGET_DIR="$REPO_ROOT/$TO/$ARCH"
|
||||
SOURCE_DB="$SOURCE_DIR/omarchy.db.tar.zst"
|
||||
|
||||
+104
-57
@@ -1,6 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Run the release workflow for a channel when work is queued.
|
||||
# Usage: auto-release <edge|rc|stable>
|
||||
# Usage: auto-release <edge|rc|stable> [<arch>|all]
|
||||
#
|
||||
# With no architecture (what the timers pass), every published architecture
|
||||
# is processed in turn, each against its own queue and its own backoff, so a
|
||||
# failing aarch64 build never holds up x86_64 or the other way round.
|
||||
#
|
||||
# Safe to run on a tight schedule. Three guards make that true:
|
||||
#
|
||||
@@ -21,7 +25,7 @@ source "$BUILD_ROOT/helpers/paths.sh"
|
||||
source "$BUILD_ROOT/helpers/lock-helpers.sh"
|
||||
|
||||
MIRROR="${1:-}"
|
||||
STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}"
|
||||
ARCH_ARG="${2:-all}"
|
||||
|
||||
# Backoff schedule: 10m, 20m, 40m, 80m, 160m, 320m, then hourly-ish forever
|
||||
# (capped at 6h, the cadence this system ran at before frequent timers).
|
||||
@@ -29,8 +33,9 @@ BACKOFF_BASE_SECONDS="${OMARCHY_BACKOFF_BASE:-600}"
|
||||
BACKOFF_MAX_SECONDS="${OMARCHY_BACKOFF_MAX:-21600}"
|
||||
|
||||
if [[ -z "$MIRROR" ]]; then
|
||||
print_error "Usage: $0 <mirror>"
|
||||
print_error "Usage: $0 <mirror> [<arch>|all]"
|
||||
echo " mirror: edge, rc, or stable"
|
||||
echo " arch: one of $VALID_ARCHES, or all (default) for every published architecture"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -39,17 +44,13 @@ if [[ "$MIRROR" != "edge" && "$MIRROR" != "rc" && "$MIRROR" != "stable" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
STATE_FILE="$STATE_DIR/.sync-needed-$MIRROR"
|
||||
FAIL_FILE="$STATE_DIR/.build-failed-$MIRROR"
|
||||
|
||||
# Nothing queued: stay quiet. At a 5-minute cadence this is most invocations,
|
||||
# and a header for each would bury the runs that matter in the journal.
|
||||
if [[ ! -f "$STATE_FILE" ]]; then
|
||||
exit 0
|
||||
if [[ "$ARCH_ARG" == "all" ]]; then
|
||||
ARCHES=$(published_arches)
|
||||
else
|
||||
require_valid_arch "$ARCH_ARG"
|
||||
ARCHES="$ARCH_ARG"
|
||||
fi
|
||||
|
||||
print_header "Processing Sync for $MIRROR"
|
||||
|
||||
# The build inputs are this checkout's contents; its HEAD identifies them.
|
||||
current_fingerprint() {
|
||||
git -C "$BUILD_ROOT" rev-parse HEAD 2>/dev/null || echo "unknown"
|
||||
@@ -65,57 +66,103 @@ backoff_seconds() {
|
||||
echo "$delay"
|
||||
}
|
||||
|
||||
FAIL_COUNT=0
|
||||
if [[ -f "$FAIL_FILE" ]]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "$FAIL_FILE" 2>/dev/null || true
|
||||
FAIL_COUNT="${FAILURE_COUNT:-0}"
|
||||
failed_at="${FAILURE_AT:-0}"
|
||||
failed_fingerprint="${FAILURE_FINGERPRINT:-}"
|
||||
# Returns 0 when this architecture's queue was processed (or was empty), 1 when
|
||||
# the release failed. Backoff and "someone else holds the lock" are not
|
||||
# failures: they are this tick deciding to do nothing.
|
||||
release_arch() {
|
||||
local arch="$1"
|
||||
local state_file fail_file
|
||||
state_file=$(sync_queue_file "$MIRROR" "$arch")
|
||||
fail_file=$(sync_fail_file "$MIRROR" "$arch")
|
||||
|
||||
if [[ "$failed_fingerprint" != "$(current_fingerprint)" ]]; then
|
||||
print_info "Repository changed since the last failure — clearing backoff and retrying"
|
||||
rm -f "$FAIL_FILE"
|
||||
FAIL_COUNT=0
|
||||
else
|
||||
delay=$(backoff_seconds "$FAIL_COUNT")
|
||||
now=$(date +%s)
|
||||
retry_at=$((failed_at + delay))
|
||||
if ((now < retry_at)); then
|
||||
print_warning "$MIRROR has failed $FAIL_COUNT time(s) on this tree — not retrying until $(date -d "@$retry_at" '+%H:%M:%S' 2>/dev/null || echo "+$((retry_at - now))s")"
|
||||
echo " Push a fix (any new commit clears this), or: rm $FAIL_FILE"
|
||||
exit 0
|
||||
fi
|
||||
print_info "Backoff elapsed — retrying $MIRROR (failure #$((FAIL_COUNT + 1)) if this fails)"
|
||||
# A queue written under the pre-architecture name belongs to x86_64.
|
||||
if [[ "$arch" == "x86_64" && ! -f "$state_file" && -f "$(legacy_sync_queue_file "$MIRROR")" ]]; then
|
||||
state_file=$(legacy_sync_queue_file "$MIRROR")
|
||||
fi
|
||||
if [[ "$arch" == "x86_64" && ! -f "$fail_file" && -f "$(legacy_sync_fail_file "$MIRROR")" ]]; then
|
||||
fail_file=$(legacy_sync_fail_file "$MIRROR")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Non-blocking: a build in progress means this tick has nothing to do.
|
||||
if ! try_release_lock; then
|
||||
holder=$(release_lock_holder)
|
||||
print_info "A release is already running (${holder:-holder unknown}) — skipping this tick"
|
||||
exit 0
|
||||
fi
|
||||
# Nothing queued: stay quiet. At a 5-minute cadence this is most
|
||||
# invocations, and a header for each would bury the runs that matter in
|
||||
# the journal.
|
||||
[[ -f "$state_file" ]] || return 0
|
||||
|
||||
print_info "State file found: $STATE_FILE"
|
||||
print_info "Starting release workflow for $MIRROR..."
|
||||
print_header "Processing Sync for $MIRROR ($arch)"
|
||||
|
||||
if "$BUILD_ROOT/bin/repo" release --mirror "$MIRROR" --skip-prod-check; then
|
||||
print_success "Release completed successfully for $MIRROR"
|
||||
rm -f "$STATE_FILE"
|
||||
rm -f "$FAIL_FILE"
|
||||
print_success "State file removed: $STATE_FILE"
|
||||
else
|
||||
status=$?
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
cat >"$FAIL_FILE" <<EOF
|
||||
FAILURE_COUNT=$FAIL_COUNT
|
||||
local fail_count=0 failed_at failed_fingerprint delay now retry_at
|
||||
if [[ -f "$fail_file" ]]; then
|
||||
FAILURE_COUNT=0 FAILURE_AT=0 FAILURE_FINGERPRINT=""
|
||||
# shellcheck disable=SC1090
|
||||
source "$fail_file" 2>/dev/null || true
|
||||
fail_count="${FAILURE_COUNT:-0}"
|
||||
failed_at="${FAILURE_AT:-0}"
|
||||
failed_fingerprint="${FAILURE_FINGERPRINT:-}"
|
||||
|
||||
if [[ "$failed_fingerprint" != "$(current_fingerprint)" ]]; then
|
||||
print_info "Repository changed since the last failure — clearing backoff and retrying"
|
||||
rm -f "$fail_file"
|
||||
fail_count=0
|
||||
else
|
||||
delay=$(backoff_seconds "$fail_count")
|
||||
now=$(date +%s)
|
||||
retry_at=$((failed_at + delay))
|
||||
if ((now < retry_at)); then
|
||||
print_warning "$MIRROR ($arch) has failed $fail_count time(s) on this tree — not retrying until $(date -d "@$retry_at" '+%H:%M:%S' 2>/dev/null || echo "+$((retry_at - now))s")"
|
||||
echo " Push a fix (any new commit clears this), or: rm $fail_file"
|
||||
return 0
|
||||
fi
|
||||
print_info "Backoff elapsed — retrying $MIRROR ($arch) (failure #$((fail_count + 1)) if this fails)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Non-blocking: a build in progress means this tick has nothing to do. The
|
||||
# lock is reentrant, so once this run holds it the remaining architectures
|
||||
# run under the same acquisition.
|
||||
if ! try_release_lock; then
|
||||
local holder
|
||||
holder=$(release_lock_holder)
|
||||
print_info "A release is already running (${holder:-holder unknown}) — skipping this tick"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_info "State file found: $state_file"
|
||||
print_info "Starting release workflow for $MIRROR ($arch)..."
|
||||
|
||||
if "$BUILD_ROOT/bin/repo" release --mirror "$MIRROR" --arch "$arch" --skip-prod-check; then
|
||||
print_success "Release completed successfully for $MIRROR ($arch)"
|
||||
local completed_state=("$state_file" "$fail_file")
|
||||
if [[ "$arch" == "x86_64" ]]; then
|
||||
completed_state+=("$(legacy_sync_queue_file "$MIRROR")" "$(legacy_sync_fail_file "$MIRROR")")
|
||||
fi
|
||||
if ! rm -f "${completed_state[@]}"; then
|
||||
print_error "Release succeeded, but its queue state could not be cleared"
|
||||
return 1
|
||||
fi
|
||||
print_success "State file removed: $state_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
fail_count=$((fail_count + 1))
|
||||
if ! cat >"$fail_file" <<EOF
|
||||
FAILURE_COUNT=$fail_count
|
||||
FAILURE_AT=$(date +%s)
|
||||
FAILURE_FINGERPRINT=$(current_fingerprint)
|
||||
EOF
|
||||
next=$(backoff_seconds "$FAIL_COUNT")
|
||||
print_error "Release failed for $MIRROR (attempt $FAIL_COUNT)"
|
||||
print_warning "State file retained for retry: $STATE_FILE"
|
||||
then
|
||||
print_error "Could not record failure state: $fail_file"
|
||||
return 1
|
||||
fi
|
||||
local next
|
||||
next=$(backoff_seconds "$fail_count")
|
||||
print_error "Release failed for $MIRROR ($arch) (attempt $fail_count)"
|
||||
print_warning "State file retained for retry: $state_file"
|
||||
print_warning "Backing off $((next / 60))m before the next attempt; a new commit retries sooner"
|
||||
exit "$status"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
status=0
|
||||
for arch in $ARCHES; do
|
||||
release_arch "$arch" || status=1
|
||||
done
|
||||
exit "$status"
|
||||
@@ -102,6 +102,8 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
require_valid_arch "$ARCH"
|
||||
|
||||
if [[ $DEFER_RUNTIME_DEPS != "false" && $DEFER_RUNTIME_DEPS != "true" ]]; then
|
||||
print_error "OMARCHY_DEFER_RUNTIME_DEPS must be true or false"
|
||||
exit 1
|
||||
@@ -143,7 +145,7 @@ if [[ $DEFER_RUNTIME_DEPS == "true" ]]; then
|
||||
fi
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
print_warning "DRY RUN MODE - build plan only; no Docker or makepkg will run"
|
||||
print_warning "DRY RUN MODE - build plan only; no container or makepkg will run"
|
||||
ARCH="$ARCH" \
|
||||
MIRROR="$MIRROR" \
|
||||
PACKAGES="$PACKAGES" \
|
||||
@@ -161,15 +163,34 @@ fi
|
||||
# Create directories if they don't exist
|
||||
mkdir -p "$BUILD_OUTPUT_DIR" "$REPO_DIR" "$SRC_DIR"
|
||||
|
||||
# Check Docker is available
|
||||
check_docker
|
||||
# Check the selected container engine is available
|
||||
check_engine
|
||||
|
||||
# Setup QEMU for aarch64 builds on x86_64 hosts
|
||||
if [[ "$(uname -m)" == "x86_64" && "$ARCH" == "aarch64" ]]; then
|
||||
# Check if QEMU is already working
|
||||
if ! docker run --rm --platform linux/arm64 alpine:3.21 /bin/true >/dev/null 2>&1; then
|
||||
print_info "Setting up QEMU for ARM64 emulation..."
|
||||
setup_qemu
|
||||
# A foreign target architecture runs under QEMU user emulation. Probe by
|
||||
# actually running a container for the target platform: that is the only
|
||||
# test that covers both "binfmt not registered" and "registered but broken".
|
||||
HOST_ARCH=$(uname -m)
|
||||
[[ "$HOST_ARCH" == "arm64" ]] && HOST_ARCH=aarch64
|
||||
if [[ "$HOST_ARCH" != "$ARCH" ]]; then
|
||||
PROBE_IMAGE="alpine:3.21"
|
||||
[[ "$CONTAINER_ENGINE" == "podman" ]] && PROBE_IMAGE="docker.io/library/alpine:3.21"
|
||||
|
||||
# Rootless Podman cannot repair host binfmt state itself. Validate the flags
|
||||
# before the basic probe, because an F-only registration can start an ARM
|
||||
# container but silently breaks sudo inside it.
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
setup_qemu "$ARCH"
|
||||
fi
|
||||
|
||||
if ! "$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$ARCH")" "$PROBE_IMAGE" /bin/true >/dev/null 2>&1; then
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
print_error "QEMU $ARCH is registered, but the container probe failed"
|
||||
print_info "Refresh the registration with: sudo systemctl restart systemd-binfmt"
|
||||
exit 1
|
||||
else
|
||||
print_info "Setting up QEMU for $ARCH emulation on this $HOST_ARCH host..."
|
||||
setup_qemu "$ARCH"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -179,7 +200,7 @@ if [[ $KEEP_BUILD_WORKSPACE == "1" ]]; then
|
||||
print_info "Keeping existing build workspace..."
|
||||
else
|
||||
print_info "Cleaning build workspace..."
|
||||
rm -rf "$BUILD_OUTPUT_DIR"/*
|
||||
rm -rf "${BUILD_OUTPUT_DIR:?}"/*
|
||||
fi
|
||||
mkdir -p "$BUILD_OUTPUT_DIR"
|
||||
|
||||
@@ -196,7 +217,7 @@ fi
|
||||
# flag is that every job runs the same bytes.
|
||||
IMAGE_TAG="omarchy-pkg-builder:latest-$ARCH-$MIRROR"
|
||||
if [[ $SKIP_BUILDER_IMAGE == "1" ]]; then
|
||||
if ! docker image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
|
||||
if ! "$CONTAINER_ENGINE" image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
|
||||
print_error "Prepared builder image is unavailable: $IMAGE_TAG"
|
||||
exit 1
|
||||
fi
|
||||
@@ -211,9 +232,12 @@ print_info "Running package build..."
|
||||
mkdir -p "$BUILD_OUTPUT_DIR"
|
||||
mkdir -p "$REPO_DIR"
|
||||
|
||||
# Ensure output directories are writable by container user
|
||||
make_dir_writable "$BUILD_OUTPUT_DIR"
|
||||
make_dir_writable "$REPO_DIR"
|
||||
# Rootful Docker writes as the image uid, so retain its existing permission
|
||||
# workaround. Rootless Podman uses keep-id and must leave ownership/modes alone.
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
make_dir_writable "$BUILD_OUTPUT_DIR"
|
||||
make_dir_writable "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# Build Docker arguments
|
||||
DOCKER_ARGS=(
|
||||
@@ -230,10 +254,16 @@ DOCKER_ARGS=(
|
||||
-v "$BUILD_ROOT/pkgbuilds:/pkgbuilds:ro"
|
||||
)
|
||||
|
||||
# Podman-created images can leave WORKDIR owned by a remapped uid. Mount the
|
||||
# existing host-user-owned workspace so the builder can write there.
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
DOCKER_ARGS+=(-v "$SRC_DIR:/src")
|
||||
fi
|
||||
|
||||
# Run the builder with assembled args
|
||||
PLATFORM_ARG=$(get_platform_arg "$ARCH")
|
||||
|
||||
docker run $PLATFORM_ARG "${DOCKER_ARGS[@]}" "$IMAGE_TAG" /build/build.sh
|
||||
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" "$PLATFORM_ARG" "${DOCKER_ARGS[@]}" "$IMAGE_TAG" /build/build.sh
|
||||
|
||||
BUILD_RESULT=$?
|
||||
|
||||
|
||||
+38
-12
@@ -1,6 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Check PKGBUILD versions against published repo versions
|
||||
# Creates state files for edge and/or stable if any packages need building
|
||||
# Creates a state file per channel and architecture when packages need building
|
||||
#
|
||||
# Usage: check-versions [--pull] [--arch <arch>]
|
||||
# --pull pull the repository first (the scheduled run does this)
|
||||
# --arch <arch> check one architecture; default: every published one
|
||||
|
||||
set -e
|
||||
|
||||
@@ -10,11 +14,27 @@ source "$BUILD_ROOT/helpers/paths.sh"
|
||||
source "$BUILD_ROOT/helpers/package-metadata.sh"
|
||||
source "$BUILD_ROOT/helpers/lock-helpers.sh"
|
||||
|
||||
STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}"
|
||||
ARCH="${ARCH:-x86_64}"
|
||||
PULL=false
|
||||
ARCHES=""
|
||||
|
||||
[[ "${1:-}" == "--pull" ]] && PULL=true
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--pull)
|
||||
PULL=true
|
||||
shift
|
||||
;;
|
||||
--arch)
|
||||
require_valid_arch "$2"
|
||||
ARCHES="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
[[ -n "$ARCHES" ]] || ARCHES=$(published_arches)
|
||||
|
||||
mkdir -p "$STATE_DIR"
|
||||
|
||||
@@ -147,11 +167,12 @@ check_package() {
|
||||
|
||||
check_mirror() {
|
||||
local mirror="$1"
|
||||
local state_file="$STATE_DIR/.sync-needed-$mirror"
|
||||
local state_file
|
||||
state_file=$(sync_queue_file "$mirror" "$ARCH")
|
||||
local needs_build=false
|
||||
local packages=()
|
||||
|
||||
print_info "Checking $mirror packages..."
|
||||
print_info "Checking $mirror packages for $ARCH..."
|
||||
|
||||
while IFS= read -r pkg; do
|
||||
local pkgdir="$PKGBUILDS_DIR/$pkg"
|
||||
@@ -159,7 +180,7 @@ check_mirror() {
|
||||
needs_build=true
|
||||
packages+=("$pkg")
|
||||
fi
|
||||
done < <(packages_for_unscoped_build "$mirror")
|
||||
done < <(packages_for_unscoped_build "$mirror" "$ARCH")
|
||||
|
||||
echo ""
|
||||
|
||||
@@ -168,18 +189,23 @@ check_mirror() {
|
||||
# this to name the packages in its start report, which is the difference
|
||||
# between "a build is running" and "your package is in this build".
|
||||
printf '%s\n' "${packages[@]}" >"$state_file"
|
||||
print_success "${mirror^} needs building (${#packages[@]} packages)"
|
||||
print_success "${mirror^} ($ARCH) needs building (${#packages[@]} packages)"
|
||||
print_info "Packages: ${packages[*]}"
|
||||
print_info "State file created: $state_file"
|
||||
else
|
||||
print_info "${mirror^} is up to date"
|
||||
print_info "${mirror^} ($ARCH) is up to date"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
check_mirror edge
|
||||
check_mirror rc
|
||||
check_mirror stable
|
||||
# One pass per published architecture: the version comparison reads that
|
||||
# architecture's channel databases, and each queue is its own file.
|
||||
for ARCH in $ARCHES; do
|
||||
update_arch_paths
|
||||
check_mirror edge
|
||||
check_mirror rc
|
||||
check_mirror stable
|
||||
done
|
||||
|
||||
print_success "Version check complete!"
|
||||
+13
-7
@@ -1,21 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Clean Docker builder images and cache
|
||||
# Clean builder images and cache for the selected container engine
|
||||
# Forces a fresh image build on next run
|
||||
|
||||
set -e
|
||||
|
||||
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
|
||||
source "$BUILD_ROOT/helpers/message-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/docker-helpers.sh"
|
||||
|
||||
print_header "Cleaning Docker Builder Images"
|
||||
check_engine
|
||||
print_header "Cleaning Container Builder Images"
|
||||
|
||||
# Remove all omarchy-pkg-builder images
|
||||
print_info "Removing omarchy-pkg-builder images..."
|
||||
docker images omarchy-pkg-builder -q | xargs -r docker rmi -f 2>/dev/null || true
|
||||
"$CONTAINER_ENGINE" images omarchy-pkg-builder -q | xargs -r "$CONTAINER_ENGINE" rmi -f 2>/dev/null || true
|
||||
|
||||
# Clear buildx cache for these builds
|
||||
print_info "Clearing buildx cache..."
|
||||
docker buildx prune -a -f
|
||||
# Clear this engine's build cache.
|
||||
print_info "Clearing build cache..."
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
"$CONTAINER_ENGINE" buildx prune -a -f
|
||||
else
|
||||
"$CONTAINER_ENGINE" image prune --build-cache -f
|
||||
fi
|
||||
|
||||
print_success "Docker builder cache cleared"
|
||||
print_success "Container builder cache cleared"
|
||||
print_info "Next build will create fresh images"
|
||||
+7
-3
@@ -31,9 +31,13 @@ clean_packages() {
|
||||
# Skip signature files
|
||||
[[ "$pkg" == *.sig ]] && continue
|
||||
|
||||
# Extract package name (remove version and architecture)
|
||||
# Format: name-version-release-arch.pkg.tar.*
|
||||
local pkgname=$(echo "$pkg" | sed -E 's/-[0-9]+.*-(any|x86_64|i686)\.pkg\.tar\..*//')
|
||||
# Format: name-version-release-arch.pkg.tar.*. Work from the right because
|
||||
# package names can themselves contain version-like pieces (qt6-5compat,
|
||||
# nvidia-580xx-utils), while pkgver and pkgrel cannot contain hyphens.
|
||||
local stem="${pkg%%.pkg.tar.*}"
|
||||
stem="${stem%-*}" # architecture
|
||||
stem="${stem%-*}" # pkgrel
|
||||
local pkgname="${stem%-*}" # pkgver
|
||||
|
||||
# Add to array
|
||||
if [[ -n "${packages[$pkgname]}" ]]; then
|
||||
|
||||
+12
-6
@@ -23,7 +23,7 @@ source "$BUILD_ROOT/helpers/paths.sh"
|
||||
source "$BUILD_ROOT/helpers/host-helpers.sh"
|
||||
|
||||
UPSTREAM_URL="${OMARCHY_UPSTREAM_URL:-https://github.com/basecamp/omarchy.git}"
|
||||
EDGE_DB_URL="${OMARCHY_EDGE_DB_URL:-https://pkgs.omarchy.org/edge/x86_64/omarchy.db.tar.zst}"
|
||||
EDGE_DB_URL="${OMARCHY_EDGE_DB_URL:-https://pkgs.omarchy.org/edge/$(reference_arch)/omarchy.db.tar.zst}"
|
||||
RELEASE_PACKAGES=(omarchy omarchy-settings)
|
||||
DEFAULT_RC_REF="quattro"
|
||||
SRCDEST_DIR="$BUILD_ROOT/.srcdest"
|
||||
@@ -327,13 +327,19 @@ regenerate_checksums() {
|
||||
|
||||
trigger_build_host() {
|
||||
local host
|
||||
queue_edge_builds() {
|
||||
mkdir -p "$STATE_DIR" || return 1
|
||||
local arch
|
||||
for arch in $(published_arches); do
|
||||
touch "$(sync_queue_file edge "$arch")" || return 1
|
||||
done
|
||||
}
|
||||
|
||||
# Explicit host configuration outranks the local-host inference (a
|
||||
# workstation that ran a full local release carries the db marker too).
|
||||
if ! resolve_repo_host "${REPO_HOST_OVERRIDE:-}" >/dev/null && on_repo_host; then
|
||||
print_info "Triggering edge build locally (this is the build host)..."
|
||||
if mkdir -p "${OMARCHY_STATE_DIR:-/root/.state}" &&
|
||||
touch "${OMARCHY_STATE_DIR:-/root/.state}/.sync-needed-edge" &&
|
||||
systemctl start --no-block omarchy-auto-release-edge.service; then
|
||||
if queue_edge_builds && systemctl start --no-block omarchy-auto-release-edge.service; then
|
||||
print_success "Edge build triggered"
|
||||
else
|
||||
print_warning "Could not start the edge release service — the 6-hourly timer will pick it up"
|
||||
@@ -343,11 +349,11 @@ trigger_build_host() {
|
||||
if ! host=$(resolve_repo_host "${REPO_HOST_OVERRIDE:-}"); then
|
||||
print_info "No repository host configured (set OMARCHY_REPO_HOST or $BUILD_ROOT/.repo-host — any ssh destination, e.g. root@<host> or an ssh-config alias)."
|
||||
print_info "The 6-hourly auto-release timer will pick this up, or trigger manually:"
|
||||
echo " ssh <build-host> 'git -C /root/omarchy-pkgs pull --ff-only && touch /root/.state/.sync-needed-edge && systemctl start omarchy-auto-release-edge.service'"
|
||||
echo " ssh <build-host> 'git -C /root/omarchy-pkgs pull --ff-only && systemctl start omarchy-check-versions.service omarchy-auto-release-edge.service'"
|
||||
return 0
|
||||
fi
|
||||
print_info "Triggering edge build on $host..."
|
||||
if ssh "$host" 'git -C /root/omarchy-pkgs pull --ff-only && mkdir -p /root/.state && touch /root/.state/.sync-needed-edge && systemctl start --no-block omarchy-auto-release-edge.service'; then
|
||||
if ssh "$host" 'git -C /root/omarchy-pkgs pull --ff-only && cd /root/omarchy-pkgs && export BUILD_ROOT=/root/omarchy-pkgs && source helpers/paths.sh && mkdir -p "$STATE_DIR" && for arch in $(published_arches); do touch "$(sync_queue_file edge "$arch")"; done && systemctl start --no-block omarchy-auto-release-edge.service'; then
|
||||
print_success "Edge build triggered on $host"
|
||||
else
|
||||
print_warning "Could not trigger $host — the 6-hourly timer will pick it up"
|
||||
|
||||
+93
-55
@@ -18,6 +18,7 @@ set -e
|
||||
|
||||
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
|
||||
source "$BUILD_ROOT/helpers/message-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/docker-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/paths.sh"
|
||||
source "$BUILD_ROOT/helpers/host-helpers.sh"
|
||||
|
||||
@@ -28,7 +29,11 @@ ISO_REPO="${OMARCHY_ISO_REPO:-omacom-io/omarchy-iso}"
|
||||
DEV_BRANCH="${OMARCHY_DEV_BRANCH:-quattro}"
|
||||
|
||||
PKGS_DB_BASE="${OMARCHY_PKGS_DB_BASE:-https://pkgs.omarchy.org}"
|
||||
RC_DB_URL="$PKGS_DB_BASE/rc/x86_64/omarchy.db.tar.zst"
|
||||
# The first published architecture supplies the version-ordering floor when
|
||||
# cutting pins. Readiness checks below still verify every published
|
||||
# architecture before an RC or final release can move forward.
|
||||
OBSERVED_ARCH=$(reference_arch)
|
||||
RC_DB_URL="$PKGS_DB_BASE/rc/$OBSERVED_ARCH/omarchy.db.tar.zst"
|
||||
|
||||
SRCDEST_DIR="$BUILD_ROOT/.srcdest"
|
||||
MIRROR_CLONE="$SRCDEST_DIR/omarchy" # bare mirror (shared with bin/omarchy-pkgs)
|
||||
@@ -181,12 +186,12 @@ ensure_work_clone() {
|
||||
# Prints omarchy's published version in a channel; empty when absent, rc 2 when
|
||||
# the database cannot be read (callers must not mistake an outage for absence).
|
||||
published_version() {
|
||||
local channel="$1" tmp descs
|
||||
local channel="$1" arch="${2:-$OBSERVED_ARCH}" tmp descs
|
||||
tmp=$(mktemp) || return 2
|
||||
# A unique query string busts the CDN cache: right after a sync the plain
|
||||
# URL can keep serving the previous db for a while, which reads as "not
|
||||
# published yet" to status, the wait loop, and ship's pre-checks.
|
||||
if ! curl -sf "$PKGS_DB_BASE/$channel/x86_64/omarchy.db.tar.zst?$(date +%s%N)" -o "$tmp"; then
|
||||
if ! curl -sf "$PKGS_DB_BASE/$channel/$arch/omarchy.db.tar.zst?$(date +%s%N)" -o "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
return 2
|
||||
fi
|
||||
@@ -207,6 +212,14 @@ published_version() {
|
||||
' <<<"$descs"
|
||||
}
|
||||
|
||||
all_arches_at_version() { # all_arches_at_version <channel> <pkgver>
|
||||
local channel="$1" want="$2" arch got
|
||||
for arch in $(published_arches); do
|
||||
got=$(published_version "$channel" "$arch" 2>/dev/null) || return 1
|
||||
[[ "${got%-*}" == "$want" ]] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
# The rc branch of THIS repo carries the current pins. Read them without
|
||||
# touching the working tree.
|
||||
rc_branch_pin() { # prints "pkgver commit", empty when no rc branch
|
||||
@@ -251,8 +264,12 @@ fi
|
||||
git -C /root/omarchy-pkgs-rc fetch origin rc
|
||||
git -C /root/omarchy-pkgs-rc reset --hard origin/rc
|
||||
cd /root/omarchy-pkgs-rc
|
||||
OMARCHY_RC_PINS=1 OMARCHY_REPO_ROOT=/root/omarchy-pkgs/pkgs.omarchy.org \
|
||||
bin/repo release --mirror rc --package omarchy omarchy-settings --skip-prod-check
|
||||
# The pair is built once per published architecture (helpers/paths.sh on the
|
||||
# host decides which), so every architecture'"'"'s rc channel carries the pins.
|
||||
for arch in $(BUILD_ROOT=/root/omarchy-pkgs-rc bash -c "source helpers/paths.sh; published_arches"); do
|
||||
OMARCHY_RC_PINS=1 OMARCHY_REPO_ROOT=/root/omarchy-pkgs/pkgs.omarchy.org \
|
||||
bin/repo release --mirror rc --arch "$arch" --package omarchy omarchy-settings --skip-prod-check
|
||||
done
|
||||
'
|
||||
|
||||
trigger_rc_build() {
|
||||
@@ -278,19 +295,25 @@ host_advance() { # host_advance <from> <to> [extra args...]
|
||||
# against this machine's (likely stale) local tree would be wrong.
|
||||
if ! resolve_repo_host "$REPO_HOST_OVERRIDE" >/dev/null && ! on_repo_host; then
|
||||
print_no_host_help "advance $from -> $to" \
|
||||
" cd /root/omarchy-pkgs && bin/repo advance --from $from --to $to --skip-prod-check $*"
|
||||
" cd /root/omarchy-pkgs && bin/repo advance --from $from --to $to --arch all --skip-prod-check $*"
|
||||
return 1
|
||||
fi
|
||||
"$BUILD_ROOT/bin/repo" advance --from "$from" --to "$to" --skip-prod-check "$@"
|
||||
# --arch all: the host advances every architecture it publishes, so a train
|
||||
# never moves a channel for one architecture and not another.
|
||||
"$BUILD_ROOT/bin/repo" advance --from "$from" --to "$to" --arch all --skip-prod-check "$@"
|
||||
}
|
||||
|
||||
wait_for_published() { # wait_for_published <channel> <version> [timeout-seconds]
|
||||
local channel="$1" want="$2" timeout="${3:-3600}" waited=0 got
|
||||
print_info "Waiting for $want to appear in the $channel channel (up to $((timeout / 60))m)..."
|
||||
local channel="$1" want="$2" timeout="${3:-3600}" waited=0 arch got pending
|
||||
print_info "Waiting for $want in $channel for: $(published_arches | tr '\n' ' ')"
|
||||
while ((waited < timeout)); do
|
||||
got=$(published_version "$channel" 2>/dev/null) || got=""
|
||||
if [[ "${got%-*}" == "$want" ]]; then
|
||||
print_success "$channel now serves omarchy $got"
|
||||
pending=""
|
||||
for arch in $(published_arches); do
|
||||
got=$(published_version "$channel" "$arch" 2>/dev/null) || got=""
|
||||
[[ "${got%-*}" == "$want" ]] || pending+=" $arch=${got:-unreachable}"
|
||||
done
|
||||
if [[ -z "$pending" ]]; then
|
||||
print_success "$channel now serves omarchy $want on every published architecture"
|
||||
return 0
|
||||
fi
|
||||
sleep 60
|
||||
@@ -298,7 +321,7 @@ wait_for_published() { # wait_for_published <channel> <version> [timeout-seconds
|
||||
printf '.' >&2
|
||||
done
|
||||
echo "" >&2
|
||||
print_warning "Timed out waiting for $want in $channel (currently: ${got:-unknown})"
|
||||
print_warning "Timed out waiting for $want in $channel (pending:$pending)"
|
||||
print_info "The build may still be running — re-run this command to resume."
|
||||
return 1
|
||||
}
|
||||
@@ -352,8 +375,8 @@ iso_checkout() { # prints a usable omarchy-iso checkout, cloning to tmp if neede
|
||||
build_iso() { # build_iso <version> [--rc]
|
||||
local version="$1" rc_flag="${2:-}" dir
|
||||
dir=$(iso_checkout) || return 1
|
||||
if ! command -v docker >/dev/null || ! docker info >/dev/null 2>&1; then
|
||||
print_warning "Docker unavailable — cannot build the ISO here. Run on a Docker machine:"
|
||||
if [[ -z "$CONTAINER_ENGINE" ]] || ! "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
print_warning "No container engine is available — cannot build the ISO here. Run on a Docker or Podman machine:"
|
||||
echo " cd $dir && bin/omarchy-iso-release ${rc_flag:+$rc_flag }$version"
|
||||
return 1
|
||||
fi
|
||||
@@ -662,15 +685,13 @@ cmd_rc() {
|
||||
if [[ -n "$pin" ]]; then
|
||||
local pin_ver="${pin%% *}" pin_commit="${pin##* }"
|
||||
if [[ "$pin_commit" == "$head" && "$pin_ver" =~ ^${version//./\\.}rc[0-9]+$ ]]; then
|
||||
local pub
|
||||
pub=$(published_version rc 2>/dev/null) || pub=""
|
||||
if [[ "${pub%-*}" == "$pin_ver" ]]; then
|
||||
print_success "$pin_ver is already cut from this head and published to rc"
|
||||
if all_arches_at_version rc "$pin_ver"; then
|
||||
print_success "$pin_ver is already cut from this head and published to rc on every architecture"
|
||||
maybe_iso "$pin_ver" rc "$iso_mode"
|
||||
return 0
|
||||
fi
|
||||
print_info "$pin_ver is pinned from this head but not published yet — re-triggering the build"
|
||||
trigger_rc_build || true
|
||||
trigger_rc_build || return 1
|
||||
[[ "$wait" == true ]] && wait_for_published rc "$pin_ver"
|
||||
maybe_iso "$pin_ver" rc "$iso_mode"
|
||||
return 0
|
||||
@@ -686,7 +707,7 @@ cmd_rc() {
|
||||
new_ver="${new_pin%% *}"
|
||||
print_success "Pinned $new_ver (rc branch pushed)"
|
||||
|
||||
trigger_rc_build || true
|
||||
trigger_rc_build || return 1
|
||||
if [[ "$wait" == true ]]; then
|
||||
wait_for_published rc "$new_ver" || return 1
|
||||
fi
|
||||
@@ -708,9 +729,7 @@ cmd_ship() {
|
||||
exit 1
|
||||
fi
|
||||
version=$(branch_to_version "$branch")
|
||||
local stable_now
|
||||
stable_now=$(published_version stable 2>/dev/null) || stable_now=""
|
||||
if [[ "${stable_now%-*}" == "$version" ]] &&
|
||||
if all_arches_at_version stable "$version" &&
|
||||
gh release view "v$version" --repo "$UPSTREAM_REPO" >/dev/null 2>&1; then
|
||||
print_success "Nothing to ship — $version is tagged, released, and live on stable"
|
||||
exit 0
|
||||
@@ -752,10 +771,8 @@ cmd_ship() {
|
||||
echo " omarchy-release rc"
|
||||
exit 1
|
||||
fi
|
||||
local pub
|
||||
pub=$(published_version rc 2>/dev/null) || pub=""
|
||||
if [[ "${pub%-*}" != "$pin_ver" ]]; then
|
||||
print_error "$pin_ver is pinned but rc serves '${pub:-nothing}' — the candidate build hasn't published"
|
||||
if ! all_arches_at_version rc "$pin_ver"; then
|
||||
print_error "$pin_ver is pinned but is not published for every architecture"
|
||||
echo "Wait for it (or re-run: omarchy-release rc), then ship."
|
||||
exit 1
|
||||
fi
|
||||
@@ -799,10 +816,9 @@ cmd_ship() {
|
||||
|
||||
# 2. Final pins into rc. Resolve the tag we just established so the final
|
||||
# PKGBUILDs record both its provenance and its exact commit.
|
||||
local rc_pub stable_pub
|
||||
rc_pub=$(published_version rc 2>/dev/null) || rc_pub=""
|
||||
if [[ "${rc_pub%-*}" == "$version" ]]; then
|
||||
print_success "2/7 Final $version already published to rc"
|
||||
local stable_pub
|
||||
if all_arches_at_version rc "$version"; then
|
||||
print_success "2/7 Final $version already published to rc on every architecture"
|
||||
else
|
||||
if [[ "$pin_ver" != "$version" ]]; then
|
||||
print_info "2/7 Pinning final $version from tag v$version..."
|
||||
@@ -810,22 +826,21 @@ cmd_ship() {
|
||||
else
|
||||
print_info "2/7 Final $version pinned — re-triggering build"
|
||||
fi
|
||||
trigger_rc_build || true
|
||||
trigger_rc_build || exit 1
|
||||
wait_for_published rc "$version" || exit 1
|
||||
fi
|
||||
|
||||
# 3. Promote rc -> stable
|
||||
stable_pub=$(published_version stable 2>/dev/null) || stable_pub=""
|
||||
if [[ "${stable_pub%-*}" == "$version" ]]; then
|
||||
print_success "3/7 Stable already serves $version"
|
||||
if all_arches_at_version stable "$version"; then
|
||||
print_success "3/7 Stable already serves $version on every architecture"
|
||||
else
|
||||
host_advance rc stable || exit 1
|
||||
stable_pub=$(published_version stable 2>/dev/null) || stable_pub=""
|
||||
if [[ "${stable_pub%-*}" != "$version" ]]; then
|
||||
print_error "Promotion ran but stable serves '${stable_pub:-nothing}' — investigate before continuing"
|
||||
if ! all_arches_at_version stable "$version"; then
|
||||
print_error "Promotion ran but stable does not serve $version on every architecture"
|
||||
exit 1
|
||||
fi
|
||||
print_success "3/7 Promoted to stable: omarchy $stable_pub"
|
||||
stable_pub=$(published_version stable 2>/dev/null) || stable_pub="$version"
|
||||
print_success "3/7 Promoted to stable: omarchy $stable_pub on every architecture"
|
||||
fi
|
||||
|
||||
# 4. Final pins onto master (keeps edge overlap publishing and the repo record)
|
||||
@@ -908,7 +923,7 @@ next_step() { # prints "<command>|<description>"
|
||||
last=$(newest_release_branch 2>/dev/null) || last=""
|
||||
if [[ -n "$last" && "$STABLE_VER" != "<unreachable>" ]]; then
|
||||
last_ver=$(branch_to_version "$last")
|
||||
if [[ "${STABLE_VER%-*}" != "$last_ver" ]] ||
|
||||
if ! all_arches_at_version stable "$last_ver" ||
|
||||
{ command -v gh >/dev/null && ! gh release view "v$last_ver" --repo "$UPSTREAM_REPO" >/dev/null 2>&1; }; then
|
||||
echo "ship|$last_ver is tagged but not fully shipped — resume ship"
|
||||
return
|
||||
@@ -924,7 +939,7 @@ next_step() { # prints "<command>|<description>"
|
||||
echo "ship|Final $TRAIN_VER is pinned — finish shipping (re-runs are safe)"
|
||||
elif [[ "$pin_commit" != "$TRAIN_HEAD" ]]; then
|
||||
echo "rc|$TRAIN has commits newer than $pin_ver — cut the next candidate"
|
||||
elif [[ "${RC_VER%-*}" != "$pin_ver" ]]; then
|
||||
elif ! all_arches_at_version rc "$pin_ver"; then
|
||||
echo "rc|$pin_ver is pinned but not published — re-run rc to re-trigger/wait"
|
||||
else
|
||||
echo "ship|$pin_ver is published to rc — test it, then ship"
|
||||
@@ -994,20 +1009,24 @@ cmd_doctor() {
|
||||
check "makepkg available (checksums)" command -v makepkg
|
||||
check "curl available" command -v curl
|
||||
check "upstream reachable ($UPSTREAM_URL)" git ls-remote "$UPSTREAM_URL" HEAD
|
||||
local ch
|
||||
local ch arch
|
||||
for ch in edge stable; do
|
||||
if published_version "$ch" >/dev/null 2>&1; then
|
||||
print_success "$ch channel db readable"
|
||||
for arch in $(published_arches); do
|
||||
if published_version "$ch" "$arch" >/dev/null 2>&1; then
|
||||
print_success "$ch/$arch channel db readable"
|
||||
else
|
||||
print_error "$ch/$arch channel db readable"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
for arch in $(published_arches); do
|
||||
if published_version rc "$arch" >/dev/null 2>&1; then
|
||||
print_success "rc/$arch channel db readable"
|
||||
else
|
||||
print_error "$ch channel db readable"
|
||||
failures=$((failures + 1))
|
||||
print_warning "rc/$arch channel db not readable — bootstrap it first: bin/repo bootstrap-rc (on the build host)"
|
||||
fi
|
||||
done
|
||||
if published_version rc >/dev/null 2>&1; then
|
||||
print_success "rc channel db readable"
|
||||
else
|
||||
print_warning "rc channel db not readable — bootstrap it first: bin/repo bootstrap-rc (on the build host)"
|
||||
fi
|
||||
local host
|
||||
if host=$(repo_host); then
|
||||
check "build host ssh ($host)" ssh -o ConnectTimeout=10 "$host" true
|
||||
@@ -1016,10 +1035,10 @@ cmd_doctor() {
|
||||
else
|
||||
print_warning "no build host configured — set OMARCHY_REPO_HOST, --host, or write an ssh destination (root@<host> or an ssh-config alias) to $BUILD_ROOT/.repo-host; until then builds trigger on the 6h timer only"
|
||||
fi
|
||||
if command -v docker >/dev/null && docker info >/dev/null 2>&1; then
|
||||
print_success "docker available (ISO builds possible here)"
|
||||
if [[ -n "$CONTAINER_ENGINE" ]] && "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
print_success "$CONTAINER_ENGINE available (ISO builds possible here)"
|
||||
else
|
||||
print_warning "docker unavailable — ISO builds will print instructions instead"
|
||||
print_warning "container engine unavailable — ISO builds will print instructions instead"
|
||||
fi
|
||||
echo ""
|
||||
if ((failures == 0)); then
|
||||
@@ -1054,6 +1073,25 @@ cmd_self_test() {
|
||||
expect "version_is_patch 5.0.0" "$(version_is_patch 5.0.0 && echo yes || echo no)" "no"
|
||||
expect "previous_patch_tag 4.0.2" "$(previous_patch_tag 4.0.2)" "v4.0.1"
|
||||
expect "previous_patch_tag 4.0.10" "$(previous_patch_tag 4.0.10)" "v4.0.9"
|
||||
|
||||
# Keep release readiness fail-closed when only one architecture has reached
|
||||
# the requested version. This replaces the network reader for this process;
|
||||
# self-test exits immediately afterwards.
|
||||
published_version() {
|
||||
case "$2" in
|
||||
x86_64) echo "${TEST_X86_VERSION:-4.0.2-1}" ;;
|
||||
aarch64) echo "${TEST_ARM_VERSION:-4.0.2-1}" ;;
|
||||
esac
|
||||
}
|
||||
PUBLISHED_ARCHES=x86_64
|
||||
expect "x86-only readiness" "$(all_arches_at_version rc 4.0.2 && echo ready || echo blocked)" "ready"
|
||||
PUBLISHED_ARCHES=aarch64
|
||||
expect "ARM-only readiness" "$(all_arches_at_version rc 4.0.2 && echo ready || echo blocked)" "ready"
|
||||
PUBLISHED_ARCHES="x86_64 aarch64"
|
||||
TEST_ARM_VERSION=4.0.1-1
|
||||
expect "mixed versions block release" "$(all_arches_at_version rc 4.0.2 && echo ready || echo blocked)" "blocked"
|
||||
TEST_ARM_VERSION=4.0.2-1
|
||||
expect "both architectures ready" "$(all_arches_at_version rc 4.0.2 && echo ready || echo blocked)" "ready"
|
||||
echo ""
|
||||
if ((failures == 0)); then
|
||||
print_success "Self-test passed"
|
||||
|
||||
+19
-8
@@ -149,11 +149,16 @@ fi
|
||||
# leave nvidia-580xx-dkms and opencl-nvidia-580xx behind. An output's own name
|
||||
# still matches, for pushing just one of them on purpose.
|
||||
#
|
||||
# pkgbase comes from .PKGINFO rather than the PKGBUILD: it is what makepkg
|
||||
# actually recorded, and it needs no guessing about which directory built what.
|
||||
pkgbase_of() {
|
||||
# Package identity comes from .PKGINFO rather than the filename or PKGBUILD: it
|
||||
# is what makepkg actually recorded, and it handles epochs and split packages.
|
||||
package_identity_of() {
|
||||
bsdtar -xOf "$1" .PKGINFO 2>/dev/null |
|
||||
awk -F ' = ' '$1 == "pkgbase" { print $2; exit }'
|
||||
awk -F ' = ' '
|
||||
$1 == "pkgname" { name = $2 }
|
||||
$1 == "pkgbase" { base = $2 }
|
||||
$1 == "pkgver" { version = $2 }
|
||||
END { print name "\t" base "\t" version }
|
||||
'
|
||||
}
|
||||
|
||||
FILES=()
|
||||
@@ -161,14 +166,18 @@ if [[ -z "$PACKAGES" ]]; then
|
||||
FILES=("${ALL_FILES[@]}")
|
||||
else
|
||||
declare -A MATCHED=()
|
||||
declare -A LATEST_FILE=()
|
||||
declare -A LATEST_VERSION=()
|
||||
for file in "${ALL_FILES[@]}"; do
|
||||
# name-version-release-arch.pkg.tar.zst -> name
|
||||
pkgname="${file%-*-*-*.pkg.tar.*}"
|
||||
pkgbase=$(pkgbase_of "$BUILD_OUTPUT_DIR/$file")
|
||||
IFS=$'\t' read -r pkgname pkgbase pkgver < <(package_identity_of "$BUILD_OUTPUT_DIR/$file")
|
||||
for wanted in $PACKAGES; do
|
||||
if [[ "$pkgname" == "$wanted" || "$pkgbase" == "$wanted" ]]; then
|
||||
FILES+=("$file")
|
||||
MATCHED["$wanted"]=1
|
||||
if [[ -z "${LATEST_FILE[$pkgname]:-}" ]] ||
|
||||
[[ $(vercmp "$pkgver" "${LATEST_VERSION[$pkgname]}") -gt 0 ]]; then
|
||||
LATEST_FILE["$pkgname"]="$file"
|
||||
LATEST_VERSION["$pkgname"]="$pkgver"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
@@ -181,6 +190,8 @@ else
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
mapfile -t FILES < <(printf '%s\n' "${LATEST_FILE[@]}" | sort)
|
||||
fi
|
||||
|
||||
if [[ ${#FILES[@]} -eq 0 ]]; then
|
||||
|
||||
+5
-1
@@ -114,7 +114,11 @@ BUILT_FILES=""
|
||||
# What the scheduled version check queued, when it was the one that asked for
|
||||
# this run. Absent for a manual run, which is fine — the report just omits it.
|
||||
QUEUED_PACKAGES=""
|
||||
QUEUE_FILE="${OMARCHY_STATE_DIR:-/root/.state}/.sync-needed-$MIRROR"
|
||||
QUEUE_FILE=$(sync_queue_file "$MIRROR" "$ARCH")
|
||||
# A queue written under the pre-architecture name belongs to x86_64.
|
||||
if [[ "$ARCH" == "x86_64" && ! -s "$QUEUE_FILE" && -s "$(legacy_sync_queue_file "$MIRROR")" ]]; then
|
||||
QUEUE_FILE=$(legacy_sync_queue_file "$MIRROR")
|
||||
fi
|
||||
[[ -s "$QUEUE_FILE" ]] && QUEUED_PACKAGES=$(grep -c '' "$QUEUE_FILE")
|
||||
|
||||
if [[ "$DRY_RUN" != true ]]; then
|
||||
|
||||
+15
-10
@@ -62,8 +62,8 @@ if [[ ! -d "$REPO_DIR" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check Docker is available
|
||||
check_docker
|
||||
# Check the selected container engine is available
|
||||
check_engine
|
||||
|
||||
# Find package files to confirm before running Docker
|
||||
cd "$REPO_DIR"
|
||||
@@ -88,24 +88,29 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build/update the Docker image (always use x86_64 for removal - it's architecture independent)
|
||||
# repo-remove is mirror-independent — always use the edge x86_64 image
|
||||
build_docker_image "$BUILD_DIR" "x86_64" "edge"
|
||||
# repo-remove is architecture-independent, so use a host-native edge image.
|
||||
TOOL_ARCH=$(docker_native_arch) || {
|
||||
print_error "Unsupported host architecture: $(uname -m)"
|
||||
exit 1
|
||||
}
|
||||
build_docker_image "$BUILD_DIR" "$TOOL_ARCH" "edge"
|
||||
|
||||
acquire_release_lock || exit 1
|
||||
|
||||
print_info "Removing package..."
|
||||
|
||||
# Ensure directory is writable by container user
|
||||
make_dir_writable "$REPO_DIR"
|
||||
# Rootless Podman uses keep-id and leaves host ownership/modes intact.
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
make_dir_writable "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# Run the removal script in Docker (always use x86_64 image)
|
||||
docker run --rm --platform linux/amd64 \
|
||||
# Run the removal script in the host-native image.
|
||||
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$TOOL_ARCH")" \
|
||||
-e ARCH="$ARCH" \
|
||||
-e MIRROR="$MIRROR" \
|
||||
-v "$REPO_ROOT:/pkgs.omarchy.org" \
|
||||
-v "$BUILD_DIR:/build:ro" \
|
||||
omarchy-pkg-builder:latest-x86_64-edge /build/remove-package.sh "$PACKAGE_NAME"
|
||||
"omarchy-pkg-builder:latest-$TOOL_ARCH-edge" /build/remove-package.sh "$PACKAGE_NAME"
|
||||
|
||||
RESULT=$?
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ set -e
|
||||
|
||||
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
|
||||
source "$BUILD_ROOT/helpers/message-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/docker-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/paths.sh"
|
||||
|
||||
CHECK_ONLY=false
|
||||
SKIP_TIMERS=false
|
||||
@@ -61,10 +63,12 @@ if command -v apt-get >/dev/null 2>&1; then
|
||||
DISTRO="debian"
|
||||
PKG_BSDTAR="libarchive-tools"
|
||||
PKG_DOCKER="docker.io"
|
||||
PKG_PODMAN="podman"
|
||||
elif command -v pacman >/dev/null 2>&1; then
|
||||
DISTRO="arch"
|
||||
PKG_BSDTAR="libarchive"
|
||||
PKG_DOCKER="docker"
|
||||
PKG_PODMAN="podman"
|
||||
else
|
||||
print_error "Unsupported distribution — need apt-get or pacman"
|
||||
exit 1
|
||||
@@ -72,18 +76,36 @@ fi
|
||||
|
||||
print_info "Distribution: $DISTRO"
|
||||
|
||||
# A fresh repository host still defaults to Docker. An explicit Podman choice,
|
||||
# or a working Podman selected by the shared helper, is left alone.
|
||||
if [[ -z "$CONTAINER_ENGINE" ]]; then
|
||||
CONTAINER_ENGINE=docker
|
||||
export CONTAINER_ENGINE
|
||||
fi
|
||||
if ! container_engine_supported; then
|
||||
print_error "Unsupported CONTAINER_ENGINE: $CONTAINER_ENGINE (use docker or podman)"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
PKG_ENGINE="$PKG_DOCKER"
|
||||
ENGINE_NAME="Docker"
|
||||
else
|
||||
PKG_ENGINE="$PKG_PODMAN"
|
||||
ENGINE_NAME="Podman"
|
||||
fi
|
||||
|
||||
if [[ "$CHECK_ONLY" != true && $EUID -ne 0 ]]; then
|
||||
print_error "Run as root (installing packages and systemd units)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docker and the release timers are both systemd units. Say so plainly rather
|
||||
# than failing later on a missing command — a container is the usual way to end
|
||||
# up here, and it cannot be a repository host.
|
||||
# The release timers are systemd units. Say so plainly rather than failing
|
||||
# later on a missing command — a container is the usual way to end up here,
|
||||
# and it cannot be a repository host.
|
||||
if [[ "$CHECK_ONLY" != true ]] && ! command -v systemctl >/dev/null 2>&1; then
|
||||
print_error "systemctl not found — the repository host must run systemd"
|
||||
echo ""
|
||||
echo "Docker and the release timers are systemd units. This looks like a"
|
||||
echo "The release timers are systemd units. This looks like a"
|
||||
echo "container; run setup on the host itself."
|
||||
exit 1
|
||||
fi
|
||||
@@ -139,24 +161,27 @@ else
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- docker ------------------------------------------------------------------
|
||||
# --- container engine --------------------------------------------------------
|
||||
|
||||
# Docker is left alone when it already works. A host may well be running a
|
||||
# The selected engine is left alone when it already works. A host may be running a
|
||||
# version from Docker's own repository rather than the distribution's, and
|
||||
# replacing that underneath a working builder would be a poor trade for
|
||||
# tidiness.
|
||||
print_info "Checking Docker..."
|
||||
print_info "Checking $ENGINE_NAME..."
|
||||
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
print_step "docker present: $(docker --version 2>/dev/null | head -1)"
|
||||
if docker info >/dev/null 2>&1; then
|
||||
print_success "Docker is installed and running — leaving it alone"
|
||||
if command -v "$CONTAINER_ENGINE" >/dev/null 2>&1; then
|
||||
print_step "$CONTAINER_ENGINE present: $("$CONTAINER_ENGINE" --version 2>/dev/null | head -1)"
|
||||
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
print_success "$ENGINE_NAME is installed and available — leaving it alone"
|
||||
elif [[ "$CHECK_ONLY" == true ]]; then
|
||||
print_warning "Docker is installed but not running; would start it"
|
||||
print_warning "$ENGINE_NAME is installed but unavailable"
|
||||
elif [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
print_error "Podman is installed but unavailable to the current user"
|
||||
exit 1
|
||||
else
|
||||
print_info "Docker is installed but not running — starting it"
|
||||
systemctl enable --now docker.service
|
||||
if docker info >/dev/null 2>&1; then
|
||||
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
print_success "Docker started"
|
||||
else
|
||||
print_error "Docker is installed but still not responding"
|
||||
@@ -165,16 +190,24 @@ if command -v docker >/dev/null 2>&1; then
|
||||
fi
|
||||
fi
|
||||
elif [[ "$CHECK_ONLY" == true ]]; then
|
||||
print_warning "Would install $PKG_DOCKER and enable it"
|
||||
else
|
||||
print_info "Installing $PKG_DOCKER..."
|
||||
install_packages "$PKG_DOCKER"
|
||||
systemctl enable --now docker.service
|
||||
if docker info >/dev/null 2>&1; then
|
||||
print_success "Docker installed and running"
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
print_warning "Would install $PKG_ENGINE and enable it"
|
||||
else
|
||||
print_error "Docker installed but not responding"
|
||||
echo " Check 'systemctl status docker' — builds cannot run without it."
|
||||
print_warning "Would install $PKG_ENGINE"
|
||||
fi
|
||||
else
|
||||
print_info "Installing $PKG_ENGINE..."
|
||||
install_packages "$PKG_ENGINE"
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
systemctl enable --now docker.service
|
||||
fi
|
||||
if "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
print_success "$ENGINE_NAME installed and available"
|
||||
else
|
||||
print_error "$ENGINE_NAME installed but not responding"
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
echo " Check 'systemctl status docker' — builds cannot run without it."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -237,6 +270,10 @@ echo ""
|
||||
|
||||
# --- release timers ----------------------------------------------------------
|
||||
|
||||
print_info "Published architectures: $(published_arches | tr '\n' ' ')"
|
||||
echo " (PUBLISHED_ARCHES in helpers/paths.sh; OMARCHY_ARCHES overrides a one-off command)"
|
||||
echo ""
|
||||
|
||||
TIMERS=(omarchy-check-versions omarchy-auto-release-edge omarchy-auto-release-rc omarchy-auto-release-stable)
|
||||
|
||||
if [[ "$SKIP_TIMERS" == true ]]; then
|
||||
|
||||
@@ -52,8 +52,8 @@ if [[ ! -d "$BUILD_OUTPUT_DIR" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check Docker is available
|
||||
check_docker
|
||||
# Check the selected container engine is available
|
||||
check_engine
|
||||
|
||||
# Check GPG credentials are in environment
|
||||
if [[ -z "$GPG_PRIVATE_KEY" ]]; then
|
||||
@@ -66,23 +66,30 @@ if [[ -z "$GPG_PASSPHRASE" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build/update the Docker image (always use x86_64 for signing - it's architecture independent)
|
||||
build_docker_image "$BUILD_DIR" "x86_64" "$MIRROR"
|
||||
# Signing is architecture-independent, so run its utility container natively
|
||||
# on either an x86_64 or ARM host.
|
||||
TOOL_ARCH=$(docker_native_arch) || {
|
||||
print_error "Unsupported host architecture: $(uname -m)"
|
||||
exit 1
|
||||
}
|
||||
build_docker_image "$BUILD_DIR" "$TOOL_ARCH" "$MIRROR"
|
||||
|
||||
print_info "Running package signing..."
|
||||
|
||||
# Ensure output directory is writable by container user
|
||||
make_dir_writable "$BUILD_OUTPUT_DIR"
|
||||
# Rootless Podman uses keep-id and leaves host ownership/modes intact.
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
make_dir_writable "$BUILD_OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
# Run the signing script in Docker (always use x86_64 image)
|
||||
docker run --rm --platform linux/amd64 \
|
||||
# Run the signing script in the host-native image.
|
||||
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$TOOL_ARCH")" \
|
||||
-e ARCH="$ARCH" \
|
||||
-e MIRROR="$MIRROR" \
|
||||
-e GPG_PRIVATE_KEY="$GPG_PRIVATE_KEY" \
|
||||
-e GPG_PASSPHRASE="$GPG_PASSPHRASE" \
|
||||
-v "$BUILD_ROOT/build-output:/build-output" \
|
||||
-v "$BUILD_DIR:/build:ro" \
|
||||
omarchy-pkg-builder:latest-x86_64-$MIRROR /build/sign.sh
|
||||
"omarchy-pkg-builder:latest-$TOOL_ARCH-$MIRROR" /build/sign.sh
|
||||
|
||||
SIGN_RESULT=$?
|
||||
|
||||
|
||||
+228
-59
@@ -17,11 +17,14 @@ SELF_TEST=false
|
||||
# rebuilding for it would ship a package built against the wrong ABI.
|
||||
OFFICIAL_REPOS=" core extra multilib core-debug extra-debug "
|
||||
|
||||
# The published repository, used as the floor a bumped pkgrel has to clear.
|
||||
# Only x86_64 is published today; aarch64 has no repository to compare against.
|
||||
# The published repositories are the floor a bumped pkgrel has to clear.
|
||||
PUBLISHED_BASE_URL="${OMARCHY_PUBLISHED_BASE_URL:-https://pkgs.omarchy.org}"
|
||||
PUBLISHED_MIRRORS=(edge stable)
|
||||
PUBLISHED_ARCH=x86_64
|
||||
|
||||
# Arch Linux ARM has no dated snapshots. This is the same live repository the
|
||||
# aarch64 builder resolves; override it only when the builder mirror changes.
|
||||
ALARM_BASE_URL="${OMARCHY_ALARM_BASE_URL:-https://fl.us.mirror.archlinuxarm.org/aarch64}"
|
||||
ALARM_REPOS=(core extra alarm aur)
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
@@ -34,10 +37,13 @@ A package opts in by naming those dependencies in .omarchy/package.json:
|
||||
|
||||
{ "source": "aur", "sync": false, "rebuild_on": ["qt6-base"] }
|
||||
|
||||
The versions the current pkgrel was bumped for are recorded alongside, in
|
||||
rebuilt_against, and written by this command:
|
||||
The versions the current pkgrel was bumped for are recorded per published
|
||||
architecture in rebuilt_against, and written by this command:
|
||||
|
||||
{ "rebuild_on": ["qt6-base"], "rebuilt_against": { "qt6-base": "6.11.2-2" } }
|
||||
{ "rebuild_on": ["qt6-base"], "rebuilt_against": {
|
||||
"x86_64": { "qt6-base": "6.11.2-3" },
|
||||
"aarch64": { "qt6-base": "6.11.2-2" }
|
||||
} }
|
||||
|
||||
pkgrel is bumped unless every package named in rebuild_on is recorded and still
|
||||
matches. A name that is missing from the record counts as changed, so opting a
|
||||
@@ -60,8 +66,9 @@ Examples:
|
||||
$0 # Update every package that declares rebuild_on
|
||||
$0 quickshell-git # Update specific packages
|
||||
|
||||
Trigger versions are read from the local pacman database, so sync it first
|
||||
(pacman -Sy) or this reports whatever that database last saw.
|
||||
x86_64 trigger versions come from the local pacman database; aarch64 versions
|
||||
come from the live Arch Linux ARM repository database. Only architectures in
|
||||
PUBLISHED_ARCHES that the package supports are considered.
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -94,7 +101,7 @@ SPECIFIC_MODE=false
|
||||
# The version of a trigger package as the build container would resolve it.
|
||||
# A name pacman does not know reports nothing rather than failing, so the caller
|
||||
# gets to say which package was left alone instead of the run dying here.
|
||||
repo_version() {
|
||||
native_repo_version() {
|
||||
local package="$1"
|
||||
local info
|
||||
|
||||
@@ -108,9 +115,59 @@ repo_version() {
|
||||
' <<<"$info"
|
||||
}
|
||||
|
||||
load_alarm_repo() {
|
||||
local repo="$1" db index
|
||||
index="$TEMP_DIR/alarm-$repo.index"
|
||||
[[ -f "$index" ]] && return 0
|
||||
|
||||
db="$TEMP_DIR/alarm-$repo.db"
|
||||
if ! curl -fsSL --max-time 120 -o "$db" "$ALARM_BASE_URL/$repo/$repo.db" 2>/dev/null; then
|
||||
print_error "Could not read the aarch64 $repo repository database"
|
||||
return 1
|
||||
fi
|
||||
if ! tar -tf "$db" >/dev/null 2>&1; then
|
||||
print_error "Unreadable aarch64 $repo repository database"
|
||||
return 1
|
||||
fi
|
||||
|
||||
tar -xOf "$db" --wildcards '*/desc' 2>/dev/null | awk '
|
||||
function emit() {
|
||||
if (name != "" && version != "") {
|
||||
print name "\t" version
|
||||
if (base != "" && base != name) print base "\t" version
|
||||
}
|
||||
name=""; base=""; version=""
|
||||
}
|
||||
$0 == "%FILENAME%" { emit(); next }
|
||||
$0 == "%NAME%" { if (name != "" && version != "") emit(); getline; name=$0; next }
|
||||
$0 == "%BASE%" { getline; base=$0; next }
|
||||
$0 == "%VERSION%" { getline; version=$0; next }
|
||||
END { emit() }
|
||||
' >"$index"
|
||||
}
|
||||
|
||||
alarm_repo_version() {
|
||||
local package="$1" repo version
|
||||
for repo in "${ALARM_REPOS[@]}"; do
|
||||
load_alarm_repo "$repo" || return 1
|
||||
version=$(awk -F '\t' -v package="$package" '$1 == package { print $2; exit }' "$TEMP_DIR/alarm-$repo.index")
|
||||
if [[ -n "$version" ]]; then
|
||||
echo "$version"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
repo_version() { # repo_version <arch> <package>
|
||||
case "$1" in
|
||||
x86_64) native_repo_version "$2" ;;
|
||||
aarch64) alarm_repo_version "$2" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
declare -A PUBLISHED_VERSION=()
|
||||
PUBLISHED_LOADED=false
|
||||
PUBLISHED_AVAILABLE=true
|
||||
|
||||
remember_published() {
|
||||
local name="$1"
|
||||
@@ -131,34 +188,35 @@ load_published_versions() {
|
||||
[[ "$PUBLISHED_LOADED" == true ]] && return 0
|
||||
PUBLISHED_LOADED=true
|
||||
|
||||
local mirror db name base version
|
||||
local arch mirror db name base version
|
||||
|
||||
for mirror in "${PUBLISHED_MIRRORS[@]}"; do
|
||||
db="$TEMP_DIR/published-$mirror.db.tar.zst"
|
||||
for arch in $(published_arches); do
|
||||
for mirror in "${PUBLISHED_MIRRORS[@]}"; do
|
||||
db="$TEMP_DIR/published-$mirror-$arch.db.tar.zst"
|
||||
|
||||
if ! curl -fsSL --max-time 120 -o "$db" \
|
||||
"$PUBLISHED_BASE_URL/$mirror/$PUBLISHED_ARCH/omarchy.db.tar.zst" 2>/dev/null; then
|
||||
print_warning "Could not read the published $mirror database; bumps are not checked against it this run"
|
||||
PUBLISHED_AVAILABLE=false
|
||||
continue
|
||||
fi
|
||||
if ! curl -fsSL --max-time 120 -o "$db" \
|
||||
"$PUBLISHED_BASE_URL/$mirror/$arch/omarchy.db.tar.zst" 2>/dev/null; then
|
||||
print_warning "Could not read the published $mirror/$arch database; bumps are not checked against it this run"
|
||||
continue
|
||||
fi
|
||||
|
||||
while IFS=$'\t' read -r name base version; do
|
||||
[[ -n "$name" && -n "$version" ]] && remember_published "$name" "$version"
|
||||
[[ -n "$base" && -n "$version" ]] && remember_published "$base" "$version"
|
||||
done < <(
|
||||
tar -xOf "$db" --wildcards '*/desc' 2>/dev/null | awk '
|
||||
function emit() {
|
||||
if (name != "" && version != "") print name "\t" base "\t" version
|
||||
name=""; base=""; version=""
|
||||
}
|
||||
$0 == "%FILENAME%" { emit(); next }
|
||||
$0 == "%NAME%" { if (name != "" && version != "") emit(); getline; name=$0; next }
|
||||
$0 == "%BASE%" { getline; base=$0; next }
|
||||
$0 == "%VERSION%" { getline; version=$0; next }
|
||||
END { emit() }
|
||||
'
|
||||
)
|
||||
while IFS=$'\t' read -r name base version; do
|
||||
[[ -n "$name" && -n "$version" ]] && remember_published "$name" "$version"
|
||||
[[ -n "$base" && -n "$version" ]] && remember_published "$base" "$version"
|
||||
done < <(
|
||||
tar -xOf "$db" --wildcards '*/desc' 2>/dev/null | awk '
|
||||
function emit() {
|
||||
if (name != "" && version != "") print name "\t" base "\t" version
|
||||
name=""; base=""; version=""
|
||||
}
|
||||
$0 == "%FILENAME%" { emit(); next }
|
||||
$0 == "%NAME%" { if (name != "" && version != "") emit(); getline; name=$0; next }
|
||||
$0 == "%BASE%" { getline; base=$0; next }
|
||||
$0 == "%VERSION%" { getline; version=$0; next }
|
||||
END { emit() }
|
||||
'
|
||||
)
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@@ -252,7 +310,17 @@ record_triggers() {
|
||||
local package_dir="$1"
|
||||
local current="$2"
|
||||
|
||||
write_metadata "$package_dir" '.rebuilt_against = $current' --argjson current "$current"
|
||||
# A flat record is the legacy x86_64 shape. Preserve records for
|
||||
# architectures outside this run, then replace the ones just rebuilt.
|
||||
write_metadata "$package_dir" '
|
||||
(.rebuilt_against // {}) as $old |
|
||||
(if ($old | length) == 0 then {}
|
||||
elif ($old | to_entries | all(.value | type == "string"))
|
||||
then {x86_64: $old}
|
||||
else $old
|
||||
end) as $by_arch |
|
||||
.rebuilt_against = ($by_arch * $current)
|
||||
' --argjson current "$current"
|
||||
}
|
||||
|
||||
# Metadata that does not parse would otherwise drop its package out of the run
|
||||
@@ -300,21 +368,41 @@ sync_package() {
|
||||
|
||||
print_info "Checking $package against ${triggers[*]}..."
|
||||
|
||||
local current="{}" trigger version
|
||||
for trigger in "${triggers[@]}"; do
|
||||
version=$(repo_version "$trigger")
|
||||
if [[ -z "$version" ]]; then
|
||||
print_error " $trigger is in no official repository; leaving $package alone"
|
||||
((++FAILED))
|
||||
return 0
|
||||
fi
|
||||
if ! current=$(jq -c --arg name "$trigger" --arg version "$version" '.[$name] = $version' <<<"$current"); then
|
||||
print_error " Could not record $trigger $version for $package"
|
||||
local current="{}" arch arch_current trigger version considered=0
|
||||
for arch in $(published_arches); do
|
||||
package_supports_arch "$package_dir" "$arch" || continue
|
||||
considered=$((considered + 1))
|
||||
arch_current="{}"
|
||||
for trigger in "${triggers[@]}"; do
|
||||
if ! version=$(repo_version "$arch" "$trigger"); then
|
||||
print_error " Could not read $arch repository versions; leaving $package alone"
|
||||
((++FAILED))
|
||||
return 0
|
||||
fi
|
||||
if [[ -z "$version" ]]; then
|
||||
print_error " $trigger is in no $arch repository; leaving $package alone"
|
||||
((++FAILED))
|
||||
return 0
|
||||
fi
|
||||
if ! arch_current=$(jq -c --arg name "$trigger" --arg version "$version" '.[$name] = $version' <<<"$arch_current"); then
|
||||
print_error " Could not record $arch/$trigger $version for $package"
|
||||
((++FAILED))
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
if ! current=$(jq -c --arg arch "$arch" --argjson versions "$arch_current" '.[$arch] = $versions' <<<"$current"); then
|
||||
print_error " Could not record $arch trigger versions for $package"
|
||||
((++FAILED))
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
if ((considered == 0)); then
|
||||
print_info " Skipping: not built for any published architecture"
|
||||
((++SKIPPED))
|
||||
return 0
|
||||
fi
|
||||
|
||||
local recorded
|
||||
if ! recorded=$(package_metadata_value "$package_dir" '.rebuilt_against' ""); then
|
||||
print_error " Could not read .omarchy/package.json for $package"
|
||||
@@ -323,13 +411,20 @@ sync_package() {
|
||||
fi
|
||||
[[ -n "$recorded" && "$recorded" != "null" ]] || recorded="{}"
|
||||
|
||||
# Before architecture-specific records existed, rebuilt_against described
|
||||
# x86_64. Read it that way without forcing a metadata-only migration.
|
||||
if jq -e 'to_entries | all(.value | type == "string")' >/dev/null <<<"$recorded"; then
|
||||
recorded=$(jq -c '{x86_64: .}' <<<"$recorded")
|
||||
fi
|
||||
|
||||
# Walk the declared triggers rather than the record, so a name the record does
|
||||
# not carry reads as changed instead of going unexamined forever.
|
||||
local moved
|
||||
if ! moved=$(jq -r --argjson recorded "$recorded" '
|
||||
to_entries
|
||||
| map(select($recorded[.key] != .value)
|
||||
| "\(.key) \($recorded[.key] // "unrecorded") -> \(.value)")
|
||||
[to_entries[] as $arch
|
||||
| $arch.value | to_entries[] as $trigger
|
||||
| select($recorded[$arch.key][$trigger.key] != $trigger.value)
|
||||
| "\($arch.key)/\($trigger.key) \($recorded[$arch.key][$trigger.key] // "unrecorded") -> \($trigger.value)"]
|
||||
| join(", ")
|
||||
' <<<"$current"); then
|
||||
print_error " Could not compare recorded trigger versions for $package"
|
||||
@@ -338,7 +433,7 @@ sync_package() {
|
||||
fi
|
||||
|
||||
if [[ -z "$moved" ]]; then
|
||||
print_info " Already rebuilt against $(jq -r 'to_entries | map("\(.key) \(.value)") | join(", ")' <<<"$current")"
|
||||
print_info " Already rebuilt against every published architecture"
|
||||
((++SKIPPED))
|
||||
return 0
|
||||
fi
|
||||
@@ -466,11 +561,11 @@ selftest_root() {
|
||||
}
|
||||
|
||||
selftest_package() {
|
||||
local root="$1" name="$2" pkgrel="$3" metadata="$4" pkgver="${5:-1.0}"
|
||||
local root="$1" name="$2" pkgrel="$3" metadata="$4" pkgver="${5:-1.0}" arches="${6:-x86_64}"
|
||||
local dir="$root/pkgbuilds/$name"
|
||||
|
||||
mkdir -p "$dir/.omarchy"
|
||||
printf 'pkgname=%s\npkgver=%s\npkgrel=%s\narch=(x86_64)\n' "$name" "$pkgver" "$pkgrel" > "$dir/PKGBUILD"
|
||||
printf 'pkgname=%s\npkgver=%s\npkgrel=%s\narch=(%s)\n' "$name" "$pkgver" "$pkgrel" "$arches" > "$dir/PKGBUILD"
|
||||
printf '%s\n' "$metadata" > "$dir/.omarchy/package.json"
|
||||
}
|
||||
|
||||
@@ -514,19 +609,51 @@ selftest_published() {
|
||||
cat > "$root/stub/curl" <<'STUB'
|
||||
#!/bin/bash
|
||||
out=""
|
||||
url=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-o) out="$2"; shift 2 ;;
|
||||
*) shift ;;
|
||||
*) url="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
db="$(dirname "$0")/omarchy.db.tar.zst"
|
||||
if [[ "$url" == */aarch64/* ]]; then
|
||||
repo="${url%/*}"
|
||||
repo="${repo##*/}"
|
||||
db="$(dirname "$0")/alarm-$repo.db"
|
||||
else
|
||||
db="$(dirname "$0")/omarchy.db.tar.zst"
|
||||
fi
|
||||
[[ -f "$db" && -n "$out" ]] || exit 22
|
||||
cp "$db" "$out"
|
||||
STUB
|
||||
chmod +x "$root/stub/curl"
|
||||
}
|
||||
|
||||
selftest_alarm() {
|
||||
local root="$1"
|
||||
shift
|
||||
local repo staging="$root/stub/alarm-db" entry name version
|
||||
|
||||
for repo in core extra; do
|
||||
rm -rf "$staging"
|
||||
mkdir -p "$staging"
|
||||
if [[ "$repo" == "core" ]]; then
|
||||
mkdir -p "$staging/unrelated-1-1"
|
||||
printf '%%FILENAME%%\nunrelated-1-1-aarch64.pkg.tar.zst\n\n%%NAME%%\nunrelated\n\n%%BASE%%\nunrelated\n\n%%VERSION%%\n1-1\n' \
|
||||
> "$staging/unrelated-1-1/desc"
|
||||
else
|
||||
for entry in "$@"; do
|
||||
name="${entry%=*}"
|
||||
version="${entry#*=}"
|
||||
mkdir -p "$staging/$name-$version"
|
||||
printf '%%FILENAME%%\n%s-%s-aarch64.pkg.tar.zst\n\n%%NAME%%\n%s\n\n%%BASE%%\n%s\n\n%%VERSION%%\n%s\n' \
|
||||
"$name" "$version" "$name" "$name" "$version" > "$staging/$name-$version/desc"
|
||||
done
|
||||
fi
|
||||
tar -czf "$root/stub/alarm-$repo.db" -C "$staging" .
|
||||
done
|
||||
}
|
||||
|
||||
cmd_self_test() {
|
||||
local failures=0
|
||||
local root
|
||||
@@ -545,7 +672,8 @@ cmd_self_test() {
|
||||
local root="$1"
|
||||
shift
|
||||
local status=0
|
||||
PATH="$root/stub:$PATH" "$root/bin/sync-rebuilds" "$@" > "$root/output" 2>&1 || status=$?
|
||||
OMARCHY_ARCHES="${SELFTEST_ARCHES:-x86_64}" \
|
||||
PATH="$root/stub:$PATH" "$root/bin/sync-rebuilds" "$@" > "$root/output" 2>&1 || status=$?
|
||||
echo "$status"
|
||||
}
|
||||
|
||||
@@ -563,7 +691,7 @@ cmd_self_test() {
|
||||
check "run succeeds" 0 "$(run_case "$root")"
|
||||
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-partial")"
|
||||
check "unrecorded trigger now recorded" "2-2" \
|
||||
"$(jq -r '.rebuilt_against["dep-b"]' "$root/pkgbuilds/t-partial/.omarchy/package.json")"
|
||||
"$(jq -r '.rebuilt_against.x86_64["dep-b"]' "$root/pkgbuilds/t-partial/.omarchy/package.json")"
|
||||
|
||||
echo "Opting a package in buys a rebuild rather than a bare record:"
|
||||
root=$(selftest_root fresh)
|
||||
@@ -573,7 +701,7 @@ cmd_self_test() {
|
||||
check "run succeeds" 0 "$(run_case "$root")"
|
||||
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-fresh")"
|
||||
check "trigger recorded" "1-1" \
|
||||
"$(jq -r '.rebuilt_against["dep-a"]' "$root/pkgbuilds/t-fresh/.omarchy/package.json")"
|
||||
"$(jq -r '.rebuilt_against.x86_64["dep-a"]' "$root/pkgbuilds/t-fresh/.omarchy/package.json")"
|
||||
|
||||
echo "An unchanged package is left alone:"
|
||||
root=$(selftest_root current)
|
||||
@@ -612,6 +740,47 @@ cmd_self_test() {
|
||||
check "suffix recorded for the next AUR sync" 1 \
|
||||
"$(jq -r '.pkgrel.suffix' "$root/pkgbuilds/t-aur/.omarchy/package.json")"
|
||||
|
||||
echo "A dependency is tracked independently for both published architectures:"
|
||||
root=$(selftest_root multiarch)
|
||||
selftest_package "$root" t-multi 1 '{"source":"local","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"1-1"}}' 1.0 'x86_64 aarch64'
|
||||
selftest_pacman "$root" dep-a=1-1
|
||||
selftest_published "$root"
|
||||
selftest_alarm "$root" dep-a=2-1
|
||||
SELFTEST_ARCHES="x86_64 aarch64"
|
||||
check "run succeeds" 0 "$(run_case "$root")"
|
||||
unset SELFTEST_ARCHES
|
||||
check "pkgrel bumped once" 2 "$(pkgrel_of "$root/pkgbuilds/t-multi")"
|
||||
check "x86_64 trigger recorded" "1-1" \
|
||||
"$(jq -r '.rebuilt_against.x86_64["dep-a"]' "$root/pkgbuilds/t-multi/.omarchy/package.json")"
|
||||
check "aarch64 trigger recorded" "2-1" \
|
||||
"$(jq -r '.rebuilt_against.aarch64["dep-a"]' "$root/pkgbuilds/t-multi/.omarchy/package.json")"
|
||||
|
||||
echo "An ARM-only run records only the ARM dependency state:"
|
||||
root=$(selftest_root arm-only)
|
||||
selftest_package "$root" t-arm 1 '{"source":"local","rebuild_on":["dep-a"]}' 1.0 'x86_64 aarch64'
|
||||
selftest_pacman "$root"
|
||||
selftest_published "$root"
|
||||
selftest_alarm "$root" dep-a=2-1
|
||||
SELFTEST_ARCHES=aarch64
|
||||
check "run succeeds" 0 "$(run_case "$root")"
|
||||
unset SELFTEST_ARCHES
|
||||
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-arm")"
|
||||
check "ARM trigger recorded" "2-1" \
|
||||
"$(jq -r '.rebuilt_against.aarch64["dep-a"]' "$root/pkgbuilds/t-arm/.omarchy/package.json")"
|
||||
check "x86_64 was not consulted" "false" \
|
||||
"$(jq -r '.rebuilt_against | has("x86_64")' "$root/pkgbuilds/t-arm/.omarchy/package.json")"
|
||||
|
||||
echo "An x86-only package ignores ARM during a dual-architecture run:"
|
||||
root=$(selftest_root x86-package)
|
||||
selftest_package "$root" t-x86 1 '{"source":"local","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"1-1"}}'
|
||||
selftest_pacman "$root" dep-a=1-1
|
||||
selftest_published "$root"
|
||||
selftest_alarm "$root" dep-a=2-1
|
||||
SELFTEST_ARCHES="x86_64 aarch64"
|
||||
check "run succeeds" 0 "$(run_case "$root")"
|
||||
unset SELFTEST_ARCHES
|
||||
check "pkgrel untouched" 1 "$(pkgrel_of "$root/pkgbuilds/t-x86")"
|
||||
|
||||
echo ""
|
||||
if [[ "$failures" -eq 0 ]]; then
|
||||
print_success "Self-test passed"
|
||||
@@ -626,9 +795,9 @@ if [[ "$SELF_TEST" == true ]]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
for tool in pacman vercmp jq curl; do
|
||||
for tool in pacman vercmp jq curl tar; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
print_error "$tool not found: reading trigger versions and ordering pkgrels both need pacman"
|
||||
print_error "$tool not found: rebuild trigger sync cannot run"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
+139
-2
@@ -20,8 +20,8 @@ Update packages that track an upstream vendor release feed instead of the AUR.
|
||||
|
||||
Packages opt in declaratively through "upstream" in .omarchy/package.json.
|
||||
Providers cover GitHub Releases with checksum manifests or API asset digests,
|
||||
semver-shaped git tags whose source URLs can be hashed, and npm dist-tags. See README.md for the
|
||||
schemas. Anything outside those conventions may provide
|
||||
semver-shaped git tags, npm dist-tags, and plain Debian Packages indexes. See
|
||||
README.md for the schemas. Anything outside those conventions may provide
|
||||
pkgbuilds/<package>/.omarchy/upstream.sh, a hook that reports JSON on stdout:
|
||||
|
||||
{
|
||||
@@ -378,6 +378,7 @@ sync_package() {
|
||||
github) release=$(github_upstream_release "$package_dir" "$min_age") || release_status=$? ;;
|
||||
git_tags) release=$(git_tags_upstream_release "$package_dir") || release_status=$? ;;
|
||||
npm) release=$(npm_upstream_release "$package_dir") || release_status=$? ;;
|
||||
debian) release=$(debian_upstream_release "$package_dir") || release_status=$? ;;
|
||||
esac
|
||||
if [[ ${release_status:-0} -ne 0 ]]; then
|
||||
print_error "$provider upstream provider failed for $package"
|
||||
@@ -544,6 +545,31 @@ EOF
|
||||
check "bypass lifts the quarantine" "2.0.0" "$(jq -r '.pkgver // "<none>"' <<<"$out")"
|
||||
check "x86_64 checksum via * binary-mode prefix" "$sum_x20" "$(jq -r '.sha256sums.x86_64[0] // "<none>"' <<<"$out")"
|
||||
|
||||
cp "$pkg/.omarchy/package.json" "$pkg/normal.json"
|
||||
jq '.upstream.latest_only = true' "$pkg/normal.json" > "$pkg/.omarchy/package.json"
|
||||
FIXTURE_RELEASES=$(jq -n --arg old "$old2d" '[
|
||||
{tag_name: "v1.9.0", published_at: $old, draft: false, prerelease: false},
|
||||
{tag_name: "v0.4.1-8", published_at: $old, draft: false, prerelease: false}
|
||||
]')
|
||||
FIXTURE_CHECKSUMS=$(printf '%s\n' \
|
||||
"$sum_x19 ./tool-v1.9.0-x64.tar.xz" \
|
||||
"$sum_a19 ./tool-v1.9.0-arm64.tar.xz")
|
||||
out=$(github_upstream_release "$pkg" 0 2>/dev/null) || out="<error>"
|
||||
check "latest_only ignores incompatible historical tags" "1.9.0" "$(jq -r '.pkgver // "<none>"' <<<"$out")"
|
||||
cp "$pkg/normal.json" "$pkg/.omarchy/package.json"
|
||||
FIXTURE_RELEASES=$(jq -n --arg young "$young" --arg old2 "$old2d" --arg old3 "$old3d" '[
|
||||
{tag_name: "v2.0.0", published_at: $young, draft: false, prerelease: false},
|
||||
{tag_name: "v1.9.9", published_at: $old2, draft: false, prerelease: true},
|
||||
{tag_name: "v1.9.8", published_at: $old2, draft: true, prerelease: false},
|
||||
{tag_name: "v1.9.0", published_at: $old2, draft: false, prerelease: false},
|
||||
{tag_name: "v1.8.0", published_at: $old3, draft: false, prerelease: false}
|
||||
]')
|
||||
FIXTURE_CHECKSUMS=$(printf '%s\n' \
|
||||
"$sum_x19 ./tool-v1.9.0-x64.tar.xz" \
|
||||
"$sum_a19 tool-v1.9.0-arm64.tar.xz" \
|
||||
"$sum_x20 *tool-v2.0.0-x64.tar.xz" \
|
||||
"$sum_a20 tool-v2.0.0-arm64.tar.xz")
|
||||
|
||||
out=$(github_upstream_release "$pkg" 8640000 2>/dev/null) || out="<error>"
|
||||
check "everything quarantined reports no update" "{}" "$(jq -c . <<<"$out")"
|
||||
|
||||
@@ -637,6 +663,117 @@ EOF
|
||||
check "provider rejects a non-boolean digests" "1" "$rc"
|
||||
cp "$digpkg/good.json" "$digpkg/.omarchy/package.json"
|
||||
|
||||
echo "Ordered GitHub assets with supplemental sources:"
|
||||
local multipkg="$TEMP_DIR/selftest-multi-assets" multi_sum support_sum multi_vst
|
||||
mkdir -p "$multipkg/.omarchy"
|
||||
printf 'pkgver=1.0.0\npkgrel=1\n' > "$multipkg/PKGBUILD"
|
||||
cat > "$multipkg/.omarchy/package.json" <<'EOF'
|
||||
{
|
||||
"source": "local",
|
||||
"upstream": {
|
||||
"github": "example/tool",
|
||||
"digests": true,
|
||||
"assets": {
|
||||
"x86_64": ["tool-{pkgver}-x86_64", "tool-{pkgver}-x86_64.asc"],
|
||||
"aarch64": ["tool-{pkgver}-aarch64", "tool-{pkgver}-aarch64.asc"]
|
||||
},
|
||||
"sources": {
|
||||
"any": ["https://example.test/tool/{tag}/support.txt"]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
local sum_x19_sig sum_a19_sig
|
||||
sum_x19_sig=$(printf '1%.0s' {1..64})
|
||||
sum_a19_sig=$(printf '2%.0s' {1..64})
|
||||
FIXTURE_RELEASES=$(jq -n --arg old "$old2d" --arg x "$sum_x19" --arg xs "$sum_x19_sig" \
|
||||
--arg a "$sum_a19" --arg as "$sum_a19_sig" '[
|
||||
{tag_name: "v1.9.0", published_at: $old, draft: false, prerelease: false, assets: [
|
||||
{name: "tool-1.9.0-x86_64", digest: ("sha256:" + $x)},
|
||||
{name: "tool-1.9.0-x86_64.asc", digest: ("sha256:" + $xs)},
|
||||
{name: "tool-1.9.0-aarch64", digest: ("sha256:" + $a)},
|
||||
{name: "tool-1.9.0-aarch64.asc", digest: ("sha256:" + $as)}
|
||||
]}
|
||||
]')
|
||||
upstream_fetch_source() { printf 'remote fixture for %s\n' "$1" > "$2"; }
|
||||
multi_sum=$(github_upstream_release "$multipkg" 0 2>/dev/null) || multi_sum="<error>"
|
||||
support_sum=$(printf 'remote fixture for %s\n' 'https://example.test/tool/v1.9.0/support.txt' | sha256sum | cut -d' ' -f1)
|
||||
check "ordered GitHub assets produce an ordered checksum array" "$sum_x19 $sum_x19_sig" \
|
||||
"$(jq -r '.sha256sums.x86_64 | join(" ")' <<<"$multi_sum")"
|
||||
check "GitHub supplemental source is downloaded and hashed" "$support_sum" \
|
||||
"$(jq -r '.sha256sums.any[0]' <<<"$multi_sum")"
|
||||
multi_vst=0; validate_package_metadata "$multipkg" >/dev/null || multi_vst=$?
|
||||
check "GitHub asset lists and disjoint sources validate" "0" "$multi_vst"
|
||||
jq '.upstream.sources.x86_64 = ["https://example.test/duplicate"]' \
|
||||
"$multipkg/.omarchy/package.json" > "$multipkg/overlap.json"
|
||||
cp "$multipkg/.omarchy/package.json" "$multipkg/good.json"
|
||||
cp "$multipkg/overlap.json" "$multipkg/.omarchy/package.json"
|
||||
multi_vst=0; validate_package_metadata "$multipkg" >/dev/null || multi_vst=$?
|
||||
check "GitHub assets and sources cannot target the same checksum array" "1" "$multi_vst"
|
||||
cp "$multipkg/good.json" "$multipkg/.omarchy/package.json"
|
||||
|
||||
echo "Debian Packages provider:"
|
||||
local debpkg="$TEMP_DIR/selftest-debian" deb_sum deb_x_sum deb_a_sum deb_vst
|
||||
mkdir -p "$debpkg/.omarchy"
|
||||
printf 'pkgver=1.0.0\npkgrel=1\nsha256sums_x86_64=("old")\nsha256sums_aarch64=("old")\n' > "$debpkg/PKGBUILD"
|
||||
cat > "$debpkg/.omarchy/package.json" <<'EOF'
|
||||
{
|
||||
"source": "local",
|
||||
"upstream": {
|
||||
"debian": "https://packages.example.test/dists/stable/main/binary-amd64/Packages",
|
||||
"package": "example-app",
|
||||
"sources": {
|
||||
"x86_64": ["https://downloads.example.test/app-{pkgver}-x64.tar.gz"],
|
||||
"aarch64": ["https://downloads.example.test/app-{pkgver}-arm64.tar.gz"]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
debian_fetch_packages() {
|
||||
cat <<'EOF'
|
||||
Package: unrelated
|
||||
Version: 99.0.0
|
||||
|
||||
Package: example-app
|
||||
Version: 1.9.0
|
||||
|
||||
Package: example-app
|
||||
Version: 1.10.0
|
||||
EOF
|
||||
}
|
||||
deb_sum=$(debian_upstream_release "$debpkg")
|
||||
deb_x_sum=$(printf 'remote fixture for %s\n' 'https://downloads.example.test/app-1.10.0-x64.tar.gz' | sha256sum | cut -d' ' -f1)
|
||||
deb_a_sum=$(printf 'remote fixture for %s\n' 'https://downloads.example.test/app-1.10.0-arm64.tar.gz' | sha256sum | cut -d' ' -f1)
|
||||
check "Debian provider selects the newest exact package stanza" "1.10.0" "$(jq -r '.pkgver' <<<"$deb_sum")"
|
||||
check "Debian x86_64 source is hashed" "$deb_x_sum" "$(jq -r '.sha256sums.x86_64[0]' <<<"$deb_sum")"
|
||||
check "Debian aarch64 source is hashed" "$deb_a_sum" "$(jq -r '.sha256sums.aarch64[0]' <<<"$deb_sum")"
|
||||
deb_vst=0; validate_package_metadata "$debpkg" >/dev/null || deb_vst=$?
|
||||
check "Debian declaration validates" "0" "$deb_vst"
|
||||
printf 'pkgver=1.10.0\npkgrel=1\nsha256sums_x86_64=("old")\nsha256sums_aarch64=("old")\n' > "$debpkg/PKGBUILD"
|
||||
check "checked-in Debian version avoids source downloads" "{}" "$(debian_upstream_release "$debpkg" | jq -c .)"
|
||||
|
||||
echo "End-to-end Debian sync with the checked-in 1password recipe:"
|
||||
local one_root="$TEMP_DIR/e2e-1password" one_dir one_version=8.12.35
|
||||
mkdir -p "$one_root"
|
||||
cp -a "$BUILD_ROOT/pkgbuilds/1password" "$one_root/1password"
|
||||
one_dir="$one_root/1password"
|
||||
debian_fetch_packages() {
|
||||
printf 'Package: 1password\nVersion: %s\n' "$one_version"
|
||||
}
|
||||
upstream_fetch_source() { printf 'remote fixture for %s\n' "$1" > "$2"; }
|
||||
local one_prev_updated=$UPDATED one_prev_failed=$FAILED
|
||||
PKGBUILDS_DIR="$one_root" sync_package 1password >/dev/null 2>&1 || true
|
||||
check "1password sync updates without failures" "updated=1 failed=0" \
|
||||
"updated=$((UPDATED - one_prev_updated)) failed=$((FAILED - one_prev_failed))"
|
||||
check "1password pkgver is the single download version source" "$one_version" \
|
||||
"$(grep -m1 '^pkgver=' "$one_dir/PKGBUILD" | cut -d= -f2-)"
|
||||
check "1password pkgrel resets to 1" "1" \
|
||||
"$(grep -m1 '^pkgrel=' "$one_dir/PKGBUILD" | cut -d= -f2-)"
|
||||
check "1password x86 URL follows the rewritten pkgver" "1password-${one_version}.x64.tar.gz" \
|
||||
"$(CARCH=x86_64 bash -c 'source "$1"; basename "${source_x86_64[0]}"' _ "$one_dir/PKGBUILD")"
|
||||
check "1password ARM URL follows the rewritten pkgver" "1password-${one_version}.arm64.tar.gz" \
|
||||
"$(CARCH=aarch64 bash -c 'source "$1"; basename "${source_aarch64[0]}"' _ "$one_dir/PKGBUILD")"
|
||||
|
||||
echo "Quarantine backstop:"
|
||||
local rel st
|
||||
rel=$(jq -n --arg p "$old2d" '{pkgver: "1.9.0", published_at: $p, sha256sums: {}}')
|
||||
|
||||
+38
-32
@@ -84,15 +84,18 @@ echo ""
|
||||
|
||||
# --- queued work -------------------------------------------------------------
|
||||
|
||||
print_info "Queued builds (state files in $STATE_DIR)"
|
||||
print_info "Queued builds (state files in $STATE_DIR; architectures: $(published_arches | tr '\n' ' '))"
|
||||
queued=false
|
||||
for channel in edge rc stable; do
|
||||
state_file="$STATE_DIR/.sync-needed-$channel"
|
||||
if [[ -f "$state_file" ]]; then
|
||||
queued=true
|
||||
since=$(date -r "$state_file" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "unknown")
|
||||
printf ' • %-7s queued since %s\n' "$channel" "$since"
|
||||
fi
|
||||
for arch in $(published_arches); do
|
||||
state_file=$(sync_queue_file "$channel" "$arch")
|
||||
[[ "$arch" == "x86_64" && ! -f "$state_file" ]] && state_file=$(legacy_sync_queue_file "$channel")
|
||||
if [[ -f "$state_file" ]]; then
|
||||
queued=true
|
||||
since=$(date -r "$state_file" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "unknown")
|
||||
printf ' • %-7s %-8s queued since %s\n' "$channel" "$arch" "$since"
|
||||
fi
|
||||
done
|
||||
done
|
||||
[[ "$queued" == false ]] && echo " (nothing queued — all channels up to date)"
|
||||
echo ""
|
||||
@@ -101,34 +104,37 @@ echo ""
|
||||
# say so plainly: it is queued but deliberately not being retried yet.
|
||||
paused=false
|
||||
for channel in edge rc stable; do
|
||||
fail_file="$STATE_DIR/.build-failed-$channel"
|
||||
[[ -f "$fail_file" ]] || continue
|
||||
if [[ "$paused" == false ]]; then
|
||||
print_error "Failing builds (backoff active)"
|
||||
paused=true
|
||||
fi
|
||||
FAILURE_COUNT=0 FAILURE_AT=0 FAILURE_FINGERPRINT=""
|
||||
# shellcheck disable=SC1090
|
||||
source "$fail_file" 2>/dev/null || true
|
||||
delay=600
|
||||
for ((i = 1; i < FAILURE_COUNT; i++)); do
|
||||
delay=$((delay * 2))
|
||||
((delay >= 21600)) && { delay=21600; break; }
|
||||
for arch in $(published_arches); do
|
||||
fail_file=$(sync_fail_file "$channel" "$arch")
|
||||
[[ "$arch" == "x86_64" && ! -f "$fail_file" ]] && fail_file=$(legacy_sync_fail_file "$channel")
|
||||
[[ -f "$fail_file" ]] || continue
|
||||
if [[ "$paused" == false ]]; then
|
||||
print_error "Failing builds (backoff active)"
|
||||
paused=true
|
||||
fi
|
||||
FAILURE_COUNT=0 FAILURE_AT=0 FAILURE_FINGERPRINT=""
|
||||
# shellcheck disable=SC1090
|
||||
source "$fail_file" 2>/dev/null || true
|
||||
delay=600
|
||||
for ((i = 1; i < FAILURE_COUNT; i++)); do
|
||||
delay=$((delay * 2))
|
||||
((delay >= 21600)) && { delay=21600; break; }
|
||||
done
|
||||
retry_at=$((FAILURE_AT + delay))
|
||||
now=$(date +%s)
|
||||
if ((now < retry_at)); then
|
||||
when="retries at $(date -d "@$retry_at" '+%H:%M:%S' 2>/dev/null || echo "+$((retry_at - now))s")"
|
||||
else
|
||||
when="retries on the next tick"
|
||||
fi
|
||||
printf ' ✗ %-7s %-8s %s consecutive failure(s), %s\n' "$channel" "$arch" "$FAILURE_COUNT" "$when"
|
||||
printf ' last attempt %s on commit %s\n' \
|
||||
"$(date -d "@$FAILURE_AT" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "$FAILURE_AT")" \
|
||||
"${FAILURE_FINGERPRINT:0:12}"
|
||||
done
|
||||
retry_at=$((FAILURE_AT + delay))
|
||||
now=$(date +%s)
|
||||
if ((now < retry_at)); then
|
||||
when="retries at $(date -d "@$retry_at" '+%H:%M:%S' 2>/dev/null || echo "+$((retry_at - now))s")"
|
||||
else
|
||||
when="retries on the next tick"
|
||||
fi
|
||||
printf ' ✗ %-7s %s consecutive failure(s), %s\n' "$channel" "$FAILURE_COUNT" "$when"
|
||||
printf ' last attempt %s on commit %s\n' \
|
||||
"$(date -d "@$FAILURE_AT" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "$FAILURE_AT")" \
|
||||
"${FAILURE_FINGERPRINT:0:12}"
|
||||
done
|
||||
if [[ "$paused" == true ]]; then
|
||||
echo " Any new commit clears the backoff; or: rm $STATE_DIR/.build-failed-<channel>"
|
||||
echo " Any new commit clears the backoff; or: rm $STATE_DIR/.build-failed-<channel>-<arch>"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
+16
-12
@@ -11,12 +11,11 @@ source "$BUILD_ROOT/helpers/docker-helpers.sh"
|
||||
source "$BUILD_ROOT/helpers/paths.sh"
|
||||
source "$BUILD_ROOT/helpers/lock-helpers.sh"
|
||||
|
||||
# Function to update repository database using Docker
|
||||
# Function to update repository database using the selected container engine
|
||||
update_database() {
|
||||
print_info "Updating repository database in Docker container..."
|
||||
print_info "Updating repository database in a container..."
|
||||
|
||||
# Check Docker is available
|
||||
check_docker
|
||||
check_engine
|
||||
|
||||
# Ensure output directory exists
|
||||
if [[ ! -d "$REPO_DIR" ]]; then
|
||||
@@ -25,20 +24,25 @@ update_database() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make output directory writable for container
|
||||
make_dir_writable "$REPO_DIR"
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
make_dir_writable "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# repo-add is architecture- and mirror-independent, so always use the edge
|
||||
# x86_64 image. This also lets bootstrap-rc build the rc database before the
|
||||
# rc channel exists remotely (an rc image can only build after it does).
|
||||
build_docker_image "$BUILD_DIR" "x86_64" "edge"
|
||||
# repo-add is architecture- and mirror-independent. Use the host-native edge
|
||||
# image, which also lets bootstrap-rc run before that channel exists remotely.
|
||||
local tool_arch
|
||||
tool_arch=$(docker_native_arch) || {
|
||||
print_error "Unsupported host architecture: $(uname -m)"
|
||||
exit 1
|
||||
}
|
||||
build_docker_image "$BUILD_DIR" "$tool_arch" "edge"
|
||||
|
||||
docker run --rm --platform linux/amd64 \
|
||||
"$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$tool_arch")" \
|
||||
-e ARCH="$ARCH" \
|
||||
-e MIRROR="$MIRROR" \
|
||||
-v "$REPO_ROOT:/output" \
|
||||
-v "$BUILD_DIR:/build:ro" \
|
||||
omarchy-pkg-builder:latest-x86_64-edge /build/update-repo.sh
|
||||
"omarchy-pkg-builder:latest-$tool_arch-edge" /build/update-repo.sh
|
||||
}
|
||||
|
||||
# Main execution
|
||||
|
||||
+14
-6
@@ -45,9 +45,7 @@ RUN if [ "${TARGETARCH}" = "amd64" ]; then \
|
||||
printf 'Server = https://mirror.omarchy.org/$repo/os/$arch\n' > /etc/pacman.d/mirrorlist; \
|
||||
fi; \
|
||||
else \
|
||||
curl -L "https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/core/pacman-mirrorlist/mirrorlist" 2>/dev/null | \
|
||||
sed -E 's/^\s*#\s*Server\s*=/Server =/g' > /etc/pacman.d/mirrorlist && \
|
||||
sed -i 's/\$arch/aarch64/g' /etc/pacman.d/mirrorlist; \
|
||||
printf 'Server = https://fl.us.mirror.archlinuxarm.org/aarch64/$repo\n' > /etc/pacman.d/mirrorlist; \
|
||||
fi
|
||||
|
||||
# Bootstrap keyrings (required before pacstrap can verify packages)
|
||||
@@ -108,11 +106,16 @@ RUN ln -sf /usr/lib/os-release /etc/os-release && \
|
||||
# Setup Omarchy keyring manually before adding repo (avoids keyserver trust issues)
|
||||
# Note: Repository is removed at the end since build scripts add it dynamically.
|
||||
# The keyring comes from this image's own channel (the bare /$arch path is a
|
||||
# stale legacy layout); %s keeps pacman's $arch literal while MIRROR expands.
|
||||
# stale legacy layout). It is always taken from the x86_64 tree, whatever the
|
||||
# image's own architecture: omarchy-keyring is an arch=any package, and the
|
||||
# x86_64 tree is the one that exists before a new architecture has published
|
||||
# anything. Bootstrapping from the target's own tree would make the first
|
||||
# aarch64 build depend on an aarch64 repository that only that build can
|
||||
# create.
|
||||
ARG MIRROR=edge
|
||||
RUN pacman-key --recv-keys 40DFB630FF42BCFFB047046CF0134EE680CAC571 --keyserver keys.openpgp.org && \
|
||||
pacman-key --lsign-key 40DFB630FF42BCFFB047046CF0134EE680CAC571 && \
|
||||
printf '\n[omarchy]\nSigLevel = Optional\nServer = https://pkgs.omarchy.org/%s/$arch\n' "${MIRROR}" >> /etc/pacman.conf && \
|
||||
printf '\n[omarchy]\nSigLevel = Optional\nServer = https://pkgs.omarchy.org/%s/x86_64\n' "${MIRROR}" >> /etc/pacman.conf && \
|
||||
pacman -Sy --noconfirm && \
|
||||
pacman -S --noconfirm omarchy-keyring && \
|
||||
pacman-key --populate omarchy && \
|
||||
@@ -137,8 +140,13 @@ RUN useradd -m -G wheel -s /bin/bash builder && \
|
||||
chmod 700 /home/builder/.gnupg && \
|
||||
chown -R builder:builder /home/builder
|
||||
|
||||
# Arch Linux ARM's makepkg.conf still defaults PKGEXT to .pkg.tar.xz; every
|
||||
# tool downstream of the build (sign.sh, push-build, sync-rebuilds, the
|
||||
# notifier) expects .pkg.tar.zst, so an aarch64 package would build and then
|
||||
# be skipped at signing. Pin the extension so both architectures match.
|
||||
RUN sed -i 's/^#MAKEFLAGS=.*/MAKEFLAGS="-j$(nproc)"/' /etc/makepkg.conf && \
|
||||
sed -i 's/^COMPRESSZST=.*/COMPRESSZST=(zstd -c -z -q --threads=0 -)/' /etc/makepkg.conf
|
||||
sed -i 's/^COMPRESSZST=.*/COMPRESSZST=(zstd -c -z -q --threads=0 -)/' /etc/makepkg.conf && \
|
||||
sed -i "s|^PKGEXT=.*|PKGEXT='.pkg.tar.zst'|" /etc/makepkg.conf
|
||||
|
||||
# Pacman wrapper that auto-resolves package conflicts (e.g. rustup vs rust).
|
||||
# makepkg only passes --noconfirm to pacman, which defaults to 'N' on conflict
|
||||
|
||||
+70
-48
@@ -5,6 +5,10 @@
|
||||
|
||||
# Setup directories
|
||||
ARCH=${ARCH:-x86_64}
|
||||
# ARCH selects the repository target for this script, but make and Kbuild also
|
||||
# interpret an exported ARCH themselves (Linux calls this target "arm64").
|
||||
# Keep the shell variable local to the orchestrator so PKGBUILDs see CARCH only.
|
||||
export -n ARCH
|
||||
MIRROR=${MIRROR:-edge}
|
||||
DRY_RUN=${DRY_RUN:-false}
|
||||
PKGBUILDS_DIR=${PKGBUILDS_DIR:-/pkgbuilds}
|
||||
@@ -60,14 +64,11 @@ if [[ "$DRY_RUN" != true ]]; then
|
||||
# Configure Omarchy repositories for dependency resolution
|
||||
echo "==> Configuring Omarchy repositories for dependency resolution..."
|
||||
|
||||
# Always add omarchy-build repo (for incremental builds)
|
||||
# Packages in build-output are unsigned, so use SigLevel = Never
|
||||
sudo tee -a /etc/pacman.conf > /dev/null <<EOF
|
||||
|
||||
[omarchy-build]
|
||||
SigLevel = Never
|
||||
Server = file://$BUILD_OUTPUT_DIR
|
||||
EOF
|
||||
# Always add omarchy-build repo first (for incremental builds). Repository
|
||||
# order is pacman's priority order, so this must precede the official repos;
|
||||
# otherwise pacman can select an older official package with the same name.
|
||||
# Packages in build-output are unsigned, so use SigLevel = Never.
|
||||
sudo sed -i "/^\[core\]$/i [omarchy-build]\nSigLevel = Never\nServer = file://$BUILD_OUTPUT_DIR\n" /etc/pacman.conf
|
||||
echo " -> omarchy-build (priority 1): $BUILD_OUTPUT_DIR"
|
||||
|
||||
# Initialize empty build database if it doesn't exist
|
||||
@@ -90,12 +91,7 @@ EOF
|
||||
|
||||
# Add omarchy repo if it has a database (stable packages)
|
||||
if [[ -f "$FINAL_OUTPUT_DIR/omarchy.db.tar.zst" ]] || [[ -f "$FINAL_OUTPUT_DIR/omarchy.db" ]]; then
|
||||
sudo tee -a /etc/pacman.conf > /dev/null <<EOF
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = file://$FINAL_OUTPUT_DIR
|
||||
EOF
|
||||
sudo sed -i "/^\[core\]$/i [omarchy]\nSigLevel = Optional TrustAll\nServer = file://$FINAL_OUTPUT_DIR\n" /etc/pacman.conf
|
||||
echo " -> omarchy (priority 2): $FINAL_OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
@@ -186,26 +182,9 @@ get_local_version() {
|
||||
# Returns 0 (success) if should build, 1 if should skip
|
||||
should_build_for_arch() {
|
||||
local pkg="$1"
|
||||
local current_arch="$ARCH"
|
||||
local pkgdir=$(find_package_dir "$pkg")
|
||||
local pkgbuild="$pkgdir/PKGBUILD"
|
||||
|
||||
[[ ! -f "$pkgbuild" ]] && return 1
|
||||
|
||||
# Check PKGBUILD arch=() array
|
||||
local pkgbuild_archs=$(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; echo "${arch[@]}"')
|
||||
|
||||
# If arch=('any'), build for all architectures
|
||||
if [[ "$pkgbuild_archs" == "any" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if current arch is in PKGBUILD arch=()
|
||||
if echo "$pkgbuild_archs" | grep -qw "$current_arch"; then
|
||||
return 0 # Build
|
||||
else
|
||||
return 1 # Skip
|
||||
fi
|
||||
local pkgdir
|
||||
pkgdir=$(find_package_dir "$pkg")
|
||||
[[ -n "$pkgdir" ]] && package_supports_arch "$pkgdir" "$ARCH"
|
||||
}
|
||||
|
||||
# For VCS packages, makepkg recalculates pkgver() before the build. If the
|
||||
@@ -352,16 +331,48 @@ build_package() {
|
||||
if PACMAN=/usr/local/bin/pacman-for-makepkg makepkg "${makepkg_flags[@]}"; then
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$BUILD_OUTPUT_DIR"
|
||||
|
||||
for pkg_file in *.pkg.tar.*; do
|
||||
[[ -f "$pkg_file" ]] && cp "$pkg_file" "$BUILD_OUTPUT_DIR/"
|
||||
|
||||
# Copy only the artifacts makepkg declares as outputs. A PKGBUILD may use
|
||||
# another pacman package as a source (schist-bin does); a *.pkg.tar.* glob
|
||||
# would mistake that source archive for one of our freshly built packages.
|
||||
local -a package_files=()
|
||||
mapfile -t package_files < <(makepkg --packagelist)
|
||||
|
||||
if [[ ${#package_files[@]} -eq 0 ]]; then
|
||||
echo " Makepkg produced no package files for $pkg"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local dependency_pkg_file=""
|
||||
local -a new_pkgs=()
|
||||
local pkg_path pkg_file
|
||||
for pkg_path in "${package_files[@]}"; do
|
||||
pkg_file=${pkg_path##*/}
|
||||
if [[ ! -f "$pkg_file" ]]; then
|
||||
# makepkg predicts an automatic -debug output whenever debug is
|
||||
# enabled, but data-only packages may contain no symbols and therefore
|
||||
# legitimately produce no debug archive.
|
||||
if [[ "$pkg_file" == *-debug-*.pkg.tar.* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " Expected package file was not produced: $pkg_file"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
|
||||
cp "$pkg_file" "$BUILD_OUTPUT_DIR/"
|
||||
new_pkgs+=("$pkg_file")
|
||||
|
||||
if [[ "$(bsdtar -xOf "$pkg_file" .PKGINFO 2>/dev/null | sed -n 's/^pkgname = //p')" == "$pkg" ]]; then
|
||||
dependency_pkg_file="$BUILD_OUTPUT_DIR/$pkg_file"
|
||||
fi
|
||||
done
|
||||
|
||||
cd "$BUILD_OUTPUT_DIR"
|
||||
|
||||
# Find ALL package files (handles split packages)
|
||||
local new_pkgs=($(ls -t ${pkg}-*.pkg.tar.* 2>/dev/null | grep -v '\.sig$' | grep -v 'omarchy-build\.db'))
|
||||
|
||||
# Add every output from this build, including split packages.
|
||||
if [[ ${#new_pkgs[@]} -gt 0 ]]; then
|
||||
repo-add omarchy-build.db.tar.zst "${new_pkgs[@]}" >/dev/null 2>&1
|
||||
ln -sf omarchy-build.db.tar.zst omarchy-build.db
|
||||
@@ -370,6 +381,24 @@ build_package() {
|
||||
|
||||
cd /src/$pkg
|
||||
|
||||
# A lower-priority official repository may contain an older package with
|
||||
# the same name. Install the exact artifact we just built before building
|
||||
# its consumers, so pacman cannot select that older provider instead.
|
||||
if [[ "${INSTALL_PACKAGES[$pkg]:-}" == "1" ]]; then
|
||||
if [[ -z "$dependency_pkg_file" ]]; then
|
||||
echo " Could not find the built $pkg package to install as a dependency"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo " Installing freshly built $pkg for dependent packages..."
|
||||
if ! sudo /usr/local/bin/pacman-for-makepkg -U --needed --noconfirm "$dependency_pkg_file"; then
|
||||
echo " Failed to install freshly built dependency $pkg"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Successfully built $pkg"
|
||||
SUCCESSFUL_PACKAGES="$SUCCESSFUL_PACKAGES $pkg"
|
||||
return 0
|
||||
@@ -488,7 +517,7 @@ check_needs_build() {
|
||||
|
||||
# Collect packages that should be built for the selected mirror
|
||||
collect_packages() {
|
||||
packages_for_unscoped_build "$MIRROR"
|
||||
packages_for_unscoped_build "$MIRROR" "$ARCH"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
@@ -540,13 +569,6 @@ if [[ -n "$PACKAGES" ]]; then
|
||||
else
|
||||
# Build all packages that need updates from the relevant directories
|
||||
while IFS= read -r pkg; do
|
||||
# Check if package should be built for this architecture
|
||||
if ! should_build_for_arch "$pkg"; then
|
||||
echo " - $pkg - not built for $ARCH"
|
||||
SKIPPED_PACKAGES="$SKIPPED_PACKAGES $pkg"
|
||||
continue
|
||||
fi
|
||||
|
||||
if check_needs_build "$pkg"; then
|
||||
PACKAGES_TO_BUILD+=("$pkg")
|
||||
else
|
||||
|
||||
+109
-23
@@ -1,25 +1,102 @@
|
||||
# Docker helper functions for Omarchy package build system
|
||||
# Container engine helpers for Omarchy package build system
|
||||
|
||||
check_docker() {
|
||||
if ! command -v docker &>/dev/null; then
|
||||
print_error "Docker is not installed"
|
||||
container_engine_supported() {
|
||||
[[ "$CONTAINER_ENGINE" == "docker" || "$CONTAINER_ENGINE" == "podman" ]]
|
||||
}
|
||||
|
||||
if [[ -z "${CONTAINER_ENGINE:-}" ]]; then
|
||||
for engine in docker podman; do
|
||||
if command -v "$engine" >/dev/null 2>&1 && "$engine" info >/dev/null 2>&1; then
|
||||
CONTAINER_ENGINE="$engine"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
export CONTAINER_ENGINE
|
||||
|
||||
# Rootless Podman otherwise maps the image's builder uid 1000 to a subordinate
|
||||
# host uid. keep-id makes files written through bind mounts belong to the user
|
||||
# who invoked the build.
|
||||
CONTAINER_RUN_ARGS=()
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
CONTAINER_RUN_ARGS+=("--userns=keep-id:uid=1000,gid=1000")
|
||||
fi
|
||||
|
||||
check_engine() {
|
||||
if [[ -n "$CONTAINER_ENGINE" ]] && ! container_engine_supported; then
|
||||
print_error "Unsupported CONTAINER_ENGINE: $CONTAINER_ENGINE (use docker or podman)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info &>/dev/null; then
|
||||
print_error "Docker daemon is not running"
|
||||
print_warning "Start Docker with: sudo systemctl start docker"
|
||||
if [[ -z "$CONTAINER_ENGINE" ]]; then
|
||||
print_error "No working container engine found (tried Docker, then Podman)"
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
print_warning "Docker is installed but unavailable. Start it with: sudo systemctl start docker"
|
||||
elif command -v podman >/dev/null 2>&1; then
|
||||
print_warning "Podman is installed but 'podman info' failed"
|
||||
else
|
||||
print_warning "Install Docker or Podman"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v "$CONTAINER_ENGINE" >/dev/null 2>&1; then
|
||||
print_error "$CONTAINER_ENGINE is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! "$CONTAINER_ENGINE" info >/dev/null 2>&1; then
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
print_error "Docker daemon is not running or is not accessible"
|
||||
print_warning "Start Docker with: sudo systemctl start docker"
|
||||
else
|
||||
print_error "Podman is not available to the current user"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
docker_native_arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64) echo x86_64 ;;
|
||||
aarch64 | arm64) echo aarch64 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
setup_qemu() {
|
||||
# Setup QEMU for building ARM64 packages on x86_64 hosts
|
||||
if ! docker run --rm --privileged multiarch/qemu-user-static --reset -p yes --credential yes >/dev/null 2>&1; then
|
||||
print_error "Failed to setup QEMU for ARM64 emulation"
|
||||
local target_arch="${1:-aarch64}"
|
||||
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
local registration="/proc/sys/fs/binfmt_misc/qemu-$target_arch"
|
||||
local packaged_registration="/usr/lib/binfmt.d/qemu-$target_arch-static.conf"
|
||||
local flags=""
|
||||
|
||||
if [[ -r "$registration" ]]; then
|
||||
flags=$(sed -n 's/^flags: //p' "$registration")
|
||||
fi
|
||||
|
||||
if [[ "$flags" == *F* && "$flags" == *C* ]]; then
|
||||
print_success "QEMU $target_arch emulation is registered"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_error "Rootless Podman requires QEMU binfmt registration with the F and C flags"
|
||||
print_info "F keeps the emulator available inside containers; C lets container sudo preserve credentials."
|
||||
print_info "Configure it once with:"
|
||||
echo " sudo pacman -S --needed qemu-user-static qemu-user-static-binfmt"
|
||||
echo " sudo mkdir -p /etc/binfmt.d"
|
||||
echo " sed 's/:FP$/:FPC/' $packaged_registration | sudo tee /etc/binfmt.d/qemu-$target_arch-static.conf >/dev/null"
|
||||
echo " sudo systemctl restart systemd-binfmt"
|
||||
exit 1
|
||||
fi
|
||||
print_success "QEMU ARM64 emulation enabled"
|
||||
|
||||
# Register emulators for builds whose target differs from the host.
|
||||
if ! "$CONTAINER_ENGINE" run --rm --privileged docker.io/multiarch/qemu-user-static --reset -p yes --credential yes >/dev/null 2>&1; then
|
||||
print_error "Failed to set up QEMU emulation"
|
||||
exit 1
|
||||
fi
|
||||
print_success "QEMU emulation enabled"
|
||||
}
|
||||
|
||||
build_docker_image() {
|
||||
@@ -39,23 +116,32 @@ build_docker_image() {
|
||||
;;
|
||||
esac
|
||||
|
||||
print_info "Building Docker image for $arch ($platform) using $mirror mirror..."
|
||||
|
||||
docker buildx build \
|
||||
--platform "$platform" \
|
||||
--build-arg MIRROR="$mirror" \
|
||||
--load \
|
||||
-t "$image_tag" \
|
||||
-f "$build_dir/Dockerfile" \
|
||||
"$build_dir"
|
||||
print_info "Building container image for $arch ($platform) using $mirror mirror..."
|
||||
|
||||
if [[ "$CONTAINER_ENGINE" == "docker" ]]; then
|
||||
"$CONTAINER_ENGINE" buildx build \
|
||||
--platform "$platform" \
|
||||
--build-arg MIRROR="$mirror" \
|
||||
--load \
|
||||
-t "$image_tag" \
|
||||
-f "$build_dir/Dockerfile" \
|
||||
"$build_dir"
|
||||
else
|
||||
"$CONTAINER_ENGINE" build \
|
||||
--platform "$platform" \
|
||||
--build-arg MIRROR="$mirror" \
|
||||
-t "$image_tag" \
|
||||
-f "$build_dir/Dockerfile" \
|
||||
"$build_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
get_platform_arg() {
|
||||
local arch="$1"
|
||||
case "$arch" in
|
||||
x86_64) echo "--platform linux/amd64" ;;
|
||||
aarch64) echo "--platform linux/arm64" ;;
|
||||
*) echo "" ;;
|
||||
x86_64) echo "--platform=linux/amd64" ;;
|
||||
aarch64) echo "--platform=linux/arm64" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
+71
-11
@@ -15,10 +15,11 @@
|
||||
# { "source": "local", "channels": ["edge"] }
|
||||
# { "source": "local", "channels": ["edge", "rc", "stable"] }
|
||||
# { "source": "local", "min_release_age": "24h" }
|
||||
# { "source": "local", "upstream": { "github": "owner/repo", "checksums": "SHASUMS256.txt", "assets": { "x86_64": "name-{tag}-x64.tar.xz" } } }
|
||||
# { "source": "local", "upstream": { "github": "owner/repo", "checksums": "SHASUMS256.txt", "assets": { "x86_64": ["name-{tag}-x64.tar.xz"] } } }
|
||||
# { "source": "local", "upstream": { "github": "owner/repo", "digests": true, "assets": { "x86_64": "name-{tag}-x64.tar.xz" } } }
|
||||
# { "source": "local", "upstream": { "git_tags": "https://example/repo.git", "tag_pattern": "v{pkgver}", "sources": { "any": ["https://example/archive/{tag}.tar.gz"] } } }
|
||||
# { "source": "local", "upstream": { "npm": "@scope/package", "sources": { "any": ["{npm_tarball}"] } } }
|
||||
# { "source": "local", "upstream": { "debian": "https://example/debian/dists/stable/main/binary-amd64/Packages", "package": "example", "sources": { "any": ["https://example/releases/{pkgver}.tar.gz"] } } }
|
||||
#
|
||||
# bin/sync-aur also writes upstream_commit for AUR-backed packages, and
|
||||
# bin/sync-rebuilds writes rebuilt_against for packages declaring rebuild_on.
|
||||
@@ -143,6 +144,31 @@ package_has_pkgbuild() {
|
||||
[[ -f "$pkgdir/PKGBUILD" ]]
|
||||
}
|
||||
|
||||
# The architectures declared by a PKGBUILD. Set CARCH while reading it so a
|
||||
# conditional arch=() assignment is evaluated for the architecture we are
|
||||
# actually checking, even when the repository host is a different one.
|
||||
package_arches() {
|
||||
local pkgdir="$1"
|
||||
local arch="${2:-${ARCH:-x86_64}}"
|
||||
|
||||
(cd "$pkgdir" && env -u OMARCHY_SRC CARCH="$arch" bash -c '
|
||||
source PKGBUILD >/dev/null 2>&1
|
||||
printf "%s\n" "${arch[*]}"
|
||||
')
|
||||
}
|
||||
|
||||
package_supports_arch() {
|
||||
local pkgdir="$1"
|
||||
local target="${2:-${ARCH:-x86_64}}"
|
||||
local arches
|
||||
|
||||
arches=$(package_arches "$pkgdir" "$target") || return 1
|
||||
case " $arches " in
|
||||
*" any "* | *" $target "*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Channel membership: where a package may be published. Packages without a
|
||||
# `channels` key are members of every channel (they flow edge -> rc -> stable).
|
||||
package_has_channels() {
|
||||
@@ -301,9 +327,12 @@ packages_for_mirror() {
|
||||
|
||||
packages_for_unscoped_build() {
|
||||
local mirror="$1"
|
||||
local arch="${2:-${ARCH:-x86_64}}"
|
||||
|
||||
package_dirs | while IFS= read -r pkgdir; do
|
||||
if package_builds_for_mirror "$pkgdir" "$mirror" && ! package_build_skipped "$pkgdir"; then
|
||||
if package_builds_for_mirror "$pkgdir" "$mirror" &&
|
||||
! package_build_skipped "$pkgdir" &&
|
||||
package_supports_arch "$pkgdir" "$arch"; then
|
||||
basename "$pkgdir"
|
||||
fi
|
||||
done
|
||||
@@ -454,30 +483,45 @@ validate_package_metadata() {
|
||||
(.key | test("\\A[a-z0-9_]+\\z"))
|
||||
and (.value | type == "array" and length > 0 and all(type == "string" and length > 0))
|
||||
));
|
||||
def valid_assets:
|
||||
type == "object" and length > 0 and (to_entries | all(
|
||||
(.key | test("\\A[a-z0-9_]+\\z"))
|
||||
and (.value |
|
||||
(type == "string" and length > 0)
|
||||
or (type == "array" and length > 0 and all(type == "string" and length > 0) and (unique | length) == length)
|
||||
)
|
||||
));
|
||||
if has("upstream") | not then true
|
||||
elif (.upstream | type) != "object" then false
|
||||
else .upstream |
|
||||
([has("github"), has("git_tags"), has("npm")] | map(select(.)) | length) == 1
|
||||
([has("github"), has("git_tags"), has("npm"), has("debian")] | map(select(.)) | length) == 1
|
||||
and if has("github") then
|
||||
(.github | type == "string" and test("\\A[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+\\z"))
|
||||
and (if has("checksums") then (.checksums | type == "string" and length > 0) else true end)
|
||||
and (if has("digests") then (.digests | type == "boolean") else true end)
|
||||
and (if has("latest_only") then (.latest_only | type == "boolean") else true end)
|
||||
and (has("checksums") != (has("digests") and .digests == true))
|
||||
and (.assets | type == "object" and length > 0 and (to_entries | all(
|
||||
(.key | test("\\A[a-z0-9_]+\\z")) and (.value | type == "string" and length > 0)
|
||||
)))
|
||||
and (.assets | valid_assets)
|
||||
and (if has("sources") then
|
||||
(.sources | valid_sources)
|
||||
and ((.assets | keys) as $assets | (.sources | keys) as $sources | ($assets - $sources | length) == ($assets | length))
|
||||
else true end)
|
||||
elif has("git_tags") then
|
||||
(.git_tags | type == "string" and test("\\Ahttps://[^[:space:]]+\\.git\\z"))
|
||||
and (.tag_pattern | type == "string" and (split("{pkgver}") | length) == 2)
|
||||
and (.sources | valid_sources)
|
||||
else
|
||||
elif has("npm") then
|
||||
(.npm | type == "string" and test("\\A(@[a-z0-9_.-]+/)?[a-z0-9_.-]+\\z"))
|
||||
and ((.dist_tag // "latest") | type == "string" and test("\\A[a-z0-9_.-]+\\z"))
|
||||
and (.sources | valid_sources)
|
||||
else
|
||||
(.debian | type == "string" and test("\\Ahttps://[^[:space:]]+\\z"))
|
||||
and (.package | type == "string" and test("\\A[a-z0-9][a-z0-9+.-]*\\z"))
|
||||
and (.sources | valid_sources)
|
||||
end
|
||||
end
|
||||
' "$metadata" >/dev/null; then
|
||||
echo "invalid upstream for $(basename "$pkgdir"): configure exactly one valid github, git_tags, or npm provider"
|
||||
echo "invalid upstream for $(basename "$pkgdir"): configure exactly one valid github, git_tags, npm, or debian provider"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -502,12 +546,28 @@ validate_package_metadata() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! jq -e '(.rebuilt_against // {}) | type == "object" and (to_entries | all(.value | type == "string" and length > 0))' "$metadata" >/dev/null; then
|
||||
echo "invalid rebuilt_against for $(basename "$pkgdir"): must be an object mapping package names to versions"
|
||||
if ! jq -e '
|
||||
def version_map:
|
||||
type == "object" and (to_entries | all(.value | type == "string" and length > 0));
|
||||
(.rebuilt_against // {}) as $record |
|
||||
($record | version_map) or
|
||||
(($record | type) == "object"
|
||||
and ((($record | keys) - ["x86_64", "aarch64"]) | length == 0)
|
||||
and ($record | to_entries | all(.value | version_map)))
|
||||
' "$metadata" >/dev/null; then
|
||||
echo "invalid rebuilt_against for $(basename "$pkgdir"): must map architectures to package-version maps"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! jq -e '((.rebuilt_against // {}) | keys) - (.rebuild_on // []) | length == 0' "$metadata" >/dev/null; then
|
||||
if ! jq -e '
|
||||
(.rebuild_on // []) as $triggers |
|
||||
(.rebuilt_against // {}) as $record |
|
||||
if ($record | to_entries | all(.value | type == "string")) then
|
||||
((($record | keys) - $triggers) | length == 0)
|
||||
else
|
||||
($record | to_entries | all((((.value | keys) - $triggers) | length) == 0))
|
||||
end
|
||||
' "$metadata" >/dev/null; then
|
||||
echo "invalid rebuilt_against for $(basename "$pkgdir"): records a package that rebuild_on does not name"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -5,6 +5,62 @@
|
||||
ARCH=${ARCH:-x86_64}
|
||||
MIRROR=${MIRROR:-edge}
|
||||
|
||||
# Architectures the tooling knows how to build.
|
||||
VALID_ARCHES="x86_64 aarch64"
|
||||
|
||||
# Architectures this repository PUBLISHES. The scheduled pipeline (version
|
||||
# check, auto-release, channel advance with --arch all) runs once per entry,
|
||||
# in this order; the first entry is the reference architecture that the
|
||||
# release train observes channels through. Adding an architecture here is the
|
||||
# enablement step: the next check-versions tick queues its packages and the
|
||||
# next auto-release tick builds them. OMARCHY_ARCHES overrides it for a
|
||||
# one-off run.
|
||||
PUBLISHED_ARCHES="${OMARCHY_ARCHES:-x86_64}"
|
||||
|
||||
validate_arch() {
|
||||
case " $VALID_ARCHES " in
|
||||
*" $1 "*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
require_valid_arch() {
|
||||
if ! validate_arch "$1"; then
|
||||
echo "Invalid architecture: $1 (must be one of: $VALID_ARCHES)" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
published_arches() {
|
||||
local arch
|
||||
for arch in $PUBLISHED_ARCHES; do
|
||||
require_valid_arch "$arch"
|
||||
echo "$arch"
|
||||
done
|
||||
}
|
||||
|
||||
reference_arch() {
|
||||
published_arches | head -1
|
||||
}
|
||||
|
||||
# Scheduled-pipeline state, one file per channel and architecture, so one
|
||||
# architecture's queue or backoff never gates another's.
|
||||
STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}"
|
||||
|
||||
sync_queue_file() { # sync_queue_file <mirror> <arch>
|
||||
echo "$STATE_DIR/.sync-needed-$1-$2"
|
||||
}
|
||||
|
||||
sync_fail_file() { # sync_fail_file <mirror> <arch>
|
||||
echo "$STATE_DIR/.build-failed-$1-$2"
|
||||
}
|
||||
|
||||
# The pre-architecture names, .sync-needed-<mirror> and .build-failed-<mirror>,
|
||||
# meant x86_64. A host upgraded mid-cycle may still hold one; readers treat
|
||||
# it as the x86_64 file until it is consumed.
|
||||
legacy_sync_queue_file() { echo "$STATE_DIR/.sync-needed-$1"; }
|
||||
legacy_sync_fail_file() { echo "$STATE_DIR/.build-failed-$1"; }
|
||||
|
||||
# Valid package channels, in pipeline order: packages move edge -> rc -> stable
|
||||
VALID_MIRRORS="edge rc stable"
|
||||
|
||||
|
||||
+142
-32
@@ -20,8 +20,8 @@
|
||||
# "v", which is stripped for pkgver. Drafts and prereleases are ignored. The
|
||||
# provider emits the same JSON contract as an upstream.sh hook, so
|
||||
# bin/sync-upstream's validation and min_release_age backstop apply
|
||||
# unchanged. Git-tag and npm providers below cover projects without GitHub
|
||||
# releases; a feed that fits no convention keeps a bespoke hook.
|
||||
# unchanged. Git-tag, npm, and Debian Packages providers below cover projects
|
||||
# without GitHub releases; a feed that fits no convention keeps a bespoke hook.
|
||||
|
||||
# Return the single declarative provider selected by a package. An empty
|
||||
# result means either no provider or an invalid/ambiguous declaration; the
|
||||
@@ -31,7 +31,7 @@ package_upstream_provider() {
|
||||
metadata=$(metadata_file_for_dir "$pkgdir")
|
||||
jq -r '
|
||||
(.upstream? | objects) as $u
|
||||
| [$u | keys[] | select(. == "github" or . == "git_tags" or . == "npm")]
|
||||
| [$u | keys[] | select(. == "github" or . == "git_tags" or . == "npm" or . == "debian")]
|
||||
| if length == 1 then .[0] else "" end
|
||||
' "$metadata"
|
||||
}
|
||||
@@ -64,6 +64,11 @@ npm_fetch_metadata() {
|
||||
curl -fsSL "https://registry.npmjs.org/$encoded"
|
||||
}
|
||||
|
||||
debian_fetch_packages() {
|
||||
local url="$1"
|
||||
curl --proto '=https' --proto-redir '=https' -fsSL "$url"
|
||||
}
|
||||
|
||||
upstream_fetch_source() {
|
||||
local url="$1" output="$2"
|
||||
curl --proto '=https' --proto-redir '=https' -fsSL -o "$output" "$url"
|
||||
@@ -198,6 +203,71 @@ npm_upstream_release() {
|
||||
printf '%s\n' "$release"
|
||||
}
|
||||
|
||||
# Discover a package version from a plain-text Debian Packages index, then
|
||||
# hash the declared immutable sources. This intentionally supports only
|
||||
# versions that are already valid Arch pkgver values; feeds needing Debian
|
||||
# epoch/revision translation keep a package-specific hook.
|
||||
debian_upstream_release() {
|
||||
local package_dir="$1" metadata index_url package packages
|
||||
metadata=$(metadata_file_for_dir "$package_dir")
|
||||
index_url=$(jq -r '.upstream.debian // ""' "$metadata")
|
||||
package=$(jq -r '.upstream.package // ""' "$metadata")
|
||||
|
||||
if [[ ! "$index_url" =~ ^https://[^[:space:]]+$ || ! "$package" =~ ^[a-z0-9][a-z0-9+.-]*$ ]]; then
|
||||
echo "invalid Debian Packages provider configuration" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! jq -e '
|
||||
.upstream.sources | type == "object" and length > 0 and (to_entries | all(
|
||||
(.key | test("\\A[a-z0-9_]+\\z"))
|
||||
and (.value | type == "array" and length > 0 and all(type == "string" and length > 0))
|
||||
))
|
||||
' "$metadata" >/dev/null; then
|
||||
echo "invalid Debian Packages source mapping" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! packages=$(debian_fetch_packages "$index_url"); then
|
||||
echo "could not fetch Debian Packages index: $index_url" >&2
|
||||
return 1
|
||||
fi
|
||||
packages=${packages//$'\r'/}
|
||||
|
||||
local best_pkgver="" candidate
|
||||
while IFS= read -r candidate; do
|
||||
if [[ ! "$candidate" =~ ^[A-Za-z0-9][A-Za-z0-9._+]*$ ]]; then
|
||||
echo "$package has an unusable Debian version: ${candidate:-<empty>}" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "$best_pkgver" || $(vercmp "$candidate" "$best_pkgver") -gt 0 ]]; then
|
||||
best_pkgver="$candidate"
|
||||
fi
|
||||
done < <(awk -v target="$package" '
|
||||
BEGIN { RS = ""; FS = "\n" }
|
||||
{
|
||||
name = version = ""
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i ~ /^Package: /) name = substr($i, 10)
|
||||
if ($i ~ /^Version: /) version = substr($i, 10)
|
||||
}
|
||||
if (name == target) print version
|
||||
}
|
||||
' <<<"$packages")
|
||||
|
||||
[[ -n "$best_pkgver" ]] || {
|
||||
echo "no usable $package release found in $index_url" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
local current_pkgver
|
||||
current_pkgver=$(grep -m1 '^pkgver=' "$package_dir/PKGBUILD" | cut -d= -f2- | tr -d "\"'")
|
||||
if [[ $(vercmp "$best_pkgver" "$current_pkgver") -le 0 ]]; then
|
||||
echo '{}'
|
||||
return 0
|
||||
fi
|
||||
|
||||
upstream_hash_sources "$package_dir" "$best_pkgver" "$best_pkgver"
|
||||
}
|
||||
|
||||
# Emits the newest qualifying release as hook-contract JSON. min_release_age
|
||||
# is honored during selection (newest release older than the window wins,
|
||||
# even when a younger one exists) and BYPASS_MIN_RELEASE_AGE=1 lifts it.
|
||||
@@ -206,7 +276,7 @@ npm_upstream_release() {
|
||||
# not silently choose from.
|
||||
github_upstream_release() {
|
||||
local package_dir="$1" min_age="${2:-0}"
|
||||
local metadata repo checksums_name use_digests
|
||||
local metadata repo checksums_name use_digests latest_only
|
||||
metadata=$(metadata_file_for_dir "$package_dir")
|
||||
|
||||
repo=$(jq -r '(.upstream? | objects | .github) // ""' "$metadata")
|
||||
@@ -218,10 +288,15 @@ github_upstream_release() {
|
||||
# reaches this provider without running the validator first.
|
||||
checksums_name=$(jq -r '(.upstream? | objects | .checksums) | strings' "$metadata")
|
||||
use_digests=$(jq -r '(.upstream? | objects | .digests) | if . == null then "false" elif type == "boolean" then tostring else "invalid" end' "$metadata")
|
||||
latest_only=$(jq -r '(.upstream? | objects | .latest_only) | if . == null then "false" elif type == "boolean" then tostring else "invalid" end' "$metadata")
|
||||
if [[ "$use_digests" == "invalid" ]]; then
|
||||
echo "upstream.digests must be true or false" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$latest_only" == "invalid" ]]; then
|
||||
echo "upstream.latest_only must be true or false" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -n "$checksums_name" && "$use_digests" == "true" ]]; then
|
||||
echo "upstream sets both checksums and digests; keep exactly one" >&2
|
||||
return 1
|
||||
@@ -230,6 +305,27 @@ github_upstream_release() {
|
||||
echo "upstream needs either checksums (a manifest asset name) or digests: true" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! jq -e '
|
||||
def valid_sources:
|
||||
type == "object" and length > 0 and (to_entries | all(
|
||||
(.key | test("\\A[a-z0-9_]+\\z"))
|
||||
and (.value | type == "array" and length > 0 and all(type == "string" and length > 0))
|
||||
));
|
||||
(.upstream.assets | type == "object" and length > 0 and (to_entries | all(
|
||||
(.key | test("\\A[a-z0-9_]+\\z"))
|
||||
and (.value |
|
||||
(type == "string" and length > 0)
|
||||
or (type == "array" and length > 0 and all(type == "string" and length > 0) and (unique | length) == length)
|
||||
)
|
||||
)))
|
||||
and (if .upstream | has("sources") then
|
||||
(.upstream.sources | valid_sources)
|
||||
and ((.upstream.assets | keys) as $assets | (.upstream.sources | keys) as $sources | ($assets - $sources | length) == ($assets | length))
|
||||
else true end)
|
||||
' "$metadata" >/dev/null; then
|
||||
echo "invalid upstream.assets or upstream.sources mapping" >&2
|
||||
return 1
|
||||
fi
|
||||
local arches
|
||||
mapfile -t arches < <(jq -r '(.upstream? | objects | .assets) // {} | keys[]' "$metadata")
|
||||
if [[ ${#arches[@]} -eq 0 ]]; then
|
||||
@@ -243,6 +339,9 @@ github_upstream_release() {
|
||||
echo "could not fetch the release feed for $repo" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$latest_only" == "true" ]]; then
|
||||
releases=$(jq '[.[] | select((.draft or .prerelease) | not)][0:1]' <<<"$releases")
|
||||
fi
|
||||
|
||||
local candidates=0 best_tag="" best_pkgver="" best_published_at=""
|
||||
local tag published_at pkgver published_epoch
|
||||
@@ -302,39 +401,50 @@ github_upstream_release() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
local jq_args=(--arg pkgver "$best_pkgver" --arg published_at "$best_published_at")
|
||||
local jq_filter='{pkgver: $pkgver, published_at: $published_at, sha256sums: {}}'
|
||||
local arch template filename checksum checksum_source
|
||||
local result
|
||||
result=$(jq -n --arg pkgver "$best_pkgver" --arg published_at "$best_published_at" \
|
||||
'{pkgver: $pkgver, published_at: $published_at, sha256sums: {}}')
|
||||
local arch template filename checksum checksum_source sums
|
||||
for arch in "${arches[@]}"; do
|
||||
if [[ ! "$arch" =~ ^[a-z0-9_]+$ ]]; then
|
||||
echo "invalid architecture key in upstream.assets: '$arch'" >&2
|
||||
return 1
|
||||
fi
|
||||
template=$(jq -r --arg arch "$arch" '.upstream.assets[$arch]' "$metadata")
|
||||
filename=${template//\{pkgver\}/$best_pkgver}
|
||||
filename=${filename//\{tag\}/$best_tag}
|
||||
if [[ "$use_digests" == "true" ]]; then
|
||||
# Only a "sha256:<hex>" digest is stripped to its hex; any other shape
|
||||
# falls through empty and fails the check below.
|
||||
checksum=$(jq -r --arg tag "$best_tag" --arg name "$filename" '
|
||||
first(.[] | select(.tag_name == $tag)) | (.assets // [])[]
|
||||
| select(.name == $name) | (.digest // "")
|
||||
| if type == "string" and test("\\Asha256:[0-9a-f]{64}\\z") then ltrimstr("sha256:") else "" end
|
||||
' <<<"$releases")
|
||||
checksum_source="the release API digest"
|
||||
else
|
||||
# Manifest lines are "<sha256> <name>", with the name sometimes prefixed
|
||||
# "./" (sha256sum of a local path) or "*" (binary-mode marker).
|
||||
checksum=$(awk -v f="$filename" '$2 == f || $2 == "./" f || $2 == "*" f { print $1; exit }' <<<"$checksums")
|
||||
checksum_source="$checksums_name"
|
||||
fi
|
||||
if [[ ! "$checksum" =~ ^[0-9a-f]{64}$ ]]; then
|
||||
echo "no valid checksum for $filename in $repo $best_tag $checksum_source" >&2
|
||||
return 1
|
||||
fi
|
||||
jq_args+=(--arg "sum_$arch" "$checksum")
|
||||
jq_filter+=" | .sha256sums[\"$arch\"] = [\$sum_$arch]"
|
||||
sums='[]'
|
||||
while IFS= read -r template; do
|
||||
filename=${template//\{pkgver\}/$best_pkgver}
|
||||
filename=${filename//\{tag\}/$best_tag}
|
||||
if [[ "$use_digests" == "true" ]]; then
|
||||
# Only a "sha256:<hex>" digest is stripped to its hex; any other shape
|
||||
# falls through empty and fails the check below.
|
||||
checksum=$(jq -r --arg tag "$best_tag" --arg name "$filename" '
|
||||
first(.[] | select(.tag_name == $tag)) | (.assets // [])[]
|
||||
| select(.name == $name) | (.digest // "")
|
||||
| if type == "string" and test("\\Asha256:[0-9a-f]{64}\\z") then ltrimstr("sha256:") else "" end
|
||||
' <<<"$releases")
|
||||
checksum_source="the release API digest"
|
||||
else
|
||||
# Manifest lines are "<sha256> <name>", with the name sometimes prefixed
|
||||
# "./" (sha256sum of a local path) or "*" (binary-mode marker).
|
||||
checksum=$(awk -v f="$filename" '$2 == f || $2 == "./" f || $2 == "*" f { print $1; exit }' <<<"$checksums")
|
||||
checksum_source="$checksums_name"
|
||||
fi
|
||||
if [[ ! "$checksum" =~ ^[0-9a-f]{64}$ ]]; then
|
||||
echo "no valid checksum for $filename in $repo $best_tag $checksum_source" >&2
|
||||
return 1
|
||||
fi
|
||||
sums=$(jq -c --arg checksum "$checksum" '. + [$checksum]' <<<"$sums")
|
||||
done < <(jq -r --arg arch "$arch" '
|
||||
.upstream.assets[$arch] | if type == "array" then .[] else . end
|
||||
' "$metadata")
|
||||
result=$(jq -c --arg arch "$arch" --argjson sums "$sums" '.sha256sums[$arch] = $sums' <<<"$result")
|
||||
done
|
||||
|
||||
jq -n "${jq_args[@]}" "$jq_filter"
|
||||
if jq -e '.upstream | has("sources")' "$metadata" >/dev/null; then
|
||||
local source_release
|
||||
source_release=$(upstream_hash_sources "$package_dir" "$best_pkgver" "$best_tag") || return 1
|
||||
result=$(jq -c --argjson source "$source_release" '.sha256sums += $source.sha256sums' <<<"$result")
|
||||
fi
|
||||
|
||||
printf '%s\n' "$result"
|
||||
}
|
||||
@@ -1,5 +1,18 @@
|
||||
{
|
||||
"source": "aur",
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"upstream_commit": "e323d0d1f8dea6b75bb651ce14acc73904cd0326"
|
||||
"upstream": {
|
||||
"debian": "https://downloads.1password.com/linux/debian/amd64/dists/stable/main/binary-amd64/Packages",
|
||||
"package": "1password",
|
||||
"sources": {
|
||||
"x86_64": [
|
||||
"https://downloads.1password.com/linux/tar/stable/x86_64/1password-{pkgver}.x64.tar.gz",
|
||||
"https://downloads.1password.com/linux/tar/stable/x86_64/1password-{pkgver}.x64.tar.gz.sig"
|
||||
],
|
||||
"aarch64": [
|
||||
"https://downloads.1password.com/linux/tar/stable/aarch64/1password-{pkgver}.arm64.tar.gz",
|
||||
"https://downloads.1password.com/linux/tar/stable/aarch64/1password-{pkgver}.arm64.tar.gz.sig"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,33 @@
|
||||
pkgname=1password
|
||||
|
||||
_tarver=8.12.34
|
||||
_tar="1password-${_tarver}.x64.tar.gz"
|
||||
pkgver=${_tarver//-/_}
|
||||
pkgrel=34
|
||||
case "$CARCH" in
|
||||
x86_64) _tararch=x64 ;;
|
||||
aarch64) _tararch=arm64 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
|
||||
pkgver=8.12.34
|
||||
pkgrel=35
|
||||
conflicts=('1password-beta' '1password-beta-bin')
|
||||
pkgdesc="Password manager and secure wallet"
|
||||
arch=('x86_64')
|
||||
arch=('x86_64' 'aarch64')
|
||||
url='https://1password.com'
|
||||
license=('LicenseRef-1Password-Proprietary')
|
||||
options=(!strip)
|
||||
install="1password.install"
|
||||
source=(https://downloads.1password.com/linux/tar/stable/${CARCH}/${_tar}{,.sig})
|
||||
sha256sums=('297784aa66770b645607a7f04c9ba2c4aebed4f46d21202487f521ba572b7b13'
|
||||
'ec085bef60de748895d3c51a8208301ba2ac8fb47db99334539ba4bd1d3260d7'
|
||||
source_x86_64=(
|
||||
"https://downloads.1password.com/linux/tar/stable/x86_64/1password-${pkgver}.x64.tar.gz"
|
||||
"https://downloads.1password.com/linux/tar/stable/x86_64/1password-${pkgver}.x64.tar.gz.sig"
|
||||
)
|
||||
source_aarch64=(
|
||||
"https://downloads.1password.com/linux/tar/stable/aarch64/1password-${pkgver}.arm64.tar.gz"
|
||||
"https://downloads.1password.com/linux/tar/stable/aarch64/1password-${pkgver}.arm64.tar.gz.sig"
|
||||
)
|
||||
sha256sums_x86_64=('297784aa66770b645607a7f04c9ba2c4aebed4f46d21202487f521ba572b7b13'
|
||||
'ec085bef60de748895d3c51a8208301ba2ac8fb47db99334539ba4bd1d3260d7'
|
||||
)
|
||||
sha256sums_aarch64=('ea5102363d6cf3442b96a7abd6743da8c1d261f56a628e1a3c183d84fa65fdcb'
|
||||
'f44db73fa44c3f68c3ab78a9cce140be9355de1dd9be4ce731c9d6597960c907'
|
||||
)
|
||||
validpgpkeys=('3FEF9748469ADBE15DA7CA80AC2D62742012EA22')
|
||||
|
||||
@@ -21,7 +35,7 @@ package() {
|
||||
depends=('hicolor-icon-theme' 'libgtk-3.so=0' 'nss' 'xdg-utils')
|
||||
|
||||
# Go to source directory
|
||||
cd "1password-${_tarver}.x64"
|
||||
cd "1password-${pkgver}.${_tararch}"
|
||||
|
||||
# Install icons
|
||||
resolutions=(32x32 64x64 256x256 512x512)
|
||||
@@ -49,7 +63,7 @@ EOF" > ./com.1password.1Password.policy
|
||||
# Move package contents to /opt/1Password
|
||||
cd "${srcdir}"
|
||||
install -dm0755 "${pkgdir}"/opt
|
||||
mv "1password-${_tarver}.x64" "${pkgdir}/opt/1Password"
|
||||
mv "1password-${pkgver}.${_tararch}" "${pkgdir}/opt/1Password"
|
||||
|
||||
# Cleanup un-needed files
|
||||
rm "${pkgdir}"/opt/1Password/com.1password.1Password.policy "${pkgdir}"/opt/1Password/com.1password.1Password.policy.tpl "${pkgdir}"/opt/1Password/install_biometrics_policy.sh
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/PKGBUILD
|
||||
+++ b/PKGBUILD
|
||||
@@ -11,7 +11,7 @@ pkgname=dropbox-cli
|
||||
pkgver=2024.04.17
|
||||
pkgrel=2
|
||||
pkgdesc="Command line interface for Dropbox"
|
||||
-arch=("any")
|
||||
+arch=("x86_64")
|
||||
url="https://www.dropbox.com"
|
||||
license=("GPL-3.0-or-later")
|
||||
makedepends=("gdk-pixbuf2")
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
pkgname=dropbox-cli
|
||||
pkgver=2024.04.17
|
||||
pkgrel=2
|
||||
pkgrel=2.1
|
||||
pkgdesc="Command line interface for Dropbox"
|
||||
arch=("any")
|
||||
arch=("x86_64")
|
||||
url="https://www.dropbox.com"
|
||||
license=("GPL-3.0-or-later")
|
||||
makedepends=("gdk-pixbuf2")
|
||||
@@ -36,4 +36,3 @@ package() {
|
||||
cd "nautilus-dropbox-${pkgver}"
|
||||
install -m 755 -D "${pkgname}" "${pkgdir}/usr/bin/${pkgname}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"upstream": {
|
||||
"git_tags": "https://github.com/hyprwm/hyprland-guiutils.git",
|
||||
"tag_pattern": "v{pkgver}",
|
||||
"sources": {
|
||||
"any": [
|
||||
"https://github.com/hyprwm/hyprland-guiutils/archive/v{pkgver}/hyprland-guiutils-{pkgver}.tar.gz"
|
||||
]
|
||||
}
|
||||
},
|
||||
"rebuild_on": [
|
||||
"aquamarine"
|
||||
],
|
||||
"rebuilt_against": {
|
||||
"aarch64": {
|
||||
"aquamarine": "0.15.0-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Maintainer: Caleb Maclennan <caleb@alerque.com>
|
||||
|
||||
pkgname=hyprland-guiutils
|
||||
pkgver=0.2.2
|
||||
pkgrel=3
|
||||
pkgdesc='Hyprland GUI utilities'
|
||||
arch=(aarch64)
|
||||
url="https://github.com/hyprwm/$pkgname"
|
||||
license=(BSD-3-Clause)
|
||||
depends=(
|
||||
libgcc
|
||||
libstdc++
|
||||
glibc # libc.so libm.so
|
||||
hyprlang
|
||||
hyprtoolkit libhyprtoolkit.so
|
||||
hyprutils libhyprutils.so
|
||||
libdrm
|
||||
pixman
|
||||
)
|
||||
makedepends=(cmake)
|
||||
replaces=(hyprland-qtutils)
|
||||
_archive="$pkgname-$pkgver"
|
||||
source=("$url/archive/v$pkgver/$_archive.tar.gz")
|
||||
sha256sums=('16f92a6c5a22ac58e1fc313f6b202c188da45e804e1f21ff57dfd0da5c1a01b7')
|
||||
|
||||
build() {
|
||||
cd "$_archive"
|
||||
local cmake_flags=(
|
||||
-D CMAKE_BUILD_TYPE=Release
|
||||
-D CMAKE_INSTALL_PREFIX=/usr
|
||||
)
|
||||
cmake -B build ${cmake_flags[@]}
|
||||
cmake --build build
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$_archive"
|
||||
DESTDIR="$pkgdir" cmake --install build
|
||||
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname" LICENSE
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"upstream": {
|
||||
"git_tags": "https://github.com/hyprwm/Hyprland.git",
|
||||
"tag_pattern": "v{pkgver}",
|
||||
"sources": {
|
||||
"any": [
|
||||
"https://github.com/hyprwm/Hyprland/releases/download/v{pkgver}/source-v{pkgver}.tar.gz"
|
||||
]
|
||||
}
|
||||
},
|
||||
"rebuild_on": [
|
||||
"aquamarine"
|
||||
],
|
||||
"rebuilt_against": {
|
||||
"aarch64": {
|
||||
"aquamarine": "0.15.0-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
# Maintainer: Caleb Maclennan <caleb@alerque.com>
|
||||
# Contributor: ThatOneCalculator <kainoa@t1c.dev>
|
||||
# Contributor: Brenno Lemos <brenno@syndel.is>
|
||||
# Contributor: Gabriel Fox <inbox@gabrielfox.dev>
|
||||
|
||||
pkgname=(hyprland hyprpm)
|
||||
pkgver=0.56.2
|
||||
pkgrel=3
|
||||
pkgdesc='a highly customizable dynamic tiling Wayland compositor'
|
||||
arch=(aarch64)
|
||||
url="https://github.com/hyprwm/${pkgname^}"
|
||||
license=(BSD-3-Clause)
|
||||
depends=(cairo # libcairo.so
|
||||
aquamarine libaquamarine.so
|
||||
libgcc # libgcc_s.so
|
||||
'libstdc++' # libstdc++.so
|
||||
glibc # libc.so libm.so
|
||||
glib2 libgio-2.0.so libgobject-2.0.so
|
||||
glslang # libglslang-default-resource-limits.so libglslang.so
|
||||
hyprcursor libhyprcursor.so
|
||||
hyprgraphics libhyprgraphics.so
|
||||
hyprland-guiutils
|
||||
hyprlang libhyprlang.so
|
||||
hyprutils libhyprutils.so
|
||||
hyprwire libhyprwire.so
|
||||
lcms2 liblcms2.so
|
||||
libdrm # libdrm.so
|
||||
libglvnd libEGL.so libGLESv2.so
|
||||
libinput # libinput.so
|
||||
libx11
|
||||
libxcb # libxcb-dri3.so libxcb-present.so libxcb-render.so libxcb-res.so libxcb-shm.so libxcb.so libxcb-xfixes.so libxcb-xinput.so
|
||||
libxcomposite # libxcb-composite.so
|
||||
libxcursor # libXcursor.so
|
||||
libxfixes
|
||||
libxkbcommon libxkbcommon.so
|
||||
libxrender
|
||||
lua # liblua.so
|
||||
mesa # libgbm.so
|
||||
muparser # libmuparser.so
|
||||
opengl-driver
|
||||
pango libpango-1.0.so libpangocairo-1.0.so
|
||||
pixman libpixman-1.so
|
||||
re2 libre2.so
|
||||
tomlplusplus libtomlplusplus.so
|
||||
util-linux-libs libuuid.so
|
||||
wayland libwayland-server.so
|
||||
wayland-protocols
|
||||
xcb-proto
|
||||
xcb-util
|
||||
xcb-util-errors # libxcb-errors.so
|
||||
xcb-util-image
|
||||
xcb-util-keysyms
|
||||
xcb-util-renderutil # libxcb-render-util.so
|
||||
xcb-util-wm # libxcb-ewmh.so libxcb-icccm.so
|
||||
xorg-xwayland)
|
||||
makedepends=(cmake
|
||||
glaze
|
||||
hyprland-protocols
|
||||
hyprwayland-scanner
|
||||
meson
|
||||
ninja
|
||||
xorgproto)
|
||||
optdepends=('hyprpm: build and install plugins'
|
||||
'hyprshutdown: clean logout and shutdown helper'
|
||||
'xdg-desktop-portal-hyprland: xdg-desktop-portal backend for hyprland')
|
||||
provides=(wayland-compositor)
|
||||
_archive="${pkgname^}-$pkgver"
|
||||
source=("$_archive.tar.gz::$url/releases/download/v$pkgver/source-v$pkgver.tar.gz")
|
||||
sha256sums=('03ad3f5ef152ff44116ffd56fcf808486211ecabf4f0ba567108ee746ba5cd2e')
|
||||
|
||||
prepare() {
|
||||
ln -sf hyprland-source "$_archive"
|
||||
cd "$_archive"
|
||||
sed -i -e '/^release:/{n;s/-D/-DCMAKE_SKIP_RPATH=ON -D/}' Makefile
|
||||
sed -i -e '/find_package.glaze/s/7...<8 //' {.,hyprpm,start}/CMakeLists.txt
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$_archive"
|
||||
make release PREFIX=/usr
|
||||
}
|
||||
|
||||
package_hyprland() {
|
||||
cd "$_archive"
|
||||
make DESTDIR="$pkgdir" install
|
||||
rm -fv "$pkgdir/usr/include/hyprland/src/version.h.in"
|
||||
find $pkgdir -name '*hyprpm*' -delete
|
||||
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
|
||||
}
|
||||
|
||||
package_hyprpm() {
|
||||
pkgdesc='Plugin manager for Hyprland'
|
||||
depends=(cmake
|
||||
cpio
|
||||
glaze
|
||||
hyprland
|
||||
hyprland-protocols
|
||||
hyprwayland-scanner
|
||||
meson)
|
||||
cd "$_archive"
|
||||
make DESTDIR="$pkgdir" install
|
||||
find $pkgdir -type f,l -not -name '*hyprpm*' -delete
|
||||
find $pkgdir -type d -empty -delete
|
||||
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"upstream": {
|
||||
"git_tags": "https://github.com/hyprwm/hyprtoolkit.git",
|
||||
"tag_pattern": "v{pkgver}",
|
||||
"sources": {
|
||||
"any": [
|
||||
"https://github.com/hyprwm/hyprtoolkit/archive/v{pkgver}/hyprtoolkit-{pkgver}.tar.gz"
|
||||
]
|
||||
}
|
||||
},
|
||||
"rebuild_on": [
|
||||
"aquamarine"
|
||||
],
|
||||
"rebuilt_against": {
|
||||
"aarch64": {
|
||||
"aquamarine": "0.15.0-2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# Maintainer: Caleb Maclennan <caleb@alerque.com>
|
||||
|
||||
pkgname=hyprtoolkit
|
||||
pkgver=0.5.4
|
||||
pkgrel=5.1
|
||||
pkgdesc='A modern C++ Wayland-native GUI toolkit'
|
||||
arch=(aarch64)
|
||||
url="https://github.com/hyprwm/$pkgname"
|
||||
license=(BSD-3-Clause)
|
||||
depends=(
|
||||
libgcc
|
||||
libstdc++
|
||||
aquamarine libaquamarine.so
|
||||
cairo libcairo.so
|
||||
glib2 libglib-2.0.so
|
||||
glibc # libc.so libm.so
|
||||
hyprgraphics libhyprgraphics.so
|
||||
hyprlang libhyprlang.so
|
||||
hyprutils libhyprutils.so
|
||||
iniparser libiniparser.so
|
||||
libdrm # libdrm.so
|
||||
libglvnd libEGL.so libOpenGL.so
|
||||
libxkbcommon libxkbcommon.so
|
||||
mesa # libgbm.so
|
||||
pango libpango-1.0.so # libpango.so
|
||||
pixman libpixman-1.so
|
||||
wayland libwayland-client.so
|
||||
)
|
||||
makedepends=(cmake
|
||||
hyprwayland-scanner)
|
||||
provides=(libhyprtoolkit.so)
|
||||
_archive="$pkgname-$pkgver"
|
||||
source=("$url/archive/v$pkgver/$_archive.tar.gz")
|
||||
sha256sums=('2fb59789f231c1c4e9154ceffc1e7524c0cae154807c0d57e6166806255b570f')
|
||||
|
||||
build() {
|
||||
cd "$_archive"
|
||||
local cmake_options=(
|
||||
-D CMAKE_BUILD_TYPE=None
|
||||
-D CMAKE_INSTALL_PREFIX=/usr
|
||||
)
|
||||
cmake -B build -W no-dev ${cmake_options[@]}
|
||||
cmake --build build
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$_archive"
|
||||
DESTDIR="$pkgdir" cmake --install build
|
||||
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
--- a/PKGBUILD
|
||||
+++ b/PKGBUILD
|
||||
@@ -3,6 +3,7 @@
|
||||
pkgname="limine-mkinitcpio-hook"
|
||||
_pkgver=1.38.0
|
||||
_extver=""
|
||||
+_gradle_version=9.7.1
|
||||
pkgver="${_pkgver}${_extver}"
|
||||
pkgrel=1
|
||||
pkgdesc="Install kernels for the Limine bootloader."
|
||||
@@ -10,7 +11,8 @@
|
||||
url="https://gitlab.com/Zesko/limine-entry-tool"
|
||||
source=("${_pkgname}::git+${url}.git#tag=${pkgver}")
|
||||
source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-x64_bin.tar.gz")
|
||||
-source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz")
|
||||
+source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz"
|
||||
+ "https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip")
|
||||
license=("GPL3")
|
||||
provides=('limine-entry-tool')
|
||||
options=(!debug !strip)
|
||||
@@ -27,12 +29,14 @@
|
||||
'sbctl: Signs UEFI boot files for Secure Boot when enabled'
|
||||
'journalctl-desktop-notification: Sends desktop notifications when errors occur'
|
||||
)
|
||||
-makedepends=('git' 'gradle')
|
||||
+makedepends=('git')
|
||||
+makedepends_x86_64=('gradle')
|
||||
backup=(etc/limine-entry-tool.conf)
|
||||
conflicts=('limine-entry-tool')
|
||||
sha256sums=('11dd8211898585f79d8361d97606965bb2ca214dccace5b133dc5121e4bb4d01')
|
||||
sha256sums_x86_64=('3f4a89de8eaa96f2ed677f09957c7e872cd8467aad3537f8b5394c1b8c4b942e')
|
||||
-sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7')
|
||||
+sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7'
|
||||
+ 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a')
|
||||
|
||||
prepare() {
|
||||
[[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}"
|
||||
@@ -48,7 +52,9 @@
|
||||
export GRAALVM_HOME="$srcdir/${_graalvm_version}"
|
||||
export JAVA_HOME="${GRAALVM_HOME}"
|
||||
export NATIVE_IMAGE_OPTIONS="-march=compatibility --future-defaults=all"
|
||||
- /usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
+ local gradle=/usr/bin/gradle
|
||||
+ [[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle"
|
||||
+ "$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
}
|
||||
|
||||
package() {
|
||||
@@ -3,14 +3,16 @@ _pkgname="limine-entry-tool"
|
||||
pkgname="limine-mkinitcpio-hook"
|
||||
_pkgver=1.38.0
|
||||
_extver=""
|
||||
_gradle_version=9.7.1
|
||||
pkgver="${_pkgver}${_extver}"
|
||||
pkgrel=1
|
||||
pkgrel=1.1
|
||||
pkgdesc="Install kernels for the Limine bootloader."
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://gitlab.com/Zesko/limine-entry-tool"
|
||||
source=("${_pkgname}::git+${url}.git#tag=${pkgver}")
|
||||
source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-x64_bin.tar.gz")
|
||||
source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz")
|
||||
source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz"
|
||||
"https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip")
|
||||
license=("GPL3")
|
||||
provides=('limine-entry-tool')
|
||||
options=(!debug !strip)
|
||||
@@ -27,12 +29,14 @@ optdepends=(
|
||||
'sbctl: Signs UEFI boot files for Secure Boot when enabled'
|
||||
'journalctl-desktop-notification: Sends desktop notifications when errors occur'
|
||||
)
|
||||
makedepends=('git' 'gradle')
|
||||
makedepends=('git')
|
||||
makedepends_x86_64=('gradle')
|
||||
backup=(etc/limine-entry-tool.conf)
|
||||
conflicts=('limine-entry-tool')
|
||||
sha256sums=('11dd8211898585f79d8361d97606965bb2ca214dccace5b133dc5121e4bb4d01')
|
||||
sha256sums_x86_64=('3f4a89de8eaa96f2ed677f09957c7e872cd8467aad3537f8b5394c1b8c4b942e')
|
||||
sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7')
|
||||
sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7'
|
||||
'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a')
|
||||
|
||||
prepare() {
|
||||
[[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}"
|
||||
@@ -48,7 +52,9 @@ build() {
|
||||
export GRAALVM_HOME="$srcdir/${_graalvm_version}"
|
||||
export JAVA_HOME="${GRAALVM_HOME}"
|
||||
export NATIVE_IMAGE_OPTIONS="-march=compatibility --future-defaults=all"
|
||||
/usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
local gradle=/usr/bin/gradle
|
||||
[[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle"
|
||||
"$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
}
|
||||
|
||||
package() {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/PKGBUILD
|
||||
+++ b/PKGBUILD
|
||||
@@ -2,12 +2,14 @@
|
||||
pkgname="limine-snapper-sync"
|
||||
pkgver=1.31.0
|
||||
pkgrel=1
|
||||
+_gradle_version=9.7.1
|
||||
pkgdesc="Integrates Limine boot entries with Snapper snapshots."
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://gitlab.com/Zesko/limine-snapper-sync"
|
||||
source=("${pkgname}::git+${url}.git#tag=${pkgver}")
|
||||
source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-x64_bin.tar.gz")
|
||||
-source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz")
|
||||
+source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz"
|
||||
+ "https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip")
|
||||
license=("GPL3")
|
||||
options=(!debug !strip)
|
||||
_graalvm_version=graalvm_ce_jdk25
|
||||
@@ -25,12 +27,14 @@
|
||||
'b3sum: Fast Blake3 hash function to prevent duplication.'
|
||||
'xxhash: Fast hashing utility for deduplication with shorter hashes.'
|
||||
)
|
||||
-makedepends=('git' 'gradle')
|
||||
+makedepends=('git')
|
||||
+makedepends_x86_64=('gradle')
|
||||
backup=(etc/limine-snapper-sync.conf)
|
||||
conflicts=('limine-snapper-cli' 'limine-snapper-sync-git')
|
||||
sha256sums=('ed236f1bbab966950bf11ba5a7958e97a76e66db7fd647b7737bab4b48c9fc40')
|
||||
sha256sums_x86_64=('e0be791c8fda4d03b6b0a0cb824fef3149736170057b3a515252b44419606af0')
|
||||
-sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71')
|
||||
+sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71'
|
||||
+ 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a')
|
||||
|
||||
prepare() {
|
||||
[[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}"
|
||||
@@ -46,7 +50,9 @@
|
||||
export GRAALVM_HOME="$srcdir/${_graalvm_version}"
|
||||
export JAVA_HOME="${GRAALVM_HOME}"
|
||||
export NATIVE_IMAGE_OPTIONS="-march=compatibility"
|
||||
- /usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
+ local gradle=/usr/bin/gradle
|
||||
+ [[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle"
|
||||
+ "$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
}
|
||||
|
||||
package() {
|
||||
@@ -1,13 +1,15 @@
|
||||
# Maintainer: Zesko
|
||||
pkgname="limine-snapper-sync"
|
||||
pkgver=1.31.0
|
||||
pkgrel=1
|
||||
pkgrel=1.1
|
||||
_gradle_version=9.7.1
|
||||
pkgdesc="Integrates Limine boot entries with Snapper snapshots."
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://gitlab.com/Zesko/limine-snapper-sync"
|
||||
source=("${pkgname}::git+${url}.git#tag=${pkgver}")
|
||||
source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-x64_bin.tar.gz")
|
||||
source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz")
|
||||
source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz"
|
||||
"https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip")
|
||||
license=("GPL3")
|
||||
options=(!debug !strip)
|
||||
_graalvm_version=graalvm_ce_jdk25
|
||||
@@ -25,12 +27,14 @@ optdepends=(
|
||||
'b3sum: Fast Blake3 hash function to prevent duplication.'
|
||||
'xxhash: Fast hashing utility for deduplication with shorter hashes.'
|
||||
)
|
||||
makedepends=('git' 'gradle')
|
||||
makedepends=('git')
|
||||
makedepends_x86_64=('gradle')
|
||||
backup=(etc/limine-snapper-sync.conf)
|
||||
conflicts=('limine-snapper-cli' 'limine-snapper-sync-git')
|
||||
sha256sums=('ed236f1bbab966950bf11ba5a7958e97a76e66db7fd647b7737bab4b48c9fc40')
|
||||
sha256sums_x86_64=('e0be791c8fda4d03b6b0a0cb824fef3149736170057b3a515252b44419606af0')
|
||||
sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71')
|
||||
sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71'
|
||||
'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a')
|
||||
|
||||
prepare() {
|
||||
[[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}"
|
||||
@@ -46,7 +50,9 @@ build() {
|
||||
export GRAALVM_HOME="$srcdir/${_graalvm_version}"
|
||||
export JAVA_HOME="${GRAALVM_HOME}"
|
||||
export NATIVE_IMAGE_OPTIONS="-march=compatibility"
|
||||
/usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
local gradle=/usr/bin/gradle
|
||||
[[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle"
|
||||
"$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}"
|
||||
}
|
||||
|
||||
package() {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
--- a/PKGBUILD
|
||||
+++ b/PKGBUILD
|
||||
@@ -36,7 +36,6 @@ depends=(
|
||||
'libcap'
|
||||
'libdrm'
|
||||
'libevdev'
|
||||
- 'libmfx'
|
||||
'libnotify'
|
||||
'libpipewire'
|
||||
'libpulse'
|
||||
@@ -53,6 +52,10 @@ depends=(
|
||||
'which'
|
||||
)
|
||||
|
||||
+depends_x86_64=(
|
||||
+ 'libmfx'
|
||||
+)
|
||||
+
|
||||
makedepends=(
|
||||
'appstream'
|
||||
'appstream-glib'
|
||||
@@ -69,6 +72,10 @@ makedepends=(
|
||||
'shaderc'
|
||||
)
|
||||
|
||||
+makedepends_aarch64=(
|
||||
+ 'vulkan-headers'
|
||||
+)
|
||||
+
|
||||
checkdepends=(
|
||||
'gcovr'
|
||||
)
|
||||
@@ -111,7 +118,12 @@ if [ -n "${optdepends+x}" ]; then
|
||||
|
||||
prepare() {
|
||||
cd "$pkgname"
|
||||
- git submodule update --recursive --init
|
||||
+ if [[ $CARCH == aarch64 ]]; then
|
||||
+ git submodule update --init
|
||||
+ git -C third-party/moonlight-common-c submodule update --init enet
|
||||
+ else
|
||||
+ git submodule update --recursive --init
|
||||
+ fi
|
||||
|
||||
# Backport https://github.com/LizardByte/Sunshine/commit/060b6b07d376e9ef4c4ce4a5c6d648d08fe0eab9
|
||||
patch -Np1 -i "${srcdir}/2026.516.143833-060b6b07-remove-setuptools-from-glad-dependencies.patch"
|
||||
@@ -145,6 +157,10 @@ build() {
|
||||
-D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
||||
)
|
||||
|
||||
+ if [[ $CARCH == aarch64 ]]; then
|
||||
+ _cmake_options+=(-D SUNSHINE_SYSTEM_VULKAN_HEADERS=ON)
|
||||
+ fi
|
||||
+
|
||||
if [[ "${_use_cuda::1}" != "t" ]]; then
|
||||
_cmake_options+=(-DSUNSHINE_ENABLE_CUDA=OFF -DCUDA_FAIL_ON_MISSING=OFF)
|
||||
else
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
pkgname='sunshine'
|
||||
pkgver=2026.516.143833
|
||||
pkgrel=4
|
||||
pkgrel=4.1
|
||||
pkgdesc="Self-hosted game stream host for Moonlight"
|
||||
arch=('x86_64' 'aarch64')
|
||||
url=https://app.lizardbyte.dev/Sunshine
|
||||
@@ -36,7 +36,6 @@ depends=(
|
||||
'libcap'
|
||||
'libdrm'
|
||||
'libevdev'
|
||||
'libmfx'
|
||||
'libnotify'
|
||||
'libpipewire'
|
||||
'libpulse'
|
||||
@@ -55,6 +54,10 @@ depends=(
|
||||
'which'
|
||||
)
|
||||
|
||||
depends_x86_64=(
|
||||
'libmfx'
|
||||
)
|
||||
|
||||
makedepends=(
|
||||
'appstream'
|
||||
'appstream-glib'
|
||||
@@ -69,6 +72,10 @@ makedepends=(
|
||||
'shaderc'
|
||||
)
|
||||
|
||||
makedepends_aarch64=(
|
||||
'vulkan-headers'
|
||||
)
|
||||
|
||||
checkdepends=(
|
||||
'gcovr'
|
||||
)
|
||||
@@ -123,7 +130,12 @@ fi
|
||||
|
||||
prepare() {
|
||||
cd "$pkgname"
|
||||
git submodule update --recursive --init
|
||||
if [[ $CARCH == aarch64 ]]; then
|
||||
git submodule update --init
|
||||
git -C third-party/moonlight-common-c submodule update --init enet
|
||||
else
|
||||
git submodule update --recursive --init
|
||||
fi
|
||||
|
||||
# Backport https://github.com/LizardByte/Sunshine/commit/060b6b07d376e9ef4c4ce4a5c6d648d08fe0eab9
|
||||
patch -Np1 -i "${srcdir}/2026.516.143833-060b6b07-remove-setuptools-from-glad-dependencies.patch"
|
||||
@@ -159,6 +171,10 @@ build() {
|
||||
-D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support'
|
||||
)
|
||||
|
||||
if [[ $CARCH == aarch64 ]]; then
|
||||
_cmake_options+=(-D SUNSHINE_SYSTEM_VULKAN_HEADERS=ON)
|
||||
fi
|
||||
|
||||
if [[ "${_use_cuda::1}" != "t" ]]; then
|
||||
_cmake_options+=(-DSUNSHINE_ENABLE_CUDA=OFF -DCUDA_FAIL_ON_MISSING=OFF)
|
||||
else
|
||||
|
||||
@@ -1,5 +1,82 @@
|
||||
{
|
||||
"source": "aur",
|
||||
"source": "local",
|
||||
"release_ring": "fast",
|
||||
"upstream_commit": "6dbf4bedbba0a2f90d8e813becfa5ba289653562"
|
||||
"min_release_age": "24h",
|
||||
"upstream": {
|
||||
"github": "peteonrails/voxtype",
|
||||
"digests": true,
|
||||
"latest_only": true,
|
||||
"assets": {
|
||||
"x86_64": [
|
||||
"voxtype-{pkgver}-linux-x86_64-avx2",
|
||||
"voxtype-{pkgver}-linux-x86_64-avx2.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-avx512",
|
||||
"voxtype-{pkgver}-linux-x86_64-avx512.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-vulkan",
|
||||
"voxtype-{pkgver}-linux-x86_64-vulkan.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-avx2",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-avx2.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-avx512",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-avx512.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-12",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-12.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-12.libonnxruntime_providers_cuda.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-12.libonnxruntime_providers_shared.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-13",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-13.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-13.libonnxruntime_providers_cuda.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-13.libonnxruntime_providers_shared.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-cuda-13.libonnxruntime.so.1.24.4",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-migraphx",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-migraphx.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-migraphx.libonnxruntime_providers_migraphx.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-onnx-migraphx.libonnxruntime_providers_shared.so",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd-gtk4",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd-gtk4.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd-quickshell",
|
||||
"voxtype-{pkgver}-linux-x86_64-osd-quickshell.asc",
|
||||
"voxtype-{pkgver}-linux-x86_64-audio-bridge",
|
||||
"voxtype-{pkgver}-linux-x86_64-audio-bridge.asc"
|
||||
],
|
||||
"aarch64": [
|
||||
"voxtype-{pkgver}-linux-aarch64-cpu",
|
||||
"voxtype-{pkgver}-linux-aarch64-cpu.asc",
|
||||
"voxtype-{pkgver}-linux-aarch64-onnx",
|
||||
"voxtype-{pkgver}-linux-aarch64-onnx.asc",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd.asc",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd-gtk4",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd-gtk4.asc",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd-quickshell",
|
||||
"voxtype-{pkgver}-linux-aarch64-osd-quickshell.asc",
|
||||
"voxtype-{pkgver}-linux-aarch64-audio-bridge",
|
||||
"voxtype-{pkgver}-linux-aarch64-audio-bridge.asc"
|
||||
]
|
||||
},
|
||||
"sources": {
|
||||
"any": [
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/config/default.toml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/systemd/voxtype.service",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/completions/voxtype.bash",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/completions/voxtype.zsh",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/completions/voxtype.fish",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/LICENSE",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/README.md",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/voxtype-configure.desktop",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/packaging/scripts/voxtype-configure-launcher",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/shell.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/OsdSurface.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/EnginePicker.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/MeetingControls.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/Theme.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/StateReader.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/AudioBridge.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/StyleLoader.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/RecipeRenderer.qml",
|
||||
"https://raw.githubusercontent.com/peteonrails/voxtype/{tag}/quickshell/voxtype-shared/qmldir"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ pkgname=voxtype-bin
|
||||
pkgver=1.0.1
|
||||
pkgrel=1
|
||||
pkgdesc="Push-to-talk voice-to-text for Linux (pre-built binaries)"
|
||||
arch=('x86_64')
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://voxtype.io"
|
||||
license=('MIT')
|
||||
depends=(
|
||||
@@ -47,7 +47,7 @@ validpgpkeys=(
|
||||
'9CCF7915B750CAE8B095ED1AA3FC9F33FD209279'
|
||||
)
|
||||
_github="https://github.com/peteonrails/voxtype/releases/download/v$pkgver"
|
||||
source=(
|
||||
source_x86_64=(
|
||||
# Whisper binaries
|
||||
"voxtype-$pkgver-avx2::$_github/voxtype-$pkgver-linux-x86_64-avx2"
|
||||
"voxtype-$pkgver-avx2.asc::$_github/voxtype-$pkgver-linux-x86_64-avx2.asc"
|
||||
@@ -97,7 +97,23 @@ source=(
|
||||
"voxtype-$pkgver-osd-quickshell.asc::$_github/voxtype-$pkgver-linux-x86_64-osd-quickshell.asc"
|
||||
"voxtype-$pkgver-audio-bridge::$_github/voxtype-$pkgver-linux-x86_64-audio-bridge"
|
||||
"voxtype-$pkgver-audio-bridge.asc::$_github/voxtype-$pkgver-linux-x86_64-audio-bridge.asc"
|
||||
# Config and support files
|
||||
)
|
||||
source_aarch64=(
|
||||
"voxtype-$pkgver-cpu::$_github/voxtype-$pkgver-linux-aarch64-cpu"
|
||||
"voxtype-$pkgver-cpu.asc::$_github/voxtype-$pkgver-linux-aarch64-cpu.asc"
|
||||
"voxtype-$pkgver-onnx::$_github/voxtype-$pkgver-linux-aarch64-onnx"
|
||||
"voxtype-$pkgver-onnx.asc::$_github/voxtype-$pkgver-linux-aarch64-onnx.asc"
|
||||
"voxtype-$pkgver-osd::$_github/voxtype-$pkgver-linux-aarch64-osd"
|
||||
"voxtype-$pkgver-osd.asc::$_github/voxtype-$pkgver-linux-aarch64-osd.asc"
|
||||
"voxtype-$pkgver-osd-gtk4::$_github/voxtype-$pkgver-linux-aarch64-osd-gtk4"
|
||||
"voxtype-$pkgver-osd-gtk4.asc::$_github/voxtype-$pkgver-linux-aarch64-osd-gtk4.asc"
|
||||
"voxtype-$pkgver-osd-quickshell::$_github/voxtype-$pkgver-linux-aarch64-osd-quickshell"
|
||||
"voxtype-$pkgver-osd-quickshell.asc::$_github/voxtype-$pkgver-linux-aarch64-osd-quickshell.asc"
|
||||
"voxtype-$pkgver-audio-bridge::$_github/voxtype-$pkgver-linux-aarch64-audio-bridge"
|
||||
"voxtype-$pkgver-audio-bridge.asc::$_github/voxtype-$pkgver-linux-aarch64-audio-bridge.asc"
|
||||
)
|
||||
source=(
|
||||
# Architecture-independent config and support files
|
||||
"config-$pkgver.toml::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/config/default.toml"
|
||||
"voxtype-$pkgver.service::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/packaging/systemd/voxtype.service"
|
||||
"voxtype-$pkgver.bash::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/packaging/completions/voxtype.bash"
|
||||
@@ -125,46 +141,62 @@ source=(
|
||||
"quickshell-voxtype-shared-RecipeRenderer-$pkgver.qml::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/quickshell/voxtype-shared/RecipeRenderer.qml"
|
||||
"quickshell-voxtype-shared-qmldir-$pkgver::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/quickshell/voxtype-shared/qmldir"
|
||||
)
|
||||
sha256sums=(
|
||||
sha256sums_x86_64=(
|
||||
# Whisper binaries
|
||||
'cb3843a894ef47aca230b30bb1c45c2ef8e0d015adf2fa754d60e55123165fd0' # voxtype-avx2
|
||||
'SKIP' # voxtype-avx2.asc
|
||||
'21357d39412619e8a3fc473153e6e2a28b219aa02007682737afedd73a08bdbe' # voxtype-avx2.asc
|
||||
'77d49275ae4c3a6d93671014278b0dabd69ba52e65d2ee6ab3ec1bff0af34d55' # voxtype-avx512
|
||||
'SKIP' # voxtype-avx512.asc
|
||||
'e3421641b4b5fa5d42ee0698eb43552e177f8b095a1acea32445693404b4fd54' # voxtype-avx512.asc
|
||||
'c569d038057464aa60290296794bcbd79b928ee0efd038e33062a4c015558ed8' # voxtype-vulkan
|
||||
'SKIP' # voxtype-vulkan.asc
|
||||
'a82bd4108dc70d7d2b6e25a83a6744170502f5110780d4a2e97a3e76047ea60d' # voxtype-vulkan.asc
|
||||
# ONNX CPU binaries
|
||||
'19b8716ff7bd388ffb18843fc0ee5e614faa84544d22918ecf72a7c3d6c02929' # voxtype-onnx-avx2
|
||||
'SKIP' # voxtype-onnx-avx2.asc
|
||||
'3021aa3a13555bdab0ecccfb522db8391d7e05810d218608a6372477f11cb2af' # voxtype-onnx-avx2.asc
|
||||
'69a6e6fc1c04a55eeb62cf1eaa5fe81873c70eabffff120ce1a4ff7ef62fd559' # voxtype-onnx-avx512
|
||||
'SKIP' # voxtype-onnx-avx512.asc
|
||||
'305d33b6f4dc8ac7a38a5f522c1af95b462355fa057b2eb39d3add59303145e1' # voxtype-onnx-avx512.asc
|
||||
# ONNX CUDA 12 binary + companion .so
|
||||
'e7180f17add10bb441368d8495fc99bde0ba1a1978ea5f7a52d7e626779eca16' # voxtype-onnx-cuda-12
|
||||
'SKIP' # voxtype-onnx-cuda-12.asc
|
||||
'34f7242fe16867ab029af9ed4854d3930aa2ed91bc37e062962edbfc65522af5' # voxtype-onnx-cuda-12.asc
|
||||
'a8584727d51ba646ac63fc991c2f36ad6cd5b8cc8b1141896e46938700b888d0' # cuda-12.libonnxruntime_providers_cuda.so
|
||||
'1b028afc079628d76a28d7eb09700a4baead4a27f9634ba82c35398486134114' # cuda-12.libonnxruntime_providers_shared.so
|
||||
# ONNX CUDA 13 binary + companion .so + dlopen-target libonnxruntime
|
||||
'4de2aac42b67a05c34ac0b23f771fc83968670fd77d14781cbf4483524304cd1' # voxtype-onnx-cuda-13
|
||||
'SKIP' # voxtype-onnx-cuda-13.asc
|
||||
'adb768be0b115f38bc28ea35614ae59e1c1adfb6e11ae08a252c45d52932fab2' # voxtype-onnx-cuda-13.asc
|
||||
'b6cb7744d0efd2faced5c83ead374c13e7f2630b5a249ffaf393cdb1e092c92b' # cuda-13.libonnxruntime_providers_cuda.so
|
||||
'c6a12593396095f5670160e284c35d1700b7708cf3037b7042e2a5200ccae772' # cuda-13.libonnxruntime_providers_shared.so
|
||||
'1aacefdf0b4afa145d410b2381bbc3db3d978c485fb182c42a2b0b09f91f5310' # cuda-13.libonnxruntime.so.1.24.4
|
||||
# ONNX MIGraphX binary + companion .so
|
||||
'f7a4cc0deaf35110b5106f1fc1f83dded41c0b1780f9fb5aa9cccc3c62e5eb6a' # voxtype-onnx-migraphx
|
||||
'SKIP' # voxtype-onnx-migraphx.asc
|
||||
'9e9c767605923c084c97659326cb0f03ad4e5db0aded4da052fa208b4de9cf45' # voxtype-onnx-migraphx.asc
|
||||
'ddd67e6193ade819ee21f1706d1b03b9151f1d2d2843701e2d19d8b183631707' # migraphx.libonnxruntime_providers_migraphx.so
|
||||
'17f7cf47ad0d7b5ac895ae588fd62c7f85a13842588161b6a24c7d480f062be4' # migraphx.libonnxruntime_providers_shared.so
|
||||
# OSD launcher + GTK4 frontend
|
||||
'7250027b1672507a6d584f795731c87e1d3b5c1de891438bd55e34b136a2d5cc' # voxtype-osd
|
||||
'SKIP' # voxtype-osd.asc
|
||||
'1a944200fbac1e773c70d036075745b0e868885443e29c30797f262d44928cc1' # voxtype-osd.asc
|
||||
'74fb0f6ad87feb0c1c9e06a8b28a7f7ecee101caef4248f77dcf613b5271238e' # voxtype-osd-gtk4
|
||||
'SKIP' # voxtype-osd-gtk4.asc
|
||||
'60224685717fea0582d570160282e9e215cd4713b3bdb695edc7bae8b6860cac' # voxtype-osd-gtk4.asc
|
||||
# Quickshell OSD launcher + audio-bridge sidecar (new in v0.7.5)
|
||||
'b809c5140e844a6add801d7e592775cd89af8cce73fa399b6a3aec15dfd09533' # voxtype-osd-quickshell
|
||||
'SKIP' # voxtype-osd-quickshell.asc
|
||||
'39412691ab1f8ffe4fa6bf1eb9763c29f94b8892d1ba59fd49dc65dd0d80297a' # voxtype-osd-quickshell.asc
|
||||
'45776290e364194d83a8b89445166406c278e890507bf07ec52a5f0e8fa57720' # voxtype-audio-bridge
|
||||
'SKIP' # voxtype-audio-bridge.asc
|
||||
# Config and support files
|
||||
'5be1174a78d70b78fd8d923c88e3406962443b39a1c452eb985b1e2484ef5668' # voxtype-audio-bridge.asc
|
||||
)
|
||||
sha256sums_aarch64=(
|
||||
'b5e31a85aaa952d1a78c12b8a16ba5cbdcd92eb31adc7d1a908f3c9d06edd4f1' # voxtype-cpu
|
||||
'3cd2f3fafca40e394a42b90dac031c67160256898a7f4a52893585b99f8f74bb' # voxtype-cpu.asc
|
||||
'c3771f3e568629178201990976520f88da6d7599ec2d9e404a137570d6c1e108' # voxtype-onnx
|
||||
'cd58773349eac0108cdad0efcc78d13f5d7c21623117381afa99b912c397b94a' # voxtype-onnx.asc
|
||||
'ea910d4fd1fe331d38dbed1c3a639cb7e0c04542919192ff6f74be2139afe3c6' # voxtype-osd
|
||||
'e079ebdd567e318502b710af95e4987fe13623d65673e21877afe88fe18bda55' # voxtype-osd.asc
|
||||
'0d2148e0cd32bac538692470edc06aa9a2f5c6a891aaa373f59fbe78c247fae3' # voxtype-osd-gtk4
|
||||
'0ce841f2caa9a1a7e8294a521bef0bab8823dddacd36fff66012b1127e0c1957' # voxtype-osd-gtk4.asc
|
||||
'097bd518d5e2eac2c3cbad714b65dd8058c818dcb4d900b9a16e442af7d65b8a' # voxtype-osd-quickshell
|
||||
'f48b8071f78fde0b2d20072e875a8b8e0d8fab4caf6c8ec91cd8e2aa0b031063' # voxtype-osd-quickshell.asc
|
||||
'35170ad89fea2874fce0f08758ccc2164892ed643aacae632bcfbc6f10433976' # voxtype-audio-bridge
|
||||
'787965900647ee9b04c8b65123d04b63e38636bfc671fa3b53360823f886b42c' # voxtype-audio-bridge.asc
|
||||
)
|
||||
sha256sums=(
|
||||
# Architecture-independent config and support files
|
||||
'f4b2bccd56b31a6a50e1c0a8b6b72383dc1e636f9ccb8cb070442d58b7314579' # config/default.toml
|
||||
'531c3658e229619e56bb01659fb81f401767b85e1d6e2acd1ac67ee3414a168c' # voxtype.service
|
||||
'65c95805d9b03ccc2fadb9d63a03ab79974b00091df8457ee8ef290ec6bd5b12' # voxtype.bash
|
||||
@@ -189,16 +221,20 @@ sha256sums=(
|
||||
)
|
||||
|
||||
package() {
|
||||
# Install Whisper CPU binaries to /usr/lib/voxtype/
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-avx2" "$pkgdir/usr/lib/voxtype/voxtype-avx2"
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-avx512" "$pkgdir/usr/lib/voxtype/voxtype-avx512"
|
||||
if [[ "$CARCH" == aarch64 ]]; then
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-cpu" "$pkgdir/usr/lib/voxtype/voxtype-cpu"
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-onnx" "$pkgdir/usr/lib/voxtype/voxtype-onnx"
|
||||
else
|
||||
# Install Whisper CPU binaries to /usr/lib/voxtype/
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-avx2" "$pkgdir/usr/lib/voxtype/voxtype-avx2"
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-avx512" "$pkgdir/usr/lib/voxtype/voxtype-avx512"
|
||||
|
||||
# Install Whisper Vulkan GPU binary
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-vulkan" "$pkgdir/usr/lib/voxtype/voxtype-vulkan"
|
||||
# Install Whisper Vulkan GPU binary
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-vulkan" "$pkgdir/usr/lib/voxtype/voxtype-vulkan"
|
||||
|
||||
# Install ONNX CPU binaries (no GPU EP, no companion .so files)
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-onnx-avx2" "$pkgdir/usr/lib/voxtype/voxtype-onnx-avx2"
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-onnx-avx512" "$pkgdir/usr/lib/voxtype/voxtype-onnx-avx512"
|
||||
# Install ONNX CPU binaries (no GPU EP, no companion .so files)
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-onnx-avx2" "$pkgdir/usr/lib/voxtype/voxtype-onnx-avx2"
|
||||
install -Dm755 "$srcdir/voxtype-$pkgver-onnx-avx512" "$pkgdir/usr/lib/voxtype/voxtype-onnx-avx512"
|
||||
|
||||
# GPU-using ONNX binaries each live in their own subdirectory alongside
|
||||
# the EP companion shared libs they dlopen at runtime. ort 2.0.0-rc.12's
|
||||
@@ -248,7 +284,8 @@ package() {
|
||||
# voxtype-onnx-rocm name. The AMD GPU EP changed from ROCm to MIGraphX
|
||||
# in v0.7.0; ship one release with both names to soften the transition.
|
||||
# Drop in v0.8.0.
|
||||
ln -sf "voxtype-onnx-migraphx" "$pkgdir/usr/lib/voxtype/voxtype-onnx-rocm"
|
||||
ln -sf "voxtype-onnx-migraphx" "$pkgdir/usr/lib/voxtype/voxtype-onnx-rocm"
|
||||
fi
|
||||
|
||||
# /usr/bin/voxtype symlink and the unversioned voxtype-onnx-cuda symlink
|
||||
# are created by the .install script's post_install/post_upgrade hooks
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/PKGBUILD
|
||||
+++ b/PKGBUILD
|
||||
@@ -14,7 +14,9 @@ arch=(any)
|
||||
license=('GPL-2.0-only AND GPL-3.0-or-later')
|
||||
-checkdepends=('dkms' 'fakeroot' 'LINUX-HEADERS')
|
||||
+checkdepends=('dkms' 'fakeroot')
|
||||
+checkdepends_x86_64=('LINUX-HEADERS')
|
||||
+checkdepends_aarch64=('linux-aarch64-headers')
|
||||
source=("xpadneo-v${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz")
|
||||
b2sums=('2858e466c5fde7e3d06d878dd7fb695751375e11a112bd3d389f9db5a82ef3ffcc1e3431b213f4807aeb8f05fd4280c7ca2a0a56305b0e984eb9b70df4843735')
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
pkgname=xpadneo-dkms
|
||||
pkgdesc='Advanced Linux Driver for Xbox One Wireless Gamepad'
|
||||
pkgver=0.10.4
|
||||
pkgrel=1
|
||||
pkgrel=1.1
|
||||
url='https://github.com/atar-axis/xpadneo'
|
||||
arch=(any)
|
||||
license=('GPL-2.0-only AND GPL-3.0-or-later')
|
||||
checkdepends=('dkms' 'fakeroot' 'LINUX-HEADERS')
|
||||
checkdepends=('dkms' 'fakeroot')
|
||||
checkdepends_x86_64=('LINUX-HEADERS')
|
||||
checkdepends_aarch64=('linux-aarch64-headers')
|
||||
source=("xpadneo-v${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz")
|
||||
b2sums=('2858e466c5fde7e3d06d878dd7fb695751375e11a112bd3d389f9db5a82ef3ffcc1e3431b213f4807aeb8f05fd4280c7ca2a0a56305b0e984eb9b70df4843735')
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Wants=network-online.target
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash -c 'source /root/.omarchy/build-credentials && /root/omarchy-pkgs/bin/auto-release edge'
|
||||
Environment=OMARCHY_STATE_DIR=/root/.state
|
||||
TimeoutStartSec=7200
|
||||
TimeoutStartSec=43200
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -12,7 +12,7 @@ Type=oneshot
|
||||
# branch's worktree with OMARCHY_RC_PINS=1.
|
||||
ExecStart=/bin/bash -c 'source /root/.omarchy/build-credentials && /root/omarchy-pkgs/bin/auto-release rc'
|
||||
Environment=OMARCHY_STATE_DIR=/root/.state
|
||||
TimeoutStartSec=7200
|
||||
TimeoutStartSec=43200
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -7,7 +7,7 @@ Wants=network-online.target
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash -c 'source /root/.omarchy/build-credentials && /root/omarchy-pkgs/bin/auto-release stable'
|
||||
Environment=OMARCHY_STATE_DIR=/root/.state
|
||||
TimeoutStartSec=7200
|
||||
TimeoutStartSec=43200
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in new issue
Block a user