Merge remote-tracking branch 'upstream/master' into spark/aarch64-settings-boot-dropins

This commit is contained in:
Marcelo Alcantara committed 2026-09-28 07:42:17 +10:00
commit 919b084b93
80 files changed
+1377 -455

No files matched your search

+28 -6
View File
@@ -1,8 +1,9 @@
name: Build changed packages
# Build every package directory a PR touches, one job per package per arch, on
# the self-hosted droplet pool. Artifacts are unsigned; publish.yml signs and
# publishes them on merge.
# Build every package directory a PR touches, one job per package per arch:
# x86_64 on the self-hosted droplet pool, aarch64 natively on GitHub's arm64
# runners. Artifacts are unsigned; publish.yml signs and publishes them on
# merge.
#
# Tooling runs from the base branch; a PR supplies only pkgbuilds/. The
# vouch gate limits who may spend compute; this limits what their PR can run.
@@ -87,8 +88,12 @@ jobs:
if [[ -n "${{ github.event.inputs.packages }}" ]]; then
names="${{ github.event.inputs.packages }}"
else
# A package the PR deletes has nothing to build.
names=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" -- pkgbuilds \
| awk -F/ '$1=="pkgbuilds" && NF>2 {print $2}' | sort -u)
| awk -F/ '$1=="pkgbuilds" && NF>2 {print $2}' | sort -u \
| while read -r name; do
if git cat-file -e "${{ github.event.pull_request.head.sha }}:pkgbuilds/$name" 2>/dev/null; then echo "$name"; fi
done)
fi
matrix=$(printf '%s\n' $names | bin/build-matrix)
# A package directory whose exact tree already has a build artifact
@@ -159,13 +164,17 @@ jobs:
build:
needs: changes
if: needs.changes.outputs.count != '0'
runs-on: [self-hosted, omarchy-builder]
# The droplets are x86, so aarch64 there runs under QEMU: omarchy-mac-boot
# took 2h47m of the 180 minutes, most of it in check().
# GitHub's arm64 runners (4 vCPU, 16 GB; ~100 GB disk free in our pilots)
# build it natively in 11 minutes, and linux-aurora in 30 (72 under QEMU).
runs-on: ${{ matrix.arch == 'aarch64' && 'ubuntu-24.04-arm' || fromJSON('["self-hosted","omarchy-builder"]') }}
timeout-minutes: 180
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.changes.outputs.matrix) }}
steps:
# Tooling from base: everything that executes on this droplet's host
# Tooling from base: everything that executes on this runner's host
# (bin/, helpers/, build/) comes from the base branch. Only the PR's
# package directories are overlaid. A PR can therefore change what
# gets built, never how the runner builds it. A PR that changes both
@@ -192,6 +201,19 @@ jobs:
env:
CONTAINER_ENGINE: docker
run: bin/build --mirror edge --arch ${{ matrix.arch }} --package ${{ matrix.package }}
# makepkg's check() leaves meson's per-test output in the build tree,
# never on stdout, so a failing test shows only a summary line in this
# job log. bin/build bind-mounts $SRC_DIR at /src, so those logs outlive
# the container. Without this upload an arch-specific test failure
# cannot be diagnosed from CI at all (seen on owe 0.2.7, aarch64).
- name: Upload test logs
if: always() && steps.build.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: test-logs-${{ matrix.package }}-${{ matrix.arch }}
path: src/**/meson-logs/
if-no-files-found: ignore
retention-days: 14
# The artifact label carries the package directory's git tree hash so
# the publish step can find the build for exactly the tree that merged.
# The package file inside keeps makepkg's standard name untouched.
+114 -8
View File
@@ -36,13 +36,18 @@ jobs:
outputs:
matrix: ${{ steps.list.outputs.matrix }}
count: ${{ steps.list.outputs.count }}
rebuild: ${{ steps.list.outputs.rebuild }}
rebuild_count: ${{ steps.list.outputs.rebuild_count }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- id: list
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if [[ -n "${{ github.event.inputs.packages }}" ]]; then
names="${{ github.event.inputs.packages }}"
else
@@ -53,17 +58,102 @@ jobs:
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
echo "count=$(jq '.include | length' <<<"$matrix")" >> "$GITHUB_OUTPUT"
jq -r '.include[] | "\(.package) \(.arch) -> \(.channels)"' <<<"$matrix"
# Reuse or rebuild, decided per entry and said out loud. An aarch64
# tree with no build artifact (PR artifacts last 7 days; a dispatch
# may name any package) goes to the rebuild job, which builds it
# natively on GitHub's arm64 runner. x86_64 builds inside the
# publish job on the droplet, as before.
rebuild=()
echo "| package | arch | tree | decision |" >> "$GITHUB_STEP_SUMMARY"
echo "| --- | --- | --- | --- |" >> "$GITHUB_STEP_SUMMARY"
while read -r entry; do
package=$(jq -r .package <<<"$entry"); arch=$(jq -r .arch <<<"$entry")
hash=$(git rev-parse "HEAD:pkgbuilds/$package")
label="$package-$arch-$hash"
found=$(curl -fsS -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/artifacts?name=$label&per_page=5" \
| jq -r '[.artifacts[] | select(.expired|not)] | sort_by(.created_at) | last | select(. != null) | "run \(.workflow_run.id), expires \(.expires_at)"')
if [[ -n "$found" ]]; then
decision="reuse the build artifact ($found)"
elif [[ $arch == aarch64 ]]; then
decision="no build artifact: rebuild natively on ubuntu-24.04-arm"
rebuild+=("$entry")
else
decision="no build artifact: build in the publish job on the self-hosted builder"
fi
echo "==> $label: $decision"
echo "| $package | $arch | ${hash:0:12} | $decision |" >> "$GITHUB_STEP_SUMMARY"
done < <(jq -c '.include[]' <<<"$matrix")
echo "rebuild=$(printf '%s\n' "${rebuild[@]}" | jq -sc '{include: .}')" >> "$GITHUB_OUTPUT"
echo "rebuild_count=${#rebuild[@]}" >> "$GITHUB_OUTPUT"
# The aarch64 half of "build it now when there is none". It builds exactly
# as build-pr.yml's aarch64 path does (same runner, same builder image,
# same bin/build call) and uploads under the same label, so the publish
# job collects this run's artifact the way it collects a PR's. No secret
# reaches this runner; signing and upload stay on the self-hosted builder.
rebuild:
needs: changes
if: needs.changes.outputs.rebuild_count != '0'
runs-on: ubuntu-24.04-arm
timeout-minutes: 180
permissions:
contents: read
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.changes.outputs.rebuild) }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
# The same check the publish job makes before building: a re-run for a
# package the channel already holds at master's version builds
# nothing, and uploads nothing that could shadow the published file.
- name: Build ${{ matrix.package }} (${{ matrix.arch }}, native)
id: build
env:
CONTAINER_ENGINE: docker
run: |
set -euo pipefail
plan=$(bin/build --dry-run --mirror edge --arch "${{ matrix.arch }}" --package "${{ matrix.package }}" 2>&1 | grep -E '^==> Plan complete' || true)
if [[ -n "$plan" && -z "$(sed -E 's/.*would build: *//' <<<"$plan" | tr -d '[:space:]')" ]]; then
echo "==> ${{ matrix.package }} (${{ matrix.arch }}): already published at master's version, nothing to build"
echo "built=false" >> "$GITHUB_OUTPUT"
exit 0
fi
bin/build --mirror edge --arch "${{ matrix.arch }}" --package "${{ matrix.package }}"
echo "built=true" >> "$GITHUB_OUTPUT"
- name: Pack artifact
if: steps.build.outputs.built == 'true'
id: pack
run: |
source helpers/artifact-helpers.sh
pack_packages build-output/edge/${{ matrix.arch }} packages.tar
tar -tvf packages.tar
echo "label=${{ matrix.package }}-${{ matrix.arch }}-$(git rev-parse "HEAD:pkgbuilds/${{ matrix.package }}")" >> "$GITHUB_OUTPUT"
- name: Upload artifact
if: steps.build.outputs.built == 'true'
uses: actions/upload-artifact@v4
with:
name: ${{ steps.pack.outputs.label }}
path: packages.tar
if-no-files-found: error
retention-days: 7
# One job for the whole merge. It collects every PR artifact for the
# merged tree (building only what has none), then walks each channel and
# merged tree (building only what has none; aarch64 comes from the
# rebuild job above), then walks each channel and
# architecture slot exactly once: pull that database, add every package
# that belongs in it, upload. Six slots, six round trips, however many
# packages the merge carried. One process is the only writer, so there
# is no race between packages; the run-level concurrency group above
# keeps one merge from overlapping the next.
# It waits for the rebuild job and runs whatever that job's result: a
# failed rebuild leaves its package without an artifact, and the collect
# step below records that and stops before any publish.
publish:
needs: changes
if: needs.changes.outputs.count != '0'
needs: [changes, rebuild]
if: ${{ !cancelled() && needs.changes.result == 'success' && needs.changes.outputs.count != '0' }}
runs-on: [self-hosted, omarchy-builder]
environment: publish
timeout-minutes: 240
@@ -104,15 +194,22 @@ jobs:
label="$package-$arch-$hash"
found=$(curl -fsS -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/artifacts?name=$label&per_page=5" \
| jq -r '[.artifacts[] | select(.expired|not)] | sort_by(.created_at) | last | .archive_download_url // empty')
| jq -r '[.artifacts[] | select(.expired|not)] | sort_by(.created_at) | last | select(. != null) | "\(.archive_download_url) \(.workflow_run.id)"')
read -r found from_run <<<"$found" || true
mkdir -p "build-output/edge/$arch"
if [[ -n "$found" ]]; then
echo "==> $label: PR artifact"
if [[ $from_run == "${{ github.run_id }}" ]]; then
kind=native-rebuild
echo "==> $label: artifact from this run's native $arch rebuild"
else
kind=pr-artifact
echo "==> $label: reusing the build artifact from run $from_run"
fi
rm -rf /tmp/artifact; mkdir -p /tmp/artifact
if curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" \
&& unzip -oq /tmp/artifact.zip -d /tmp/artifact \
&& unpack_packages /tmp/artifact "build-output/edge/$arch"; then
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"pr-artifact"}' >> sources.jsonl
jq -nc --arg p "$package" --arg a "$arch" --arg s "$kind" '{package:$p, arch:$a, source:$s}' >> sources.jsonl
else
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"artifact-download-failed"}' >> sources.jsonl; failed=1; break
fi
@@ -128,6 +225,14 @@ jobs:
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"already-published"}' >> sources.jsonl
continue
fi
# aarch64 never builds here: this droplet is x86 and would
# emulate it. No artifact means the native rebuild failed (see
# the rebuild job), or an artifact expired between planning
# and now (re-run all jobs).
if [[ $arch == aarch64 ]]; then
echo "::error::$label: no artifact from the native rebuild; not building aarch64 under emulation"
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"native-build-failed"}' >> sources.jsonl; failed=1; break
fi
echo "==> $label: no artifact for this tree, building"
if OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package"; then
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"built"}' >> sources.jsonl
@@ -269,7 +374,7 @@ jobs:
run: |
jq -r --arg outcome "${{ needs.publish.result }}" '
def pkgs: [.packages[] | select(test("-debug-")|not)] | join(", ");
def src: if .source=="pr-artifact" then "PR artifact" elif .source=="built" then "built here" elif .source=="already-published" then "already published, skipped" else "**" + .source + "**" end;
def src: if .source=="pr-artifact" then "PR artifact" elif .source=="native-rebuild" then "rebuilt natively on arm64" elif .source=="built" then "built here" elif .source=="already-published" then "already published, skipped" else "**" + .source + "**" end;
"### Publish " + (if $outcome=="success" then "succeeded" else "FAILED" end) +
" → **" + .target + "**" + (if .target!="live" then " (proof prefix, not live)" else "" end),
"",
@@ -322,5 +427,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- run: |
echo "publish result: ${{ needs.publish.result }}"
echo "changes result: ${{ needs.changes.result }}, publish result: ${{ needs.publish.result }}"
[[ "${{ needs.changes.result }}" == "success" ]]
[[ "${{ needs.publish.result }}" == "success" || "${{ needs.publish.result }}" == "skipped" ]]
+4 -2
View File
@@ -47,11 +47,13 @@ jobs:
useradd -m -u "$HOST_UID" -g "$HOST_GID" runner
chown -R runner:runner /workspace/pkgbuilds
# The reviewed lane only: packages marked auto_merge ride
# track-branches.yml, which merges without a human.
if [[ -n "${PACKAGES:-}" ]]; then
read -r -a package_args <<< "$PACKAGES"
runuser -u runner -- ./bin/sync-upstream "${package_args[@]}"
runuser -u runner -- ./bin/sync-upstream --lane reviewed "${package_args[@]}"
else
runuser -u runner -- ./bin/sync-upstream
runuser -u runner -- ./bin/sync-upstream --lane reviewed
fi
'
env:
+1
View File
@@ -59,6 +59,7 @@ jobs:
./tests/partial-release.sh
./tests/published-build-plan.sh
./tests/settings-boot-config.sh
./tests/pinned-sources.sh
./tests/controller.sh
./tests/artifact-helpers.sh
./tests/limine-mkinitcpio-hook.sh
+161
View File
@@ -0,0 +1,161 @@
name: Track upstream branches
# The unattended lane. Packages marked "auto_merge": true follow a moving
# upstream branch (omarchy-dev and omarchy-settings-dev on quattro, omasnap-git
# on main) rather than tagged releases, so nothing in this repository changes
# when their source does. This workflow makes each new branch tip a commit pin
# in the recipe, which publish.yml then treats like any other version bump:
# the PR builds on the droplets, auto-merge lands it when `result` is green,
# and the merge publishes the artifacts. A tip that fails to build stays an
# unmerged red PR that the next tick supersedes.
#
# The PR and auto-merge use the PAT in PKGS_BOT_TOKEN so they trigger the
# build and publish workflows. The built-in GITHUB_TOKEN cannot drive this
# unattended chain. The PAT needs Contents: write and Pull requests: write
# on this repository, and its owner must be trusted by the build workflow.
on:
schedule:
# Every 2 hours, off the hour to dodge the scheduling backlog at :00
- cron: '35 */2 * * *'
workflow_dispatch:
inputs:
packages:
description: 'Specific packages to track (space-separated, leave empty for every auto_merge package)'
required: false
default: ''
# One tracker at a time: two runs racing on auto/track-branches would each
# force-push their own pin over the other's.
concurrency:
group: track-branches
cancel-in-progress: false
jobs:
track:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Require the tracking token
env:
PKGS_BOT_TOKEN: ${{ secrets.PKGS_BOT_TOKEN }}
run: |
if [[ -z "$PKGS_BOT_TOKEN" ]]; then
echo "::error::Set PKGS_BOT_TOKEN to a PAT with Contents: write and Pull requests: write on this repository, owned by an account trusted to trigger builds."
exit 1
fi
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
# Same container as the reviewed sync: vercmp decides whether a pin is
# an upgrade with the comparator pacman uses on users' machines.
- name: Pin tracked branches to their current tips
id: sync
run: |
docker run --rm \
-e PACKAGES="$PACKAGES" \
-e UPSTREAM_GITHUB_TOKEN="$UPSTREAM_GITHUB_TOKEN" \
-e HOST_UID="$(id -u)" \
-e HOST_GID="$(id -g)" \
-v "$PWD/bin:/workspace/bin:ro" \
-v "$PWD/helpers:/workspace/helpers:ro" \
-v "$PWD/pkgbuilds:/workspace/pkgbuilds" \
-w /workspace \
archlinux:base-devel bash -lc '
set -euo pipefail
pacman -Syu --noconfirm git jq python libarchive
groupadd -g "$HOST_GID" runner
useradd -m -u "$HOST_UID" -g "$HOST_GID" runner
chown -R runner:runner /workspace/pkgbuilds
if [[ -n "${PACKAGES:-}" ]]; then
read -r -a package_args <<< "$PACKAGES"
runuser -u runner -- ./bin/sync-upstream --lane auto-merge "${package_args[@]}"
else
runuser -u runner -- ./bin/sync-upstream --lane auto-merge
fi
'
env:
PACKAGES: ${{ github.event.inputs.packages }}
UPSTREAM_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check for changes
if: ${{ !cancelled() && steps.sync.outcome != 'skipped' }}
id: changes
run: |
if [ -z "$(git status --porcelain)" ]; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "has_changes=true" >> "$GITHUB_OUTPUT"
git status --porcelain
{
echo "### Pinned"
git diff --unified=0 -- 'pkgbuilds/*/PKGBUILD' | grep -E '^\+(pkgver|_commit)=' | sed 's/^+/- /'
} >> "$GITHUB_STEP_SUMMARY"
fi
# The PR title names what moved, so the merged history reads like a
# changelog: "Track upstream branches: omarchy-dev 4.0.0.r6520.g1a2b3c4, ...".
- name: Describe the pins
if: ${{ !cancelled() && steps.changes.outputs.has_changes == 'true' }}
id: describe
run: |
title=$(git diff --unified=0 -- 'pkgbuilds/*/PKGBUILD' \
| awk '/^\+\+\+ b\/pkgbuilds\//{split($2,p,"/"); pkg=p[3]} /^\+pkgver=/{sub(/^\+pkgver=/,""); printf "%s %s, ", pkg, $0}' \
| sed 's/, $//')
echo "title=Track upstream branches: ${title}" >> "$GITHUB_OUTPUT"
- name: Open or update the tracking PR
if: ${{ !cancelled() && steps.changes.outputs.has_changes == 'true' }}
id: pr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.PKGS_BOT_TOKEN }}
commit-message: ${{ steps.describe.outputs.title }}
title: ${{ steps.describe.outputs.title }}
body: |
Automated pin of packages that follow a moving upstream branch
(`"auto_merge": true` in `.omarchy/package.json`). Each package's
`_commit` now points at the branch tip. Fresh tips wait until
their commit timestamp is at least `min_release_age` old.
This PR auto-merges once the build checks pass. A failing build
leaves it open; the next tracker run replaces it with the newer tip.
branch: auto/track-branches
delete-branch: true
labels: automated
# Auto-merge, not a direct merge: branch protection still has to see
# `result`, `self-tests` and `build-isolation` green, and this lane
# inherits every rule the reviewed lane has except the human.
- name: Enable auto-merge
if: ${{ !cancelled() && steps.pr.outputs.pull-request-number != '' }}
env:
GH_TOKEN: ${{ secrets.PKGS_BOT_TOKEN }}
PR: ${{ steps.pr.outputs.pull-request-number }}
run: |
# Idempotent across re-runs of an updated PR: enabling twice errors.
if [[ "$(gh pr view "$PR" -R "${{ github.repository }}" --json autoMergeRequest --jq '.autoMergeRequest != null')" == true ]]; then
echo "auto-merge already enabled on #$PR"
exit 0
fi
gh pr merge --auto --merge "$PR" -R "${{ github.repository }}"
- name: Notify Basecamp on failure
if: failure() && env.BASECAMP_CHATBOT_URL != ''
env:
BASECAMP_CHATBOT_URL: ${{ secrets.BASECAMP_CHATBOT_URL }}
run: |
curl -s -o /dev/null \
-H "Content-Type: application/json" \
-d "$(jq -n --arg content \
"🔴 <strong>Branch tracking failed</strong><br><a href=\"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\">View run</a>" \
'{content: $content}')" \
"$BASECAMP_CHATBOT_URL"
+19 -1
View File
@@ -23,6 +23,14 @@ The filesystem no longer encodes release policy. Instead:
(`OMARCHY_RC_PINS=1`, which `omarchy-release rc` sets) may build it for rc — master's
shipped pins can never overwrite an in-flight RC. The dev pair
(`omarchy-dev`, `omarchy-settings-dev`) is pinned to `edge`
- packages that follow a moving upstream branch (the dev pair on `quattro`,
`omasnap-git` on `main`) still pin an exact commit in their PKGBUILD. A
`git_branch` upstream watch moves that pin, and `"auto_merge": true` puts the
package on the unattended lane: `track-branches.yml` opens the bump PR every
two hours and auto-merges it once the build checks pass, so a branch tip
reaches the edge channel without anyone clicking. No PKGBUILD may carry an
unpinned git source (`tests/pinned-sources.sh`); a branch that has to be
followed gets a watch, not a `#branch=` fragment
- Omarchy owns every checked-in recipe; upstream watches update release metadata without replacing packaging or architecture support
- packages can opt out of unscoped builds with `skip_build`; explicit `--package` builds remain available
- packages follow direct upstream watches/providers in `.omarchy/package.json`, or a custom `.omarchy/upstream.sh` hook
@@ -719,6 +727,7 @@ Fields:
- `upstream`: optional direct release watch (see [Upstream watches](docs/upstream-sources.md)), or an existing GitHub, git-tag, npm, or Debian provider. 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`: `false` records an existing manual maintenance hold. Held packages have no upstream watch/provider/hook and are excluded from automatic updates.
- `auto_merge`: optional boolean; defaults to `false`. `true` moves the package's upstream updates from the reviewed 6-hourly sync PR to the unattended lane: `track-branches.yml` opens its bump PR and auto-merges it when CI is green. Meant for packages that follow a moving branch through a `git_branch` watch, where every tip is a release and there is nothing for a reviewer to read. Requires an upstream watch, provider, or hook.
- `origin`: optional historical import provenance, with `aur` (package name) and `commit`. It does not control updates.
- `release_ring`: optional. `fast` means the package is built directly for stable as well as edge, with the artifacts replicated into rc for parity. Packages without a ring build in edge and reach stable through the pipeline (`bin/repo advance`).
- `channels`: optional array bounding where the package may be built (`edge`, `rc`, `stable`). Without the key a package is a member of every channel and follows the default build rules above; `bin/repo advance` refuses to carry a package anywhere it isn't a member.
@@ -880,8 +889,17 @@ The repository includes GitHub workflows and systemd services for automated rele
#### GitHub Workflows
1. **sync-upstream.yml** (Every 6 hours): Watches direct upstream feeds and updates owned recipes. Successful package updates reach a PR even if another feed fails; failed recipes stay untouched and the workflow remains red.
1. **sync-upstream.yml** (Every 6 hours): Watches direct upstream feeds and updates owned recipes on the reviewed lane. Successful package updates reach a PR even if another feed fails; failed recipes stay untouched and the workflow remains red.
2. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR.
3. **track-branches.yml** (Every 2 hours): The unattended lane. Pins every `"auto_merge": true` package to the tip of its watched branch once its commit timestamp clears `min_release_age`, opens one PR for all of them, and enables auto-merge. Packages pinned from the same branch move together or not at all, including targeted syncs. The PR builds like any other; a tip that fails to build stays an open red PR until the next tick supersedes it.
The tracking PR and auto-merge use the PAT stored in `PKGS_BOT_TOKEN`, with
Contents and Pull requests write access to this repository and an owner trusted
to trigger builds. The existing controller PAT can be reused. No GitHub App is
required. The built-in Actions `GITHUB_TOKEN` cannot drive the unattended
build-and-publish chain, so the tracker requires this secret before it runs.
The reviewed sync workflows continue to use `GITHUB_TOKEN` and require
maintainer approval as before. See [setup instructions](docs/upstream-sources.md#enable-unattended-branch-updates).
To approve builds for an unvouched contributor's PR, apply **`build-approved`**.
Until approval, the PR shows **Awaiting build approval** and its required
+134 -5
View File
@@ -12,6 +12,7 @@ trap 'rm -rf "$TEMP_DIR"' EXIT
export UPSTREAM_CACHE_DIR="$TEMP_DIR/watch-cache"
SPECIFIC_PACKAGES=()
LANE=all
usage() {
cat <<EOF
@@ -49,6 +50,14 @@ the bypass, so the resulting change still goes through a reviewed PR.
Arguments:
PACKAGE One or more package names to update (optional)
Options:
--lane <reviewed|auto-merge|all>
Which delivery lane to sync (default: all). Packages marked
"auto_merge": true ride the unattended lane (the branch tracker
opens and auto-merges their PR); everything else is reviewed.
The scheduled workflows each pass their own lane so a moving
branch tip never waits on a vendor release, or the reverse.
Commands:
self-test Run the offline fixture tests for release selection, the
quarantine backstop, and metadata parsing
@@ -65,6 +74,14 @@ while [[ $# -gt 0 ]]; do
usage
exit 0
;;
--lane)
LANE="${2:-}"
case "$LANE" in
reviewed|auto-merge|all) ;;
*) print_error "Invalid --lane '$LANE' (expected reviewed, auto-merge, or all)"; exit 1 ;;
esac
shift 2
;;
--*)
print_error "Unknown option: $1"
exit 1
@@ -141,17 +158,22 @@ set_pkgbuild_array() {
local rewritten="$TEMP_DIR/pkgbuild-rewritten"
if ! awk -v prefix="${name}=(" -v block="$block" '
# The code on a line, minus any comment. Checksum arrays hold quoted hex
# (or SKIP), so a "#" can only ever start a comment here.
function code(s) { sub(/#.*/, "", s); return s }
!replaced && index($0, prefix) == 1 {
while ((getline line < block) > 0) print line
close(block)
replaced = 1
# A ")" anywhere past the opening closes the array; testing for one at end
# of line instead would treat a trailing comment as a continuation and eat
# every line up to the next ")".
if (index(substr($0, length(prefix) + 1), ")") == 0) skipping = 1
# every line up to the next ")". A ")" inside a comment -- "# sidecar
# (new in v0.7.5)" -- closes nothing, and ending the skip there would
# leave the rest of the old array behind a stray ")".
if (index(code(substr($0, length(prefix) + 1)), ")") == 0) skipping = 1
next
}
skipping { if ($0 ~ /\)/) skipping = 0; next }
skipping { if (code($0) ~ /\)/) skipping = 0; next }
{ print }
' "$pkgbuild" > "$rewritten"; then
print_error "Failed to rewrite ${name} in $pkgbuild"
@@ -945,6 +967,29 @@ EOF
vst=0; validate_package_metadata "$npmpkg" >/dev/null || vst=$?
check "npm declaration validates" "0" "$vst"
# A ")" in a comment inside a checksum array must not end the rewrite early;
# voxtype-bin annotates its arrays with "(new in v0.7.5)" and the like.
echo "Checksum array rewrite across commented lines:"
local commented="$TEMP_DIR/commented-pkgbuild" sum_c=$(printf 'c%.0s' {1..64})
cat > "$commented" <<'EOF'
sha256sums_x86_64=(
# Binaries
'aaaa' # tool
# Sidecar (new in v0.7.5)
'bbbb' # sidecar (x86_64)
)
sha256sums=( # support files (arch-independent)
'dddd'
)
package() { :; }
EOF
set_pkgbuild_array "$commented" sha256sums_x86_64 "$sum_c" "$sum_c"
set_pkgbuild_array "$commented" sha256sums "$sum_c"
check "commented arrays rewrite to valid shell" "0" \
"$(bash -n "$commented" 2>/dev/null; echo $?)"
check "commented arrays hold only the new checksums" "$sum_c $sum_c|$sum_c|package" \
"$(bash -c 'source "$1"; printf "%s|%s|%s" "${sha256sums_x86_64[*]}" "${sha256sums[*]}" "$(declare -F package)"' _ "$commented")"
# End to end over the real mise-bin package: its checked-in metadata and
# PKGBUILD, the full sync_package path (selection, validation, backstop,
# rewrite, read-back verification), with only the two network fetches
@@ -1014,16 +1059,100 @@ if [[ ${#SPECIFIC_PACKAGES[@]} -gt 0 && "${SPECIFIC_PACKAGES[0]}" == "self-test"
exit 0
fi
# Packages that pin the same upstream branch move together or not at all.
# The watch reads one shared clone per run, so they only disagree when one
# package's update failed after the tip was chosen (a checksum fetch, say).
# Leaving the other one advanced would ship omarchy-dev and
# omarchy-settings-dev from different commits, which is exactly the skew the
# release pair's lockstep guard exists to prevent. Restore the packages that
# moved and count the group as failed; the next run tries again.
declare -A BEFORE_SYNC=()
snapshot_package() {
local package="$1" pkgbuild="$PKGBUILDS_DIR/$1/PKGBUILD"
[[ -f "$pkgbuild" ]] || return 0
mkdir -p "$TEMP_DIR/before"
cp "$pkgbuild" "$TEMP_DIR/before/$package"
BEFORE_SYNC["$package"]=1
}
branch_watch_key() {
local package_dir="$1"
jq -r '
(.upstream.watch? | objects | select(has("git_branch")))
| "\(.git_branch)#\(.branch)"
' "$package_dir/.omarchy/package.json" 2>/dev/null
}
enforce_branch_lockstep() {
local package key
declare -A groups=()
for package in "${!BEFORE_SYNC[@]}"; do
key=$(branch_watch_key "$PKGBUILDS_DIR/$package")
[[ -n "$key" ]] || continue
groups["$key"]+="$package "
done
for key in "${!groups[@]}"; do
local members commits pin
read -r -a members <<<"${groups[$key]}"
(( ${#members[@]} > 1 )) || continue
commits=$(for package in "${members[@]}"; do
pin=$(grep -m1 -E '^_commit=' "$PKGBUILDS_DIR/$package/PKGBUILD" | cut -d= -f2- | tr -d "\"'" || true)
printf '%s\n' "${pin:-missing:$package}"
done | sort -u | grep -c .)
(( commits > 1 )) || continue
print_error "Lockstep violation on $key: ${members[*]} pin different commits; restoring all of them"
for package in "${members[@]}"; do
if ! cmp -s "$TEMP_DIR/before/$package" "$PKGBUILDS_DIR/$package/PKGBUILD"; then
cp "$TEMP_DIR/before/$package" "$PKGBUILDS_DIR/$package/PKGBUILD"
# Not ((--UPDATED)): an arithmetic command that evaluates to zero
# returns 1, and under errexit that would end the run right here.
UPDATED=$((UPDATED > 0 ? UPDATED - 1 : 0))
fi
done
((++FAILED))
done
}
sync_in_lane() {
local package="$1" package_dir="$PKGBUILDS_DIR/$1"
snapshot_package "$package"
if [[ -d "$package_dir" ]] && ! package_in_lane "$package_dir" "$LANE"; then
print_info "Skipping $package: not in the $LANE lane"
((++SKIPPED))
return 0
fi
sync_package "$package"
}
if [[ ${#SPECIFIC_PACKAGES[@]} -gt 0 ]]; then
SPECIFIC_MODE=true
# A targeted run is still a branch update: include every sibling watching
# the same branch, otherwise the lockstep check never sees the omitted one.
declare -A selected=() selected_branches=()
for package in "${SPECIFIC_PACKAGES[@]}"; do
sync_package "$package"
selected["$package"]=1
key=$(branch_watch_key "$PKGBUILDS_DIR/$package" || true)
[[ -z "$key" ]] || selected_branches["$key"]=1
done
for package_dir in "$PKGBUILDS_DIR"/*; do
[[ -f "$package_dir/PKGBUILD" ]] || continue
package=${package_dir##*/}
[[ -z "${selected[$package]:-}" ]] || continue
key=$(branch_watch_key "$package_dir" || true)
if [[ -n "$key" && -n "${selected_branches[$key]:-}" ]]; then
SPECIFIC_PACKAGES+=("$package")
fi
done
for package in "${SPECIFIC_PACKAGES[@]}"; do
sync_in_lane "$package"
done
else
while IFS= read -r package; do
sync_package "$package"
sync_in_lane "$package"
done < <(packages_for_upstream_sync)
fi
enforce_branch_lockstep
echo ""
if [[ $FAILED -gt 0 ]]; then
+7 -3
View File
@@ -6,8 +6,9 @@ signing on merge exactly as before.
## Pieces
- `.github/workflows/build-pr.yml` — on a PR touching `pkgbuilds/**`, one job
per changed package on runners labelled `omarchy-builder`. Uploads the
unsigned `.pkg.tar.zst` as a workflow artifact (7 days).
per changed package on runners labelled `omarchy-builder`. aarch64 jobs
run on GitHub's native `ubuntu-24.04-arm` runners instead. Uploads the unsigned
`.pkg.tar.zst` as a workflow artifact (7 days).
- `runner-cloud-init.yaml` — Ubuntu 24.04 user-data: docker + buildx, the
GitHub runner registered `--ephemeral`, runs one job, powers off.
- `controller.sh` — systemd timer every minute on a small always-on droplet.
@@ -67,7 +68,10 @@ Watch it with `journalctl -u omarchy-controller -f` on the box.
- Publish is incremental and immutable: pull the channel db, refuse
different bytes under an existing name, accept identical bytes, upload
packages then signatures then the db.
- aarch64 under QEMU with credential-preserving binfmt.
- aarch64 under QEMU with credential-preserving binfmt. PR builds now run
aarch64 natively on `ubuntu-24.04-arm` (QEMU was up to ~15x slower). When a
merged aarch64 tree has no artifact, publish.yml rebuilds it there too, in its
own job, and signs and uploads it on the droplet like a PR artifact.
- Vouch gate: collaborators, `.github/VOUCHED.td`, or the `build-approved`
label; denounced authors cannot be overridden by the label.
- Tests run on PRs only; `result`, `self-tests`, `build-isolation` are the
+59 -2
View File
@@ -48,8 +48,63 @@ pkgrel to 1, but the complete epoch:pkgver-pkgrel must still increase.
GitHub releases exclude drafts and prereleases unless `allow_prerelease` is true.
Existing `min_release_age` policies apply: a feed without a verifiable publication
time cannot bypass a configured hold. Git branch watches derive a commit count
and date from the actual branch history and write an immutable source pin.
time cannot bypass a configured hold.
## Branch watches
A `git_branch` watch treats every commit on a branch as a release and writes an
immutable pin (`"_commit": "{commit}"`) so the recipe never carries a moving
`#branch=` source; `tests/pinned-sources.sh` enforces that. The clone is bare,
blobless and single-branch, read only with git, and shared by every package
that watches the same branch in one run, so two recipes pinned from it always
see the same commit. Values available to `version`:
- `{date}` (default), `{count}` (commits on the branch), `{commit}`
(`{commit:.7}` for the short form)
- with `tag_pattern` (a regular expression with a named `version` group,
matched against whole tags): `{tag}`, `{version}` from that tag, and
`{distance}`, the number of commits past it. Only tags in the pinned
commit's own history count, so a release cut on another branch is ignored.
`{version}.r{distance}.g{commit:.7}` gives `1.21.0.r15.gabc1234`, which pacman
orders above the `1.21.0` release it follows and below `1.21.1`; `omasnap-git`
uses it. The Omarchy dev pair uses `{version}.r{count}.g{commit:.7}` instead
because its published history counted every commit and the number must never
go down.
`min_release_age` holds a branch tip until its commit timestamp is old enough.
A fresh tip leaves the existing pin alone; the watch never walks backward to
an older commit. This uses Git's committer date, not the time a commit was
pushed. `BYPASS_MIN_RELEASE_AGE=1` bypasses the hold.
Packages marked `"auto_merge": true` ride the unattended lane
(`track-branches.yml`) instead of the reviewed sync PR: their bump PR is opened
and auto-merged as soon as the build checks pass. `bin/sync-upstream --lane
reviewed|auto-merge|all` selects a lane; the scheduled workflows each pass their
own. Packages that pin the same branch move in lockstep: if one of them fails
to update, the run restores the others and reports the group as failed. A
targeted sync includes the other packages watching that branch, so requesting
only `omarchy-dev` also updates `omarchy-settings-dev`.
### Enable unattended branch updates
The schedule already runs in GitHub Actions; no server cron job is needed.
It uses a personal access token so its PRs trigger builds and its merges trigger
publishing without manual approval. No GitHub App is required.
1. Use a fine-grained PAT with access to **omacom/omarchy-pkgs** and repository
**Contents: Read and write** and **Pull requests: Read and write** permissions.
Its owner must be trusted by the build workflow (for example, a collaborator).
The existing controller PAT can be reused when it has these permissions.
2. In the repository's
[Actions secrets](https://github.com/omacom/omarchy-pkgs/settings/secrets/actions),
save the PAT as `PKGS_BOT_TOKEN`. Update this secret when the token is rotated
or expires. The built-in Actions `GITHUB_TOKEN` cannot run this unattended chain.
3. Keep **Allow auto-merge** enabled and require `result`, `self-tests`, and
`build-isolation` on `master`; the tracker does not request a protection bypass.
4. After merging the tracker, run **Track upstream branches** once from Actions
to verify that its PR builds, auto-merges, and starts **Publish merged packages**.
Subsequent runs happen every two hours.
Checksums retain their algorithms (SHA256, SHA512, BLAKE2, etc.) and source order.
Changed git sources are hashed with makepkg's git-archive convention. Unchanged
@@ -131,6 +186,8 @@ in `origin` and has no effect on release selection.
| `localsend` | github | [localsend/localsend](https://github.com/localsend/localsend) |
| `localsend-bin` | github | [localsend/localsend](https://github.com/localsend/localsend) |
| `macbook12-spi-driver-dkms` | git_branch | [https://github.com/marc-git/macbook12-spi-driver.git](https://github.com/marc-git/macbook12-spi-driver.git) |
| `omarchy-dev`, `omarchy-settings-dev` | git_branch (auto-merge) | [https://github.com/basecamp/omarchy.git](https://github.com/basecamp/omarchy.git) `quattro` |
| `omasnap-git` | git_branch (auto-merge) | [https://github.com/omacom/omasnap.git](https://github.com/omacom/omasnap.git) `main` |
| `makima-bin` | github | [cyber-sushi/makima](https://github.com/cyber-sushi/makima) |
| `minecraft-launcher` | archive | [https://launcher.mojang.com/download/Minecraft.deb](https://launcher.mojang.com/download/Minecraft.deb) |
| `nautilus-dropbox` | github | [dropbox/nautilus-dropbox](https://github.com/dropbox/nautilus-dropbox) |
+35
View File
@@ -13,6 +13,7 @@
# { "source": "local", "channels": ["edge"] }
# { "source": "local", "channels": ["edge", "rc", "stable"] }
# { "source": "local", "min_release_age": "24h" }
# { "source": "local", "auto_merge": true, "upstream": { "watch": { "git_branch": "...", "branch": "main" } } }
# { "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"] } } }
@@ -327,6 +328,31 @@ packages_for_upstream_sync() {
done
}
# Upstream updates travel in one of two lanes. The reviewed lane is the
# 6-hourly sync PR a maintainer reads before merging. A package that marks
# "auto_merge": true rides the unattended lane instead: its bump PR is opened
# and auto-merged by the branch tracker as soon as CI is green, which is how a
# package that follows a moving branch (omarchy-dev, omasnap-git) gets rebuilt
# without anyone clicking. The lanes are disjoint so a branch tip can never
# hold up a reviewed vendor release, or the other way round.
package_auto_merge() {
local pkgdir="$1" metadata
metadata=$(metadata_file_for_dir "$pkgdir")
[[ -f "$metadata" ]] || return 1
[[ "$(jq -r 'if has("auto_merge") then .auto_merge else false end' "$metadata")" == "true" ]]
}
# package_in_lane <pkgdir> <reviewed|auto-merge|all>
package_in_lane() {
local pkgdir="$1" lane="$2"
case "$lane" in
all | "") return 0 ;;
auto-merge) package_auto_merge "$pkgdir" ;;
reviewed) ! package_auto_merge "$pkgdir" ;;
*) echo "invalid lane: $lane (expected reviewed, auto-merge, or all)" >&2; return 2 ;;
esac
}
# Packages that must be rebuilt when a dependency they link against changes,
# even though nothing in their own source moved. `rebuild_on` names those
# dependencies; `rebuilt_against` records the versions the checked-in pkgrel was
@@ -514,6 +540,15 @@ validate_package_metadata() {
return 1
fi
if ! jq -e 'if has("auto_merge") | not then true else (.auto_merge | type) == "boolean" end' "$metadata" >/dev/null; then
echo "invalid auto_merge for $(basename "$pkgdir"): must be boolean"
return 1
fi
if package_auto_merge "$pkgdir" && ! package_has_upstream_provider "$pkgdir" && ! package_has_upstream_hook "$pkgdir"; then
echo "invalid auto_merge for $(basename "$pkgdir"): only an upstream watch, provider, or hook can be auto-merged"
return 1
fi
# `has` rather than `// {}`: jq's // treats false as absent, which would
# let "upstream": false slip through as an empty declaration.
if ! jq -e '
+64 -9
View File
@@ -82,7 +82,7 @@ def validate(watch):
allowed = PROVIDERS | {"pattern", "path", "package", "branch", "variables", "fields",
"submodules", "allow_prerelease", "unescape_json", "filenames",
"sequence", "version", "revision", "revision_variable",
"mutable_sources", "member", "dist_tag"}
"mutable_sources", "member", "dist_tag", "tag_pattern"}
if watch.keys() - allowed:
raise ValueError(f"unknown watch fields: {sorted(watch.keys() - allowed)}")
value = watch[provider]
@@ -113,6 +113,18 @@ def validate(watch):
if not isinstance(branch, str) or not branch or branch.startswith("-"):
raise ValueError("git branch watch needs an explicit branch")
run(["git", "check-ref-format", "refs/heads/" + branch])
# A branch watch whose version template names a tag needs to know
# which tags count as releases; anything else is an untagged branch.
if "tag_pattern" in watch:
if not isinstance(watch["tag_pattern"], str) or not watch["tag_pattern"]:
raise ValueError("watch.tag_pattern must be a regular expression string")
if "version" not in re.compile(watch["tag_pattern"]).groupindex:
raise ValueError("tag_pattern needs a named version group")
template = watch.get("version", "{version}")
if any(field in template for field in ("{tag", "{distance")) and "tag_pattern" not in watch:
raise ValueError("a version built from {tag}/{distance} needs a tag_pattern")
elif "tag_pattern" in watch:
raise ValueError("tag_pattern only applies to git_branch watches")
for field in ("variables", "submodules", "fields"):
mapping = watch.get(field, {})
if not isinstance(mapping, dict):
@@ -172,6 +184,53 @@ def matches(watch, text, extra=None, full=False):
yield candidate(watch, {**(extra or {}), **match.groupdict()})
def git_branch_tip(url, branch, tag_pattern, cache):
"""Describe the current tip of an upstream branch:
commit, total count, date, and with a tag_pattern
the newest release tag reachable from it plus the distance from that tag,
so a branch build can be versioned <tag>.r<n>.g<sha>, above the release it
follows and below the next one, the way a pkgver() function would.
One blobless single-branch clone per (url, branch) per run, shared by
every package that tracks it, so two recipes pinned from one clone always
see the same commit. The clone is read with git only; nothing in it runs.
select_release applies the age hold to this tip, without walking back
into history (which could select a commit from a merged side branch).
"""
https(url)
key = hashlib.sha256(f"{url}#{branch}".encode()).hexdigest()
work = Path(cache) / f"{key}.branch.git"
if not work.exists():
scratch = work.with_name(f"{work.name}.{os.getpid()}.tmp")
subprocess.run(["git", "clone", "--quiet", "--bare", "--filter=blob:none", "--single-branch", "--branch", branch, url, str(scratch)], check=True)
scratch.replace(work)
git = ["git", "-C", str(work)]
commit = run([*git, "rev-parse", "HEAD"], text=True).strip()
if not re.fullmatch(r"[0-9a-f]{40}", commit):
raise ValueError("branch tip is not a commit")
count = run([*git, "rev-list", "--count", commit], text=True).strip()
date = run([*git, "show", "-s", "--format=%cs", commit], text=True).strip().replace("-", "")
timestamp = run([*git, "show", "-s", "--format=%cI", commit], text=True).strip()
values = {"version": date, "date": date, "count": count, "commit": commit, "published_at": timestamp}
if tag_pattern:
pattern = re.compile(tag_pattern)
best = None
# Only tags in this commit's history count; a release cut on another
# branch is not something this branch is "past".
for tag in run([*git, "tag", "--merged", commit], text=True).split():
match = pattern.fullmatch(tag)
if not match:
continue
version = match.group("version")
if best is None or vercmp(version, best[0]) > 0:
best = (version, tag)
if best is None:
raise ValueError(f"no tag on {branch} matches {tag_pattern}")
distance = run([*git, "rev-list", "--count", f"{best[1]}..{commit}"], text=True).strip()
values.update({"tag": best[1], "version": best[0], "distance": distance})
return values
def discover(watch, fetch):
provider = validate(watch)
feed = watch[provider]
@@ -199,13 +258,8 @@ def discover(watch, fetch):
for tag, commit in tags.items():
results.extend(matches(watch, tag, {"tag": tag, "commit": commit}, full=True))
elif provider == "git_branch":
with tempfile.TemporaryDirectory(prefix="upstream-git-") as work:
subprocess.run(["git", "clone", "--quiet", "--bare", "--filter=blob:none", "--single-branch", "--branch", watch["branch"], feed, work], check=True)
commit = run(["git", "-C", work, "rev-parse", "HEAD"], text=True).strip()
count = run(["git", "-C", work, "rev-list", "--count", "HEAD"], text=True).strip()
date = run(["git", "-C", work, "show", "-s", "--format=%cs", "HEAD"], text=True).strip().replace("-", "")
timestamp = run(["git", "-C", work, "show", "-s", "--format=%cI", "HEAD"], text=True).strip()
results.append(candidate(watch, {"version": date, "date": date, "count": count, "commit": commit, "published_at": timestamp}))
tip = git_branch_tip(feed, watch["branch"], watch.get("tag_pattern"), fetch.cache)
results.append(candidate(watch, tip))
elif provider == "npm":
data = fetch.json("https://registry.npmjs.org/" + quote(feed, safe=""))
version = data["dist-tags"][watch.get("dist_tag", "latest")]
@@ -479,7 +533,8 @@ def sync(package, fetch, min_age=0, check=False):
path = package / "PKGBUILD"
original = path.read_text()
before = read_recipe(path)
release = select_release(discover(watch, fetch), min_age, bypass=os.environ.get("BYPASS_MIN_RELEASE_AGE") == "1")
bypass = os.environ.get("BYPASS_MIN_RELEASE_AGE") == "1"
release = select_release(discover(watch, fetch), min_age, bypass=bypass)
if release is None:
return {"status": "skipped", "reason": "minimum release age"}
current = scalar(before, "pkgver")
+5 -7
View File
@@ -1,6 +1,6 @@
pkgname=1password-beta
_tarver=8.12.38-25.BETA
_tarver=8.12.40-23.BETA
case "${CARCH}" in
x86_64)
_archdir="x64"
@@ -9,8 +9,8 @@ case "${CARCH}" in
_archdir="arm64"
;;
esac
pkgver=8.12.38_25.BETA
pkgrel=25.2
pkgver=8.12.40_23.BETA
pkgrel=1
conflicts=('1password' '1password-beta-bin')
pkgdesc="Password manager and secure wallet"
arch=('x86_64' 'aarch64')
@@ -22,10 +22,8 @@ source=()
sha256sums=()
source_x86_64=(https://downloads.1password.com/linux/tar/beta/x86_64/1password-${_tarver}.x64.tar.gz{,.sig})
source_aarch64=(https://downloads.1password.com/linux/tar/beta/aarch64/1password-${_tarver}.arm64.tar.gz{,.sig})
sha256sums_x86_64=('c6d302a2c7404a7ded34a3c4f1c401a43eafeed8b147d128dcb416284c2c2b71'
'cc0f00054749c32d77fba31a12a8dece812e409f4b9d81850d2f9b50fab55dca')
sha256sums_aarch64=('1fd62cd0df90098dd5e50d22e9a6c0a5221f9db6355b7c848db7af7076b395fd'
'4d273b71ab987dcadad9e4fa7cfac7e0173dc4dbe7908c9a3e76af274313dd76')
sha256sums_x86_64=('dc1e21c2a6589dacbbb6d56901fdf2bc8c294fd18766a299aca8b84d9f396dcb' 'df3042ed9e897f32888a51447cf0bc977eef130954e7e34f203d96ab036f995a')
sha256sums_aarch64=('a1153234abe0f9b7ccbf2d713be548cfd3a66e9fc487efbc42a72fd2d9e6dbbf' 'ae3c9954fcf43b08f50a4ef6429311c80b2605d321fade6643aa1a28a61c0a2a')
validpgpkeys=('3FEF9748469ADBE15DA7CA80AC2D62742012EA22')
package() {
+3 -3
View File
@@ -4,7 +4,7 @@
# Automation repository: https://github.com/fabifont/claude-code-aur
pkgname=claude-code
pkgver=2.1.278
pkgver=2.1.283
pkgrel=1
pkgdesc="An agentic coding tool that lives in your terminal"
arch=('x86_64' 'aarch64')
@@ -29,8 +29,8 @@ source_x86_64=("claude-${pkgver}-x86_64::https://downloads.claude.ai/claude-code
source_aarch64=("claude-${pkgver}-aarch64::https://downloads.claude.ai/claude-code-releases/${pkgver}/linux-arm64/claude")
sha256sums=('SKIP')
sha256sums_x86_64=('5c4735937844e84f8a93306e841a5b0e12252909b07870f789b190468da147ab')
sha256sums_aarch64=('7de6cab134e48321148e30182c98614118e8f4666819412bead45865190b34ed')
sha256sums_x86_64=('1859583ce32920595c61ef868bee52e1b1594f7486db209935e01f1e5e804ae2')
sha256sums_aarch64=('346d294f0103d6fc0de11ac953579b5c62dfa90698a4cfc486b6f927c615e697')
package() {
install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude"
+3 -3
View File
@@ -6,7 +6,7 @@
# repository's package index.
pkgname=claude-desktop
pkgver=2.2553.1
pkgver=2.7032.0
pkgrel=1
pkgdesc="Official Claude desktop app with Claude Code"
arch=('x86_64' 'aarch64')
@@ -63,8 +63,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}")
source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}")
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
sha256sums=('edfdbc63b65891ef7c481b07086c7e630fc102c042b6ed65331a52fcaf72b14a')
sha256sums_x86_64=('6700fdd84e77a6b8c93912c2f69eb5d1e40fa99bcd9d37f438f809ef2a6fe6f8')
sha256sums_aarch64=('0003a6f9605a210f03c38670d62cd59c71153c2702aa4427e4cabe2e2e5f3390')
sha256sums_x86_64=('1e7f4504bca5b2f6b2d3c4123d145d727647e77f2ee2d046850711e61e7d7b11')
sha256sums_aarch64=('6dca79fa4c8b65267780b5460c627159852e2dfa2ad011d03a0488f7bf226ec3')
package() {
cd "${srcdir}"
+5 -5
View File
@@ -3,7 +3,7 @@
# Maintainer: caarlos0 <carlos@charm.sh>
pkgname='crush-bin'
pkgver=0.96.0
pkgver=0.96.1
pkgrel=1
pkgdesc='A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal.'
url='https://charm.sh/crush'
@@ -13,16 +13,16 @@ provides=('crush')
conflicts=('crush')
source_aarch64=("${pkgname}_${pkgver}_aarch64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_arm64.tar.gz")
sha256sums_aarch64=('667062a39d499506b0fe151148f8d7a1c5cb5722902080d44bb3dd2ddafbf5c1')
sha256sums_aarch64=('4bfe4a37aedeb4219d51eb7a25b837304084070378e77fd578999764b487f01f')
source_armv7h=("${pkgname}_${pkgver}_armv7h.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_armv7.tar.gz")
sha256sums_armv7h=('1de4c1ccb237743e4debb8c302df612fcef5c9b3b5378f5b65c8c6f8bc15cbfa')
sha256sums_armv7h=('e2926383bdf97ab97e52e214fe810570abcff39d00cfe72eaf07eca958f1214c')
source_i686=("${pkgname}_${pkgver}_i686.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_i386.tar.gz")
sha256sums_i686=('4ec66431565de5721afb7afdd99e45ff6bc9c7e667bd18d9696ea7c5622e158d')
sha256sums_i686=('bff753c454b1e9f18d5c3ab4f4395e3e6a505d1a4c033d50653e004647c166c2')
source_x86_64=("${pkgname}_${pkgver}_x86_64.tar.gz::https://github.com/charmbracelet/crush/releases/download/v${pkgver}/crush_${pkgver}_Linux_x86_64.tar.gz")
sha256sums_x86_64=('5b33303a404acacf761c027e9fa9e69d4d2dd050c2690abe40877c49574b7475')
sha256sums_x86_64=('5411b0906a82162dcab4a99071d70accf1caad0eee69789416dd607943c6680d')
package() {
case "$CARCH" in
+3 -3
View File
@@ -18,7 +18,7 @@
# binary to point at pm.sh, a stand-in that declines and names pacman instead.
pkgname=cua-driver-bin
pkgver=0.28.2
pkgver=0.29.1
pkgrel=1
pkgdesc="Computer-use driver for native GUI apps: accessibility-tree snapshots and input injection"
arch=('x86_64' 'aarch64')
@@ -46,8 +46,8 @@ source_x86_64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v$
source_aarch64=("https://github.com/trycua/cua/releases/download/cua-driver-rs-v${pkgver}/cua-driver-rs-${pkgver}-linux-arm64.tar.gz")
sha256sums=('c0779290c1d4783169aa3dbfb55feb505e563ef8a004bbf55298ceffcfbda8d9'
'c76e251c3ed424200eac52bec35ba534336307fabd83a175ab0b47e2084ab0d8')
sha256sums_x86_64=('8f3e5b669e2bcd98d0eecc64f40640aac77f358b6332a06abc6ee79991620f7d')
sha256sums_aarch64=('cadd7e6b757c3ce50f2b5f6e273c154ea48450fb5fcaff744209b382915eddf5')
sha256sums_x86_64=('61a0c0f24d6b03e31bb7a73390db875ecf0de2ce53aa435eadb03d70979d79a5')
sha256sums_aarch64=('47c1efa081057c9c1a18e45b20cb7dd0d7d2313520d18ba7d0d35f271005fe19')
case "${CARCH}" in
x86_64) _platform="linux-x86_64" ;;
+5 -5
View File
@@ -1,8 +1,8 @@
# Maintainer: Gunther Schulz <dev@guntherschulz.de>
pkgname=cursor-bin
pkgver=3.21.16
pkgrel=3
pkgver=3.22.7
pkgrel=1
pkgdesc='AI-first coding environment'
arch=('x86_64' 'aarch64')
url="https://www.cursor.com"
@@ -18,13 +18,13 @@ depends_aarch64=(
libxkbcommon libxrandr mesa nspr nss pango systemd-libs which
)
options=(!strip !debug) # Don't break ext of VSCode
_commit=8ae78e8eee1e63479c7e0504b664bc0a80c6800f
_commit=37076c6c3f9e253c0fa2305197e45befd13a2268
source_x86_64=("https://downloads.cursor.com/production/${_commit}/linux/x64/deb/amd64/deb/cursor_${pkgver}_amd64.deb"
"https://gitlab.archlinux.org/archlinux/packaging/packages/code/-/raw/main/code."{sh,mjs}
rg.sh)
sha512sums_x86_64=('032c86a5d51f154ce36b1a0bf34aa06b2d117666b4372a787ea3117fc0b2b1686e952c721388f2eaf7787f2e0581378c98608048126f7470df2e85e9dbd75ca4' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a')
sha512sums_x86_64=('f061675a7de3552feebda762d6ff5a296035e13527da9405c73e89cde9604137c52a1c8681ef29ad6aeb37b29ad6ab3733fe46e342950850241c91041c6613f8' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a')
source_aarch64=("https://downloads.cursor.com/production/${_commit}/linux/arm64/deb/arm64/deb/cursor_${pkgver}_arm64.deb")
sha512sums_aarch64=('88a163c130e7ee8d9f29b93ccf1258e9f5eb0138d4de5d2333f5bc2992c0a4d0c3a72e8f5912b2e9ac9819a8d758de8e7249cd33bdf3ac631271001ca92700f7')
sha512sums_aarch64=('32d64ef0fdd9f672c374ea33a1d1d6b6b68df3f598f840b33215f5428c491deba1d587b93f4460ffe0f815126b928dd3befed8878b6fe6b3bcd375da8bed1716')
noextract=(cursor_${pkgver}_amd64.deb cursor_${pkgver}_arm64.deb) # avoid double tarball
_app=usr/share/cursor/resources/app
package() {
+3 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: Ismet Togay <ismet.togay at gmail dot com>
# Contributor: Christopher Cooper <christopher@cg505.com>
pkgname=cursor-cli
pkgver=2026.09.18.1.9a7762b
pkgver=2026.09.26.1.dd393fe
# Upstream is YYYY.MM.DD-<hash>. pkgver cannot contain hyphens, and hashes are
# not monotonically ordered, so pkgver is YYYY.MM.DD.<n>.<hash>: n resets to 1
# on a new date and increments when the same date gets a new hash.
@@ -25,8 +25,8 @@ source_x86_64=("cursor-cli-${_upstream_ver}-x86_64.tar.gz::https://downloads.cur
source_aarch64=("cursor-cli-${_upstream_ver}-aarch64.tar.gz::https://downloads.cursor.com/lab/${_upstream_ver}/linux/arm64/agent-cli-package.tar.gz")
b2sums=('d241ee9895bdb1c17514438fde8528222a8f2326568bd7a033d7a1b11432ce6b4575ff1a50625764bfe6bc6f8a9dc060f7439c3be7e95f8fd02912cdd37a011d'
'1928e04c713e13911ea607f84c3e4a2fed1f76af9795503811078f43d2b53c753e28b2233e553fc17e766831800fb0dbc272aad2a80b387f95ba6071d7d4116a')
b2sums_x86_64=('3fccee6929df1042d03461895e56c222a996d3ae9e4f9c61dcc5e6ab7b1d075d3265c21a44f48dd94de0dcde4f8012cc39bfbf323e2bb0c6106cac79885c35ae')
b2sums_aarch64=('3d3bb0a3cb7e2409acf4925f207eaa4e3f41782c3c947e2834b69664b116b972da0b67eea17147fc524ea248af9919494570adc7c48d12c44f12deca17ba2c28')
b2sums_x86_64=('799276ea8ba5dc410ff7e4ae1b9c095bcbaaa7ed6806a78ce249c10dbf9cc523a0ee5402f743e5a5a2cac87be59ffeff7a1b3dbb1ed062932dc300e2e57c9009')
b2sums_aarch64=('417bfda50e13b9848f15ace73fb828632db766b54eb05bd0944bbe14ec49c780f870ea850d67dad40e073692e683436134056e24be5b3287bf8c481d713d9840')
prepare() {
# Block cursor-agent auto-updates by making its versions directory
+4 -4
View File
@@ -2,7 +2,7 @@
_pkgname="dbxcli"
pkgname="${_pkgname}-bin"
pkgver=3.7.3
pkgver=3.7.4
pkgrel=1
pkgdesc="A command line client for Dropbox built using the Go SDK"
arch=(
@@ -33,9 +33,9 @@ source_armv7h=(
source_x86_64=(
"${url}/releases/download/v${pkgver}/${_pkgname}_${pkgver}_linux_amd64.tar.gz"
)
sha256sums_aarch64=('9d654da62a1ac10c9e32ee8f66fa6cc8d88ed29bc95555435a5ce4255eb4b96a')
sha256sums_armv7h=('8067cee274dc2f062a06ceda26200c44d9251336ec235f7d7a3826743c9a379e')
sha256sums_x86_64=('fee977ce4144174356cd7d1bae0b546aecad2570f14666bd44417e96af943484')
sha256sums_aarch64=('c2101af4149ff4104dcfac515c85dedf3a9a3fdff43aac0d650c16df17fcf1f2')
sha256sums_armv7h=('90311a7058ce706e38f6bac06461660308460f59e1c4e5ff5743e62eb3292097')
sha256sums_x86_64=('eb9624bbe2c89287caa5b02ba120bc486d9f4c5ffb5f51d884fc7c40620da730')
prepare() {
local source_array="source_${CARCH}[0]"
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-all
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='elephant + all official elephant providers'
url='https://github.com/abenz1267/elephant'
@@ -12,7 +12,7 @@ makedepends=('go')
conflicts=('elephant' 'elephant-playerctl' 'elephant-wireplumber' 'elephant-bitwarden' 'elephant-dnfpackages' 'elephant-1password' 'elephant-bookmarks' 'elephant-nirisessions' 'elephant-niriactions' 'elephant-archlinuxpkgs' 'elephant-bluetooth' 'elephant-calc' 'elephant-clipboard' 'elephant-desktopapplications' 'elephant-files' 'elephant-menus' 'elephant-providerlist' 'elephant-runner' 'elephant-snippets' 'elephant-symbols' 'elephant-todo' 'elephant-unicode' 'elephant-websearch' 'elephant-windows')
provides=('elephant' 'elephant-playerctl' 'elephant-wireplumber' 'elephant-nirisessions' 'elephant-niriactions' 'elephant-archlinuxpkgs' 'elephant-bluetooth' 'elephant-calc' 'elephant-clipboard' 'elephant-desktopapplications' 'elephant-files' 'elephant-menus' 'elephant-providerlist' 'elephant-runner' 'elephant-snippets' 'elephant-symbols' 'elephant-todo' 'elephant-unicode' 'elephant-websearch' 'elephant-windows')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
# Build main elephant binary
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-archlinuxpkgs
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='archlinuxpkgs provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-archlinuxpkgs')
provides=('elephant-archlinuxpkgs')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/archlinuxpkgs
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-bluetooth
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='bluetooth provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-bluetooth')
provides=('elephant-bluetooth')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/bluetooth
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-calc
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='calc provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -12,7 +12,7 @@ makedepends=('go')
conflicts=('elephant-calc')
provides=('elephant-calc')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/calc
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-clipboard
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='clipboard provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -12,7 +12,7 @@ makedepends=('go')
conflicts=('elephant-clipboard')
provides=('elephant-clipboard')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/clipboard
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-desktopapplications
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='desktopapplications provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-desktopapplications')
provides=('elephant-desktopapplications')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/desktopapplications
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-files
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='files provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -12,7 +12,7 @@ makedepends=('go')
conflicts=('elephant-files')
provides=('elephant-files')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/files
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-menus
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='menus provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-menus')
provides=('elephant-menus')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/menus
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-providerlist
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='providerlist provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-providerlist')
provides=('elephant-providerlist')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/providerlist
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-runner
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='runner provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-runner')
provides=('elephant-runner')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/runner
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-symbols
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='symbols provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-symbols')
provides=('elephant-symbols')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/symbols
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-todo
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='todo provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-todo')
provides=('elephant-todo')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/todo
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-unicode
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='unicode provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-unicode')
provides=('elephant-unicode')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/unicode
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-websearch
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='websearch provider for elephant'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant-websearch')
provides=('elephant-websearch')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/websearch
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant
pkgver=2.22.0
pkgver=2.22.1
pkgrel=1
pkgdesc='general purpose datasource and executor'
url='https://github.com/abenz1267/elephant'
@@ -11,7 +11,7 @@ makedepends=('go')
conflicts=('elephant')
provides=('elephant')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('c6caa61727e4b5c3981099943b4b616c338a6e1b4e33b5e1d32078b8e4dbe120')
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd ${pkgname}-${pkgver}/cmd/elephant
-17
View File
@@ -1,17 +0,0 @@
# elsewhen
Installs the Elsewhen world clock plugin from the `v{pkgver}` GitHub tag archive into `/usr/share/omarchy/shell/plugins/omacom.elsewhen/` (the directory name is the plugin id the shell scans for, not the package name), plus `LICENSE` under `/usr/share/licenses/elsewhen/` and the upstream `README.md` under `/usr/share/doc/elsewhen/`. The shell scans this directory alongside its bundled plugins.
`package()` copies an explicit allow-list (`manifest.json`, every `*.qml` and `*.js`, `cities.json`, `world.json`, `worldclock-data.py`), so `tests/`, `.github/` and `.gitignore` never ship, and it fails the build if `manifest.json` is missing, does not declare `omacom.elsewhen`, or does not name a present `Panel.qml` as the entry point. An upstream release that adds a runtime file outside those patterns needs the allow-list extended here; the sync only moves versions and checksums. Every file is 0644: `Panel.qml` runs the script as `python3 <plugin dir>/worldclock-data.py`, so it needs no execute bit. No install hook: Omarchy restarts the shell after `omarchy update`, and nothing here may write into a user home. The script's only writes go to `$XDG_CACHE_HOME/omacom-elsewhen/`, which it creates itself at runtime.
Dependencies, cited as `file: tool` in the upstream tree:
- `omarchy`: `ArcText.qml`, `Chip.qml`, `EarthRow.qml`, `Globe.qml`, `MiniGlobe.qml`, `MoonDot.qml`, `Panel.qml: import qs.Commons`; `EarthRow.qml`, `Globe.qml`, `Panel.qml: import qs.Ui`. Owns `/usr/share/omarchy` and the shell plugin directory.
- `quickshell`: `Globe.qml`, `Panel.qml: import Quickshell`; `Globe.qml`, `MiniGlobe.qml`, `Panel.qml: import Quickshell.Io` (`Process`, `FileView`, `StdioCollector`).
- `python`: `Panel.qml: python3 <plugin dir>/worldclock-data.py` (the facts process). `worldclock-data.py` imports only `json`, `os`, `sys`, `time`, `urllib`.
- Left implicit as members of `base`, per Arch convention: `bash` (`Panel.qml`, `Globe.qml: bash -c` wraps every probe), `coreutils` (`Panel.qml`, `Globe.qml: date`, one probe per refresh), `systemd` (`Panel.qml: timedatectl show`, `timedatectl list-timezones`, each with a fallback: `/etc/localtime` for the home zone and `find /usr/share/zoneinfo` for the catalog), `sed` and `grep` (`Panel.qml`: the symlink target of `/etc/localtime` and the zoneinfo catalog filter), `findutils` and `tzdata` (that fallback; `worldclock-data.py: /usr/share/zoneinfo/zone1970.tab`). `omarchy` cannot run without any of them either.
- Not a dependency: `iso-codes`. Only `tests/currency_check.py` reads `/usr/share/iso-codes/json`, to validate the currency table before a release; the runtime never touches it.
Release tracking: `bin/sync-upstream` follows `omacom/elsewhen` through the `upstream.watch.github` provider, which reads the GitHub Releases feed (drafts and prereleases excluded; a tag with no published Release is not seen) and matches exactly `vX.Y.Z`, the grammar upstream's `scripts/set-version.sh` enforces. A newer release rewrites `pkgver`, resets `pkgrel` to 1, fetches `archive/refs/tags/v{pkgver}.tar.gz` again and rewrites `sha256sums` from the download. The Release's `published_at` is what lets `min_release_age: 24h` hold a fresh release for a day; `release_ring: fast` builds it straight to rc and stable as well as edge.
The watch only moves on a version increase, so the first release's digest is filled in by hand (`curl -fsSL <archive url> | sha256sum`), which is why the recipe carries a placeholder until the `v0.1.0` tag exists. Until upstream has published at least one Release, the watch finds nothing and fails the scheduled `sync-upstream` run for every package in the batch, so this recipe stays a draft until then.
-11
View File
@@ -1,11 +0,0 @@
{
"source": "local",
"release_ring": "fast",
"min_release_age": "24h",
"upstream": {
"watch": {
"github": "omacom/elsewhen",
"pattern": "v(?P<version>[0-9]+\\.[0-9]+\\.[0-9]+)"
}
}
}
-63
View File
@@ -1,63 +0,0 @@
# Maintainer: Spencer Bull <spencer.bull@hey.com>
pkgname=elsewhen
pkgver=1.0.0
pkgrel=2
pkgdesc='World clock plugin for the Omarchy shell'
arch=('any')
url='https://github.com/omacom/elsewhen'
license=('MIT')
# What the plugin needs to load and run. It also shells out to bash, date
# (coreutils) and timedatectl (systemd) and reads /usr/share/zoneinfo
# (tzdata); those are members of the base group and stay implicit, per Arch
# convention. The citations for each entry are in .omarchy/README.md.
depends=(
'omarchy'
'python'
'quickshell'
)
options=('!debug')
source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('3124f0c0a19ebc1b158bcf04151cddd6c733ceeead88052186b6a54c46bee263')
package() {
# Install alongside the bundled plugins in the shell's plugin directory.
local plugin="$pkgdir/usr/share/omarchy/shell/plugins/omacom.elsewhen"
cd "$srcdir/$pkgname-$pkgver" || return 1
# The shell loads the entry point each manifest declares. A tree without
# either would install cleanly and never load, so fail the build instead of
# shipping it.
[[ -f manifest.json ]] || {
echo "release tree is missing manifest.json" >&2
return 1
}
grep -Eq '"id"[[:space:]]*:[[:space:]]*"omacom\.elsewhen"' manifest.json || {
echo "manifest.json does not declare the plugin id omacom.elsewhen" >&2
return 1
}
grep -Eq '"barWidget"[[:space:]]*:[[:space:]]*"Panel\.qml"' manifest.json || {
echo "manifest.json does not name Panel.qml as the bar widget entry point" >&2
return 1
}
[[ -f Panel.qml ]] || {
echo "release tree is missing the entry point Panel.qml" >&2
return 1
}
# An explicit allow-list of runtime files, so tests/, .github/ and the rest
# of the repository never reach the package. Directories end up 0755 and
# every file 0644: worldclock-data.py runs as `python3 <path>` and needs no
# execute bit. An unmatched glob is left literal and fails install, which
# is the right outcome for a release tree missing its QML or JS.
local file
for file in manifest.json cities.json world.json worldclock-data.py *.qml *.js; do
install -Dm644 "$file" "$plugin/$file"
done
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md"
}
+15 -3
View File
@@ -1,8 +1,8 @@
# Maintainer: GM <gianmarcomorales@icloud.com>
pkgname=flea
pkgver=0.3.1
pkgrel=2
pkgver=0.3.4
pkgrel=1
pkgdesc='Fast, keyboard-first file manager for Omarchy'
arch=('x86_64' 'aarch64')
url='https://github.com/thisisgm/flea'
@@ -52,7 +52,7 @@ options=('!debug')
source=(
"$url/releases/download/v$pkgver/$pkgname-v$pkgver.tar.gz"
)
sha256sums=('b146ac3f5025da987eae623c4392c44ce69a6a7275a8df3ec1a84563920a4dd2')
sha256sums=('e5ad258126ae796d262b51254bfbd4a768416ae4d02da772663e6e24c90cdfe4')
build() {
cd "$pkgname-$pkgver"
@@ -151,6 +151,18 @@ check() {
--skip backend::child::tests::a_child_that_never_started_is_told_apart_from_one_that_ran_and_failed
--skip backend::menu_registry::tests::unavailable_failed_and_oversized_queries_are_named_errors
)
# deep_directory_tree_fits_the_worker_stack sizes a tree 1900 folders
# deep and expects a complete answer, but the listing walk stops at its
# 2000 ms deadline (dirsize::DEADLINE_MS) and reports partial; emulated
# read_dir over paths near PATH_MAX does not finish in time.
# closing_a_query_kills_its_process_group_and_releases_the_service
# cancels an `sh -c 'sleep 600 & wait'` child the moment it is
# registered and waits 5 s for the capture to return. Unchanged since
# 0.3.1, which passed it here; under emulation it now loses that race.
test_args+=(
--skip backend::dirsizeworker::tests::deep_directory_tree_fits_the_worker_stack
--skip backend::menu_registry::tests::closing_a_query_kills_its_process_group_and_releases_the_service
)
fi
local test_tmp test_status=0 suite
+3 -3
View File
@@ -6,7 +6,7 @@ _npmmodule=@github/copilot
pkgname=github-copilot-cli
_pkgexec=copilot
pkgver=1.0.86
pkgver=1.0.88
pkgrel=1
pkgdesc="GitHub Copilot CLI brings the power of Copilot coding agent directly to your terminal."
@@ -31,8 +31,8 @@ source=("https://registry.npmjs.org/${_npmmodule}/-/copilot-${pkgver}.tgz"
noextract=("copilot-${pkgver}.tgz")
sha256sums=(
'4c6433345f08199e96dcf8db1c3e46a337dfab96cea32132d6127ffcd63a6200'
'b94d2aab574cf3e0c8d950e72430186cdd918261a1376146de971fa90ba0a672'
'2ccb1e1d287ddd3c4d74ef02d95ee0151d2d6a3e1fc5e18a3756de211f0d8193'
'782da64fdc6608e595aa03125d4a1fd0a5430f86cdf3c79b22166a5660dc5dff'
)
# Document: https://wiki.archlinux.org/title/Node.js_package_guidelines
+1
View File
@@ -1,5 +1,6 @@
{
"source": "local",
"sync": false,
"release_ring": "fast",
"upstream": {
"git_tags": "https://github.com/hyprwm/Hyprland.git",
+7 -3
View File
@@ -5,7 +5,7 @@
pkgname=(hyprland hyprpm)
pkgver=0.56.2
pkgrel=3
pkgrel=4
pkgdesc='a highly customizable dynamic tiling Wayland compositor'
arch=(aarch64)
url="https://github.com/hyprwm/${pkgname^}"
@@ -65,12 +65,16 @@ optdepends=('hyprpm: build and install plugins'
'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')
source=("$_archive.tar.gz::$url/releases/download/v$pkgver/source-v$pkgver.tar.gz"
software-renderer.patch)
sha256sums=('03ad3f5ef152ff44116ffd56fcf808486211ecabf4f0ba567108ee746ba5cd2e'
'380bb6d61c36d6c68bcccf242131f5b259734e8570ea39b3bc519b9ed137eddd')
prepare() {
ln -sf hyprland-source "$_archive"
cd "$_archive"
# Backport of hyprwm/Hyprland#16343; drop once the packaged release includes it
patch -Np1 --fuzz=0 -i "$srcdir/software-renderer.patch"
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
}
+7
View File
@@ -0,0 +1,7 @@
# Hyprland software-rendering backport
Automatic upstream version bumps are held (`sync: false`) while the packaged release carries [Hyprland #16343](https://github.com/hyprwm/Hyprland/pull/16343) as `software-renderer.patch`. `prepare()` applies that patch with `--fuzz=0`. Hyprland's `release_ring: fast` builds edge, rc, and stable from this recipe. Aquamarine changes in the official/ALARM repositories are checked by the separate six-hour `sync-rebuilds` job through `rebuild_on`, which proposes a package release bump for rebuilding.
The hold does not require staying on v0.56.2 until #16343 lands. If a newer upstream release does not yet include the fix, update `pkgver`, rebase the patch and refresh its checksum, and test software rendering and accelerated rendering before publishing. Keep `sync: false` while the backport is needed.
Remove `sync: false` and `software-renderer.patch` in the same change once the selected upstream release includes the #16343 behavior. Set `pkgver` to that release, then test software rendering and accelerated rendering before publishing.
@@ -0,0 +1,76 @@
From: Scott Jones <scottajones@gmail.com>
Subject: [PATCH] render: detect software rendering from the GL renderer (0.56.2 backport)
Backport-of: 61d0ff60a7547d49229714a68b7ca9c0b6658727
Backport-of: c3dcabc15ba7b71bd1bcd880e9f543909dd9372d
Upstream-PR: https://github.com/hyprwm/Hyprland/pull/16343
Co-authored-by: Eryk Wieliczko <44800858+erykwieliczko@users.noreply.github.com>
Adapt constructor and logger-context differences against v0.56.2 while
preserving the GL classification behavior. v0.56.2 has no
StringUtils.hpp, so the ASCII case-insensitive matcher lives as a
file-local helper in GLRenderer.cpp. Remove this backport once the
packaged upstream version includes this behavior.
--- a/src/render/GLRenderer.cpp
+++ b/src/render/GLRenderer.cpp
@@ -22,6 +22,7 @@
#include "./gl/GLTexture.hpp"
#include <cstdint>
+#include <string_view>
#include <hyprutils/memory/SharedPtr.hpp>
#include <hyprutils/memory/UniquePtr.hpp>
#include <hyprutils/utils/ScopeGuard.hpp>
@@ -36,7 +37,30 @@ extern "C" {
#include <xf86drm.h>
}
-CHyprGLRenderer::CHyprGLRenderer() : IHyprRenderer(), m_elementRenderer(makeUnique<CGLElementRenderer>()) {}
+// Whether haystack contains needle, ignoring ASCII case only; all other bytes must match exactly.
+static bool containsCaseInsensitive(const std::string_view haystack, const std::string_view needle) {
+ const auto lower = [](const unsigned char c) { return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; };
+
+ for (size_t i = 0; i + needle.size() <= haystack.size(); ++i) {
+ size_t j = 0;
+ while (j < needle.size() && lower(haystack[i + j]) == lower(needle[j]))
+ ++j;
+
+ if (j == needle.size())
+ return true;
+ }
+
+ return false;
+}
+
+CHyprGLRenderer::CHyprGLRenderer() : IHyprRenderer(), m_elementRenderer(makeUnique<CGLElementRenderer>()) {
+ // KMS can be display-only; classify the active GL renderer instead of the DRM driver.
+ g_pHyprOpenGL->makeEGLCurrent();
+ if (const auto* renderer = rc<const char*>(glGetString(GL_RENDERER))) {
+ const std::string_view name{renderer};
+ m_software = containsCaseInsensitive(name, "llvmpipe") || containsCaseInsensitive(name, "softpipe") || containsCaseInsensitive(name, "Software Rasterizer");
+ }
+}
IHyprRenderer::eType CHyprGLRenderer::type() {
return RT_GL;
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -104,8 +104,6 @@ IHyprRenderer::IHyprRenderer() {
m_nvidia = true;
else if (name.contains("i915"))
m_intel = true;
- else if (name.contains("softpipe") || name.contains("Software Rasterizer") || name.contains("llvmpipe"))
- m_software = true;
Log::logger->log(Log::DEBUG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
@@ -126,8 +124,6 @@ IHyprRenderer::IHyprRenderer() {
m_nvidia = true;
else if (name.contains("i915"))
m_intel = true;
- else if (name.contains("softpipe") || name.contains("Software Rasterizer") || name.contains("llvmpipe"))
- m_software = true;
Log::logger->log(Log::DEBUG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor,
DRMV->version_patchlevel, std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Dan Wahlin <dwahlin@gmail.com>
pkgname=learn-omarchy
pkgver=0.2.2
pkgver=0.2.4
pkgrel=1
pkgdesc="Interactive, theme-aware courses for learning Omarchy"
arch=('any')
@@ -25,7 +25,7 @@ optdepends=(
)
options=('!strip')
source=("$pkgname-$pkgver.tar.gz::$url/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz")
sha256sums=('67f14778c2b66d56c1504695b0e11cab603f1a002570abc94b4bae9b0bec6066')
sha256sums=('34e13cb452dbef9104400cfc468dcee84575e511c11f425b69fd6a9b462599e5')
package() {
cd "$srcdir/$pkgname-$pkgver"
+3 -3
View File
@@ -2,8 +2,8 @@
_pkgname="limine-entry-tool"
pkgname="limine-mkinitcpio-hook"
_gradle_version=9.7.1
pkgver=1.39.0
pkgrel=2
pkgver=1.40.0
pkgrel=1
pkgdesc="Install kernels for the Limine bootloader."
arch=('x86_64' 'aarch64')
url="https://gitlab.com/Zesko/limine-entry-tool"
@@ -33,7 +33,7 @@ makedepends=('git')
makedepends_x86_64=('gradle')
backup=(etc/limine-entry-tool.conf)
conflicts=('limine-entry-tool')
sha256sums=('6c4affb6fb6367a1222f7d0c54957a3142781d7894bbf61b1a274bd153e5d869')
sha256sums=('267e0496d863b01903d6b99dae8c222a0ec33c4108a8a5d6e9b38eaa4a4a2edf')
sha256sums_x86_64=('3f4a89de8eaa96f2ed677f09957c7e872cd8467aad3537f8b5394c1b8c4b942e')
sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7'
'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a'
+2 -2
View File
@@ -10,7 +10,7 @@
_auroraver=7.1.12
_aurorarel=2
pkgrel=10
pkgrel=11
# Immutable pin on aurora-silicon/linux (branch aurora-wip). Every bump is a
# PR that moves _commit and the archive checksum; the pinned commit is cold-boot
@@ -38,7 +38,7 @@ source=(
rust-toolchain.toml
)
sha256sums=('6347354537148120fc5448afcb8671a558ce336f731c70690cd88062a903f84d'
'4228006ad9c5fcc2237b91b3fd1f70934d23e6d8bdb012faf5a763e042a6edee'
'e8f3818e6bfa70166dd5caff228a0becfdd5d4f0165b589efa38150fd0b59cc9'
'2a95563bb9f5b216cc3c170a17e9471448bc63a7084bdd67df23d074939b366c')
# Kbuild takes ARCH literally and knows arm64, not aarch64.
+1 -1
View File
@@ -6618,7 +6618,7 @@ CONFIG_TYPEC_UCSI=m
# CONFIG_UCSI_STM32G0 is not set
CONFIG_TYPEC_TPS6598X_CORE=m
CONFIG_TYPEC_TPS6598X=m
# CONFIG_TYPEC_SN201202X is not set
CONFIG_TYPEC_SN201202X=m
# CONFIG_TYPEC_ANX7411 is not set
# CONFIG_TYPEC_RT1719 is not set
# CONFIG_TYPEC_HD3SS3220 is not set
+3 -3
View File
@@ -1,6 +1,6 @@
# Maintainer: Jeff Dickey <releases@mise.jdx.dev>
pkgname=mise-bin
pkgver=2026.9.12
pkgver=2026.9.14
pkgrel=1
pkgdesc="dev tools, env vars, task runner"
arch=('x86_64' 'aarch64')
@@ -14,8 +14,8 @@ provides=('mise')
conflicts=('mise')
source_x86_64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-x64.tar.xz")
source_aarch64=("https://github.com/jdx/mise/releases/download/v${pkgver}/mise-v${pkgver}-linux-arm64.tar.xz")
sha256sums_x86_64=('30c79a0a24d8f0ad80e6c9b11ec54816be2a9b77e7eeae32c1267a5b9d34d3d7')
sha256sums_aarch64=('7bc2a5558b787a33f22e4b5955cfec58871ad3723658418ad3d2cdf5a0e693b9')
sha256sums_x86_64=('849cf8eb77d4ccf1eb9fd87cbd757e863e64bcd8623a8865a651af2a1579dace')
sha256sums_aarch64=('3405d3fe8c1491ace3bfbb76e88b5ddbbbfc2f1495dcaad6455607ec782d2a5d')
package() {
install -Dm755 "${srcdir}/mise/bin/mise" "${pkgdir}/usr/bin/mise"
+10 -1
View File
@@ -1,3 +1,12 @@
{
"source": "local"
"source": "local",
"upstream": {
"git_tags": "https://github.com/omacom/monologue.git",
"tag_pattern": "v{pkgver}",
"sources": {
"any": [
"https://github.com/omacom/monologue/archive/refs/tags/{tag}.tar.gz"
]
}
}
}
+6 -9
View File
@@ -1,8 +1,8 @@
# Maintainer: David Heinemeier Hansson <david@hey.com>
pkgname=monologue
pkgver=0.1.0
pkgrel=3
pkgver=0.2.0
pkgrel=1
pkgdesc='A simple, theme-synced webcam recorder for Omarchy'
arch=('x86_64' 'aarch64')
url='https://github.com/omacom/monologue'
@@ -19,19 +19,16 @@ depends=(
'xdg-desktop-portal'
)
makedepends=('gcc' 'make' 'pkgconf')
optdepends=('omacut: trim recordings directly from Monologue')
# Pin the published source until a tagged release is available.
_commit=23e0844f60feef2f9d2cf2c9d89f13eb0bf5adef
source=("$pkgname-$_commit.tar.gz::$url/archive/$_commit.tar.gz")
sha256sums=('1a04b9e47b29846e9135d110978f7f35c0274f7361729f0b6ac03796499c0ad6')
source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('aef0e8d2d5f978e03d0e3a6c9685b828ff6a128d2dc136cb36e45458cdf62c69')
build() {
cd "$srcdir/$pkgname-$_commit"
cd "$srcdir/$pkgname-$pkgver"
./bin/build
}
package() {
cd "$srcdir/$pkgname-$_commit"
cd "$srcdir/$pkgname-$pkgver"
install -Dm755 build/monologue "$pkgdir/usr/bin/monologue"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
+2 -2
View File
@@ -1,5 +1,5 @@
pkgname=omakade
pkgver=1.10.0
pkgver=1.12.0
pkgrel=1
pkgdesc='A beautiful, local-first game library for Omarchy'
arch=('x86_64' 'aarch64')
@@ -11,7 +11,7 @@ depends=('glib2' 'hicolor-icon-theme' 'libsecret' 'libzip' 'openssl' 'qt6-base'
makedepends=('cmake' 'ninja' 'pkgconf' 'wayland-protocols')
options=('!debug')
source=("$pkgname-$pkgver.tar.gz::https://github.com/btsouth/omakade/releases/download/v$pkgver/$pkgname-$pkgver.tar.gz")
sha256sums=('01a4c1aa35c51aba54f57fd0d4eab4a00a14ca2bd4d1b6163264b8ba6fed5b55')
sha256sums=('712788a432682465040fd3b384f18ce0cc60c8e699410bed63cbecadb8171729')
build() {
cmake -S "$pkgname-$pkgver" -B build -G Ninja \
+17 -1
View File
@@ -1 +1,17 @@
{ "source": "local", "channels": ["edge"] }
{
"source": "local",
"channels": ["edge"],
"auto_merge": true,
"min_release_age": "30m",
"upstream": {
"watch": {
"git_branch": "https://github.com/basecamp/omarchy.git",
"branch": "quattro",
"tag_pattern": "v(?P<version>[0-9]+\\.[0-9]+\\.[0-9]+)",
"version": "{version}.r{count}.g{commit:.7}",
"variables": {
"_commit": "{commit}"
}
}
}
}
+12 -22
View File
@@ -1,9 +1,13 @@
# Maintainer: Ryan Hughes <ryan@omarchy.org>
pkgname='omarchy-dev'
pkgver=4.0.0.r847.g4de185b
pkgver=4.0.0.r6646.gbf44355
pkgrel=1
_pkgver_base=4.0.0
_pkgver_base_tag=v3.8.2
# Pinned by the upstream watch in .omarchy/package.json (bin/sync-upstream):
# every quattro tip becomes a commit pin here, so the package is versioned,
# checksummed and built exactly like a release, just more often. The r-number
# is the branch's total commit count, not the distance from the last tag: the
# published history used the total, and pacman must never see it go down.
_commit=bf44355a985b1bb82cb33df47fc17f765f3b2c4f
pkgdesc='Beautiful, modern, and opinionated Arch Linux by DHH (quattro branch tip)'
# The payload is architecture-independent, but the dependency set is not: the
# boot stack differs per architecture (see depends_x86_64 / depends_aarch64),
@@ -73,30 +77,16 @@ makedepends=(
'git'
)
# Source: quattro branch tip by default; set OMARCHY_SRC=/path/to/checkout
# to build from a local source tree instead (mirrors omarchy-zsh/omarchy-fish DX).
# Source: the pinned quattro commit. Set OMARCHY_SRC=/path/to/checkout to
# build from a local source tree instead (mirrors omarchy-zsh/omarchy-fish DX);
# the arrays are emptied below so nothing is downloaded in that case.
source=("omarchy::git+https://github.com/basecamp/omarchy.git#commit=${_commit}")
sha256sums=('7a90239fd67124279817d614fa6aa19554f40796c523ba698669fbf57fa41668')
if [[ -n "${OMARCHY_SRC:-}" ]]; then
source=()
sha256sums=()
else
source=("omarchy::git+https://github.com/basecamp/omarchy.git#branch=quattro")
sha256sums=('SKIP')
fi
pkgver() {
cd "$srcdir/omarchy"
local commit_count commit_hash
if git rev-parse --verify "${_pkgver_base_tag}^{commit}" >/dev/null 2>&1; then
commit_count=$(git rev-list --count "${_pkgver_base_tag}..HEAD")
else
commit_count=$(git rev-list --count HEAD)
fi
commit_hash=$(git rev-parse --short=7 HEAD)
printf "%s.r%s.g%s" "$_pkgver_base" "$commit_count" "$commit_hash"
}
prepare() {
if [[ -n "${OMARCHY_SRC:-}" ]]; then
rm -rf "$srcdir/omarchy"
+9 -6
View File
@@ -7,8 +7,8 @@ pkgname=omarchy-mac-boot
# pkgver is the UTC commit date of _commit, so it sorts above the fork's
# 20260921-N. Reset pkgrel to 1 when pkgver changes; bump it to re-pin or
# rebuild on the same day.
pkgver=20260925
pkgrel=4
pkgver=20260927
pkgrel=1
pkgdesc='Apple Silicon boot support for Omarchy: initramfs, in-place encryption, first boot and Limine activation'
arch=('aarch64')
groups=('omarchy-platform-apple-silicon')
@@ -20,20 +20,23 @@ conflicts=('omarchy-apple-boot' 'omarchy-first-boot')
replaces=('omarchy-apple-boot' 'omarchy-first-boot')
install=omarchy-mac-boot.install
# An exact omarchy-mac commit, never a branch.
_commit=84352fdb8fd03d149682ac54466b1a1add176f84
_commit=ff7ce0d4dfaea9e17270b3061e642ee095b7b265
source=("omarchy-mac::git+https://github.com/omacom/omarchy-mac.git#commit=${_commit}")
sha256sums=('06514d03eef7e8468277ae97c3258bc595f307aa0cf3356d3f71cfb6b0d14fe2')
sha256sums=('7530c284cd323d451540205c0a677c4e187070f0b8c4081a2e85f487f2ebb985')
prepare() {
# Tests and staging must not be able to read the surrounding desktop source.
# Staging must not be able to read the surrounding desktop source.
rm -rf "$srcdir/boot"
cp -a "$srcdir/omarchy-mac/packages/omarchy-mac/boot" "$srcdir/boot"
[[ $(git -C "$srcdir/omarchy-mac" rev-parse HEAD) == "$_commit" ]]
[[ $(TZ=UTC0 git -C "$srcdir/omarchy-mac" show -s --format=%cd --date=format-local:%Y%m%d HEAD) == "$pkgver" ]]
}
# The tests run in the checkout: some compare the payload with the desktop
# source around it (the HOOKS baseline in etc/, the first-run user units and the
# default package lists, from omacom/omarchy-mac#582 and #598).
check() {
"$srcdir/boot/test/all"
"$srcdir/omarchy-mac/packages/omarchy-mac/boot/test/all"
}
package() {
+4 -1
View File
@@ -1,6 +1,6 @@
# omarchy-mac-boot
Apple Silicon boot support for Omarchy: the Mac mkinitcpio drop-ins and initcpio hooks, in-place LUKS conversion in the initramfs, vendor firmware in early boot, first boot of a Mac image, the Limine activation gate and the boot check. The source is `packages/omarchy-mac/boot/` in omacom/omarchy-mac, with its own tests. The recipe pins an exact omarchy-mac commit, copies that directory away from the surrounding desktop tree in `prepare()`, runs its `test/all` in `check()` and stages the package with its `install` script. The recipe itself holds only metadata, `backup=` and the pacman scriptlet.
Apple Silicon boot support for Omarchy: the Mac mkinitcpio drop-ins and initcpio hooks, in-place LUKS conversion in the initramfs, vendor firmware in early boot, first boot of a Mac image, the Limine activation gate and the boot check. The source is `packages/omarchy-mac/boot/` in omacom/omarchy-mac, with its own tests. The recipe pins an exact omarchy-mac commit, copies that directory away from the surrounding desktop tree in `prepare()` and stages the package from the copy with its `install` script. `check()` runs its `test/all` in the full checkout instead, because some tests compare the payload with the desktop source around it (omacom/omarchy-mac#582 and #598). The recipe itself holds only metadata, `backup=` and the pacman scriptlet.
It follows the fork recipe in maralcbr/omarchy-pkgs (`asahi-quattro`, `pkgbuilds/omarchy-mac-boot` at 20260921-10), which carried the payload as files in the recipe.
@@ -21,6 +21,8 @@ A new pin publishes on merge, so check what the pinned source needs first:
- **Settings baseline.** A pin that includes omacom/omarchy-mac#544 (no `93-omarchy-mac-plymouth.conf`) needs omarchy-settings with the HOOKS baseline (omacom/omarchy-mac#542) published on aarch64, and providing `omarchy-mkinitcpio-hooks-baseline`. Publish that first; otherwise this build cannot be installed.
- **Update verification.** A pin that includes omacom/omarchy-mac#543 (`/usr/lib/omarchy/mac-boot/update-verify`) must publish before any runtime that carries #543. Otherwise that runtime blocks every update on Macs whose `omarchy-mac-boot` predates it.
- **Reset and key-slot entrypoints.** A pin that includes omacom/omarchy-mac#552 (`reset-prepare`, `reset-verify`, `reset-commit`, `reset-rollback`) and #553 (`luks-slots`) must publish before any runtime that carries them. That runtime's `omarchy-lifecycle-dispatch` requires them on Apple Silicon, so otherwise factory reset, owner setup and `omarchy-drive-password` on the system disk fail on Macs whose `omarchy-mac-boot` predates them.
- **Reset first-boot markers.** A pin that includes omacom/omarchy-mac#579 (`reset-prepare` clears the factory root's first-boot state and arms `mac-first-boot/pending`) must publish before any runtime that carries #579's `omarchy-system-factory-reset`, which no longer does that inline. Otherwise a factory reset on a Mac whose `omarchy-mac-boot` predates it leaves the factory root without the Mac's first boot, and so without its package keyring, or with an older image's conversion token. A newer boot package with an older runtime is safe: the steps are idempotent.
- **Speaker safety owner.** A pin that includes omacom/omarchy-mac#567 no longer presets or enables `speakersafetyd`; `omarchy-mac` owns it from omacom/omarchy-mac#535. Re-pin `omarchy-mac` at or past #535 in the same merge as that pin, or publish it first. Edge `omarchy-mac` 0.1.0-5 (b4a79d83d) predates #535 and ships no preset for it, so with only the boot package re-pinned a `systemctl preset-all` on an edge Mac disables the speaker amps' safety daemon, and an image built from edge fails its image check.
## Transition
@@ -35,3 +37,4 @@ Updates are reviewed pins, never a branch:
1. Set `_commit` to the full omarchy-mac SHA and `pkgver` to its UTC commit date (`TZ=UTC0 git show -s --format=%cd --date=format-local:%Y%m%d <sha>`); `prepare()` checks both.
2. Reset `pkgrel` to 1 when `pkgver` changes; bump it for a second pin on the same date or a rebuild.
3. Refresh `sha256sums` with `makepkg -g`.
4. Check the pin against [Publish order](#publish-order). Before the first pin that includes omacom/omarchy-mac#567 publishes, `omarchy-mac` must be published at or past #535, or re-pinned in the same pull request.
+6 -4
View File
@@ -5,17 +5,18 @@ pkgname=omarchy-mac
# pkgver matches packages/omarchy-mac/version at _commit. Bump pkgrel to re-pin
# or rebuild the same add-on version; reset it to 1 when pkgver increases.
pkgver=0.1.0
pkgrel=5
pkgrel=6
pkgdesc='Apple Silicon configuration and support services for Omarchy'
arch=('aarch64')
groups=('omarchy-platform-apple-silicon')
url='https://github.com/omacom/omarchy-mac'
license=('MIT')
makedepends=('git' 'findutils')
checkdepends=('diffutils' 'python' 'systemd')
# An exact quattro-upstream commit, never a branch.
_commit=b4a79d83d1144c4de90b29a2d8b4090090d7a9d8
_commit=ff7ce0d4dfaea9e17270b3061e642ee095b7b265
source=("omarchy-mac::git+https://github.com/omacom/omarchy-mac.git#commit=${_commit}")
sha256sums=('93676ce29791a29efe3b098fd8d129fa2248cd32d04253d9520a5b4c0697be6f')
sha256sums=('7530c284cd323d451540205c0a677c4e187070f0b8c4081a2e85f487f2ebb985')
prepare() {
# Tests and staging must not be able to read the surrounding desktop source.
@@ -33,7 +34,8 @@ package() {
# Runtime-only: the builder does not need the Omarchy desktop to stage or
# test the add-on.
depends=('omarchy' 'bash' 'coreutils' 'diffutils' 'grep' 'sed' 'gawk' 'systemd' 'pciutils' 'kmod'
'networkmanager' 'iwd' 'python' 'pipewire' 'pipewire-pulse' 'libpulse' 'wireplumber')
'mkinitcpio' 'networkmanager' 'iwd' 'python' 'pipewire' 'pipewire-pulse' 'libpulse' 'wireplumber'
'asahi-audio' 'alsa-ucm-conf-asahi' 'rtkit' 'pipewire-alsa')
"$srcdir/addon/install" "$pkgdir"
install -Dm644 "$srcdir/addon/README.md" "$pkgdir/usr/share/doc/$pkgname/README.md"
@@ -2,7 +2,7 @@
pkgname=omarchy-meeting-recorder-bin
_name=omarchy-meeting-recorder
pkgver=1.0.2
pkgver=1.4.0
pkgrel=1
pkgdesc="Meeting Recorder for Omarchy: record the mic and the computer audio, transcribed on your own machine with speakers, chapters and a player"
arch=('x86_64')
@@ -16,7 +16,7 @@ conflicts=("$_name")
install="$_name.install"
options=('!debug')
source_x86_64=("$url/releases/download/v$pkgver/$_name-$pkgver-x86_64-linux.tar.gz")
sha256sums_x86_64=('78746ecc90366f12f308801637b98fc5e5b844bb28ba413e50ed3efe5c24079f')
sha256sums_x86_64=('d8358178d11e01f5a34a69839dfcf497dc193163b489107076cd62b34472c639')
package() {
cd "$_name-$pkgver"
@@ -1 +1,17 @@
{ "source": "local", "channels": ["edge"] }
{
"source": "local",
"channels": ["edge"],
"auto_merge": true,
"min_release_age": "30m",
"upstream": {
"watch": {
"git_branch": "https://github.com/basecamp/omarchy.git",
"branch": "quattro",
"tag_pattern": "v(?P<version>[0-9]+\\.[0-9]+\\.[0-9]+)",
"version": "{version}.r{count}.g{commit:.7}",
"variables": {
"_commit": "{commit}"
}
}
}
}
+13 -23
View File
@@ -1,9 +1,13 @@
# Maintainer: Ryan Hughes <ryan@omarchy.org>
pkgname='omarchy-settings-dev'
pkgver=4.0.0.r847.g4de185b
pkgrel=3
_pkgver_base=4.0.0
_pkgver_base_tag=v3.8.2
pkgver=4.0.0.r6646.gbf44355
pkgrel=2
# Pinned by the upstream watch in .omarchy/package.json (bin/sync-upstream):
# every quattro tip becomes a commit pin here, so the package is versioned,
# checksummed and built exactly like a release, just more often. The r-number
# is the branch's total commit count, not the distance from the last tag: the
# published history used the total, and pacman must never see it go down.
_commit=bf44355a985b1bb82cb33df47fc17f765f3b2c4f
pkgdesc='Omarchy user defaults, /etc/skel content, fonts, plymouth theme, and support helpers (quattro branch tip)'
# Arch-specific because the shipped /etc tree is not the same on every
# architecture: the zram and oomd drop-ins belong to the x86_64 memory stack
@@ -113,30 +117,16 @@ _etc_override_paths=(
'etc/plymouth/plymouthd.conf'
)
# Source: quattro branch tip by default; set OMARCHY_SRC=/path/to/checkout
# to build from a local source tree instead (mirrors omarchy-zsh/omarchy-fish DX).
# Source: the pinned quattro commit. Set OMARCHY_SRC=/path/to/checkout to
# build from a local source tree instead (mirrors omarchy-zsh/omarchy-fish DX);
# the arrays are emptied below so nothing is downloaded in that case.
source=("omarchy::git+https://github.com/basecamp/omarchy.git#commit=${_commit}")
sha256sums=('7a90239fd67124279817d614fa6aa19554f40796c523ba698669fbf57fa41668')
if [[ -n "${OMARCHY_SRC:-}" ]]; then
source=()
sha256sums=()
else
source=("omarchy::git+https://github.com/basecamp/omarchy.git#branch=quattro")
sha256sums=('SKIP')
fi
pkgver() {
cd "$srcdir/omarchy"
local commit_count commit_hash
if git rev-parse --verify "${_pkgver_base_tag}^{commit}" >/dev/null 2>&1; then
commit_count=$(git rev-list --count "${_pkgver_base_tag}..HEAD")
else
commit_count=$(git rev-list --count HEAD)
fi
commit_hash=$(git rev-parse --short=7 HEAD)
printf "%s.r%s.g%s" "$_pkgver_base" "$commit_count" "$commit_hash"
}
prepare() {
if [[ -n "${OMARCHY_SRC:-}" ]]; then
rm -rf "$srcdir/omarchy"
@@ -0,0 +1,17 @@
{
"source": "local",
"channels": ["edge"],
"auto_merge": true,
"min_release_age": "30m",
"upstream": {
"watch": {
"git_branch": "https://github.com/omacom/omasnap.git",
"branch": "main",
"tag_pattern": "v(?P<version>[0-9]+\\.[0-9]+\\.[0-9]+)",
"version": "{version}.r{distance}.g{commit:.7}",
"variables": {
"_commit": "{commit}"
}
}
}
}
+72
View File
@@ -0,0 +1,72 @@
# Maintainer: Ryan Hughes <ryan@omarchy.org>
# The main-branch build of omasnap. Pinned by the upstream watch in
# .omarchy/package.json (bin/sync-upstream): every main tip becomes a commit
# pin here, versioned <last tag>.r<commits since>.g<sha> so it sorts above the
# tagged release it follows and below the next one.
pkgname=omasnap-git
pkgver=1.21.0.r76.g614cdf5
pkgrel=1
_commit=614cdf55b42a43c1dcee2c85cd01e4764a52bdae
pkgdesc="Native Wayland screenshot and annotation overlay for Hyprland (main branch)"
arch=('x86_64' 'aarch64')
url="https://github.com/omacom/omasnap"
license=('MIT' 'OFL-1.1')
depends=(
'hyprland'
'layer-shell-qt'
'qt6-base'
'tesseract'
'tesseract-data-eng'
'wayland'
'wl-clipboard'
)
makedepends=(
'cmake'
'git'
'ninja'
'pkgconf'
'wayland-protocols'
)
provides=('omasnap')
conflicts=('omasnap')
options=('!debug')
source=("omasnap::git+$url.git#commit=${_commit}")
sha256sums=('952539c68a81ac373c0f2d5fc084106d3419ee3e5ec2d544d02b510a3f416484')
build() {
cmake -S omasnap -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build --parallel
}
check() {
# The smoke suite fsyncs its working documents under /tmp. On the CI
# droplets the build leaves about a gigabyte of dirty pages, and the
# flush that starts a few seconds into the suite makes those fsyncs stall
# long enough to overrun the suite's 5-second settle windows. Flush first.
local runtime_dir status started
started=$(date +%s%N); sync
echo "flushed dirty pages in $(( ($(date +%s%N) - started) / 1000000 )) ms"
runtime_dir=$(mktemp -d /dev/shm/omasnap-runtime.XXXXXX)
if QT_QPA_PLATFORM=offscreen QT_FORCE_STDERR_LOGGING=1 \
XDG_RUNTIME_DIR="$runtime_dir" \
./build/omasnap-smoke "$srcdir/omasnap-smoke-output"; then
status=0
else
status=$?
echo "omasnap-smoke exited with status $status" >&2
fi
rm -r -- "$runtime_dir"
return "$status"
}
package() {
cmake --install build --prefix "$pkgdir/usr"
install -Dm644 omasnap/README.md \
"$pkgdir/usr/share/doc/omasnap/README.md"
install -Dm644 omasnap/LICENSE \
"$pkgdir/usr/share/licenses/omasnap/LICENSE"
}
+2 -2
View File
@@ -1,5 +1,5 @@
pkgname=omazed
pkgver=2.1.2
pkgver=2.2.0
pkgrel=1
pkgdesc="Live theme switching for Zed in Omarchy - automatically synchronize your Zed editor theme with your Omarchy system theme"
arch=('any')
@@ -10,7 +10,7 @@ makedepends=('git')
backup=()
install=omazed.install
source=("$pkgname-$pkgver.tar.gz::https://github.com/aps6/$pkgname/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('ca0708c86969547b14958a307ae3df89f63d92ffa68af3b5c6bf79c036b8cab9')
sha256sums=('5461f819c039be9f8150ffc1f8045589eda41ce711f95afa961e845b4d28ba02')
package() {
cd "$srcdir/$pkgname-$pkgver"
+3 -3
View File
@@ -2,7 +2,7 @@
# shellcheck disable=SC2034
# Maintainer: Chmouel Boudjnah <chmouel@chmouel.com>
pkgname=openai-codex-bin
pkgver=0.155.1
pkgver=0.157.1
pkgrel=1
pkgdesc="Arch Linux package for OpenAI's Codex CLI - Auto Updated"
arch=('x86_64' 'aarch64')
@@ -21,8 +21,8 @@ source_x86_64=(
"codex-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-x86_64-unknown-linux-musl.tar.gz"
"codex-code-mode-host-${pkgver}-x86_64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-code-mode-host-x86_64-unknown-linux-musl.tar.gz"
)
sha256sums_x86_64=('a0ef8b2debc3bf747e07b1a039354de31300ac0dcc2276498ba281470b5d9115' '9fd083743af55be818aceb351d371fb5136f5b6aa3938f167087373d27067b2d')
sha256sums_aarch64=('d6c7e62fbd688d52ee04f3929d0613705d32a920a42db7a139e366eaf1f4a2d7' '516f2ed76d4ae96c2074d3c08f4576ed1bdc5c3a97e26734d7319de8b6861683')
sha256sums_x86_64=('e98c1e8e028e8137fa2d2415c82ec58e7b3701a627e3554aace5b3ca31454af2' '3516f9b8bbe6bc06ee7bdb92b293a17eab194b3f10b9b9ea10c5b839e972d7fc')
sha256sums_aarch64=('4c6b1c17c1c5fd0d4fb2951b7481867b95ea732b1feab269c98588b15db16253' 'e83742806da98e9a77ad24309ebd1629e8227755a341ad0b428f885c97bb318e')
source_aarch64=(
"codex-${pkgver}-aarch64.tar.gz::https://github.com/openai/codex/releases/download/rust-v${pkgver}/codex-aarch64-unknown-linux-musl.tar.gz"
+3 -3
View File
@@ -5,7 +5,7 @@
# the version and checksums below from that repository's package index.
pkgname=openai-codex-desktop
pkgver=26.915.31945
pkgver=26.924.22138
pkgrel=1
pkgdesc="Official ChatGPT desktop app with Codex"
arch=('x86_64' 'aarch64')
@@ -71,8 +71,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}")
source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}")
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c')
sha256sums_x86_64=('d27a9c02919cfe484dcc5f34584b9ea9fd0d7a65c69dcc872b5bdcfa0efb5983')
sha256sums_aarch64=('b94c494b5f0fd7c720fa6fccd5ef609879affc62332ca930ed29b907d537bc6d')
sha256sums_x86_64=('ce3bb1aa82ccdfe3037ada2fd8d187796ea4a0d5ed031d0e4ec8adce8b7014e7')
sha256sums_aarch64=('6570f078c5ea25461ce103b2e31fa7dd6c5e717136fa9237c701d22db62b5e3f')
package() {
cd "${srcdir}"
+2 -2
View File
@@ -7,7 +7,7 @@
# upstream's release cadence outruns the AUR.
pkgname=openclaw
pkgver=2026.9.5
pkgver=2026.9.6
pkgrel=1
pkgdesc='Multi-channel AI gateway with extensible messaging integrations'
arch=(x86_64 aarch64)
@@ -29,7 +29,7 @@ optdepends=(
'go: for installing skill tools not packaged for Arch'
)
source=($pkgname-$pkgver.tgz::https://registry.npmjs.org/$pkgname/-/$pkgname-$pkgver.tgz)
sha256sums=('1fb6ef4fae447af14f1e3b1028334f39146d181a66a4cce2848d4f741c636340')
sha256sums=('1a7355691bc0e605222ba818f1f72c1787253c78dfeb0df6be2086ec73b71e63')
options=(!debug !strip)
install=$pkgname.install
noextract=($pkgname-$pkgver.tgz)
+2 -2
View File
@@ -1,6 +1,6 @@
# Maintainer: owe contributors
pkgname=owe-lockfeed
pkgver=0.2.6
pkgver=0.2.7
pkgrel=1
pkgdesc="Lock screen video feed module for the OWE wallpaper engine"
arch=('x86_64' 'aarch64')
@@ -9,7 +9,7 @@ license=('MIT')
depends=('qt6-declarative')
makedepends=('cmake' 'qt6-declarative')
source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('e5c10e60bdfaebed861a3b7515c691a5a78fc0fe3ab29c0e96d934eb1a957cf8')
sha256sums=('93c88257111e36537c43a9fb6acc9a6b8fb1f6ba5149444e828d719a02a533cd')
build() {
cmake -S "$srcdir/owe-$pkgver/qml-plugin" -B build \
+13 -3
View File
@@ -1,6 +1,6 @@
# Maintainer: owe contributors
pkgname=owe
pkgver=0.2.6
pkgver=0.2.7
pkgrel=1
pkgdesc="High-performance wallpaper engine for Omarchy (mp4, gif, stills)"
arch=('x86_64' 'aarch64')
@@ -12,7 +12,7 @@ checkdepends=('python')
optdepends=('intel-media-driver: VAAPI hardware decode on Intel GPUs'
'libva-mesa-driver: VAAPI hardware decode on AMD GPUs')
source=("$pkgname-$pkgver.tar.gz::https://github.com/omacom/owe/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('e5c10e60bdfaebed861a3b7515c691a5a78fc0fe3ab29c0e96d934eb1a957cf8')
sha256sums=('93c88257111e36537c43a9fb6acc9a6b8fb1f6ba5149444e828d719a02a533cd')
build() {
meson setup build "$srcdir/owe-$pkgver" -Dbuildtype=release -Dprefix=/usr
@@ -20,7 +20,17 @@ build() {
}
check() {
meson test -C build
# transition's "both outputs show intermediate colors" wants at least three
# blended frames from a 250 ms fade rendered with software GL. aarch64
# builds run under QEMU user-mode emulation, which renders too few frames
# in that window (reproduced 3/3 locally); it passes natively. Run every
# other test there.
local -a tests=()
if [[ $CARCH == aarch64 ]]; then
mapfile -t tests < <(meson test -C build --list | sed 's/^owe://' | grep -vx transition)
(( ${#tests[@]} )) || return 1
fi
meson test -C build "${tests[@]}"
}
package() {
+3 -3
View File
@@ -5,7 +5,7 @@
# from that repository's package index.
pkgname=perplexity
pkgver=26.9.4+build72244
pkgver=26.9.6+build89647
pkgrel=1
pkgdesc="Official Perplexity desktop app"
arch=('x86_64' 'aarch64')
@@ -81,8 +81,8 @@ source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64//+/%2B}")
source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64//+/%2B}")
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
sha256sums=('b180ca6fbd268712a277a34d4215f176001c0031a4f6360686458623f47fad65')
sha256sums_x86_64=('fe64a09a82f8e6b0e3de5637ee768dc5aee94a326af795dce8bcbaf5c7660409')
sha256sums_aarch64=('855330d95401f8e8360f846031ebbefe84bbe0fd9d6ec7814f0e79ef5c4c8bc6')
sha256sums_x86_64=('c08baea924b9591367ec176493d1638d0175a0e48f13373d621bc03273ead9f6')
sha256sums_aarch64=('914b0b39dd8ec4658823c39093c127815fa1e6a7ad2257b03e1ff23b4f9f286e')
package() {
cd "${srcdir}"
+3 -3
View File
@@ -1,6 +1,6 @@
# Maintainer: Infrawrench LLC <astrid@infrawrench.com>
pkgname=schist-bin
pkgver=0.14.0
pkgver=0.15.0
pkgrel=1
# Upstream's own package release, embedded in the asset name. It is
# packages.sh's "release=" and only moves when the packaging changes under
@@ -32,8 +32,8 @@ options=(!strip !debug)
# script.
source_x86_64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-x86_64.pkg.tar.zst")
source_aarch64=("$url/releases/download/v$pkgver/schist-$pkgver-$_relver-aarch64.pkg.tar.zst")
sha256sums_x86_64=('1e7f51ed0141f4573c65296f73d9e7005c897c1b2fb39085f3d6f7f95bbcefbf')
sha256sums_aarch64=('52c0d6810094183ea1dc2248a147e60afae98ce63f0b41975dafa7f63644ef20')
sha256sums_x86_64=('ef4501ecc8109e21d1813fdfc8d618090a9be5bb238545527614a1ff60d983c1')
sha256sums_aarch64=('11e12bd6bc0ee6fb6d27004809750c62a180d64c5eb274a2aac685fdabdeeff1')
package() {
# makepkg has already extracted the payload into srcdir; its .PKGINFO
+31 -5
View File
@@ -1,6 +1,6 @@
pkgname=strata
pkgver=0.19.0
pkgrel=2
pkgver=0.20.1
pkgrel=1
pkgdesc='Fast, keyboard-first file manager for modern Linux desktops'
arch=('x86_64' 'aarch64')
url='https://github.com/lgse/strata'
@@ -30,6 +30,8 @@ depends=(
'xdg-terminal-exec'
)
makedepends=('cargo' 'git' 'glib2-devel' 'pkgconf')
# The example actions' tests convert images with ImageMagick, WebP included.
checkdepends=('imagemagick' 'libwebp')
optdepends=(
'gvfs-smb: browse SMB network shares'
'imagemagick: additional camera RAW preview support'
@@ -39,7 +41,7 @@ conflicts=('strata-git')
options=('!debug' '!lto')
source=("$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('51701930728625ce1d6394949a4b6b2705f0999fd08be87f1a26d900209d62e0')
sha256sums=('cdbe7f196970cbaa1fa41c427833899e35c2dcaa8bb68a864c3afa6428827e2f')
prepare() {
cd "$pkgname-$pkgver"
@@ -87,9 +89,15 @@ check() {
# Run them on tmpfs; other suites execute fixtures, so cannot use noexec /dev/shm.
local search_tmp
search_tmp=$(mktemp -d /dev/shm/strata-tests.XXXXXXXX) || return 1
# rename_refresh_rescores_every_session_sharing_the_index asserts that
# every Results event carries the query it set, but the index worker can
# publish its first walk before query() lands. Natively query() always
# wins; under the QEMU emulation aarch64 builds run in, the worker does.
local -a search_skip=()
[[ $CARCH == aarch64 ]] && search_skip+=(--skip services::search::tests::refresh::rename_refresh_rescores_every_session_sharing_the_index)
local test_status=0
TMPDIR="$search_tmp" cargo test --frozen --release --all-targets --all-features \
services::search::tests:: -- --test-threads=1 || test_status=$?
services::search::tests:: -- --test-threads=1 "${search_skip[@]}" || test_status=$?
rm -rf -- "$search_tmp"
(( test_status == 0 )) || return "$test_status"
@@ -100,13 +108,31 @@ check() {
# Upstream CI runs on Ubuntu, where sh is dash and rejects the number.
# Skip until upstream waits on a real pid.
local skip=(--skip services::search::tests:: --skip ui::settings::tests::restart_waiter_)
# checksum_example_handles_native_names_... hands the SHA-256 example a
# file named with a raw 0xff byte. The action's log() print()s that name,
# and under a UTF-8 locale Python's stdout refuses the surrogate it
# decodes to, so the action dies with UnicodeEncodeError. The builder sets
# LANG=en_US.UTF-8; upstream's test container sets no locale, and in the
# C locale Python's stdout escapes the byte instead. A real
# bug in the example for users with UTF-8 locales; skip until upstream
# logs names with errors="surrogateescape".
skip+=(--skip adapters::local_jobs::tests::examples::checksum_example_handles_native_names_and_refuses_existing_files_and_links)
# ownership_probe_errors_disable_in_place_updates points the pacman path
# at a directory and expects Command::output() to fail. aarch64 builds
# run under QEMU user-mode emulation, where glibc's posix_spawn cannot
# observe the child's failed execve (natively it returns EACCES); the
# spawn "succeeds" with exit 127, the probe reads that as "not owned",
# and the assertion fails. Passes natively.
[[ $CARCH == aarch64 ]] && skip+=(--skip services::update_install::tests::ownership_probe_errors_disable_in_place_updates)
# a_missing_working_directory_fails_instead_of_using_stratas_cwd is the
# same blind spot: the child's failed chdir never reaches the parent.
# in_place_retirement_signals_and_waits_for_an_owned_process finds its
# target by /proc/<pid>/exe, which under QEMU user-mode names the
# emulator rather than `sleep`, so nothing is signalled.
[[ $CARCH == aarch64 ]] && skip+=(
--skip services::update_install::tests::ownership_probe_errors_disable_in_place_updates
--skip adapters::local_jobs::tests::lifecycle::a_missing_working_directory_fails_instead_of_using_stratas_cwd
--skip services::update_install::tests::in_place_retirement_signals_and_waits_for_an_owned_process
)
cargo test --frozen --release --all-targets --all-features \
-- --test-threads=1 "${skip[@]}"
}
+3 -3
View File
@@ -1,7 +1,7 @@
# Maintainer: Manuel Hüsers <aur@huesers.de>
pkgname=sublime-text-4
pkgver=4.4213
pkgver=4.4215
pkgrel=1
pkgdesc='Sophisticated text editor for code, html and prose - stable build'
arch=('x86_64' 'aarch64')
@@ -16,8 +16,8 @@ source_x86_64=("${pkgname//-/_}_${pkgver/./_}_${pkgrel}_x64.tar.xz::https://down
source_aarch64=("${pkgname//-/_}_${pkgver/./_}_${pkgrel}_arm64.tar.xz::https://download.sublimetext.com/sublime_text_build_${pkgver:2}_arm64.tar.xz")
sha512sums=('ac56e9b7dddaebb3d222795cfc644109c93cc3f79695b8f9ee56022c74fe04a1134dd54cab07c74ff1f96b783cb3dbc026c16095552f1d2dd83115ea274dc2e9')
sha512sums_x86_64=('0d222ba954d7f6c5c7b03ce1eff3751e2d92b233058524208eb8e007c347b9a3628b9487e832c3c5599e7d2bcb940407466bd7b000a4e389f9ed916950bd049e')
sha512sums_aarch64=('e2ee9de786d1ca6ef28f6703626be226dc0b15f74a61ca4de58522fa7c9f295c8a38b052463d95878a8930366bf1f5d4740a876c7022e1655c4b906a0a83cef1')
sha512sums_x86_64=('e49d032b4ee3b609913a9d8733f75e910f0b02accf9a77ce34a79bb1967140deaecfcf243989846b9d9e1a6fb09058ebf05676ed0981fac0c5d53ddb612e7d89')
sha512sums_aarch64=('7e4670497be0e731e8afd3115d2152adf40180486c389f624af1ec61d780958b383211e4f14c1010bb18f8ea83b055ab3666a6f526b8ce07cc85cc6967ac0b61')
prepare() {
sed -i -e "s|@ST_PATH@|/opt/sublime_text|g" "${pkgname}.sh"
+20 -23
View File
@@ -36,36 +36,33 @@ public distribution", so the terms themselves may still move.
Nothing in the packaging depends on the answer -- it is a question for the
publisher, and it is recorded here so it is not mistaken for settled.
## The versionless download URL
## Where releases come from
Every TMOG release is served from one path:
Since 1.0.0 the site lives under `/rtm/`, and each Linux artifact is published
under a versioned name with a `.sha256` sidecar beside it:
```text
https://tmog.org/downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz
https://tmog.org/rtm/version.txt
https://tmog.org/rtm/downloads/TaskManagerOG-<version>-linux-x86_64.tar.gz
https://tmog.org/rtm/downloads/TaskManagerOG-<version>-linux-x86_64.tar.gz.sha256
```
Nothing in it identifies a version, and `downloads/release.json` -- the manifest
the macOS updater verifies -- describes the DMG only. So the Linux side has no
manifest to read a checksum out of, and `.omarchy/upstream.sh` computes one from
the artifact. That download is 7.9 MB and happens only when `/version.txt`
reports something other than the checked-in `pkgver`, so the six-hourly check
normally costs a single small request.
`downloads/release.json` -- the manifest the macOS updater verifies -- still
describes the DMG only, so `.omarchy/upstream.sh` reads the version from
`version.txt` and the checksum from the sidecar, and checks that the sidecar
names the tarball it was asked about. The check costs two small requests and
never downloads the tarball.
Two details follow from the path being mutable:
Up to 0.1.1 every release was served from one versionless path,
`/downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz`, and the hook downloaded it
to compute a checksum. That path now returns 404, which is what broke the
upstream sync when 1.0.0 shipped.
- **The `?v=<version>-free` query string** in `source=()` is upstream's own
cache key; tmog.org appends it to its Linux download links for the same
reason, so a CDN holding an older object under this path cannot answer for a
new release.
- **The hook checks the tarball's top-level directory**, which upstream names
`TaskManagerOG-<version>-linux-x86_64`. It is the only evidence available that
the bytes that arrived are the release `/version.txt` announced. On a mismatch
the hook reports no update and leaves the package alone, which is the right
answer whether the cause is a half-published release or a stale object.
`sha256sums` is reported under the key `any` rather than `x86_64`: upstream
publishes no aarch64 build, so the package has one plain `source=()` array, and
`any` is `bin/sync-upstream`'s name for the unsuffixed checksum array.
`sha256sums` is reported under the key `any` rather than `x86_64`: the package
builds x86_64 alone, so it has one plain `source=()` array, and `any` is
`bin/sync-upstream`'s name for the unsuffixed checksum array. Upstream began
publishing an aarch64 tarball (with its own sidecar) at 1.0.0; adding it means
moving to `source_x86_64`/`source_aarch64` and reporting both keys.
## Testing
+18 -30
View File
@@ -1,19 +1,12 @@
#!/bin/bash
# TMOG publishes no manifest for its Linux builds -- release.json describes the
# macOS DMG only -- so the version comes from /version.txt and the checksum has
# to be computed from the artifact itself. That is 8 MB, and only when the
# version has actually moved, so the six-hourly check normally costs one tiny
# request.
#
# The download path carries no version, which makes it worth proving that what
# arrived is what was announced: the tarball's top-level directory is named for
# the release, and a mismatch means the object served is not the one
# /version.txt describes. Reporting no update leaves the checked-in package
# alone and lets the next run try again, which is the right answer whether the
# cause is a half-published release or a stale CDN object.
# macOS DMG only -- so the version comes from /rtm/version.txt. Each Linux
# artifact is published under a versioned name with a `<artifact>.sha256`
# sidecar beside it, and that sidecar is the checksum reported here, so the
# six-hourly check costs two tiny requests and never the tarball itself.
set -euo pipefail
BASE_URL="https://tmog.org"
BASE_URL="https://tmog.org/rtm"
current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'")
@@ -28,27 +21,22 @@ if [[ $version == "$current" ]]; then
exit 0
fi
tarball=$(mktemp)
trap 'rm -f "$tarball"' EXIT
curl -fsSL -o "$tarball" \
"$BASE_URL/downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz?v=${version}-free"
# Every entry is listed rather than just the first: `head -1` would close the
# pipe under `tar` and take the whole hook down with SIGPIPE, and reading them
# all also catches a tarball that unpacks more than one top-level directory.
expected_dir="TaskManagerOG-${version}-linux-x86_64"
served_dir=$(tar tzf "$tarball" | cut -d/ -f1 | sort -u)
if [[ $served_dir != "$expected_dir" ]]; then
echo "Download holds $served_dir, but /version.txt announced $version; skipping" >&2
echo '{}'
exit 0
# The sidecar names the file it describes; insisting on that name catches a
# sidecar left over from another release or architecture. A failed download or
# a file without a trailing newline leaves `read` short, which the check below
# reports rather than letting set -e exit silently.
artifact="TaskManagerOG-${version}-linux-x86_64.tar.gz"
sha256="" name=""
read -r sha256 name < <(curl -fsSL "$BASE_URL/downloads/$artifact.sha256") || true
if [[ ! $sha256 =~ ^[0-9a-f]{64}$ || ${name#\*} != "$artifact" ]]; then
echo "Unusable checksum for $artifact: '$sha256 $name'" >&2
exit 1
fi
# "any" is bin/sync-upstream's name for the unsuffixed sha256sums array, which
# is the one this package has: upstream publishes x86_64 alone, so there is a
# single plain source=() rather than per-architecture arrays.
# is the one this package has: it builds x86_64 alone, so there is a single
# plain source=() rather than per-architecture arrays.
jq -n \
--arg pkgver "$version" \
--arg sha256 "$(sha256sum "$tarball" | cut -d' ' -f1)" \
--arg sha256 "$sha256" \
'{pkgver: $pkgver, sha256sums: {any: [$sha256]}}'
+6 -10
View File
@@ -5,13 +5,12 @@
# is 55 MB of bundled Qt -- the same binary, minus a second copy of what
# Omarchy already installs.
#
# The download URL carries no version: tmog.org serves every release from the
# same path. .omarchy/upstream.sh rewrites the pkgver and sha256 below when
# /version.txt moves, and checks the tarball's own directory name to be sure
# the mutable URL really served the version it announced.
# .omarchy/upstream.sh rewrites the pkgver and sha256 below when
# /rtm/version.txt moves, taking the checksum from the .sha256 sidecar tmog.org
# publishes beside each versioned tarball.
pkgname=tmog-bin
pkgver=0.1.1
pkgver=1.0.0
pkgrel=1
pkgdesc="Native system monitor and task manager"
arch=('x86_64')
@@ -39,11 +38,8 @@ options=('!debug' '!strip')
_srcdir="TaskManagerOG-${pkgver}-linux-x86_64"
# The query string is upstream's own cache key -- tmog.org appends it to the
# Linux links for the same reason, so a CDN holding an older object under this
# mutable path cannot answer for a new release.
source=("${pkgname}-${pkgver}.tar.gz::${url}downloads/TMOG-Task-Manager-Linux-x86_64.tar.gz?v=${pkgver}-free")
sha256sums=('4d319d3d27f513e83801daeec8eb64cb78ddec1f6483bbe90d57d11e607af39d')
source=("${pkgname}-${pkgver}.tar.gz::${url}rtm/downloads/${_srcdir}.tar.gz")
sha256sums=('a147c613d4a6f5c0ec16eaf52965593de523f9f0231e09c241460cc63352f325')
package() {
cd "${_srcdir}"
+4 -4
View File
@@ -2,7 +2,7 @@
pkgname=visual-studio-code-bin
_pkgname=visual-studio-code
pkgver=1.138.0
pkgver=1.139.1
pkgrel=1
pkgdesc="Visual Studio Code (vscode): Editor for building and debugging modern web and cloud applications (official binary version)"
arch=('x86_64' 'aarch64' 'armv7h')
@@ -27,9 +27,9 @@ source_x86_64=(code_${pkgver}_amd64.deb::https://update.code.visualstudio.com/${
source_aarch64=(code_${pkgver}_arm64.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-arm64/stable)
source_armv7h=(code_${pkgver}_armhf.deb::https://update.code.visualstudio.com/${pkgver}/linux-deb-armhf/stable)
sha256sums=('bd0d9edf69283ebdf4e73e0a7b168d2fcf50acbd01f63674cad93ed4fe42fdad')
sha256sums_x86_64=('73389cdcef7e66171a2039d1e49b9530e5ed02937e6159d3e6af93484e63cbad')
sha256sums_aarch64=('09760b73fb96ca19f8c6e483ec5b69123f34edd2c762cc9e0faf73fa3d400145')
sha256sums_armv7h=('bb74a3023aced544c71d4274d5942ce69c59a2ec0ffaf9094fa7c0fddb506366')
sha256sums_x86_64=('cc8e35cf69ff4c7e515e19fa981bf6aba41f61ddb61c79370e9fe460c5dbaf8b')
sha256sums_aarch64=('53cdf61fd870ec9663ea7baa5e4f79014acafc36d8c45b2678a8ce80d72d737d')
sha256sums_armv7h=('09afa2bcd369ce7a8231a297bed487a9f7aa1ba3776cdac3bfd481d1bb08b708')
package() {
bsdtar -xf data.tar.xz -C "${pkgdir}/"
+63 -73
View File
@@ -1,6 +1,6 @@
# Maintainer: Peter Jackson <pete@peteonrails.com>
pkgname=voxtype-bin
pkgver=1.0.1
pkgver=1.1.0
pkgrel=1
pkgdesc="Push-to-talk voice-to-text for Linux (pre-built binaries)"
arch=('x86_64' 'aarch64')
@@ -142,82 +142,72 @@ source=(
"quickshell-voxtype-shared-qmldir-$pkgver::https://raw.githubusercontent.com/peteonrails/voxtype/v$pkgver/quickshell/voxtype-shared/qmldir"
)
sha256sums_x86_64=(
# Whisper binaries
'cb3843a894ef47aca230b30bb1c45c2ef8e0d015adf2fa754d60e55123165fd0' # voxtype-avx2
'21357d39412619e8a3fc473153e6e2a28b219aa02007682737afedd73a08bdbe' # voxtype-avx2.asc
'77d49275ae4c3a6d93671014278b0dabd69ba52e65d2ee6ab3ec1bff0af34d55' # voxtype-avx512
'e3421641b4b5fa5d42ee0698eb43552e177f8b095a1acea32445693404b4fd54' # voxtype-avx512.asc
'c569d038057464aa60290296794bcbd79b928ee0efd038e33062a4c015558ed8' # voxtype-vulkan
'a82bd4108dc70d7d2b6e25a83a6744170502f5110780d4a2e97a3e76047ea60d' # voxtype-vulkan.asc
# ONNX CPU binaries
'19b8716ff7bd388ffb18843fc0ee5e614faa84544d22918ecf72a7c3d6c02929' # voxtype-onnx-avx2
'3021aa3a13555bdab0ecccfb522db8391d7e05810d218608a6372477f11cb2af' # voxtype-onnx-avx2.asc
'69a6e6fc1c04a55eeb62cf1eaa5fe81873c70eabffff120ce1a4ff7ef62fd559' # voxtype-onnx-avx512
'305d33b6f4dc8ac7a38a5f522c1af95b462355fa057b2eb39d3add59303145e1' # voxtype-onnx-avx512.asc
# ONNX CUDA 12 binary + companion .so
'e7180f17add10bb441368d8495fc99bde0ba1a1978ea5f7a52d7e626779eca16' # voxtype-onnx-cuda-12
'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
'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
'9e9c767605923c084c97659326cb0f03ad4e5db0aded4da052fa208b4de9cf45' # voxtype-onnx-migraphx.asc
'ddd67e6193ade819ee21f1706d1b03b9151f1d2d2843701e2d19d8b183631707' # migraphx.libonnxruntime_providers_migraphx.so
'17f7cf47ad0d7b5ac895ae588fd62c7f85a13842588161b6a24c7d480f062be4' # migraphx.libonnxruntime_providers_shared.so
# OSD launcher + GTK4 frontend
'7250027b1672507a6d584f795731c87e1d3b5c1de891438bd55e34b136a2d5cc' # voxtype-osd
'1a944200fbac1e773c70d036075745b0e868885443e29c30797f262d44928cc1' # voxtype-osd.asc
'74fb0f6ad87feb0c1c9e06a8b28a7f7ecee101caef4248f77dcf613b5271238e' # voxtype-osd-gtk4
'60224685717fea0582d570160282e9e215cd4713b3bdb695edc7bae8b6860cac' # voxtype-osd-gtk4.asc
# Quickshell OSD launcher + audio-bridge sidecar (new in v0.7.5)
'b809c5140e844a6add801d7e592775cd89af8cce73fa399b6a3aec15dfd09533' # voxtype-osd-quickshell
'39412691ab1f8ffe4fa6bf1eb9763c29f94b8892d1ba59fd49dc65dd0d80297a' # voxtype-osd-quickshell.asc
'45776290e364194d83a8b89445166406c278e890507bf07ec52a5f0e8fa57720' # voxtype-audio-bridge
'5be1174a78d70b78fd8d923c88e3406962443b39a1c452eb985b1e2484ef5668' # voxtype-audio-bridge.asc
'e7d5de68cc8fc610c3c961c47f879451db9bee4a2df152e9a66f1078072e7f28'
'fdf2c35826ea7590a703993c5bdf69804672a5a0c76312e66bc4f14399d8f2ce'
'bb2da45c7676bc128da998da928cb239ab6eef9fe53c31c9b4a77e819e521715'
'd6158e18ac2446a2ae79b2ae23ed9744c6579eeabfa567b5c3db0a2575f95ac9'
'db2c7938392ff08ec8b50b8afb90f8bd3d0111eccf5943df2f51c40a0368fec2'
'2b6b6afbaecd0c8adff536db4c5e0ea50b8781ad6f2643344e96c8cba2ea672a'
'07ee9863f1d611ee3fc638f9ba766f3bd38783b9a97b276d7eceb9b995a7167b'
'b5e15277f49f52ffd99bb0cc3ef91548841d83ed3787a3ff7809d4fba596327e'
'b3fabe0fa67452aaa76ccf3f84cd71a3c23d27354c840128c396690cb3a1c9a6'
'b2da321a562d7de459881be305626a1f68942786939c534360757efe686802e7'
'171869a953b0d85cb36b54c5cb0c64013051317bff2a1afe09297caf67967d01'
'24df2a2e1f1505c5ea3118ad354770f4ff1106a82b63e63fb62f3bf5e07fb448'
'a8584727d51ba646ac63fc991c2f36ad6cd5b8cc8b1141896e46938700b888d0'
'1b028afc079628d76a28d7eb09700a4baead4a27f9634ba82c35398486134114'
'06e74651565ed63ab20e8eedd7380ceb658558125d97dfde2bb5eafeeac82c7d'
'050438373390c779967a23ec4acbcd701cf3ac7e6ae9746c4eb06d999a44f810'
'b6cb7744d0efd2faced5c83ead374c13e7f2630b5a249ffaf393cdb1e092c92b'
'c6a12593396095f5670160e284c35d1700b7708cf3037b7042e2a5200ccae772'
'1aacefdf0b4afa145d410b2381bbc3db3d978c485fb182c42a2b0b09f91f5310'
'4085f24c336ffb0862f9d1022f9d5acafcc4278a5bcd3fd45e6d89692f71d301'
'3c8d3eb1ad6db8881c59b3d25a317ea4bbadedab4388811b085920c21321d654'
'ddd67e6193ade819ee21f1706d1b03b9151f1d2d2843701e2d19d8b183631707'
'17f7cf47ad0d7b5ac895ae588fd62c7f85a13842588161b6a24c7d480f062be4'
'0c9ac447bc236728f355d25b7c500afd464186a4591ccc18f482fcc98b16a928'
'5844758469bd89b56c864e4934b783870cf0118b3b06d0fc9af9f3f348f85af6'
'19535f63c69748408199f3fbfe2bb2f786f5bf4faa54d5390895eecae4603dc7'
'3757b039b9a09c53b54c81e518222a1e44b4e50ba100084c6ab088aea31f7070'
'b9dc8eca049f21e2507511700108d57ce5704350e5828418753ef9989f86eb08'
'57e6e3c8de2307d17c1c45b498e2c92eec77cdefa818ab28aa0abfcd476e15fc'
'36333a15e27d13d9988045179582f0daecadc630e3ec01bb0996ab798cb77487'
'cf48b19667ea235460d9e7391a04e57b2bc2b9e361eef380196a2c51693fde81'
)
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
'2fcf0945d424a116c1947ea738da1afa9f83abbae66cebb53f06189111a6f392'
'13c78d392751957631645c45668dca5b798b648e6cefb5dbb33e25ba80e713bf'
'49ecde9a394492c9a34e764911d98258c495ed2f0ced386e6974bccf3f9f164f'
'0b5f1e64e16086a68f9ac4f5be06e9c0937bd328eab6f257a2894bbb616a2081'
'34d83a7edb73ae2e15dabc0638d39f2c30ddb3af8f2565400ff043ef6558dc2b'
'9c86d7e11e60e143e68a398b8b3f25ebeaf3225478e3ceb15f84970df5dd76b4'
'4d730a6677342158c1861bfb73f1cb86da05afeb74fdf737134df5c8ad9a1eb1'
'00a3bd82bd457b6b43bf832c2342a4ee99bed3eb38c70e8e156052a9a46bc7c6'
'365c1b5223329604001fe591398d3c308120048567c7f3171d2602005661d594'
'2d0a8b55ba20efbb9c273b03ec042d434d6336fdc8bc822363e8b0f128dfa425'
'39c4a186ac8a95f7236cfdd46255207f143f76363a5f758eb127509b163d5172'
'f2348ab4b25e19a75f5442355c2ae7e250779814a524f09a41a59237aa495430'
)
sha256sums=(
# Architecture-independent config and support files
'f4b2bccd56b31a6a50e1c0a8b6b72383dc1e636f9ccb8cb070442d58b7314579' # config/default.toml
'531c3658e229619e56bb01659fb81f401767b85e1d6e2acd1ac67ee3414a168c' # voxtype.service
'65c95805d9b03ccc2fadb9d63a03ab79974b00091df8457ee8ef290ec6bd5b12' # voxtype.bash
'e5e63b3c7f48238cf719e4f2ef90c1f9c5c7e8cd25eaebc9f78bdd34b24b6605' # voxtype.zsh
'f720ddd24ee97c105b448323899c36bca7c63d00c2d42c4a3da70c3d157dccbb' # voxtype.fish
'31123c45b4ff9cb5fd9e01083350fea6ccaf14969013fd48e4c95fdf89e6eb4b' # LICENSE
'e5b2ec5da5eafe2ce8f7b84b81a889f2ff496ad6488d56b6b9b32b73d025ed53' # README.md
# Desktop entry + launcher
'32144a4a5210092b0aa909f6de7a43ebe8bbf82fa3dfb1f3519787512fdf8e4b' # voxtype-configure.desktop
'044b1f7b52cc610ce57ba624111d882029b0ce4bc3e2c2c360f96d07f69e0e85' # voxtype-configure-launcher
# Quickshell QML tree (new in v0.7.5)
'd3d0b0b24a3fc3e252623a6fad898c7d1d147fb8c2e49de90fbf452e95de63ab' # quickshell/shell.qml
'70a611fd4eabde43189aee0619899827de21e36695191648dc36470d4c333de6' # quickshell/OsdSurface.qml
'4d6eef505ec161080ca92ae6a355ca00dcc7bb05d5b190534a1851fcbb726e55' # quickshell/EnginePicker.qml
'54271a8f0e4b52f40505f32801f4c78399ac356ed1e80906ca8a068ecb7ee734' # quickshell/MeetingControls.qml
'aaa011682b92d8e25863a9ea34a469b897bac15ad939292d8144b012fa05b209' # quickshell/voxtype-shared/Theme.qml
'74345f9d8b77de3f1d6d08a759e52506c606e8af3d04a97a5bfe7954d0f64604' # quickshell/voxtype-shared/StateReader.qml
'2ad530f92f13fc7f1100e6f6c9910878c35d911e91dc60feb902c2542b619230' # quickshell/voxtype-shared/AudioBridge.qml
'45180488129f16a0568c217c743ce7e45831acb0cb287346d6da5b2fc097717b' # quickshell/voxtype-shared/StyleLoader.qml
'd5e9a86946dc8dc2afabdcd00d79d973181e51b2e5e8aea2772960aaf1ff2283' # quickshell/voxtype-shared/RecipeRenderer.qml
'41b894baa1487e47db5f9ec4baeea9c02b6a76d3c8198b4700a88e2cb7ec0b62' # quickshell/voxtype-shared/qmldir
'f4b2bccd56b31a6a50e1c0a8b6b72383dc1e636f9ccb8cb070442d58b7314579'
'531c3658e229619e56bb01659fb81f401767b85e1d6e2acd1ac67ee3414a168c'
'65c95805d9b03ccc2fadb9d63a03ab79974b00091df8457ee8ef290ec6bd5b12'
'e5e63b3c7f48238cf719e4f2ef90c1f9c5c7e8cd25eaebc9f78bdd34b24b6605'
'f720ddd24ee97c105b448323899c36bca7c63d00c2d42c4a3da70c3d157dccbb'
'31123c45b4ff9cb5fd9e01083350fea6ccaf14969013fd48e4c95fdf89e6eb4b'
'b06ee68e1305174a4f66876750f62d4048d0ebee48e15ee525961a54115ff80d'
'32144a4a5210092b0aa909f6de7a43ebe8bbf82fa3dfb1f3519787512fdf8e4b'
'044b1f7b52cc610ce57ba624111d882029b0ce4bc3e2c2c360f96d07f69e0e85'
'd3d0b0b24a3fc3e252623a6fad898c7d1d147fb8c2e49de90fbf452e95de63ab'
'70a611fd4eabde43189aee0619899827de21e36695191648dc36470d4c333de6'
'4d6eef505ec161080ca92ae6a355ca00dcc7bb05d5b190534a1851fcbb726e55'
'54271a8f0e4b52f40505f32801f4c78399ac356ed1e80906ca8a068ecb7ee734'
'aaa011682b92d8e25863a9ea34a469b897bac15ad939292d8144b012fa05b209'
'74345f9d8b77de3f1d6d08a759e52506c606e8af3d04a97a5bfe7954d0f64604'
'2ad530f92f13fc7f1100e6f6c9910878c35d911e91dc60feb902c2542b619230'
'45180488129f16a0568c217c743ce7e45831acb0cb287346d6da5b2fc097717b'
'd5e9a86946dc8dc2afabdcd00d79d973181e51b2e5e8aea2772960aaf1ff2283'
'41b894baa1487e47db5f9ec4baeea9c02b6a76d3c8198b4700a88e2cb7ec0b62'
)
package() {
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=walker
pkgver=2.17.0
pkgver=2.17.1
pkgrel=1
pkgdesc='wayland application runner'
url='https://github.com/abenz1267/walker'
@@ -12,7 +12,7 @@ depends=('gtk4-layer-shell' 'poppler-glib' 'cairo')
conflicts=('walker')
provides=('walker')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=("c3498742a9866422b2947340a515eeb7932333bb8f99b171d159c0a7ece0a12f")
sha256sums=('891de6f3c0974e91a89fc6bb775c7d8b3f9ee50adf81158be048d9496df18be4')
build() {
cd ${pkgname}-${pkgver}
+2 -2
View File
@@ -6,7 +6,7 @@
# Adapted from omarchy-mac/omarchy-pkgs-aarch64 PR #25.
pkgname=zed
pkgver=1.20.2
pkgver=1.21.0
pkgrel=1
pkgdesc='A high-performance, multiplayer code editor from the creators of Atom and Tree-sitter'
arch=('aarch64')
@@ -36,7 +36,7 @@ conflicts=('zed-bin' 'zed-git' 'zed-preview-bin')
# The vendor binaries are already stripped.
options=('!strip')
source_aarch64=("${pkgname}-${pkgver}-aarch64.tar.gz::https://github.com/zed-industries/zed/releases/download/v${pkgver}/zed-linux-aarch64.tar.gz")
sha256sums_aarch64=('715a5252234522bc9e8e4a8c1f9b462cf7bb2881eed23b7c8ae650b41c24aa6f')
sha256sums_aarch64=('69eff51b22203be7a4d0fd9df0864a8abd4d5183e8fb9aafa2af57f3cd42b9a3')
package() {
cd 'zed.app'
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# Every git source in the repository names an immutable commit or a tag.
#
# A source that follows a branch ("#branch=quattro", or no fragment at all)
# produces a package whose contents depend on when it was built, and nothing
# in this repository changes when that branch moves, so the CI publish path,
# which builds what a merge touched, never rebuilds it. Packages that need to
# follow a branch declare a git_branch upstream watch instead, and the tracker
# turns each new tip into a commit pin here (docs/upstream-sources.md).
set -euo pipefail
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
PKGBUILDS_DIR=${PKGBUILDS_DIR:-$BUILD_ROOT/pkgbuilds}
failures=0
checked=0
for pkgdir in "$PKGBUILDS_DIR"/*/; do
[[ -f "$pkgdir/PKGBUILD" ]] || continue
package=$(basename "$pkgdir")
for arch in x86_64 aarch64; do
# Sourced the way the build tooling reads recipes: CARCH set, the local
# source override unset, so conditional and arch-suffixed arrays count.
sources=$(cd "$pkgdir" && env -u OMARCHY_SRC CARCH="$arch" bash -c '
source PKGBUILD >/dev/null 2>&1
printf "%s\n" "${source[@]}" "${source_x86_64[@]}" "${source_aarch64[@]}"' 2>/dev/null) || {
echo "FAIL: $package: PKGBUILD could not be sourced for $arch"
failures=$((failures + 1))
continue
}
while IFS= read -r entry; do
[[ -n "$entry" ]] || continue
url="${entry#*::}"
[[ "$url" == git+* ]] || continue
checked=$((checked + 1))
case "$url" in
*'#commit='*|*'#tag='*) ;;
*)
echo "FAIL: $package ($arch): git source is not pinned to a commit or tag: $url"
failures=$((failures + 1))
;;
esac
done <<<"$sources"
done
done
if ((failures)); then
echo "$failures unpinned git source(s). Pin with #commit= (and a git_branch upstream watch to move the pin), or #tag= with a checksum."
exit 1
fi
echo "PASS: $checked git source(s) across pkgbuilds/ are pinned to a commit or tag"
+154
View File
@@ -178,6 +178,160 @@ b2sums=('old' 'local-b2')
expected = subprocess.check_output(['git', '-c', 'core.abbrev=no', '-C', str(repo), 'archive', '--format', 'tar', 'v1.0'])
self.assertEqual(archive.read_bytes(), expected)
def branch_fixture(self, fresh_tip=False):
"""An upstream with two release tags and commits past the newest one,
all committed years ago; with fresh_tip, one more commit dated now."""
repo = self.root / 'branch-upstream'
repo.mkdir()
git = ['git', '-C', str(repo), '-c', 'user.name=Test', '-c', 'user.email=test@example.test']
old = {**os.environ, 'GIT_COMMITTER_DATE': '2020-01-01T00:00:00+00:00', 'GIT_AUTHOR_DATE': '2020-01-01T00:00:00+00:00'}
subprocess.run(['git', 'init', '-q', '-b', 'main', str(repo)], check=True)
shas = []
def commit(index, env):
(repo / 'source').write_text(f'revision {index}')
subprocess.run([*git, 'add', '.'], check=True)
subprocess.run([*git, 'commit', '-qm', f'commit {index}'], env=env, check=True)
shas.append(subprocess.check_output([*git, 'rev-parse', 'HEAD'], text=True).strip())
for index, tag in enumerate([None, 'v1.0.0', 'v1.1.0', None, None]):
commit(index, old)
if tag:
subprocess.run([*git, 'tag', tag], check=True)
# A newer release tagged on another branch is not something main is "past".
subprocess.run([*git, 'checkout', '-q', '-b', 'hotfix', shas[1]], check=True)
(repo / 'hotfix').write_text('x')
subprocess.run([*git, 'add', '.'], check=True)
subprocess.run([*git, 'commit', '-qm', 'hotfix'], env=old, check=True)
subprocess.run([*git, 'tag', 'v9.9.9'], check=True)
subprocess.run([*git, 'checkout', '-q', 'main'], check=True)
if fresh_tip:
commit(len(shas), os.environ)
return repo, shas
def redirect_clone(self, repo):
command = w.subprocess.run
def redirect(args, **kwargs):
if 'clone' in args:
args = [f'file://{repo}' if arg == 'https://example.test/tool.git' else arg for arg in args]
return command(args, **kwargs)
return patch.object(w.subprocess, 'run', side_effect=redirect)
def test_git_branch_versions_from_reachable_tag_and_shares_one_clone(self):
repo, shas = self.branch_fixture()
with self.redirect_clone(repo):
tip = w.git_branch_tip('https://example.test/tool.git', 'main', r'v(?P<version>[0-9.]+)', self.fetch.cache)
again = w.git_branch_tip('https://example.test/tool.git', 'main', None, self.fetch.cache)
self.assertEqual((tip['commit'], tip['tag'], tip['version'], tip['distance'], tip['count']), (shas[-1], 'v1.1.0', '1.1.0', '2', '5'))
self.assertEqual(again['commit'], shas[-1])
self.assertEqual(len(list(self.fetch.cache.glob('*.branch.git'))), 1, 'one clone per branch per run')
watch = {'git_branch': 'https://example.test/tool.git', 'branch': 'main', 'tag_pattern': r'v(?P<version>[0-9.]+)',
'version': '{version}.r{distance}.g{commit:.7}', 'variables': {'_commit': '{commit}'}}
pkgver = w.candidate(watch, tip)['pkgver']
self.assertEqual(pkgver, f'1.1.0.r2.g{shas[-1][:7]}')
self.assertEqual(w.vercmp(pkgver, '1.1.0'), 1)
self.assertEqual(w.vercmp(pkgver, '1.1.1'), -1)
with self.redirect_clone(repo), self.assertRaisesRegex(ValueError, 'no tag'):
w.git_branch_tip('https://example.test/tool.git', 'main', r'release-(?P<version>[0-9.]+)', self.root / 'other-cache')
def test_git_branch_min_age_holds_the_tip_instead_of_selecting_history(self):
repo, shas = self.branch_fixture(fresh_tip=True)
watch = {'git_branch': 'https://example.test/tool.git', 'branch': 'main'}
with self.redirect_clone(repo):
releases = w.discover(watch, self.fetch)
self.assertEqual(w.select_release(releases)['values']['commit'], shas[-1])
self.assertIsNone(w.select_release(releases, min_age=3600))
self.assertEqual(w.select_release(releases, min_age=3600, bypass=True)['values']['commit'], shas[-1])
def branch_sync_fixture(self):
repo, shas = self.branch_fixture()
for directory in ['bin', 'helpers']:
shutil.copytree(ROOT / directory, self.root / directory)
for name in ['dev', 'settings-dev']:
package = self.root / 'pkgbuilds' / name
(package / '.omarchy').mkdir(parents=True)
(package / '.omarchy/package.json').write_text(json.dumps({
'source': 'local', 'auto_merge': True, 'upstream': {'watch': {
'git_branch': 'https://example.test/tool.git', 'branch': 'main',
'tag_pattern': r'v(?P<version>[0-9.]+)',
'version': '{version}.r{count}.g{commit:.7}',
'variables': {'_commit': '{commit}'}}}}))
(package / 'PKGBUILD').write_text(f'''pkgname={name}
pkgver=1.0.0
pkgrel=1
_commit={shas[1]}
arch=('any')
source=("tool::git+https://example.test/tool.git#commit=${{_commit}}")
sha256sums=('old')
''')
stub = self.root / 'stub'
stub.mkdir()
git = stub / 'git'
git.write_text('''#!/usr/bin/env python3
import os, sys
args = [os.environ['BRANCH_FIXTURE'] if arg == 'https://example.test/tool.git' else arg for arg in sys.argv[1:]]
os.execv(os.environ['REAL_GIT'], ['git', *args])
''')
git.chmod(0o755)
env = {**os.environ, 'PATH': str(stub) + os.pathsep + os.environ['PATH'],
'BRANCH_FIXTURE': f'file://{repo}', 'REAL_GIT': shutil.which('git')}
def sync(*args):
return subprocess.run([str(self.root / 'bin/sync-upstream'), *args],
env=env, text=True, capture_output=True)
return self.root / 'pkgbuilds', shas[-1], sync
def test_targeted_branch_sync_updates_siblings_and_then_noops(self):
packages, tip, sync = self.branch_sync_fixture()
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
for package in packages.iterdir():
recipe = w.read_recipe(package / 'PKGBUILD')
self.assertEqual(w.scalar(recipe, '_commit'), tip)
self.assertEqual(w.scalar(recipe, 'pkgver'), f'1.1.0.r5.g{tip[:7]}')
self.assertRegex(recipe['sha256sums'][0], r'^[0-9a-f]{64}$')
self.assertIn('Updated: 2', result.stdout)
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
def test_branch_sync_rolls_back_when_a_sibling_fails(self):
packages, tip, sync = self.branch_sync_fixture()
broken = packages / 'settings-dev/PKGBUILD'
broken.write_text(broken.read_text().replace("sha256sums=('old')", 'sha256sums=()'))
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
self.assertIn('Lockstep violation', result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_reviewed_lane_leaves_auto_merge_packages_untouched(self):
packages, tip, sync = self.branch_sync_fixture()
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'reviewed')
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertIn('Updated: 0', result.stdout)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_different_lanes_cannot_split_a_branch_pair(self):
packages, tip, sync = self.branch_sync_fixture()
metadata = packages / 'settings-dev/.omarchy/package.json'
metadata.write_text(metadata.read_text().replace('"auto_merge": true', '"auto_merge": false'))
before = {p: p.read_bytes() for p in packages.glob('*/PKGBUILD')}
result = sync('--lane', 'auto-merge', 'dev')
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
self.assertIn('Lockstep violation', result.stdout + result.stderr)
self.assertEqual(before, {p: p.read_bytes() for p in before})
def test_git_branch_tag_template_requires_tag_pattern(self):
base = {'git_branch': 'https://example.test/tool.git', 'branch': 'main'}
w.validate({**base, 'version': '{date}.r{count}'})
w.validate({**base, 'tag_pattern': r'v(?P<version>[0-9.]+)', 'version': '{version}.r{distance}.g{commit:.7}'})
for extra in [{'version': '{version}.r{distance}'}, {'version': '{tag}'}, {'tag_pattern': 'v[0-9.]+'},
{'tag_pattern': 7}, {'tag_pattern': ''}]:
with self.subTest(extra=extra), self.assertRaises(ValueError):
w.validate({**base, **extra})
with self.assertRaisesRegex(ValueError, 'only applies'):
w.validate({'github': 'owner/tool', 'pattern': r'v(?P<version>[0-9.]+)', 'tag_pattern': r'v(?P<version>[0-9.]+)'})
def test_invalid_optional_metadata_fails_validation(self):
valid = {'github': 'owner/tool', 'pattern': r'v(?P<version>[0-9.]+)'}
for extra in [{'variables': []}, {'fields': {'commit': 3}}, {'submodules': {'pkgver': 'libs/common'}},