Merge upstream master so local Omarchy builds carry the published version

This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 23:48:13 -04:00
commit a4cc32340c
1156 files changed
+272275 -65277

No files matched your search

+5 -4
View File
@@ -6,9 +6,10 @@ const BOT = 'github-actions[bot]';
// resulting pull_request runs for approval and, unlike a person's push,
// creates no pull_request_target run, so approve-pr.yml never sees it. The
// sync workflow therefore releases the runs for the commit it just pushed,
// under the same rule approve-pr.yml applies: only while a maintainer's
// build-approved label is on the PR. It acts only on its own bot-authored,
// same-repository PR for the branch and commit it pushed.
// under the same rule approve-pr.yml applies: only while build-approved is
// on the PR. The sync applies that label itself, so its pushes build without
// a maintainer. It acts only on its own bot-authored, same-repository PR for
// the branch and commit it pushed.
module.exports = async function approveSyncPush({ github, context, core,
number, branch, headSha, since, approve = approvePrWorkflows, ...options }) {
if (!Number.isInteger(number) || !branch || !headSha || !since) {
@@ -25,7 +26,7 @@ module.exports = async function approveSyncPush({ github, context, core,
return;
}
if (!pr.labels.some(label => label.name === 'build-approved')) {
core.info(`PR #${number} has no build-approved label; its runs wait for a maintainer.`);
core.info(`PR #${number} has no build-approved label; its runs stay held.`);
return;
}
await approve({ github, context, core, vouchStatus: 'bot', pullRequest: pr,
+84
View File
@@ -0,0 +1,84 @@
// Whether a PR rides to master on its own once the required checks pass.
//
// The rule is the build gate's, from build-pr.yml: a PR trusted to build is
// trusted to ship. Collaborators, vouched authors and bots are trusted; an
// unknown author is trusted while the PR carries build-approved; a
// denouncement is absolute. Two limits on top of it:
//
// - Only package changes. A PR's workflows, scripts and build tooling never
// run in its own build (build-pr.yml overlays only its package directories
// onto base tooling), so green checks say nothing about them, and after
// merge they run with the publish secrets. Allowed: anything under
// pkgbuilds/, plus the test a package PR brings with it, which is a new
// file under tests/ and lines in test.yml that only run new tests/*.sh.
// test.yml runs on PRs only; an existing test may also run on master
// (builder-images.yml runs tests/build-isolation.sh with packages: write),
// so editing one still needs a maintainer.
// - Not the upstream sync. It labels its own PR build-approved to release
// GitHub's hold on its pushes, which is no one's approval; it stays on the
// reviewed lane.
const PACKAGES = 'pkgbuilds/';
const TESTS = 'tests/';
const TEST_WORKFLOW = '.github/workflows/test.yml';
const TEST_LINE = /^\+\s*\.\/tests\/[A-Za-z0-9._-]+\.sh\s*$/;
// Every changed line adds a ./tests/<name>.sh call; nothing removed. A diff
// too large for the API has no patch and does not qualify.
function onlyRunsTests(patch) {
if (!patch) return false;
const changed = patch.split('\n').filter(line =>
/^[+-]/.test(line) && !line.startsWith('+++') && !line.startsWith('---'));
return changed.length > 0 && changed.every(line => TEST_LINE.test(line));
}
function packageChange(file) {
if (file.previous_filename && !file.previous_filename.startsWith(PACKAGES)) return false;
if (file.filename.startsWith(PACKAGES)) return true;
if (file.filename.startsWith(TESTS)) return file.status === 'added';
if (file.filename === TEST_WORKFLOW) return file.status === 'modified' && onlyRunsTests(file.patch);
return false;
}
const REVIEWED_BRANCHES = /^auto\/sync-upstream(\/|$)/;
function decide({ pr, files, vouchStatus, repository }) {
if (pr.state !== 'open') return { enable: false, reason: 'PR is not open' };
if (pr.draft) return { enable: false, reason: 'PR is a draft' };
const labelled = pr.labels.some(label => label.name === 'build-approved');
let trusted;
switch (vouchStatus) {
case 'bot': case 'collaborator': case 'vouched': trusted = true; break;
case 'unknown': trusted = labelled; break;
default: trusted = false; // denounced, or a failed lookup
}
if (!trusted) {
return { enable: false, reason: `author not trusted to build (${vouchStatus || 'missing'}${labelled ? ', labelled' : ''})` };
}
if (pr.head.repo?.full_name === repository && REVIEWED_BRANCHES.test(pr.head.ref)) {
return { enable: false, reason: `${pr.head.ref} stays on the reviewed lane` };
}
if (!files.length) return { enable: false, reason: 'PR changes no files' };
const outside = files.filter(file => !packageChange(file));
if (outside.length) {
const names = outside.slice(0, 3).map(file => file.filename).join(', ');
return { enable: false, reason: `changes more than packages and their new tests: ${names}${outside.length > 3 ? ', ...' : ''}` };
}
return { enable: true, reason: `${vouchStatus === 'unknown' ? 'build-approved' : vouchStatus} author, package changes only` };
}
module.exports = async function autoMerge({ github, context, core, number, vouchStatus }) {
const { data: pr } = await github.rest.pulls.get({ ...context.repo, pull_number: number });
const files = await github.paginate(github.rest.pulls.listFiles, {
...context.repo, pull_number: number, per_page: 100,
});
const decision = decide({
pr, files, vouchStatus, repository: `${context.repo.owner}/${context.repo.repo}`,
});
core.info(`#${number}: ${decision.enable ? 'auto-merge' : 'leave for a maintainer'} (${decision.reason})`);
core.setOutput('enable', String(decision.enable));
core.setOutput('head_sha', pr.head.sha);
return decision;
};
module.exports.decide = decide;
+108
View File
@@ -0,0 +1,108 @@
name: Auto-merge approved package PRs
# A package PR trusted to build is trusted to ship: once its builds are
# green it should merge and publish without a maintainer pressing the
# button. This enables GitHub's auto-merge on such PRs; branch protection
# still holds the merge until `result`, `self-tests` and `build-isolation`
# pass, and a red build stays an open PR. .github/scripts/auto-merge-pr.cjs
# has the rule.
#
# Auto-merge is enabled with the PAT in PKGS_BOT_TOKEN: a merge made with the
# built-in GITHUB_TOKEN does not start publish.yml.
#
# pull_request_target runs this default-branch code with secrets; the PR's
# code is never checked out here.
on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review, labeled, unlabeled]
workflow_dispatch:
inputs:
pr:
description: 'PR number to evaluate'
required: true
permissions:
contents: read
pull-requests: read
concurrency:
group: auto-merge-pr-${{ github.event.pull_request.number || github.event.inputs.pr }}
cancel-in-progress: true
jobs:
auto-merge:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false
- name: Find the PR's author
id: pr
uses: actions/github-script@v7
env:
NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr }}
with:
script: |
const { data: pr } = await github.rest.pulls.get({
...context.repo, pull_number: Number(process.env.NUMBER),
});
core.setOutput('number', String(pr.number));
core.setOutput('author', pr.user.login);
- id: vouch
uses: mitchellh/vouch/action/check-user@f23dbb5e745334f97414ec70463ce7301071a661 # v1
with:
user: ${{ steps.pr.outputs.author }}
allow-fail: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Decide
id: decide
uses: actions/github-script@v7
env:
NUMBER: ${{ steps.pr.outputs.number }}
VOUCH_STATUS: ${{ steps.vouch.outputs.status }}
with:
script: |
const autoMerge = require('./.github/scripts/auto-merge-pr.cjs');
await autoMerge({ github, context, core,
number: Number(process.env.NUMBER), vouchStatus: process.env.VOUCH_STATUS });
- name: Enable auto-merge
if: steps.decide.outputs.enable == 'true'
env:
GH_TOKEN: ${{ secrets.PKGS_BOT_TOKEN }}
PR: ${{ steps.pr.outputs.number }}
HEAD_SHA: ${{ steps.decide.outputs.head_sha }}
run: |
if [[ -z "$GH_TOKEN" ]]; then
echo "::error::Set PKGS_BOT_TOKEN; a GITHUB_TOKEN merge would not publish."
exit 1
fi
# Idempotent: enabling twice errors. Bot lanes enable their own.
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
# --match-head-commit: never arm a merge for a commit newer than
# the one just judged.
gh pr merge --auto --squash --match-head-commit "$HEAD_SHA" "$PR" -R "$GITHUB_REPOSITORY"
# Removing build-approved withdraws the approval, so withdraw the
# auto-merge it armed too. Only on that event: auto-merge a maintainer
# enabled by hand on any other PR is theirs to keep.
- name: Withdraw auto-merge
if: >-
steps.decide.outputs.enable == 'false' &&
github.event.action == 'unlabeled' && github.event.label.name == 'build-approved'
env:
GH_TOKEN: ${{ secrets.PKGS_BOT_TOKEN }}
PR: ${{ steps.pr.outputs.number }}
run: |
if [[ "$(gh pr view "$PR" -R "$GITHUB_REPOSITORY" --json autoMergeRequest --jq '.autoMergeRequest != null')" == true ]]; then
gh pr merge --disable-auto "$PR" -R "$GITHUB_REPOSITORY"
fi
+71 -48
View File
@@ -24,11 +24,10 @@ on:
description: "Space-separated package directories to publish from master"
required: true
# Merges serialize. Two publishes into one channel at once would race on
# the database; queued is fine, cancelled is not.
concurrency:
group: publish
cancel-in-progress: false
# Only the publish job serializes (see its concurrency group): two publishes
# into one channel at once would race on the database. Builds run outside the
# lock, so a merge waits behind another merge's signing and upload, seconds,
# never behind its kernel build.
jobs:
changes:
@@ -58,11 +57,10 @@ 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.
# Reuse or rebuild, decided per entry and said out loud. A tree with
# no build artifact (PR artifacts last 7 days; a dispatch may name
# any package) goes to the rebuild job: aarch64 natively on GitHub's
# arm64 runner, x86_64 on a builder droplet, one runner per entry.
rebuild=()
echo "| package | arch | tree | decision |" >> "$GITHUB_STEP_SUMMARY"
echo "| --- | --- | --- | --- |" >> "$GITHUB_STEP_SUMMARY"
@@ -73,13 +71,23 @@ jobs:
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)"')
# The plan the publish job makes, made here before a runner is
# asked for: a tree the channel already holds at master's version
# (a re-run, or a dispatch naming a package that is fine) needs
# no build, and an x86 rebuild would wait minutes for a droplet
# to find that out in seconds.
plan=""
[[ -n "$found" ]] || plan=$(bin/build --dry-run --mirror edge --arch "$arch" --package "$package" 2>&1 | grep -E '^==> Plan complete' || true)
if [[ -n "$found" ]]; then
decision="reuse the build artifact ($found)"
elif [[ -n "$plan" && -z "$(sed -E 's/.*would build: *//' <<<"$plan" | tr -d '[:space:]')" ]]; then
decision="already published at master's version, nothing to build"
elif [[ $arch == aarch64 ]]; then
decision="no build artifact: rebuild natively on ubuntu-24.04-arm"
rebuild+=("$entry")
rebuild+=("$(jq -c '. + {runner: "[\"ubuntu-24.04-arm\"]"}' <<<"$entry")")
else
decision="no build artifact: build in the publish job on the self-hosted builder"
decision="no build artifact: rebuild on a builder droplet"
rebuild+=("$(jq -c '. + {runner: "[\"self-hosted\",\"omarchy-builder\"]"}' <<<"$entry")")
fi
echo "==> $label: $decision"
echo "| $package | $arch | ${hash:0:12} | $decision |" >> "$GITHUB_STEP_SUMMARY"
@@ -87,16 +95,19 @@ jobs:
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.
# "Build it now when there is none". Each entry builds exactly as
# build-pr.yml builds it (same runner kind, 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 these runners, and they hold no lock: entries build in parallel,
# and other merges publish while they do.
rebuild:
needs: changes
if: needs.changes.outputs.rebuild_count != '0'
runs-on: ubuntu-24.04-arm
timeout-minutes: 180
runs-on: ${{ fromJSON(matrix.runner) }}
# The droplets are x86, so aarch64 never builds there. omarchy-mac-boot
# under QEMU took 2h47m; native arm64 and x86 kernels fit easily.
timeout-minutes: 240
permissions:
contents: read
strategy:
@@ -109,7 +120,7 @@ jobs:
# 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)
- name: Build ${{ matrix.package }} (${{ matrix.arch }})
id: build
env:
CONTAINER_ENGINE: docker
@@ -140,23 +151,26 @@ jobs:
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; aarch64 comes from the
# rebuild job above), then walks each channel and
# One job for the whole merge. It collects every artifact for the merged
# tree (PR builds, or 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.
# is no race between packages; the concurrency group keeps one merge's
# publish from overlapping the next. It builds nothing, so it runs on a
# hosted runner in about a minute instead of waiting for a droplet.
# 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, rebuild]
if: ${{ !cancelled() && needs.changes.result == 'success' && needs.changes.outputs.count != '0' }}
runs-on: [self-hosted, omarchy-builder]
runs-on: ubuntu-latest
environment: publish
timeout-minutes: 240
timeout-minutes: 30
concurrency:
group: publish
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
with:
@@ -172,8 +186,8 @@ jobs:
EOF_MATRIX
cat plan.txt
# Fetch each package's PR artifact into build-output/edge/<arch>/, or
# build it when no artifact exists for exactly this tree. An artifact
# Fetch each package's artifact into build-output/edge/<arch>/: the PR's,
# or the rebuild job's when the PR's had expired. An artifact
# carries its package files inside packages.tar (see build-pr.yml and
# helpers/artifact-helpers.sh: the upload action rejects the colon in
# an epoch filename).
@@ -199,8 +213,8 @@ jobs:
mkdir -p "build-output/edge/$arch"
if [[ -n "$found" ]]; then
if [[ $from_run == "${{ github.run_id }}" ]]; then
kind=native-rebuild
echo "==> $label: artifact from this run's native $arch rebuild"
kind=rebuild
echo "==> $label: artifact from this run's $arch rebuild"
else
kind=pr-artifact
echo "==> $label: reusing the build artifact from run $from_run"
@@ -225,20 +239,11 @@ 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
else
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"build-failed"}' >> sources.jsonl; failed=1; break
fi
# Nothing builds here. No artifact means the rebuild failed (see
# the rebuild job), or an artifact expired between planning and
# now (re-run all jobs).
echo "::error::$label: no artifact from the rebuild job"
jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"build-failed"}' >> sources.jsonl; failed=1; break
fi
done < plan.txt
ls -1 build-output/edge/*/*.pkg.tar.zst 2>/dev/null || true
@@ -280,8 +285,26 @@ jobs:
cat publish-record.json
exit 0
fi
docker image inspect omarchy-pkg-builder:latest-x86_64-edge >/dev/null 2>&1 \
|| docker buildx build --load -t omarchy-pkg-builder:latest-x86_64-edge --build-arg MIRROR=edge build
# A fresh runner has no images, and building this one here cost
# every publish about 100 s (and 20 s more to start a container
# from it) for the 14 s of signing and upload it is needed for.
# builder-images.yml already publishes the tested image for exactly
# these build inputs under their key; pull that. Build only when no
# image carries the key: a merge that changed build/ publishes
# before the refresh it triggered has finished.
builder=omarchy-pkg-builder:latest-x86_64-edge
if ! docker image inspect "$builder" >/dev/null 2>&1; then
key=$(bin/builder-image key --arch x86_64 --mirror edge)
published="ghcr.io/omacom/omarchy-pkg-builder:$key"
if docker pull --quiet "$published" &&
[[ $(docker image inspect "$published" --format '{{index .Config.Labels "org.omarchy.builder.key"}}') == "$key" ]]; then
docker tag "$published" "$builder"
echo "==> Builder image: pulled $published"
else
echo "==> Builder image: none published for $key, building it"
docker buildx build --load -t "$builder" --build-arg MIRROR=edge build
fi
fi
# Group the merge's files by the (channel, architecture) slot each
# belongs to. A package's files live under build-output/edge/<built
@@ -374,7 +397,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=="native-rebuild" then "rebuilt natively on arm64" 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=="rebuild" or .source=="native-rebuild" then "rebuilt at merge" 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),
"",
+37 -47
View File
@@ -1,5 +1,14 @@
name: Sync Rebuild Triggers
# Rebuilds ride the unattended lane, like track-branches.yml: the pkgrel bump
# PR builds on the droplets, auto-merge lands it once `result`, `self-tests`
# and `build-isolation` are green, and the merge publishes. A rebuild that
# fails stays an unmerged red PR for a maintainer.
#
# The PR and auto-merge use the PAT in PKGS_BOT_TOKEN, because a merge made
# with the built-in GITHUB_TOKEN does not start publish.yml, and its pushes
# are held for approval instead of building.
on:
schedule:
# Every 6 hours, off the hour to dodge the scheduling backlog at :00
@@ -17,14 +26,17 @@ jobs:
permissions:
contents: write
pull-requests: write
outputs:
branch: ${{ steps.branch.outputs.branch }}
pushed_at: ${{ steps.pushed.outputs.at }}
number: ${{ steps.cpr.outputs.pull-request-number }}
operation: ${{ steps.cpr.outputs.pull-request-operation }}
head_sha: ${{ steps.cpr.outputs.pull-request-head-sha }}
steps:
- name: Require the bot 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:
@@ -85,19 +97,12 @@ jobs:
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
# Runs created by this push are newer than this; the approve job
# waits for them. A minute's slack absorbs runner clock skew.
- name: Record push time
if: steps.changes.outputs.has_changes == 'true'
id: pushed
run: echo "at=$(date -u -d '-1 minute' +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
- name: Create Pull Request
if: steps.changes.outputs.has_changes == 'true'
id: cpr
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.PKGS_BOT_TOKEN }}
commit-message: 'chore: rebuild against updated dependencies'
title: "chore: rebuild against updated dependencies${{ steps.branch.outputs.scope && format(' ({0})', steps.branch.outputs.scope) || '' }}"
body: |
@@ -109,10 +114,27 @@ jobs:
bump is what makes the rebuilt package an upgrade pacman will offer;
without it the build produces the version already published and no
one receives it.
This PR auto-merges once the build checks pass. A failing rebuild
leaves it open for a maintainer.
branch: ${{ steps.branch.outputs.branch }}
delete-branch: true
labels: automated
reviewers: ryanrhughes
# Auto-merge, not a direct merge: branch protection still has to see
# the build checks green before the rebuild lands.
- name: Enable auto-merge
if: steps.cpr.outputs.pull-request-number != ''
env:
GH_TOKEN: ${{ secrets.PKGS_BOT_TOKEN }}
PR: ${{ steps.cpr.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 != ''
@@ -125,35 +147,3 @@ jobs:
"🔴 <strong>Rebuild trigger sync failed</strong><br><a href=\"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\">View run</a>" \
'{content: $content}')" \
"$BASECAMP_CHATBOT_URL"
# GitHub holds pull_request runs from a GITHUB_TOKEN push for approval and
# creates no pull_request_target run for it, so approve-pr.yml never sees
# the sync's own pushes. Once a maintainer has labelled the PR
# build-approved, release the held runs for the commit just pushed. A
# separate job, so the sync container's token never holds actions: write.
approve:
needs: sync
if: ${{ !cancelled() && needs.sync.outputs.operation == 'updated' }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
actions: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Release held build and test runs if build-approved
uses: actions/github-script@v7
env:
NUMBER: ${{ needs.sync.outputs.number }}
BRANCH: ${{ needs.sync.outputs.branch }}
HEAD_SHA: ${{ needs.sync.outputs.head_sha }}
SINCE: ${{ needs.sync.outputs.pushed_at }}
with:
script: |
const approve = require('./.github/scripts/approve-sync-push.cjs');
const { NUMBER, BRANCH, HEAD_SHA, SINCE } = process.env;
await approve({ github, context, core, number: Number(NUMBER),
branch: BRANCH, headSha: HEAD_SHA, since: SINCE });
+11 -6
View File
@@ -113,7 +113,11 @@ jobs:
are left untouched; check the workflow result for outstanding failures.
branch: ${{ steps.branch.outputs.branch }}
delete-branch: true
labels: automated
# The bot is trusted; build-approved lets the approve job below
# release GitHub's hold on its pushes without a maintainer.
labels: |
automated
build-approved
reviewers: ryanrhughes
- name: Notify Basecamp on failure
@@ -130,12 +134,13 @@ jobs:
# GitHub holds pull_request runs from a GITHUB_TOKEN push for approval and
# creates no pull_request_target run for it, so approve-pr.yml never sees
# the sync's own pushes. Once a maintainer has labelled the PR
# build-approved, release the held runs for the commit just pushed. A
# separate job, so the sync container's token never holds actions: write.
# the sync's own pushes. The sync labels its PR build-approved, so release
# the held runs for the commit just pushed, whether it opened the PR or
# updated it. A separate job, so the sync container's token never holds
# actions: write.
approve:
needs: sync
if: ${{ !cancelled() && needs.sync.outputs.operation == 'updated' }}
if: ${{ !cancelled() && (needs.sync.outputs.operation == 'created' || needs.sync.outputs.operation == 'updated') }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
@@ -146,7 +151,7 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Release held build and test runs if build-approved
- name: Release held build and test runs
uses: actions/github-script@v7
env:
NUMBER: ${{ needs.sync.outputs.number }}
+1
View File
@@ -67,6 +67,7 @@ jobs:
./tests/artifact-helpers.sh
./tests/limine-mkinitcpio-hook.sh
./tests/voxtype-bin-install.sh
./tests/superwhisper-bin-install.sh
pacman -S --noconfirm --quiet rclone >/dev/null
./tests/publish-artifact.sh
'
+79
View File
@@ -0,0 +1,79 @@
name: Unpublish retired packages
# Takes packages out of the channel databases after their recipes are gone
# from master. Deleting a recipe stops it building; this stops pacman
# offering it. Files stay in the bucket (see bin/unpublish-packages).
#
# Only packages with no recipe on master: one that still has a recipe would
# come back on its next publish, and refusing it keeps a typo from pulling a
# live package out of every channel.
on:
workflow_dispatch:
inputs:
packages:
description: "Space-separated pkgbases whose recipes were removed from master"
required: true
channels:
description: "Channels to remove them from"
required: true
default: "edge rc stable"
jobs:
unpublish:
runs-on: ubuntu-latest
environment: publish
timeout-minutes: 15
# The publish job's group: one writer per channel database at a time.
concurrency:
group: publish
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Refuse packages that still have a recipe
env:
PACKAGES: ${{ github.event.inputs.packages }}
CHANNELS: ${{ github.event.inputs.channels }}
run: |
set -euo pipefail
for c in $CHANNELS; do
[[ $c == edge || $c == rc || $c == stable ]] || { echo "::error::Unknown channel: $c"; exit 1; }
done
for p in $PACKAGES; do
[[ $p =~ ^[a-z0-9@._+-]+$ ]] || { echo "::error::Not a package name: $p"; exit 1; }
if [[ -e pkgbuilds/$p ]]; then
echo "::error::pkgbuilds/$p still exists on master; remove the recipe first"
exit 1
fi
done
- name: Unpublish
env:
PACKAGES: ${{ github.event.inputs.packages }}
CHANNELS: ${{ github.event.inputs.channels }}
RCLONE_CONFIG_R2_TYPE: s3
RCLONE_CONFIG_R2_PROVIDER: Cloudflare
RCLONE_CONFIG_R2_NO_CHECK_BUCKET: "true"
RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
OMARCHY_PUBLISH_PREFIX: ${{ vars.OMARCHY_PUBLISH_PREFIX }}
run: |
set -euo pipefail
# repo-remove and bsdtar are Arch tools: run in the tested builder
# image, as the publish job does.
builder=ghcr.io/omacom/omarchy-pkg-builder:$(bin/builder-image key --arch x86_64 --mirror edge)
docker pull --quiet "$builder"
for mirror in $CHANNELS; do
for arch in x86_64 aarch64; do
docker run --rm \
-e OMARCHY_PUBLISH_PREFIX \
-e RCLONE_CONFIG_R2_TYPE -e RCLONE_CONFIG_R2_PROVIDER -e RCLONE_CONFIG_R2_ENDPOINT -e RCLONE_CONFIG_R2_NO_CHECK_BUCKET \
-e RCLONE_CONFIG_R2_ACCESS_KEY_ID -e RCLONE_CONFIG_R2_SECRET_ACCESS_KEY \
-v "$PWD:/w:ro" -w /w "$builder" \
bin/unpublish-packages --remote R2:omarchy-pkgs --mirror "$mirror" --arch "$arch" $PACKAGES
done
done
+38 -11
View File
@@ -565,12 +565,26 @@ bin/repo deploy # Build locally, then publish from the host
bin/repo push # Upload local builds to the host and publish
bin/add-package <package> # Add an Omarchy-owned package with metadata
bin/package-worktree <package> # Inspect historical AUR provenance in a scratch workspace
bin/repo remove <package> # Remove package
bin/repo remove <package> # Remove package (host workflow; CI uses unpublish.yml)
bin/sync-upstream # Update packages that track a vendor release feed
bin/sync-rebuilds # Bump pkgrel for packages whose dependencies moved
bin/clean-docker # Clear Docker images/cache (forces fresh rebuild)
```
### Retiring a package
Delete its recipe directory in a PR. Once that merges, take it out of the
channel databases with the **Unpublish retired packages** workflow:
```
gh workflow run unpublish.yml -f packages="<pkgbase> ..." -f channels="edge rc stable"
```
It removes every entry built from those pkgbases (split outputs and `-debug`
included) from both architectures' databases, and refuses any package that
still has a recipe on master. Package files stay in the bucket: published
filenames are immutable, and nothing references them once the entries are gone.
### Package Metadata Tools
```bash
@@ -893,15 +907,15 @@ 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 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.
2. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories, opens a PR, and enables auto-merge. The PR lands once its build checks pass; a rebuild that fails stays an open red PR for a maintainer.
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
The tracking and rebuild PRs and their 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
build-and-publish chain, so both workflows require this secret before they run.
The reviewed upstream sync continues to use `GITHUB_TOKEN` and requires
maintainer approval as before. See [setup instructions](docs/upstream-sources.md#enable-unattended-branch-updates).
Scheduled runs regenerate one shared PR (`auto/sync-upstream`, `auto/sync-rebuilds`)
@@ -912,13 +926,26 @@ pending updates. The next scheduled run still picks the same update up in the
shared PR if it has not merged by then; identical package trees reuse the same
build artifacts.
Sync PRs are pushed with `GITHUB_TOKEN`, so GitHub holds their build and test
Upstream sync PRs are pushed with `GITHUB_TOKEN`, so GitHub holds their build and test
runs for approval on every push and starts no `pull_request_target` workflow
for them. Once **`build-approved`** is on a sync PR, the sync workflow's own
`approve` job releases the held runs for each commit it pushes. A push to an
`auto/sync-*` branch does not cancel the PR's in-flight build: the new build
waits for it and then reuses its artifacts, so a long aarch64 build is not
restarted by every sync.
for them. The upstream sync labels its own PRs **`build-approved`**, and
its `approve` job releases the held runs for each commit they push, including
the push that opens the PR. A push to an `auto/sync-*` branch does not cancel
the PR's in-flight build: the new build waits for it and then reuses its
artifacts, so a long aarch64 build is not restarted by every sync.
Package PRs that are trusted to build also merge themselves.
`auto-merge-pr.yml` enables auto-merge (with `PKGS_BOT_TOKEN`, so the merge
publishes) on any open, non-draft PR whose author is a collaborator, vouched,
or a bot, or that carries **`build-approved`**, and that changes only
packages: anything under `pkgbuilds/`, plus the test a package PR brings with
it (a new file under `tests/`, and `test.yml` lines that only run new
`./tests/*.sh`). The PR lands once `result`, `self-tests` and
`build-isolation` pass; a red build stays open. PRs that also touch
workflows, scripts, build tooling or existing tests still need a maintainer, as does
the upstream sync (`auto/sync-upstream`), which labels itself. Removing
`build-approved` withdraws the auto-merge it armed. For a PR opened before
the workflow existed, run it by hand: `gh workflow run auto-merge-pr.yml -f pr=<number>`.
To approve builds for an unvouched contributor's PR, apply **`build-approved`**.
Until approval, the PR shows **Awaiting build approval** and its required
+1 -1
View File
@@ -86,7 +86,7 @@ while [[ $# -gt 0 ]]; do
echo " $0 --arch aarch64"
echo " $0 --mirror stable"
echo " $0 --package yay"
echo " $0 --package yay elephant cursor-bin"
echo " $0 --package yay walker cursor-bin"
echo ""
echo "Environment (for CI and resumed builds; defaults keep today's behaviour):"
echo " OMARCHY_KEEP_BUILD_WORKSPACE=1 keep build-output and reuse packages already there"
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# Retire packages from one channel of the remote repository.
#
# unpublish-packages --mirror <edge|rc|stable> --arch <arch> <pkgbase...>
#
# The counterpart of publish-artifact, with the same steps:
# 1. pull the channel's current database from the remote
# 2. find every entry built from the named pkgbases (so a package's split
# outputs and -debug go with it)
# 3. repo-remove them
# 4. upload the database
#
# Package files stay in the bucket. Published filenames are immutable and the
# R2 cache cannot recover from a rewrite; an unreferenced file costs nothing
# and pacman never sees it. Naming a package the channel does not hold is not
# an error, so a re-run is harmless.
#
# The remote is an rclone remote (REMOTE, default the production one);
# OMARCHY_PUBLISH_PREFIX can point a proof run at a scratch prefix.
set -euo pipefail
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
REMOTE=${REMOTE:-pkgs.omarchy.org:omarchy-pkgs}
PREFIX=${OMARCHY_PUBLISH_PREFIX:-}
BASES=()
while [[ $# -gt 0 ]]; do
case $1 in
--mirror) MIRROR=$2; require_valid_mirror "$MIRROR"; shift 2 ;;
--arch) ARCH=$2; require_valid_arch "$ARCH"; shift 2 ;;
--remote) REMOTE=$2; shift 2 ;;
-h|--help) sed -n '2,19p' "$0"; exit 0 ;;
-*) print_error "Unknown option: $1"; exit 1 ;;
*) BASES+=("$1"); shift ;;
esac
done
(( ${#BASES[@]} )) || { print_error "No packages given"; exit 1; }
DEST="$REMOTE/${PREFIX:+$PREFIX/}$MIRROR/$ARCH"
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
print_header "Unpublish from $DEST"
# --- 1. pull the current database -----------------------------------------
mkdir -p "$WORK/repo"
listing=$(rclone lsf "$DEST/" --s3-no-head 2>/dev/null || true)
if ! grep -q '^omarchy.db.tar.zst$' <<<"$listing"; then
print_info "No database at $DEST; nothing to remove"
exit 0
fi
rclone copy "$DEST/omarchy.db.tar.zst" "$WORK/repo" --s3-no-head
rclone copy "$DEST/omarchy.files.tar.zst" "$WORK/repo" --s3-no-head 2>/dev/null || true
before=$(tar -tf "$WORK/repo/omarchy.db.tar.zst" | grep -c '/$')
print_info "Pulled current database ($before entries)"
# --- 2. entries built from the named pkgbases -----------------------------
names=$(bsdtar -xOf "$WORK/repo/omarchy.db.tar.zst" --include '*/desc' |
awk -v bases=" ${BASES[*]} " '
/^%NAME%$/ { getline name }
/^%BASE%$/ { getline base; if (index(bases, " " base " ")) print name }')
if [[ -z "$names" ]]; then
print_info "None of ${BASES[*]} is in $MIRROR/$ARCH; nothing to remove"
exit 0
fi
mapfile -t NAMES <<<"$names"
for n in "${NAMES[@]}"; do print_step "removing $n"; done
# --- 3. repo-remove ---------------------------------------------------------
( cd "$WORK/repo" && repo-remove --quiet omarchy.db.tar.zst "${NAMES[@]}" )
ln -sf omarchy.db.tar.zst "$WORK/repo/omarchy.db"
ln -sf omarchy.files.tar.zst "$WORK/repo/omarchy.files"
after=$(tar -tf "$WORK/repo/omarchy.db.tar.zst" | grep -c '/$')
(( before - after == ${#NAMES[@]} )) || {
print_error "Expected to remove ${#NAMES[@]} entries, removed $((before - after))"; exit 1; }
print_info "Database now has $after entries"
# --- 4. upload the database -------------------------------------------------
rclone copy "$WORK/repo" "$DEST" --s3-no-head --checksum --copy-links --filter '+ omarchy.db*' --filter '+ omarchy.files*' --filter '- *'
print_success "Removed ${#NAMES[@]} package(s) from $DEST"
+17 -4
View File
@@ -12,9 +12,12 @@ signing on merge exactly as before.
- `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.
Polls for queued jobs with our label, creates one g5-32vcpu-64gb-50gb droplet (ric1) per job up
Polls for queued jobs with our label, creates one g5-32vcpu-64gb-50gb droplet per job up
to `MAX_DROPLETS`, deletes droplets that are powered off or older than
`MAX_AGE_MINUTES`. No inbound endpoint. Plain curl against both APIs, no
`MAX_AGE_MINUTES`, or still provisioning after `MAX_BOOT_MINUTES`. Builders go in any region DigitalOcean lists the size in
stock in (`REGIONS` only sets which to try first); a refused create, logged
with DigitalOcean's message, falls back to the next region, then the next
of `SIZES`. No inbound endpoint. Plain curl against both APIs, no
doctl and no gh: a token in the environment cannot pick the wrong account
the way a saved doctl context can. Needs curl and jq.
`tests/controller.sh` exercises every decision against canned responses.
@@ -31,6 +34,13 @@ Administration read+write (registration tokens). The DO token is baked into
the box's env file, so it is the account that pays for builder droplets.
Watch it with `journalctl -u omarchy-controller -f` on the box.
Each tick pulls the box's checkout first, so a merged `controller.sh` is live
within a minute. The unit and timer are copies made at creation; after
changing them, on the box:
cp /opt/omarchy-pkgs/ci/controller-box/omarchy-controller.{service,timer} /etc/systemd/system/
systemctl daemon-reload
## What the spike proved (2026-09-17, fork ryanrhughes/omarchy-pkgs)
- `bin/build` works from a bare clone: with no local published tree it
@@ -70,8 +80,11 @@ Watch it with `journalctl -u omarchy-controller -f` on the box.
packages then signatures then the db.
- 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.
merged tree has no artifact, publish.yml rebuilds it in its own job, aarch64
there and x86_64 on a droplet, outside the publish lock.
- Publish itself builds nothing: it signs and uploads on `ubuntu-latest` in the
tested builder image pulled from GHCR, and only that job holds the `publish`
concurrency group, so a merge waits for seconds of signing, not for builds.
- 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
+6 -2
View File
@@ -5,10 +5,14 @@ GITHUB_TOKEN=github_pat_...
REPO=omacom/omarchy-pkgs
LABEL=omarchy-builder
TAG=omarchy-builder
REGION=ric1
SIZE=g5-32vcpu-64gb-50gb
# Builder sizes, tried in order in any region that has them in stock.
SIZES="g5-32vcpu-64gb-50gb g5-32vcpu-128gb-50gb"
# Optional: regions to try first, e.g. "ric1". Empty means any.
REGIONS=
MAX_DROPLETS=6
MAX_AGE_MINUTES=200
# Delete a droplet DigitalOcean still reports as provisioning after this long.
MAX_BOOT_MINUTES=10
LOCK=/run/omarchy-controller/lock
# Operator public keys for root on every builder droplet (JSON array).
# create.sh fills this from the operators' GitHub keys.
@@ -7,6 +7,9 @@ Wants=network-online.target
Type=oneshot
User=controller
EnvironmentFile=/etc/omarchy-controller.env
# Run the branch's current controller, not the one cloned when the box was
# built. As root (the checkout's owner); a failed pull keeps the last one.
ExecStartPre=-+/usr/bin/git -C /opt/omarchy-pkgs pull --ff-only --quiet
ExecStart=/opt/omarchy-pkgs/ci/controller.sh
# The reaper's safety net is time, not state; a hung tick must not hold the lock.
TimeoutStartSec=240
+88 -18
View File
@@ -4,7 +4,8 @@
# Run from a systemd timer every minute on a small always-on droplet. No
# inbound endpoint: it polls GitHub for queued jobs wanting our label, creates
# one ephemeral droplet per job (up to MAX_DROPLETS), and deletes droplets
# that have powered off or exceeded MAX_AGE_MINUTES. The reaper does not
# that have powered off, exceeded MAX_AGE_MINUTES, or are still provisioning
# after MAX_BOOT_MINUTES. The reaper does not
# trust its own bookkeeping: it lists by tag and acts on what DigitalOcean
# reports.
#
@@ -21,11 +22,19 @@ REPO=${REPO:?owner/name}
: "${DIGITALOCEAN_TOKEN:?}" "${GITHUB_TOKEN:?}"
LABEL=${LABEL:-omarchy-builder}
TAG=${TAG:-omarchy-builder}
REGION=${REGION:-ric1}
SIZE=${SIZE:-g5-32vcpu-64gb-50gb}
# Sizes to try, in order, in any region DigitalOcean lists them in stock. A
# size can sell out in a region for hours; the create is then refused with
# 422 and the next region, then the next size, is tried. REGIONS only orders
# the regions tried first. SIZE and REGION, if set, are one-item lists.
SIZES=${SIZES:-${SIZE:-g5-32vcpu-64gb-50gb g5-32vcpu-128gb-50gb}}
REGIONS=${REGIONS:-${REGION:-}}
IMAGE=${IMAGE:-ubuntu-24-04-x64}
MAX_DROPLETS=${MAX_DROPLETS:-4}
MAX_AGE_MINUTES=${MAX_AGE_MINUTES:-200}
# A droplet DigitalOcean still reports as "new" this long after creation is
# stuck provisioning. Left alone it counts as a runner booting, and holds a
# queued job until MAX_AGE_MINUTES.
MAX_BOOT_MINUTES=${MAX_BOOT_MINUTES:-10}
RUNNER_VERSION=${RUNNER_VERSION:-2.337.0}
CLOUD_INIT=${CLOUD_INIT:-$(dirname "$0")/runner-cloud-init.yaml}
# Operator public keys authorized on every builder (JSON array of strings).
@@ -39,7 +48,8 @@ log() { echo "$(date '+%F %T') $*"; }
# both, so every decision below is exercised against canned responses.
do_api() { # do_api <path> [curl args...]
local path=$1; shift
curl -fsS -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
# --fail-with-body: a refused create still prints why.
curl -sS --fail-with-body -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
-H "Content-Type: application/json" "https://api.digitalocean.com/v2/$path" "$@"
}
gh_api() { # gh_api <path> [curl args...]
@@ -55,7 +65,8 @@ reap() {
while read -r id status created; do
[[ -n "$id" ]] || continue
age=$(( (now - $(date -d "$created" +%s)) / 60 ))
if [[ $status == off ]] || (( age > MAX_AGE_MINUTES )); then
if [[ $status == off ]] || (( age > MAX_AGE_MINUTES )) ||
{ [[ $status == new ]] && (( age > MAX_BOOT_MINUTES )); }; then
log "deleting droplet $id (status=$status age=${age}m)"
do_api "droplets/$id" -X DELETE
fi
@@ -64,18 +75,40 @@ reap() {
}
# --- demand ----------------------------------------------------------------
# Emit every item, including later pages of large build matrices. Keep API
# failures fatal so a failed query cannot look like an empty queue.
gh_items() {
local path=$1 key=$2 page=1 response count separator="?"
[[ $path != *"?"* ]] || separator="&"
while :; do
response=$(gh_api "${path}${separator}per_page=100&page=$page") || return 1
count=$(jq -er --arg key "$key" '.[$key] | arrays | length' <<< "$response") || return 1
jq -c --arg key "$key" '.[$key][]' <<< "$response" || return 1
(( count == 100 )) || break
((page += 1))
done
}
queued_jobs() {
local run
gh_api "repos/$REPO/actions/runs?status=queued&per_page=50" --get \
| jq -r '.workflow_runs[].id' |
local status runs run
# A workflow can be in progress while most of its matrix is still queued.
runs=$(
for status in queued in_progress; do
gh_items "repos/$REPO/actions/runs?status=$status" workflow_runs || exit 1
done
) || return 1
jq -r '.id' <<< "$runs" | sort -u |
while read -r run; do
gh_api "repos/$REPO/actions/runs/$run/jobs" \
| jq -r --arg l "$LABEL" '.jobs[] | select(.status=="queued") | select(.labels | index($l)) | .id'
done | wc -l
gh_items "repos/$REPO/actions/runs/$run/jobs" jobs |
jq -r --arg l "$LABEL" 'select(.status=="queued") | select(.labels | index($l)) | .id' || return 1
done | sort -u | wc -l
}
live_droplets() {
do_api "droplets?tag_name=$TAG&per_page=200" | jq '[.droplets[] | select(.status != "off")] | length'
# Not the ones reap() just deleted: DigitalOcean can list them for a while.
do_api "droplets?tag_name=$TAG&per_page=200" | jq --argjson boot "$MAX_BOOT_MINUTES" '
[.droplets[] | select(.status != "off")
| select(.status != "new" or (now - (.created_at | fromdateiso8601)) / 60 <= $boot)] | length'
}
busy_runners() {
@@ -83,22 +116,59 @@ busy_runners() {
| jq --arg l "$LABEL" '[.runners[] | select(.busy) | select(any(.labels[]; .name == $l))] | length'
}
# --- capacity --------------------------------------------------------------
# "size region" lines to try, best first: SIZES order, then REGIONS order,
# then every other region where DigitalOcean lists the size in stock.
candidates() {
local page=1 response count catalog=""
while :; do
response=$(do_api "sizes?per_page=200&page=$page") || return 1
count=$(jq -er '.sizes | arrays | length' <<< "$response") || return 1
catalog+=$(jq -c '.sizes[]' <<< "$response")$'\n'
(( count == 200 )) || break
((page += 1))
done
jq -rs --arg sizes "$SIZES" --arg regions "$REGIONS" '
($regions | split(" ") | map(select(length > 0))) as $pref
| INDEX(.slug) as $by
| $sizes | split(" ") | map(select(length > 0)) | .[]
| . as $size | $by[$size] // {} | select(.available == true)
| .regions as $in
| (($pref | map(select(. as $r | $in | index($r)))) + ($in - $pref))[]
| "\($size) \(.)"' <<< "$catalog"
}
# --- create ----------------------------------------------------------------
# Built once per tick by the first create; a refused pair is dropped from it.
CANDIDATES=""
create_droplet() {
local token userdata name body
local token userdata name size region body response
[[ -n $CANDIDATES ]] || CANDIDATES=$(candidates) || return 1
token=$(gh_api "repos/$REPO/actions/runners/registration-token" -X POST | jq -r .token)
userdata=$(sed -e "s|__REPO__|$REPO|g" -e "s|__RUNNER_TOKEN__|$token|g" \
-e "s|__RUNNER_LABELS__|$LABEL|g" -e "s|__RUNNER_VERSION__|$RUNNER_VERSION|g" \
-e "s|__SSH_KEYS_JSON__|$SSH_KEYS_JSON|" "$CLOUD_INIT")
name="$TAG-$(date +%s)-$RANDOM"
body=$(jq -n --arg name "$name" --arg region "$REGION" --arg size "$SIZE" --arg image "$IMAGE" \
--arg tag "$TAG" --arg ud "$userdata" \
'{name:$name, region:$region, size:$size, image:$image, tags:[$tag], user_data:$ud, monitoring:false}')
log "creating $name ($SIZE)"
do_api droplets -X POST -d "$body" | jq -r '"created droplet \(.droplet.id)"'
while read -r size region; do
[[ -n $size ]] || continue
body=$(jq -n --arg name "$name" --arg region "$region" --arg size "$size" --arg image "$IMAGE" \
--arg tag "$TAG" --arg ud "$userdata" \
'{name:$name, region:$region, size:$size, image:$image, tags:[$tag], user_data:$ud, monitoring:false}')
log "creating $name ($size in $region)"
if response=$(do_api droplets -X POST -d "$body"); then
jq -r '"created droplet \(.droplet.id)"' <<< "$response"
return 0
fi
log "$size in $region refused: $(jq -r .message <<< "$response" 2>/dev/null || echo "$response")"
CANDIDATES=$(grep -Fvx "$size $region" <<< "$CANDIDATES" || true)
done <<< "$CANDIDATES"
# Every size refused everywhere: the rest of this tick's creates would be too.
log "no size in '$SIZES' can be created in any region"
return 1
}
controller_tick() {
CANDIDATES=""
reap
local queued live busy available need room
queued=$(queued_jobs)
+4 -2
View File
@@ -45,6 +45,10 @@ write_files:
content: |
#!/bin/bash
set -euo pipefail
# Power off after the one job, and also when the download or the
# registration fails: the controller deletes powered-off droplets, but
# counts a running one as a runner still booting until MAX_AGE_MINUTES.
trap 'sudo poweroff' EXIT
cd /home/runner
mkdir -p actions-runner && cd actions-runner
arch=$(uname -m); [[ $arch == x86_64 ]] && arch=x64
@@ -58,8 +62,6 @@ write_files:
--labels "__RUNNER_LABELS__" \
--replace
./run.sh
# One job done. Power off; the controller deletes powered-off droplets.
sudo poweroff
runcmd:
# With no account ssh key attached, DO expires root's password, and sshd
+1 -20
View File
@@ -151,7 +151,6 @@ in `origin` and has no effect on release selection.
| `1password-beta` | debian | [https://downloads.1password.com/linux/debian/amd64/dists/beta/main/binary-amd64/Packages](https://downloads.1password.com/linux/debian/amd64/dists/beta/main/binary-amd64/Packages) |
| `1password-cli` | json | [https://app-updates.agilebits.com/check/1/0/CLI2/en/0](https://app-updates.agilebits.com/check/1/0/CLI2/en/0) |
| `aether` | github | [omacom/aether](https://github.com/omacom/aether) |
| `asusctl` | git_tags | [https://github.com/OpenGamingCollective/asusctl.git](https://github.com/OpenGamingCollective/asusctl.git) |
| `basecamp-cli` | github | [basecamp/basecamp-cli](https://github.com/basecamp/basecamp-cli) |
| `bun-bin` | github | [oven-sh/bun](https://github.com/oven-sh/bun) |
| `claude-code` | regex | [https://downloads.claude.ai/claude-code-releases/latest](https://downloads.claude.ai/claude-code-releases/latest) |
@@ -162,21 +161,6 @@ in `origin` and has no effect on release selection.
| `dbxcli-bin` | github | [dropbox/dbxcli](https://github.com/dropbox/dbxcli) |
| `dropbox` | redirect | [https://www.dropbox.com/download?plat=lnx.x86_64](https://www.dropbox.com/download?plat=lnx.x86_64) |
| `dropbox-cli` | regex | [https://linux.dropbox.com/packages/](https://linux.dropbox.com/packages/) |
| `elephant` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-all` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-archlinuxpkgs` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-bluetooth` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-calc` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-clipboard` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-desktopapplications` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-files` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-menus` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-providerlist` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-runner` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-symbols` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-todo` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-unicode` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `elephant-websearch` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) |
| `heroic-games-launcher-bin` | github | [Heroic-Games-Launcher/HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) |
| `hyprshade` | pypi | [hyprshade](https://pypi.org/project/hyprshade/) |
| `lib32-nvidia-580xx-utils` | regex | [https://download.nvidia.com/XFree86/Linux-x86_64/](https://download.nvidia.com/XFree86/Linux-x86_64/) |
@@ -213,7 +197,6 @@ in `origin` and has no effect on release selection.
| `vi` | regex | [https://sources.archlinux.org/other/vi/](https://sources.archlinux.org/other/vi/) |
| `visual-studio-code-bin` | json | [https://update.code.visualstudio.com/api/update/linux-deb-x64/stable/latest](https://update.code.visualstudio.com/api/update/linux-deb-x64/stable/latest) |
| `walker` | github | [abenz1267/walker](https://github.com/abenz1267/walker) |
| `xdg-terminal-exec` | git_tags | [https://gitlab.freedesktop.org/Vladimir-csp/xdg-terminal-exec.git](https://gitlab.freedesktop.org/Vladimir-csp/xdg-terminal-exec.git) |
| `xpadneo-dkms` | github | [atar-axis/xpadneo](https://github.com/atar-axis/xpadneo) |
| `yaru-icon-theme` | git_tags | [https://github.com/ubuntu/yaru.git](https://github.com/ubuntu/yaru.git) |
| `yay` | github | [Jguer/yay](https://github.com/Jguer/yay) |
@@ -221,12 +204,10 @@ in `origin` and has no effect on release selection.
## Existing manual holds
`grok-bot`, `libfprint-git`, `libretro-cap32-git`, `libretro-database-git`, `libretro-fbneo-git`, `libretro-uae-git`, `libretro-vice-git`, `quickshell-git`, `supergfxctl`.
`libfprint-git`, `libretro-cap32-git`, `libretro-database-git`, `libretro-fbneo-git`, `libretro-uae-git`, `libretro-vice-git`, `quickshell-git`, `supergfxctl`.
These packages were already excluded from automatic AUR updates. The migration preserves that policy.
`linux-firmware-cirrus` is a deliberate hold: a self-retiring shim that ships Arch's linux-firmware-cirrus 20260910-2 payload to stable while stable's Arch snapshot is on 20260810-2 (Dell XPS 13 DX13260 / 1028:0e54 speaker firmware). It is versioned 20260810-3 so the genuine Arch package supersedes it as soon as the snapshot advances; bumping it to the Arch version would defeat that. Delete the recipe once stable's snapshot carries linux-firmware >= 20260910.
`m1n1-aurora` and `uboot-asahi` are deliberate holds: Apple Silicon boot code, pinned by hand like `linux-aurora`, and bumped only after a cold boot on the qualification Macs. `m1n1-aurora` pins an aurora-silicon/m1n1 commit plus a local patch. `uboot-asahi` follows asahi-alarm's recipe and patch set (asahi-alarm/PKGBUILDs), which a tag watch on AsahiLinux/u-boot cannot carry.
`cua-driver-bin` is a deliberate hold: Omarchy bumps it by hand, so a Cua release ships only when a maintainer has verified it. It keeps its `.omarchy/upstream.sh` hook and `min_release_age`, so lifting the hold means removing `"sync": false`. `cua-hyprland-plugin` declares no upstream source, so no automation updates it either.
+1 -1
View File
@@ -10,7 +10,7 @@ case "${CARCH}" in
;;
esac
pkgver=8.12.40_27.BETA
pkgrel=1
pkgrel=2
conflicts=('1password' '1password-beta-bin')
pkgdesc="Password manager and secure wallet"
arch=('x86_64' 'aarch64')
+1 -1
View File
@@ -3,7 +3,7 @@
pkgname=1password-cli
pkgver=2.40.0
pkgrel=1
pkgrel=2
pkgdesc="1Password command line tool"
arch=('x86_64' 'i686' 'arm' 'armv6h' 'aarch64')
url="https://app-updates.agilebits.com/product_history/CLI2"
+6 -6
View File
@@ -1,6 +1,6 @@
pkgname=1password
pkgver=8.12.38
pkgrel=1
pkgver=8.12.40
pkgrel=2
conflicts=('1password-beta' '1password-beta-bin')
pkgdesc="Password manager and secure wallet"
arch=('x86_64' 'aarch64')
@@ -17,12 +17,12 @@ source_aarch64=(
"https://downloads.1password.com/linux/tar/stable/aarch64/1password-${pkgver}.arm64.tar.gz.sig"
)
sha256sums_x86_64=(
'8b9767276ad6795a8f1b79306aa8282f7d79617c7ca08beda7846ff79a1bb4f2'
'5e22ccd53626d814b84de65f9637c2e6994f9f42d4df29f611bc1e4f7e3057f8'
'0ae9645d31be78a8fb57d15f49e5fa4f0b67a0b3608797a410e8fd36f0206266'
'2f777820dc2eb6e7b7b38f4557a897f97fb3259443261fdfb2008127bd975817'
)
sha256sums_aarch64=(
'cb8b3667a0f51705e40a4e1e4ab83d440c57324cfab3f3bfacb713e40e63129d'
'2e92ec19393c7bdaf84e62f2b9ed493f2871b043ae875b302b049f4e2f2ec8e1'
'7476c0fc8215338cd9f304b14822688010fd8ed54d5ea4367c0bbbf72845be1e'
'80412176560a3f76180f7c05ae7ebafe21fac764349cfeed71fe498ee25564ee'
)
validpgpkeys=('3FEF9748469ADBE15DA7CA80AC2D62742012EA22')
+5 -5
View File
@@ -1,7 +1,7 @@
# Maintainer: Bjarne Øverli <bjarne@oever.li>
pkgname=aether
pkgver=4.31.1
pkgrel=1
pkgver=4.32.0
pkgrel=2
pkgdesc='Desktop theming application - extract colors from wallpapers and apply cohesive themes'
arch=('x86_64' 'aarch64')
url='https://github.com/omacom/aether'
@@ -10,9 +10,9 @@ depends=('webkit2gtk-4.1' 'gtk3')
source=("aether-${pkgver}.tar.gz::https://github.com/omacom/aether/archive/refs/tags/v${pkgver}.tar.gz")
source_x86_64=("aether-linux-amd64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-amd64")
source_aarch64=("aether-linux-arm64-${pkgver}::https://github.com/omacom/aether/releases/download/v${pkgver}/aether-linux-arm64")
sha256sums=('bf828f39d4317a1fb52343712dcf6b22824780596850c32426ca19ad825d18d6')
sha256sums_x86_64=('2ac775a33d63d60e4686cf4ab1515edd32041d3ebccca061f736255e4ae1387a')
sha256sums_aarch64=('d74313db4ba62da50c37228ff2ee2d2b1391399e73ac4f4b473a5326edd88b7e')
sha256sums=('3234e5138a46699f8f47330ba582244d5063c8356ffaae1458323e4dda02be82')
sha256sums_x86_64=('c705a4abef734b17ae37cdbff58a9a796517e6aa5f93ef18b68e3ee99d547ff9')
sha256sums_aarch64=('f70195deba008204d58661c3ec1442a16e63f3358b4579969facb0e55dbf63c4')
noextract=("aether-linux-amd64-${pkgver}" "aether-linux-arm64-${pkgver}")
package() {
-3
View File
@@ -1,3 +0,0 @@
[asusctl]
source = "git"
git = "https://github.com/OpenGamingCollective/asusctl.git"
-13
View File
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"git_tags": "https://github.com/OpenGamingCollective/asusctl.git",
"pattern": "(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "asusctl",
"commit": "b0ec6ca495eb331a684db91b0fe12085a868b632"
}
}
-59
View File
@@ -1,59 +0,0 @@
# Maintainer: Mahdi Sarikhani <mahdisarikhani@outlook.com>
# Contributor: Fabian Bornschein <fabiscafe@archlinux.org>
# Contributor: Static_Rocket
pkgbase=asusctl
pkgname=(asusctl rog-control-center)
pkgver=6.5.0
pkgrel=1
pkgdesc="Daemon and tools to control your ASUS ROG laptop"
arch=('x86_64')
url="https://asus-linux.org"
license=('MPL-2.0')
makedepends=('cargo' 'fontconfig')
source=("${pkgbase}-${pkgver}.tar.gz::https://github.com/OpenGamingCollective/asusctl/archive/${pkgver}.tar.gz")
b2sums=('4179e08a60f9480b62e41d84faade1f46407140a213ca4d60c8699837a2486bda8e66b4ca43fa06149667d02e3d060c3efd792348f9a93a675f762d6ea2d05f8')
prepare() {
cd "${pkgbase}-${pkgver}"
export RUSTUP_TOOLCHAIN=stable
cargo fetch --locked --target host-tuple
}
build() {
cd "${pkgbase}-${pkgver}"
export RUSTUP_TOOLCHAIN=stable
export CARGO_TARGET_DIR=target
make build
}
package_asusctl() {
pkgdesc="An utility for Linux to control many aspects of various ASUS laptops"
depends=('glibc' 'libgcc' 'libusb' 'systemd-libs')
optdepends=(
'acpi_call: fan control'
'asusctltray: tray profile switcher'
'rog-control-center: graphical user interface for asusctl'
'supergfxctl: hybrid GPU control'
)
install=asusctl.install
cd "${pkgbase}-${pkgver}"
make DESTDIR="${pkgdir}" \
install-asusctl \
install-asusd \
install-asusd_user \
install-asus-shutdown \
install-data-asusd \
install-data-asusd_user
}
package_rog-control-center() {
pkgdesc="Graphical user interface for asusctl"
depends=('asusctl' 'fontconfig' 'glibc' 'hicolor-icon-theme' 'libgcc' 'systemd-libs')
cd "${pkgbase}-${pkgver}"
make DESTDIR="${pkgdir}" \
install-rog_gui \
install-data-rog_gui
}
-18
View File
@@ -1,18 +0,0 @@
post_install() {
printf ":: asusd provides a service that is activated by an udev rule on\n"
printf ":: startup. Please reboot the system or run\n"
printf ":: # systemctl start asusd.service\n"
printf ":: to make it work.\n"
printf ":: See https://github.com/OpenGamingCollective/asusctl#kernel-requirements\n"
printf ":: for latest required kernel patches/versions\n"
}
post_upgrade() {
if systemctl is-active asusd.service --quiet; then
printf ":: asusd service will be restarted…\n"
systemctl daemon-reload
systemctl restart asusd.service
fi
printf ":: See https://github.com/OpenGamingCollective/asusctl#kernel-requirements\n"
printf ":: for latest required kernel patches/versions\n"
}
+4 -4
View File
@@ -1,7 +1,7 @@
# Maintainer: Basecamp <support@basecamp.com>
pkgname=basecamp-cli
pkgver=0.11.0
pkgrel=2
pkgver=0.12.0
pkgrel=1
pkgdesc="CLI for Basecamp project management"
arch=('x86_64' 'aarch64')
url="https://github.com/basecamp/basecamp-cli"
@@ -15,8 +15,8 @@ optdepends=(
)
source_x86_64=("https://github.com/basecamp/basecamp-cli/releases/download/v${pkgver}/basecamp_${pkgver}_linux_amd64.tar.gz")
source_aarch64=("https://github.com/basecamp/basecamp-cli/releases/download/v${pkgver}/basecamp_${pkgver}_linux_arm64.tar.gz")
sha256sums_x86_64=('425ffab1251c4315c5f731f8367c3c8c37b54b6b1050eafdbe369e11e1a1ce51')
sha256sums_aarch64=('9c433b12a704402a98b238abb3128a0844a0bc682064adb260b11bc228b3595e')
sha256sums_x86_64=('25d61c38de5660e97855661a2bf7329264912fcd46e2b3fb893fbc70bb467b5c')
sha256sums_aarch64=('1f692d2a8cc733ef95232eeb107414e32f1dd3228a0dde6c9039538661e0f2ca')
package() {
install -Dm755 "basecamp" "${pkgdir}/usr/bin/basecamp"
+4
View File
@@ -0,0 +1,4 @@
{
"source": "local",
"release_ring": "fast"
}
+48
View File
@@ -0,0 +1,48 @@
# Maintainer: Ryan Hughes <ryan@omarchy.org>
# Contributor: Bart De Vries <bart at mogwai dot be>
# Contributor: Dan Johansen <strit@manjaro.org>
#
# Runs x86_64-only Linux programs (dropbox) on AArch64. Pinned past v0.4.5-1:
# that release crashes in its glib wrapper as soon as Dropbox starts its tray
# icon. Move to a release tag once one includes the pinned commit.
pkgname=box64
pkgver=0.4.5.1.r309.gd58d619
pkgrel=1
_commit=d58d619e84e03282326e8a26c2cbfe749931b5f8
pkgdesc='Linux userspace x86_64 emulator with native library wrapping'
arch=('aarch64')
url='https://github.com/ptitSeb/box64'
license=('MIT')
depends=('gcc-libs' 'glibc')
makedepends=('cmake' 'python')
backup=('etc/box64.box64rc')
options=('!strip' '!emptydirs')
source=("$pkgname-$_commit.tar.gz::$url/archive/$_commit.tar.gz")
sha256sums=('f7615a3c4ac5412a983a3fd26be79311e6e2702884d8bdfde954b23bad39fff8')
build() {
# ARM64 is box64's generic AArch64 profile, so the binary does not depend
# on the CPU of the machine that built it.
cmake -S "$pkgname-$_commit" -B build \
-DARM64=ON \
-DARM_DYNAREC=ON \
-DNOGIT=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INSTALL_PREFIX=/usr
cmake --build build --parallel
}
package() {
DESTDIR="$pkgdir" cmake --install build
# Packages call box64 explicitly. A binfmt handler would compete with
# qemu-user-static-binfmt for every x86_64 executable on the system.
rm -r "$pkgdir/etc/binfmt.d"
# The Qt rcfile editor needs PySide, and its launcher entry would show up
# on every system that installs box64 only as a dependency.
rm "$pkgdir/usr/bin/box64-configurator" \
"$pkgdir/usr/share/applications/box64-configurator.desktop"
install -Dm644 "$pkgname-$_commit/LICENSE" -t "$pkgdir/usr/share/licenses/$pkgname"
}
+1 -1
View File
@@ -11,7 +11,7 @@
pkgname=brave-bin
pkgver=1.96.61
pkgrel=1
pkgrel=2
epoch=1
pkgdesc='Web browser that blocks ads and trackers by default (binary release)'
arch=(x86_64 aarch64)
+1 -1
View File
@@ -2,7 +2,7 @@
pkgname=brave-origin-bin
pkgver=1.96.61
pkgrel=1
pkgrel=2
epoch=1
pkgdesc='The minimalist browser from the makers of Brave (binary release).'
arch=(x86_64 aarch64)
+4 -4
View File
@@ -4,8 +4,8 @@
# Automation repository: https://github.com/fabifont/claude-code-aur
pkgname=claude-code
pkgver=2.1.289
pkgrel=1
pkgver=2.1.291
pkgrel=2
pkgdesc="An agentic coding tool that lives in your terminal"
arch=('x86_64' 'aarch64')
url="https://github.com/anthropics/claude-code"
@@ -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=('a186b99e4a9c88366cd49df2f7dad56c61fc306ef0140b19ee64b7c42a8d1348')
sha256sums_aarch64=('d100d5e41dcbee220c80d3a3099292e4b5a508b57cafd181856efedf29f84f28')
sha256sums_x86_64=('078fad28d0297c9a25d306b635b2d8816c6839347520f29eb54ffea5d56142fb')
sha256sums_aarch64=('c18473a04cc4f077435d5d9081f09ebea46e699eb2825cea64741c4bccb87647')
package() {
install -Dm755 "${srcdir}/claude-${pkgver}-${CARCH}" "${pkgdir}/opt/claude-code/bin/claude"
+4 -4
View File
@@ -6,8 +6,8 @@
# repository's package index.
pkgname=claude-desktop
pkgver=2.9939.4
pkgrel=1
pkgver=2.19675.1
pkgrel=2
pkgdesc="Official Claude desktop app with Claude Code"
arch=('x86_64' 'aarch64')
url="https://claude.ai"
@@ -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=('3cfddb23bf2911e05e27b4ed3856b8e795df94643b2c35b59deb317cf995bca0')
sha256sums_aarch64=('108ed79ea164b08c4fa0bb4387deef4779957b3f0f9b2d9898e359f363ebf1bc')
sha256sums_x86_64=('9ba127eeccf270f6e60d35f5c5333654053bf0540c88fc82a009d01711b106fc')
sha256sums_aarch64=('681d122ae97d0eb302f0e6d92c7f232847064bb01746458dc50a2c095a40ed12')
package() {
cd "${srcdir}"
+1 -1
View File
@@ -1,7 +1,7 @@
# Maintainer: bjarneo <https://github.com/bjarneo>
pkgname=cliamp
pkgver=2.3.0
pkgrel=1
pkgrel=2
pkgdesc='A retro terminal music player inspired by Winamp 2.x'
arch=('x86_64' 'aarch64')
url='https://github.com/bjarneo/cliamp'
+1 -1
View File
@@ -4,7 +4,7 @@
pkgname='crush-bin'
pkgver=0.97.1
pkgrel=1
pkgrel=2
pkgdesc='A powerful terminal-based AI assistant for developers, providing intelligent coding assistance directly in your terminal.'
url='https://charm.sh/crush'
arch=('aarch64' 'armv7h' 'i686' 'x86_64')
+7 -8
View File
@@ -19,10 +19,8 @@
# binary to point at pm.sh, a stand-in that declines and names pacman instead.
pkgname=cua-driver-bin
# Held at 0.28.2: 0.28.3 and newer break screenshots. Bump by hand once a
# fixed release is verified.
pkgver=0.28.2
pkgrel=3
pkgver=0.33.4
pkgrel=1
pkgdesc="Computer-use driver for native GUI apps: accessibility-tree snapshots and input injection"
arch=('x86_64' 'aarch64')
url="https://github.com/trycua/cua"
@@ -49,8 +47,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=('a4759cc41c00691a345f08abfc28ece79aef41447d27a463ddd8662939fa3378')
sha256sums_aarch64=('63a1e858a1a407c44ceb407ad133909b8cddedd713aea3b56d7ccb6db784eb48')
case "${CARCH}" in
x86_64) _platform="linux-x86_64" ;;
@@ -72,8 +70,8 @@ prepare() {
return 1
fi
# In 0.28.1 the URL appears in the updater, the printed reinstall command,
# and two embedded copies of Skills/cua-driver/README.md. Rewrite all four
# Through 0.33.4 the URL appears in the updater, the printed reinstall
# command, and two embedded copies of Skills/cua-driver/README.md. Rewrite all four
# so the embedded instructions also defer to pacman. Any other count means
# the release layout changed and needs review before packaging.
local expected=4 found
@@ -113,4 +111,5 @@ package() {
ln -s ../lib/cua-driver/cua-driver "${pkgdir}/usr/bin/cua-driver"
install -Dm644 "${srcdir}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -Dm644 THIRD_PARTY_NOTICES.md "${pkgdir}/usr/share/licenses/${pkgname}/THIRD_PARTY_NOTICES.md"
}
+3 -3
View File
@@ -1,6 +1,6 @@
# Optional Cua Hyprland plugin
This package targets **Omarchy x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Release `0.32.0-3` is an edge candidate built from the plugin source published with Driver `0.32.0`, paired with `cua-driver-bin` `0.28.2`. That source carries the independent agent keymaps and compatible Num Lock handling that releases `0.26.1-5` through `0.28.2-2` applied as an Omarchy patch; this release applies a smaller one, `downstream.patch`, so foreground typing keeps working with modifier and Compose remaps (see *Keyboard behavior*) and so that, with its guard active, restarting fcitx5 does not crash Hyprland (see *Input-method popups*). The upstream native qualification below covers older, unpatched source. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target.
This package targets **Omarchy x86_64**, with Inkscape `1.4.4-6` and two independent background-input lanes. Release `0.32.0-3` is an edge candidate built from the plugin source published with Driver `0.32.0`, paired with `cua-driver-bin` `0.33.4`; the plugin sources are unchanged from 0.32.0 through 0.33.4. That source carries the independent agent keymaps and compatible Num Lock handling that releases `0.26.1-5` through `0.28.2-2` applied as an Omarchy patch; this release applies a smaller one, `downstream.patch`, so foreground typing keeps working with modifier and Compose remaps (see *Keyboard behavior*) and so that, with its guard active, restarting fcitx5 does not crash Hyprland (see *Input-method popups*). The upstream native qualification below covers older, unpatched source. Cua's native qualification is recorded in [the kit's qualification record](https://github.com/trycua/cua/releases/download/cua-hyprland-kit-v1.1.0-omarchy-stable-20260910/QUALIFICATION.md) and [Cua #3698](https://github.com/trycua/cua/pull/3698). Omabot replay and Omarchy's merge decision are recorded in [omarchy-pkgs #346](https://github.com/omacom/omarchy-pkgs/pull/346). Scheduling the recipe does not expand the qualified stable target.
The plugin is optional. Cua Driver works independently, and installation does not load the plugin or enable input. The package follows the normal edge-to-RC-to-stable promotion path instead of the fast release ring. Its PKGBUILD limits builds to x86_64. The upstream qualification covers the original stable profile; the updated Aquamarine profile needs its own Omabot validation before promotion.
@@ -8,7 +8,7 @@ The plugin is optional. Cua Driver works independently, and installation does no
The package uses the [Driver 0.32.0 plugin source](https://github.com/trycua/cua/releases/tag/cua-driver-rs-v0.32.0). Against the Driver 0.26.1 source the profile kit was qualified with, it adds the keyboard behaviour below ([Cua #3970](https://github.com/trycua/cua/pull/3970), adapted from [#473](https://github.com/omacom/omarchy-pkgs/pull/473)) and gives agent keyboards the user seat's key repeat rate instead of zero ([Cua #4358](https://github.com/trycua/cua/pull/4358)), which crashed single-seat clients such as imv that bound an agent seat ([Cua #4257](https://github.com/trycua/cua/issues/4257)). The input protocol header is unchanged.
The qualified upstream Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with the upstream module. This package pairs with `cua-driver-bin 0.28.2`, which speaks the same input protocol v3 to this source; Driver finds the plugin only through its versioned input socket, not through the plugin's provenance. Discovery protocol v2 is separate. `cua-driver-bin` stays at 0.28.2 because Driver 0.28.3 through 0.32.0 refuse desktop capture on Hyprland with more than one output or with one output away from the origin ([Cua #4161](https://github.com/trycua/cua/issues/4161)), where 0.28.2 captures. This pairing is a changed pairing and requires affected replay before promotion.
The qualified upstream Driver pairing is `cua-driver-bin 0.27.0-1`, with input protocol v3. Driver 0.27.0 contains the bounded stale-geometry retry validated with the upstream module. This package pairs with `cua-driver-bin 0.33.4`, which speaks the same input protocol v3 to this source; Driver finds the plugin only through its versioned input socket, not through the plugin's provenance. Discovery protocol v2 is separate. Driver 0.28.3 through 0.33.3 refuse desktop capture on Hyprland with more than one output or with one output away from the origin ([Cua #4161](https://github.com/trycua/cua/issues/4161)); 0.33.4 captures there again ([Cua #4305](https://github.com/trycua/cua/pull/4305)). This pairing is a changed pairing and requires affected replay before promotion.
Profile `omarchy-hyprland-0562r4-remaps`, kit tooling `1.1.0`, and package release `3` pin:
@@ -19,7 +19,7 @@ Profile `omarchy-hyprland-0562r4-remaps`, kit tooling `1.1.0`, and package relea
This profile derives from Cua's `omarchy-stable-20260910` profile. Arch's Hyprland `0.56.2-4` is a rebuild of the same 0.56.2 release against vulkan-sdk 1.4.363 and glslang, built with the same GCC `16.2.1 20260810` and linked to the same `libstdc++`. Its executable (SHA-256 `55da553be71222566ee73b973d2f56dbb9939044d8f22f81aa54b66c83f2f6d1`) and two of its 497 headers differ from `-3`: `src/version.h` now names the Aquamarine `0.15.1` and hyprutils `0.14.2` it was built against, and `protocols/hyprland-input-capture-v1.hpp` gains a destroy handler. The header inventory is re-measured the way `profile_verify.py` measures it, giving `1fdefe6ac027a159d04a5dfee4928ec7ebd15544a9a25b5f66d2f5a46fcf364a`; that method reproduces the kit's `-2`/`-3` values exactly.
The checked-in `PROFILE.json` changes only the profile name, package release, source release, exact Hyprland, Aquamarine and glibc package versions, and the re-measured compositor executable and header hashes. Compiler and libstdc++ runtime identities remain Cua's; the separately recorded patch changes the build source. Cua publishes the profile tooling only in the 0.26.1 kit, and the Driver 0.32.0 source manifest has exactly the fields that kit's `profile_verify.py` checks. The download wrapper verifies the original kit and the Driver 0.32.0 source archive before substituting that archive and its manifest into the kit, deriving the updated profile and provenance, and rendering the recipe from the kit's own `PROFILE-PKGBUILD.in`. It then verifies every derived member against its recorded digest, so the result is the kit Cua's `profile_verify.py` accepts as complete for this profile.
The native qualification below was recorded with package `0.26.1-2` and Hyprland `-2`. The 0.32.0 source and its Omarchy patch, the Aquamarine and glibc updates, and the Driver 0.28.2 pairing need their own application and Driver replay before promotion. Hyprland `0.56.2-4`, Aquamarine `0.15.1-1` and glibc `2.44+r50+g1848099f063e-1` must all reach a destination channel before this artifact can be installed there; publication still follows edge → RC → stable.
The native qualification below was recorded with package `0.26.1-2` and Hyprland `-2`. The 0.32.0 source and its Omarchy patch, the Aquamarine and glibc updates, and the Driver 0.33.4 pairing need their own application and Driver replay before promotion. Hyprland `0.56.2-4`, Aquamarine `0.15.1-1` and glibc `2.44+r50+g1848099f063e-1` must all reach a destination channel before this artifact can be installed there; publication still follows edge → RC → stable.
The generated `PKGBUILD` identifies the immutable kit download, outer checksum,
and member checksums. The kit records the full source and tooling revisions,
+5 -5
View File
@@ -1,8 +1,8 @@
# Maintainer: Gunther Schulz <dev@guntherschulz.de>
pkgname=cursor-bin
pkgver=3.23.12
pkgrel=1
pkgver=3.23.23
pkgrel=2
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=2d29876d567da1607532b23bbf2cd5ddbca496fe
_commit=2dac2428994fe34f12658d9ecad1541b98db2c04
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=('45f25a65d42018fef96c67b555401c579f4354ea5a66489f24c92817b598702eb8a6aa904b52222eed229903c960130ed1312f222525549dcd8cc91f6ab72ecd' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a')
sha512sums_x86_64=('acdf6f2677cd817c41fe91181075f8fa2cbf6fe21211c937a750769f1b036911a05c2e48c3f5186cc5e3d71a1b56aac8e6fbfead84a3c86902c39b77f8776328' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a')
source_aarch64=("https://downloads.cursor.com/production/${_commit}/linux/arm64/deb/arm64/deb/cursor_${pkgver}_arm64.deb")
sha512sums_aarch64=('9ca4455198d2d629b52f71db92969d03c943f3c20a89e08cdfa8a2744f2c6e3f1f13c8657661713a380e30075d3372ef7f27dbb922f37c8170d3a409f02f4397')
sha512sums_aarch64=('28ae4e335d48a8c9aa189645e75e26a2384462c8d2c910a7a1340442259eda55beb065210f049f895eeb809c4cdc331823e0c6b539a79bab209a94594777d5c0')
noextract=(cursor_${pkgver}_amd64.deb cursor_${pkgver}_arm64.deb) # avoid double tarball
_app=usr/share/cursor/resources/app
package() {
+1 -1
View File
@@ -8,7 +8,7 @@ pkgver=2026.10.01.1.e373342
# Derive the upstream version (YYYY.MM.DD-<hash>) from that pkgver.
_upstream_ver="${pkgver%.*}"
_upstream_ver="${_upstream_ver%.*}-${pkgver##*.}"
pkgrel=1
pkgrel=2
# epoch=1: bumped when switching from the original `20250808.0.<sha>` scheme
# to the current `YYYY.MM.DD.<n>.<hash>` scheme (2025-08-09). Never decrease.
epoch=1
+4 -4
View File
@@ -2,8 +2,8 @@
pkgname=disktree-bin
_name=disktree
pkgver=0.10.1
pkgrel=1
pkgver=0.11.0
pkgrel=2
pkgdesc="Disk space treemap for Omarchy: see what fills a disk by kind, mark what should go, and remove it"
arch=('x86_64' 'aarch64')
url="https://github.com/tobi/disktree"
@@ -16,8 +16,8 @@ conflicts=("$_name")
options=('!debug')
source_x86_64=("$url/releases/download/v$pkgver/$_name-$pkgver-x86_64-linux.tar.gz")
source_aarch64=("$url/releases/download/v$pkgver/$_name-$pkgver-aarch64-linux.tar.gz")
sha256sums_x86_64=('838a5b7085dfd5532070cadade68ca5cfa4e61809188211a5c890412e201a113')
sha256sums_aarch64=('e4927a4935736ffba9ba034ea63ecf3e2bac74bbf60721759fdf7446f6aa1d3d')
sha256sums_x86_64=('7e75afa2283c8b4f9290d52eadbfc00d9f14c13aed2d224ccdf0f7826fcc05b2')
sha256sums_aarch64=('3c75f9c82069e40310c821357a52aee2f11a9c3e2b45452c9893dbf7cb5e454a')
package() {
cd "$_name-$pkgver-$CARCH-linux"
+2 -2
View File
@@ -7,9 +7,9 @@
pkgname=dropbox-cli
pkgver=2026.09.28
pkgrel=1
pkgrel=3
pkgdesc="Command line interface for Dropbox"
arch=("x86_64")
arch=("any")
url="https://www.dropbox.com"
license=("GPL-3.0-or-later")
makedepends=("gdk-pixbuf2")
+13 -2
View File
@@ -7,10 +7,13 @@ pkgname=dropbox
pkgver=272.4.3798
pkgrel=1
pkgdesc="A free service that lets you bring your photos, docs, and videos anywhere and share them easily."
arch=("x86_64")
arch=("x86_64" "aarch64")
url="https://www.dropbox.com"
license=(custom:Dropbox)
depends=("libsm" "libxslt" "libxmu" "libxdamage" "libxrender" "libxxf86vm" "libxcomposite" "fontconfig" "dbus")
# Dropbox ships Linux builds for x86_64 only. AArch64 runs the same client
# under box64, which maps its glibc and GTK calls onto the native libraries.
depends_aarch64=("box64")
makedepends=("gendesk")
optdepends=(
'ufw-extras: ufw rules for dropbox'
@@ -43,7 +46,15 @@ package() {
chmod 755 "$pkgdir"/opt/dropbox/*.so
install -d "$pkgdir"/usr/bin
ln -s ../../opt/dropbox/dropbox "$pkgdir"/usr/bin/dropbox
if [[ $CARCH == aarch64 ]]; then
# `dropbox-cli start` runs dropboxd, so pointing dropboxd at box64 and
# /usr/bin/dropbox at dropboxd sends every launch through the emulator.
sed -i 's|^exec "$PAR"/dropbox "$@"$|exec /usr/bin/box64 "$PAR"/dropbox "$@"|' "$pkgdir"/opt/dropbox/dropboxd
grep -qxF 'exec /usr/bin/box64 "$PAR"/dropbox "$@"' "$pkgdir"/opt/dropbox/dropboxd
ln -s ../../opt/dropbox/dropboxd "$pkgdir"/usr/bin/dropbox
else
ln -s ../../opt/dropbox/dropbox "$pkgdir"/usr/bin/dropbox
fi
install -Dm644 "$srcdir"/dropbox.desktop -t "$pkgdir"/usr/share/applications
install -Dm644 "$srcdir"/DropboxGlyph_Blue.svg "$pkgdir"/usr/share/pixmaps/dropbox.svg
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-all",
"commit": "5614a0a61616643e448fb7c68d58237715ce2739"
}
}
-47
View File
@@ -1,47 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-all
pkgver=2.22.1
pkgrel=1
pkgdesc='elephant + all official elephant providers'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
depends=('libqalculate' 'wl-clipboard' 'imagemagick' 'fd' 'wtype' 'jq' 'sqlite3')
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=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
# Build main elephant binary
cd elephant-${pkgver}/cmd/elephant
go build -ldflags="-s -w" -buildvcs=false -x -o elephant -trimpath
# Build all provider plugins
cd ../../internal/providers
# Build each provider
for provider in playerctl wireplumber archlinuxpkgs bitwarden dnfpackages 1password bookmarks bluetooth nirisessions niriactions calc clipboard desktopapplications files menus providerlist runner snippets symbols todo unicode websearch windows; do
cd $provider
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
cd ..
done
}
package() {
# Install main elephant binary
cd elephant-${pkgver}/cmd/elephant
install -Dm 755 elephant -t "${pkgdir}/usr/bin"
# Install all provider plugins
cd ../../internal/providers
for provider in playerctl wireplumber archlinuxpkgs bitwarden dnfpackages bookmarks 1password nirisessions niriactions bluetooth calc clipboard desktopapplications files menus providerlist runner snippets symbols todo unicode websearch windows; do
install -Dm 755 $provider/$provider.so -t "${pkgdir}/usr/lib/elephant"
done
# Install license
cd ../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-archlinuxpkgs",
"commit": "659b81f1aa74a13fd2ebec222e19da2046d8e977"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-archlinuxpkgs
pkgver=2.22.1
pkgrel=1
pkgdesc='archlinuxpkgs provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-archlinuxpkgs')
provides=('elephant-archlinuxpkgs')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/archlinuxpkgs
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/archlinuxpkgs
install -Dm 755 archlinuxpkgs.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-bluetooth",
"commit": "42d9dd5424884c51b8fe6bf7692caf0a31007f05"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-bluetooth
pkgver=2.22.1
pkgrel=1
pkgdesc='bluetooth provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-bluetooth')
provides=('elephant-bluetooth')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/bluetooth
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/bluetooth
install -Dm 755 bluetooth.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-calc",
"commit": "84aba9e90bbd65af45f83168cd6c7bce6ec4322e"
}
}
-28
View File
@@ -1,28 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-calc
pkgver=2.22.1
pkgrel=1
pkgdesc='calc provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
depends=('libqalculate')
makedepends=('go')
conflicts=('elephant-calc')
provides=('elephant-calc')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/calc
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/calc
install -Dm 755 calc.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-clipboard",
"commit": "3176f9de1445e7115009383f9cdac116729fc7be"
}
}
-28
View File
@@ -1,28 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-clipboard
pkgver=2.22.1
pkgrel=1
pkgdesc='clipboard provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
depends=('wl-clipboard' 'imagemagick')
makedepends=('go')
conflicts=('elephant-clipboard')
provides=('elephant-clipboard')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/clipboard
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/clipboard
install -Dm 755 clipboard.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-desktopapplications",
"commit": "c30e33db5fef912dec9aa157773b10ffab1e0307"
}
}
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-desktopapplications
pkgver=2.22.1
pkgrel=1
pkgdesc='desktopapplications provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-desktopapplications')
provides=('elephant-desktopapplications')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/desktopapplications
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/desktopapplications
install -Dm 755 desktopapplications.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-files",
"commit": "2d16502b7a905e7d7a03e0026c5519c3b3c4abf2"
}
}
-28
View File
@@ -1,28 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-files
pkgver=2.22.1
pkgrel=1
pkgdesc='files provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
depends=('fd')
makedepends=('go')
conflicts=('elephant-files')
provides=('elephant-files')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/files
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/files
install -Dm 755 files.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-menus",
"commit": "5ab583fee6ba3e387d49ffe4e409bb84bc60ea24"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-menus
pkgver=2.22.1
pkgrel=1
pkgdesc='menus provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-menus')
provides=('elephant-menus')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/menus
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/menus
install -Dm 755 menus.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-providerlist",
"commit": "1d756a138e926a81b9d33265f0197b8661168845"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-providerlist
pkgver=2.22.1
pkgrel=1
pkgdesc='providerlist provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-providerlist')
provides=('elephant-providerlist')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/providerlist
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/providerlist
install -Dm 755 providerlist.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-runner",
"commit": "e47641530d912199372204cf8780ef37f99f0b37"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-runner
pkgver=2.22.1
pkgrel=1
pkgdesc='runner provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-runner')
provides=('elephant-runner')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/runner
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/runner
install -Dm 755 runner.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-symbols",
"commit": "32263e8b71390ab38b8aa1fd82fc2595b41a5157"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-symbols
pkgver=2.22.1
pkgrel=1
pkgdesc='symbols provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-symbols')
provides=('elephant-symbols')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/symbols
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/symbols
install -Dm 755 symbols.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-todo",
"commit": "447978df5ea3afd1e10959d7973c0b35367724c3"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-todo
pkgver=2.22.1
pkgrel=1
pkgdesc='todo provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-todo')
provides=('elephant-todo')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/todo
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/todo
install -Dm 755 todo.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-unicode",
"commit": "23222b0d304a234c74f630c5b9176d58c6c6e0b3"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-unicode
pkgver=2.22.1
pkgrel=1
pkgdesc='unicode provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-unicode')
provides=('elephant-unicode')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/unicode
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/unicode
install -Dm 755 unicode.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant-websearch",
"commit": "6b5da831da33e3533593823826a8ffb1a008a299"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant-websearch
pkgver=2.22.1
pkgrel=1
pkgdesc='websearch provider for elephant'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant-websearch')
provides=('elephant-websearch')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd elephant-${pkgver}/internal/providers/websearch
go build -ldflags="-s -w" -buildvcs=false -buildmode=plugin -trimpath
}
package() {
cd elephant-${pkgver}/internal/providers/websearch
install -Dm 755 websearch.so -t "${pkgdir}/usr/lib/elephant"
cd ../../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
-13
View File
@@ -1,13 +0,0 @@
{
"source": "local",
"upstream": {
"watch": {
"github": "abenz1267/elephant",
"pattern": "v(?P<version>[0-9]+(?:\\.[0-9]+)*)"
}
},
"origin": {
"aur": "elephant",
"commit": "6dd02e6987a7a91be6a33e9600147523efa7fa5a"
}
}
-27
View File
@@ -1,27 +0,0 @@
# Maintainer: Andrej Benz <hello[at]benz[dot]dev>
pkgname=elephant
pkgver=2.22.1
pkgrel=1
pkgdesc='general purpose datasource and executor'
url='https://github.com/abenz1267/elephant'
arch=('x86_64' 'aarch64')
license=('GPL')
makedepends=('go')
conflicts=('elephant')
provides=('elephant')
source=("${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('3d1d0d4c55ae531fa3f06406b96504b5165a0d7b53523d1f8351d9d93e457f44')
build() {
cd ${pkgname}-${pkgver}/cmd/elephant
go build -ldflags="-s -w" -buildvcs=false -x -o elephant -trimpath
}
package() {
cd ${pkgname}-${pkgver}/cmd/elephant
install -Dm 755 elephant -t "${pkgdir}/usr/bin"
cd ../../
install -Dm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
+1 -1
View File
@@ -2,7 +2,7 @@
pkgname=flea
pkgver=0.3.7
pkgrel=1
pkgrel=2
pkgdesc='Fast, keyboard-first file manager for Omarchy'
arch=('x86_64' 'aarch64')
url='https://github.com/thisisgm/flea'
+4 -4
View File
@@ -6,8 +6,8 @@ _npmmodule=@github/copilot
pkgname=github-copilot-cli
_pkgexec=copilot
pkgver=1.0.91
pkgrel=1
pkgver=1.0.92
pkgrel=2
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=(
'4f305d718a1e6cb994e926d0f570883eb63bfb79ef091d00d5ff9c67d9d83781'
'7785011a8c97314f0800b76e02bdac7951bae7e6bfde49416c142ae4fca08345'
'4711a32a1917bf4c64308818a76efb1fb633384ac895312d6e9d12f26b78f95a'
'242fb78a1c6e4ff05acb6b9135fc6e3cb0714ecbe87cddbd8bf69d2fa2559c37'
)
# Document: https://wiki.archlinux.org/title/Node.js_package_guidelines
+4 -4
View File
@@ -7,8 +7,8 @@
# or use: $ curl -sSf https://dl.google.com/linux/chrome/deb/dists/stable/main/binary-amd64/Packages | grep -A1 "Package: google-chrome-stable" | awk '/Version/{print $2}' | cut -d '-' -f1
pkgname=google-chrome
pkgver=154.0.8037.97
pkgrel=1
pkgver=155.0.8059.39
pkgrel=2
pkgdesc="The popular web browser by Google (Stable Channel)"
arch=(
'x86_64'
@@ -39,8 +39,8 @@ source=('eula_text.html'
"google-chrome-$_channel.sh")
sha512sums=('a225555c06b7c32f9f2657004558e3f996c981481dbb0d3cd79b1d59fa3f05d591af88399422d3ab29d9446c103e98d567aeafe061d9550817ab6e7eb0498396'
'de02b498a4b5b93e21622c8dba57befe795d733a04656be911cc38e28bfef0e20470450f44be523bbde8d4de28f79c10434846ca01fc2a2f4e67707b79332f94')
sha512sums_x86_64=('990f133f1091d0aea48cc0bfbcc8f303fee80d128a93f02f7910c0e0bb46c45ee96971879037cde100bb35899284fff4fe5b172ace9b9d5e6465d45f311d1ae0')
sha512sums_aarch64=('7955d74192d8364ba22b25cf1de1c7a7b58428a04a04ac095b773f838224b506dc4c74dca340d1a80b54f012a339c01fcba752b5c63a55a4ea6a9886fa36fd8e')
sha512sums_x86_64=('42b4ec9ec61fee532a848fdf35973d3aba6c083028ee45c98572f1bbd9e51e865cbd5bf9fbbe695b6c9a76936472aaccd58f860ecb8bcce380afa6fd57bcb472')
sha512sums_aarch64=('bcb58757677389245952e4fba354c71c586228abe1e91cf7563895dda3702dcddd031838dbde8e246525e1b15fbfdf6b13c59ed7fc1f4cb52c088d499857adb7')
source_x86_64=("https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-${_channel}/google-chrome-${_channel}_${pkgver}-1_amd64.deb")
source_aarch64=("https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-${_channel}/google-chrome-${_channel}_${pkgver}-1_arm64.deb")
+1 -1
View File
@@ -1,6 +1,6 @@
{
"source": "local",
"sync": false,
"release_ring": "fast",
"origin": {
"aur": "grok-bot",
"commit": "05eb78fca06b482affda28b26223cbf249d4bbcd"
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
# Cursor publishes Grok Bot from its own Debian repository, one index per
# architecture. Each index carries the version and the SHA256, so an update
# is two small HTTP requests instead of downloading the debs, and the pool
# URL is keyed by version. bin/sync-upstream can rewrite pkgver and the
# checksums; it cannot rewrite a commit id embedded in the old
# downloads.cursor.com/grokbot/stable/<commit>/ URL.
set -euo pipefail
BASE_URL="https://downloads.cursor.com/aptrepo"
declare -A DEB_ARCHES=([x86_64]=amd64 [aarch64]=arm64)
# Print "<version> <sha256>" for the newest grok-bot stanza. Newest is
# vercmp's opinion, which is the one bin/sync-upstream and pacman both use;
# sort -V disagrees with it over versions like 1.0a. The winner's Filename
# must be the versioned pool path the PKGBUILD downloads from.
newest_release() {
local index="$1" debarch="$2"
local version sha256 filename best_version="" best_sha256="" best_filename=""
while read -r version sha256 filename; do
[[ -n "$version" && -n "$sha256" ]] || continue
if [[ -z "$best_version" ]] || [[ "$(vercmp "$version" "$best_version")" -gt 0 ]]; then
best_version="$version"
best_sha256="$sha256"
best_filename="$filename"
fi
done < <(awk '
{ sub(/\r$/, "") }
/^Package:/ { package = $2 }
/^Version:/ { version = $2 }
/^SHA256:/ { sha256 = $2 }
/^Filename:/ { filename = $2 }
/^$/ {
if (package == "grok-bot" && version && sha256) print version, sha256, filename
package = version = sha256 = filename = ""
}
END {
if (package == "grok-bot" && version && sha256) print version, sha256, filename
}
' <<<"$index")
[[ -n "$best_version" ]] || return 1
local expected="pool/grok-bot/g/gr/grok-bot_${best_version}_${debarch}.deb"
if [[ "$best_filename" != "$expected" ]]; then
echo "Unexpected Grok Bot $best_version $debarch Filename: '${best_filename}' (expected $expected)" >&2
return 1
fi
echo "$best_version $best_sha256"
}
versions=()
declare -A checksums=()
for arch in "${!DEB_ARCHES[@]}"; do
index=$(curl -fsSL "$BASE_URL/dists/grok-bot/main/binary-${DEB_ARCHES[$arch]}/Packages")
read -r version sha256 <<<"$(newest_release "$index" "${DEB_ARCHES[$arch]}")"
if [[ -z "${version:-}" || -z "${sha256:-}" ]]; then
echo "No usable Grok Bot release found for $arch" >&2
exit 1
fi
versions+=("$version")
checksums[$arch]="$sha256"
done
# A release can land one architecture at a time. Wait until both agree so one
# pkgver always describes both artifacts.
for version in "${versions[@]}"; do
if [[ "$version" != "${versions[0]}" ]]; then
echo "Upstream architectures are mid-release (${versions[*]}); skipping" >&2
echo '{}'
exit 0
fi
done
jq -n \
--arg pkgver "${versions[0]}" \
--arg x86_64 "${checksums[x86_64]}" \
--arg aarch64 "${checksums[aarch64]}" \
'{pkgver: $pkgver, sha256sums: {x86_64: [$x86_64], aarch64: [$aarch64]}}'
+8 -6
View File
@@ -2,9 +2,8 @@
# Contributor: Omarchy
pkgname=grok-bot
pkgver=0.47.0
pkgver=0.68.1
pkgrel=1
_commit=c1e7d7a46549956d25f53e9c0b9f59666e03aa3a
pkgdesc='Grok Bot desktop agent'
arch=('x86_64' 'aarch64')
url='https://x.ai/bot'
@@ -30,20 +29,23 @@ install=grok-bot.install
_deb_x86_64="grok-bot_${pkgver}_amd64.deb"
_deb_aarch64="grok-bot_${pkgver}_arm64.deb"
# Versioned pool paths — Packages indexes carry SHA256 so upstream.sh
# can bump pkgver without embedding a Cursor commit id.
_pool="https://downloads.cursor.com/aptrepo/pool/grok-bot/g/gr"
source=(
'grok-bot.sh'
'grok-bot.desktop'
)
source_x86_64=(
"${_deb_x86_64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/x64/${_deb_x86_64}"
"${_deb_x86_64}::${_pool}/${_deb_x86_64}"
)
source_aarch64=(
"${_deb_aarch64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/arm64/${_deb_aarch64}"
"${_deb_aarch64}::${_pool}/${_deb_aarch64}"
)
sha256sums=('6dfa6c305941afa6cbaefbeaae06d05ab5a88f31630005d25a819a160c20c7a3'
'3e2a2461ea58d17ac1777616be9ba660f7cb9ceefa9292016e36c55758bf78dd')
sha256sums_x86_64=('11ca0f51a535b97af51a352adf9c0f9ecd2e1b0430a69ae9451b688a7a065808')
sha256sums_aarch64=('836f8d19d3826c6573c31ac45c7a9b797abc73381ae0d2b1e7a8dae5410e7e46')
sha256sums_x86_64=('b2be8106d2b3eae07d983d5f1ca77b657accde666dc440db2a409421ecff3359')
sha256sums_aarch64=('3f85fbe2ba3c1d122aa16f8be672076bc19146e07e9d431f37a93b85fa75a93f')
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
package() {
-49
View File
@@ -1,49 +0,0 @@
#!/usr/bin/env bash
# Resolve current Grok Bot stable from Cursor's update feed and pin PKGBUILD.
# Linux has no latest alias (linux-x64 feed returns 204). The darwin-arm64
# sand feed publishes version + commit; the Linux .deb lives at the same commit.
# Darwin can ship first — HEAD-check the Linux URL and fail loudly if 404.
set -euo pipefail
PKGBUILD_PATH="${1:-PKGBUILD}"
[[ -f "${PKGBUILD_PATH}" ]] || { echo "Error: PKGBUILD not found at '${PKGBUILD_PATH}'" >&2; exit 1; }
FEED='https://api2.cursor.sh/updates/api/update/darwin-arm64/sand/0.0.0/00000000-0000-0000-0000-000000000000/stable'
json="$(curl -fsSL -H 'cache-control: no-cache' "${FEED}")"
ver="$(jq -er '.name // .version' <<<"${json}")"
feed_url="$(jq -er '.url' <<<"${json}")"
commit="$(sed -nE 's@.*/(grokbot|sand)/stable/([0-9a-f]{40})/.*@\2@p' <<<"${feed_url}")"
[[ -n "${ver}" && -n "${commit}" ]] || {
echo "Error: could not parse version/commit from feed: ${json}" >&2
exit 1
}
deb_url="https://downloads.cursor.com/grokbot/stable/${commit}/linux/x64/Grok_Bot_${ver}.deb"
code="$(curl -fsSIL -o /dev/null -w '%{http_code}' "${deb_url}")"
[[ "${code}" == "200" ]] || {
echo "Error: Linux deb not fetchable (${code}): ${deb_url}" >&2
exit 1
}
tmp="$(mktemp)"
trap 'rm -f "${tmp}"' EXIT
curl -fL --retry 3 -o "${tmp}" "${deb_url}"
sum="$(sha256sum "${tmp}" | awk '{print $1}')"
current_ver="$(sed -nE 's/^pkgver=([^[:space:]#]+).*/\1/p' "${PKGBUILD_PATH}" | head -n1)"
sed -i -E \
-e "s/^_commit=.*/_commit=${commit}/" \
-e "s/^pkgver=.*/pkgver=${ver}/" \
-e "0,/^[[:space:]]*'[0-9a-f]{64}'/s// '${sum}'/" \
"${PKGBUILD_PATH}"
if [[ "${ver}" != "${current_ver}" ]]; then
sed -i -E 's/^pkgrel=.*/pkgrel=1/' "${PKGBUILD_PATH}"
fi
echo "${ver} ${commit}"
echo "${deb_url}"
echo "${sum}"
+4
View File
@@ -0,0 +1,4 @@
[gtk2]
source = "git"
git = "https://gitlab.gnome.org/GNOME/gtk.git"
include_regex = '2\.24\.\d+'
+7
View File
@@ -0,0 +1,7 @@
{
"source": "local",
"origin": {
"aur": "gtk2",
"commit": "19829b43450b1a7e838896f9b2dd391a227eabd1"
}
}
@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)" <heftig@archlinux.org>
Date: Sat, 22 Jun 2024 22:08:43 +0200
Subject: [PATCH] Lower severity of XID collision warnings
---
gdk/x11/gdkxid.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdk/x11/gdkxid.c b/gdk/x11/gdkxid.c
index 1005f9e40c0d..1523fa70b2d3 100644
--- a/gdk/x11/gdkxid.c
+++ b/gdk/x11/gdkxid.c
@@ -58,7 +58,7 @@ _gdk_xid_table_insert (GdkDisplay *display,
(GEqualFunc) gdk_xid_equal);
if (g_hash_table_lookup (display_x11->xid_ht, xid))
- g_warning ("XID collision, trouble ahead");
+ g_debug ("XID collision, trouble ahead");
g_hash_table_insert (display_x11->xid_ht, xid, data);
}
@@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthias Clasen <mclasen@redhat.com>
Date: Sat, 15 Jun 2024 14:18:01 -0400
Subject: [PATCH] Stop looking for modules in cwd
This is just not a good idea. It is surprising, and can be misused.
Fixes: #6786
---
gtk/gtkmodules.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/gtk/gtkmodules.c b/gtk/gtkmodules.c
index 50729b61a590..c0f0c30a2148 100644
--- a/gtk/gtkmodules.c
+++ b/gtk/gtkmodules.c
@@ -229,13 +229,8 @@ find_module (const gchar *name)
gchar *module_name;
module_name = _gtk_find_module (name, "modules");
- if (!module_name)
- {
- /* As last resort, try loading without an absolute path (using system
- * library path)
- */
- module_name = g_module_build_path (NULL, name);
- }
+ if (module_name == NULL)
+ return NULL;
module = g_module_open (module_name, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,176 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the library's name and an idea of what it does.
Copyright (C) year name of author
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.
signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+112
View File
@@ -0,0 +1,112 @@
# Maintainer: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
# Maintainer: Jan de Groot <jgc@archlinux.org>
pkgname=gtk2
pkgver=2.24.33
pkgrel=5
pkgdesc="GObject-based multi-platform GUI toolkit (legacy)"
url="https://www.gtk.org/"
# Built for aarch64 only: Valve's native arm64 Steam client loads GTK 2 from
# the host, which Arch Linux ARM no longer ships. On x86_64 Steam brings its
# own copy in its runtime.
arch=(aarch64)
license=(LGPL-2.1-or-later)
depends=(
atk
cairo
desktop-file-utils
fontconfig
gdk-pixbuf2
glib2
glibc
gtk-update-icon-cache
libcups
librsvg
libx11
libxcomposite
libxcursor
libxdamage
libxext
libxfixes
libxi
libxinerama
libxrandr
libxrender
pango
shared-mime-info
)
makedepends=(
git
glib2-devel
gobject-introspection
gtk-doc
)
source=(
"git+https://gitlab.gnome.org/GNOME/gtk.git#tag=$pkgver"
gtk-query-immodules-2.0.hook
0001-Lower-severity-of-XID-collision-warnings.patch
0002-Stop-looking-for-modules-in-cwd.patch
)
b2sums=('1b18d1cfef55466209cf93be45af15dc058a8b74d13ab590cfc7f0b09b0584adc62d4330aaed65185c0142cc8c326e4274c8e75e0af94bec5be3cfcca105c1e6'
'9c531f9f605e1739e13c39c1cac22daddd9574f3082f18bcf0b9dfaa4c41f2485d55be03a9ed12fb4504d509f0d5ac63980a9d9349e3f80a06595c6430c78096'
'45ecc976d9eb9d990fc204230aa052a6d1b2bdfdc94788be37d576ab262a1da49855eb46ecd4bfce4efde6e2f817a1660c6d1fa756be3b372f7f8d13b0ef0fd0'
'06ca1c6f0e8f6a7c7a3cc08ce3d358af978d28fc4aa8d9e981883e3ad5adf7d821bcb27bc8b93bf65171a92396ac8f7ad62c90db501a492cca7c30b6081e957f')
prepare() {
cd gtk
git apply -3 ../0001-Lower-severity-of-XID-collision-warnings.patch
# CVE-2024-6655: https://www.openwall.com/lists/oss-security/2024/09/09/1
# https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/7361
git apply -3 ../0002-Stop-looking-for-modules-in-cwd.patch
sed -i '/AM_INIT_AUTOMAKE/s/]/ foreign]/' configure.ac
autoreconf -fvi
}
build() {
local configure_options=(
--prefix=/usr
--sysconfdir=/etc
--localstatedir=/var
--with-xinput=yes
--disable-gtk-doc
)
CFLAGS+=" -Wno-error=implicit-int -Wno-error=incompatible-pointer-types"
cd gtk
./configure "${configure_options[@]}"
sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0/g' libtool
make
}
package() {
optdepends=(
'adwaita-fonts: Default font'
'adwaita-icon-theme: Default icon theme'
'gnome-themes-extra-gtk2: Default widget theme'
'python: gtk-builder-convert'
)
provides=(
libgailutil.so
libgdk-x11-2.0.so
libgtk-x11-2.0.so
)
install=gtk2.install
make -C gtk DESTDIR="$pkgdir" install
install -Dm644 /dev/stdin "$pkgdir/usr/share/gtk-2.0/gtkrc" <<END
gtk-icon-theme-name = "Adwaita"
gtk-theme-name = "Adwaita"
gtk-font-name = "Adwaita Sans 11"
END
install -Dm644 gtk-query-immodules-2.0.hook -t "$pkgdir/usr/share/libalpm/hooks"
# Built by GTK 4, shared with GTK 2/3
rm "$pkgdir/usr/bin/gtk-update-icon-cache"
}
# vim:set sw=2 sts=-1 et:
@@ -20,3 +20,11 @@ path = [
]
SPDX-FileCopyrightText = "Arch Linux contributors"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = [
"0001-Lower-severity-of-XID-collision-warnings.patch",
"0002-Stop-looking-for-modules-in-cwd.patch",
]
SPDX-FileCopyrightText = "gtk2 contributors"
SPDX-License-Identifier = "LGPL-2.1-or-later"
@@ -0,0 +1,11 @@
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Operation = Remove
Target = usr/lib/gtk-2.0/2.10.0/immodules/*.so
[Action]
Description = Probing GTK2 input method modules...
When = PostTransaction
Exec = /usr/bin/gtk-query-immodules-2.0 --update-cache
+3
View File
@@ -0,0 +1,3 @@
pre_remove() {
rm -f /usr/lib/gtk-2.0/2.10.0/immodules.cache
}
+1 -1
View File
@@ -5,7 +5,7 @@
pkgname=hermes-desktop
pkgver=2026.9.7
pkgrel=3
pkgrel=4
pkgdesc='Native desktop shell for Hermes Agent'
arch=('x86_64')
url='https://github.com/NousResearch/hermes-agent'
@@ -1,21 +0,0 @@
{
"source": "local",
"release_ring": "fast",
"upstream": {
"git_tags": "https://github.com/hyprwm/hyprland-guiutils.git",
"tag_pattern": "v{pkgver}",
"sources": {
"any": [
"https://github.com/hyprwm/hyprland-guiutils/archive/v{pkgver}/hyprland-guiutils-{pkgver}.tar.gz"
]
}
},
"rebuild_on": [
"aquamarine"
],
"rebuilt_against": {
"aarch64": {
"aquamarine": "0.15.0-2"
}
}
}
-40
View File
@@ -1,40 +0,0 @@
# Maintainer: Caleb Maclennan <caleb@alerque.com>
pkgname=hyprland-guiutils
pkgver=0.2.2
pkgrel=3
pkgdesc='Hyprland GUI utilities'
arch=(aarch64)
url="https://github.com/hyprwm/$pkgname"
license=(BSD-3-Clause)
depends=(
libgcc
libstdc++
glibc # libc.so libm.so
hyprlang
hyprtoolkit libhyprtoolkit.so
hyprutils libhyprutils.so
libdrm
pixman
)
makedepends=(cmake)
replaces=(hyprland-qtutils)
_archive="$pkgname-$pkgver"
source=("$url/archive/v$pkgver/$_archive.tar.gz")
sha256sums=('16f92a6c5a22ac58e1fc313f6b202c188da45e804e1f21ff57dfd0da5c1a01b7')
build() {
cd "$_archive"
local cmake_flags=(
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_INSTALL_PREFIX=/usr
)
cmake -B build ${cmake_flags[@]}
cmake --build build
}
package() {
cd "$_archive"
DESTDIR="$pkgdir" cmake --install build
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname" LICENSE
}
@@ -2,7 +2,7 @@
pkgname="hyprland-preview-share-picker"
pkgver=0.2.1
pkgrel=2
pkgrel=3
pkgdesc="An alternative share picker for hyprland with window and monitor previews"
arch=(x86_64 aarch64)
url="https://github.com/WhySoBad/hyprland-preview-share-picker"
+1 -1
View File
@@ -16,7 +16,7 @@
],
"rebuilt_against": {
"aarch64": {
"aquamarine": "0.15.0-2"
"aquamarine": "0.15.1-1.1"
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
pkgname=(hyprland hyprpm)
pkgver=0.56.2
pkgrel=4
pkgrel=5
pkgdesc='a highly customizable dynamic tiling Wayland compositor'
arch=(aarch64)
url="https://github.com/hyprwm/${pkgname^}"
@@ -1,21 +0,0 @@
{
"source": "local",
"release_ring": "fast",
"upstream": {
"git_tags": "https://github.com/hyprwm/hyprtoolkit.git",
"tag_pattern": "v{pkgver}",
"sources": {
"any": [
"https://github.com/hyprwm/hyprtoolkit/archive/v{pkgver}/hyprtoolkit-{pkgver}.tar.gz"
]
}
},
"rebuild_on": [
"aquamarine"
],
"rebuilt_against": {
"aarch64": {
"aquamarine": "0.15.0-2"
}
}
}
-50
View File
@@ -1,50 +0,0 @@
# Maintainer: Caleb Maclennan <caleb@alerque.com>
pkgname=hyprtoolkit
pkgver=0.6.0
pkgrel=1
pkgdesc='A modern C++ Wayland-native GUI toolkit'
arch=(aarch64)
url="https://github.com/hyprwm/$pkgname"
license=(BSD-3-Clause)
depends=(
libgcc
libstdc++
aquamarine libaquamarine.so
cairo libcairo.so
glib2 libglib-2.0.so
glibc # libc.so libm.so
hyprgraphics libhyprgraphics.so
hyprlang libhyprlang.so
hyprutils libhyprutils.so
iniparser libiniparser.so
libdrm # libdrm.so
libglvnd libEGL.so libOpenGL.so
libxkbcommon libxkbcommon.so
mesa # libgbm.so
pango libpango-1.0.so # libpango.so
pixman libpixman-1.so
wayland libwayland-client.so
)
makedepends=(cmake
hyprwayland-scanner)
provides=(libhyprtoolkit.so)
_archive="$pkgname-$pkgver"
source=("$url/archive/v$pkgver/$_archive.tar.gz")
sha256sums=('53c41be72af97d9ede274a63c9c1034c58726d862905763ed6e5a564ae42ba6b')
build() {
cd "$_archive"
local cmake_options=(
-D CMAKE_BUILD_TYPE=None
-D CMAKE_INSTALL_PREFIX=/usr
)
cmake -B build -W no-dev ${cmake_options[@]}
cmake --build build
}
package() {
cd "$_archive"
DESTDIR="$pkgdir" cmake --install build
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
}
+1 -1
View File
@@ -2,7 +2,7 @@
pkgname=learn-omarchy
pkgver=0.2.5
pkgrel=1
pkgrel=2
pkgdesc="Interactive, theme-aware courses for learning Omarchy"
arch=('any')
url="https://github.com/DanWahlin/learn-omarchy"
+1 -1
View File
@@ -16,7 +16,7 @@
pkgname=libfprint-git
pkgver=1.94.100.r10.g6f9479c
pkgrel=2
pkgrel=3
# Retain the epoch used to supersede the previously published untested build.
epoch=1
pkgdesc="Library for fingerprint readers (pinned upstream snapshot with FocalTech and Synaptics 06cb:010b support, and Apple Touch ID on aarch64)"
@@ -8,5 +8,10 @@
},
"rebuild_on": [
"libva"
]
],
"rebuilt_against": {
"aarch64": {
"libva": "2.24.1-1"
}
}
}
Loaded 100 of 1156 files, more files were not shown because too many files have changed in this diff. Show more