Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pkgbuild-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Contract tests
run: python3 -m unittest tests.test_pkgbuild_release_contract -v
run: python3 -m unittest discover -s tests -p "test_pkgbuild_release_contract.py" -v

arch-package:
name: arch build + install
Expand Down
31 changes: 31 additions & 0 deletions pkgbuilds/terraphim-clients-bin/.SRCINFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
pkgbase = terraphim-clients-bin
pkgdesc = Terraphim AI command-line clients (prebuilt static MUSL binaries)
pkgver = 1.21.16
pkgrel = 1
url = https://terraphim.ai
arch = x86_64
arch = aarch64
license = Apache-2.0
license = MIT
options = !strip
options = !debug
source_x86_64 = terraphim-agent-1.21.16-x86_64-unknown-linux-musl.tar.gz::https://github.com/terraphim/terraphim-clients/releases/download/v1.21.16/terraphim-agent-1.21.16-x86_64-unknown-linux-musl.tar.gz
source_x86_64 = terraphim-grep-1.21.16-x86_64-unknown-linux-musl.tar.gz::https://github.com/terraphim/terraphim-clients/releases/download/v1.21.16/terraphim-grep-1.21.16-x86_64-unknown-linux-musl.tar.gz
sha256sums_x86_64 = 71cb87455959f2eaa04fab1bd2655564635df58988dfae306c4aeb5583938151
sha256sums_x86_64 = 872a7d7fe1167c75340807be0e3a0bb079389e28d813eb4e198b3d1757e7a583
source_aarch64 = terraphim-agent-1.21.16-aarch64-unknown-linux-musl.tar.gz::https://github.com/terraphim/terraphim-clients/releases/download/v1.21.16/terraphim-agent-1.21.16-aarch64-unknown-linux-musl.tar.gz
source_aarch64 = terraphim-grep-1.21.16-aarch64-unknown-linux-musl.tar.gz::https://github.com/terraphim/terraphim-clients/releases/download/v1.21.16/terraphim-grep-1.21.16-aarch64-unknown-linux-musl.tar.gz
sha256sums_aarch64 = f8530d963171e3f72b52b8b729653cafa5ae5e105e219f7ecec7b170037acaa7
sha256sums_aarch64 = 194d4cac04eccbfb998c4f060e44b286873510d354fd3a3a160bf63b2c5e025c

pkgname = terraphim-agent-bin
pkgdesc = Terraphim AI agent CLI (prebuilt static MUSL binary)
license = Apache-2.0
provides = terraphim-agent
conflicts = terraphim-agent

pkgname = terraphim-grep-bin
pkgdesc = Terraphim AI grep CLI (prebuilt static MUSL binary)
license = MIT
provides = terraphim-grep
conflicts = terraphim-grep
87 changes: 87 additions & 0 deletions pkgbuilds/terraphim-clients-bin/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Maintainer: Terraphim Team <team@terraphim.ai>
# Contributor: Alex Mikhalev <alex@metacortex.engineer>
#
# Canonical split PKGBUILD for the prebuilt Terraphim AI client CLIs.
#
# This file is the single upstream source of truth for the AUR package
# `terraphim-clients-bin` (Gitea terraphim-clients#316). The downstream
# Omarchy directory
# `omacom/omarchy-pkgs/pkgbuilds/terraphim-clients-bin/` consumes the same
# split-package semantics (Gitea terraphim-clients#249).
#
# The release archives are self-contained (binary + both license texts) and
# are static-PIE linked, so nothing is compiled and neither output has a
# runtime library dependency.
#
# Regenerate the committed .SRCINFO after any edit; ./verify.sh fails on
# drift. See README.md for the container/CI invocation.

pkgbase=terraphim-clients-bin
pkgname=(terraphim-agent-bin terraphim-grep-bin)
pkgver=1.21.16
pkgrel=1
pkgdesc='Terraphim AI command-line clients (prebuilt static MUSL binaries)'
arch=('x86_64' 'aarch64')
url='https://terraphim.ai'
license=('Apache-2.0' 'MIT')
options=('!strip' '!debug')

_repo='terraphim/terraphim-clients'
_release="https://github.com/${_repo}/releases/download/v${pkgver}"

# One archive per binary per architecture. Every archive extracts the CLI plus
# the repository's two license texts (identical bytes in both archives, so the
# colliding extraction is harmless).
source_x86_64=(
"terraphim-agent-${pkgver}-x86_64-unknown-linux-musl.tar.gz::${_release}/terraphim-agent-${pkgver}-x86_64-unknown-linux-musl.tar.gz"
"terraphim-grep-${pkgver}-x86_64-unknown-linux-musl.tar.gz::${_release}/terraphim-grep-${pkgver}-x86_64-unknown-linux-musl.tar.gz"
)
source_aarch64=(
"terraphim-agent-${pkgver}-aarch64-unknown-linux-musl.tar.gz::${_release}/terraphim-agent-${pkgver}-aarch64-unknown-linux-musl.tar.gz"
"terraphim-grep-${pkgver}-aarch64-unknown-linux-musl.tar.gz::${_release}/terraphim-grep-${pkgver}-aarch64-unknown-linux-musl.tar.gz"
)

# Digests are the authoritative SHA-256 values published in the release's
# SHA256SUMS asset for v${pkgver}. tests/test_pkgbuild_release_contract.py pins
# the same values so a version bump cannot silently keep stale digests.
sha256sums_x86_64=(
'71cb87455959f2eaa04fab1bd2655564635df58988dfae306c4aeb5583938151'
'872a7d7fe1167c75340807be0e3a0bb079389e28d813eb4e198b3d1757e7a583'
)
sha256sums_aarch64=(
'f8530d963171e3f72b52b8b729653cafa5ae5e105e219f7ecec7b170037acaa7'
'194d4cac04eccbfb998c4f060e44b286873510d354fd3a3a160bf63b2c5e025c'
)

# Prebuilt, already-stripped static binaries: never strip or emit debug info.
# `depends` is intentionally left unset (empty) for both outputs: the MUSL
# binaries are static-PIE and pull in no runtime libraries.
# `arch`, `source*` and `sha256sums*` are shared by both split outputs.

package_terraphim-agent-bin() {
pkgdesc='Terraphim AI agent CLI (prebuilt static MUSL binary)'
license=('Apache-2.0')
provides=('terraphim-agent')
conflicts=('terraphim-agent')

install -Dm0755 "${srcdir}/terraphim-agent" \
"${pkgdir}/usr/bin/terraphim-agent"
install -Dm0644 "${srcdir}/LICENSE-Apache-2.0" \
"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE-Apache-2.0"
install -d "${pkgdir}/usr/share/terraphim/package-manager.d"
printf 'pacman\n' > "${pkgdir}/usr/share/terraphim/package-manager.d/terraphim-agent"
}

package_terraphim-grep-bin() {
pkgdesc='Terraphim AI grep CLI (prebuilt static MUSL binary)'
license=('MIT')
provides=('terraphim-grep')
conflicts=('terraphim-grep')

install -Dm0755 "${srcdir}/terraphim-grep" \
"${pkgdir}/usr/bin/terraphim-grep"
install -Dm0644 "${srcdir}/LICENSE-MIT" \
"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE-MIT"
install -d "${pkgdir}/usr/share/terraphim/package-manager.d"
printf 'pacman\n' > "${pkgdir}/usr/share/terraphim/package-manager.d/terraphim-grep"
}
71 changes: 71 additions & 0 deletions pkgbuilds/terraphim-clients-bin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# terraphim-clients-bin (Arch / AUR / Omarchy)

Canonical split PKGBUILD for the prebuilt Terraphim AI client CLIs, published
from the public immutable GitHub release `terraphim/terraphim-clients`.

- **pkgbase:** `terraphim-clients-bin`
- **outputs:** `terraphim-agent-bin` (Apache-2.0) and `terraphim-grep-bin` (MIT)
- **architectures:** `x86_64`, `aarch64` (static MUSL binaries, no runtime deps)
- **tracks:** Gitea terraphim-clients#316 (AUR), #249 (Omarchy downstream)

Each split output owns exactly one executable, one license text and one
per-binary package-manager receipt:

| Owners | `terraphim-agent-bin` | `terraphim-grep-bin` |
|---|---|---|
| executable | `/usr/bin/terraphim-agent` | `/usr/bin/terraphim-grep` |
| license | `/usr/share/licenses/terraphim-agent-bin/LICENSE-Apache-2.0` | `/usr/share/licenses/terraphim-grep-bin/LICENSE-MIT` |
| receipt | `/usr/share/terraphim/package-manager.d/terraphim-agent` = `pacman` | `/usr/share/terraphim/package-manager.d/terraphim-grep` = `pacman` |

The receipt is what makes the packaged clients treat themselves as
package-managed: no startup update request and no self-update writing a shadow
binary under `~/.local/bin` (see `crates/terraphim_update/src/policy.rs`).

## Verification

`verify.sh` builds the split package as an unprivileged user, checks
`.SRCINFO` drift, runs `namcap`, asserts split ownership, then installs,
`pacman -Qkk`\ s, smoke-tests `--version` against `pkgver`, checks both
receipts and removes the packages.

Run it in an Arch container (Docker/OrbStack on macOS):

```bash
cd pkgbuilds/terraphim-clients-bin
docker run --rm -v "$PWD":/w -w /w archlinux:base-devel bash -lc \
'pacman -Sy --noconfirm namcap >/dev/null && ./verify.sh'
```

```bash
python3 -m unittest tests.test_pkgbuild_release_contract -v
```

## Regenerating .SRCINFO

`.SRCINFO` is generated, never hand-edited:

```bash
docker run --rm -v "$PWD":/w -w /w archlinux:base-devel bash -lc \
'makepkg --printsrcinfo' > .SRCINFO
```

## Releasing a new version

1. Confirm the new public GitHub release exists with all four MUSL archives.
2. Bump `pkgver` in `PKGBUILD`.
3. Copy the two x86_64 and two aarch64 SHA-256 values from the release's
`SHA256SUMS` into the matching `sha256sums_*` arrays.
4. Update the pinned digests in `tests/test_pkgbuild_release_contract.py`.
5. Regenerate `.SRCINFO` and run `./verify.sh`.
6. AUR: clone `ssh://aur@aur.archlinux.org/terraphim-clients-bin.git`,
copy `PKGBUILD` and `.SRCINFO` to the repo root, commit and push
`master`. AUR is not on the Omarchy critical path.

## Downstream Omarchy

Omarchy consumes this package as one directory,
`omacom/omarchy-pkgs/pkgbuilds/terraphim-clients-bin/`, with
`.omarchy/package.json` using `"source": "local"`, `"release_ring": "fast"`
and an `upstream.watch.github` entry for `terraphim/terraphim-clients`
(see Gitea terraphim-clients#249). The split semantics above are the contract;
do not fork the PKGBUILD.
69 changes: 69 additions & 0 deletions pkgbuilds/terraphim-clients-bin/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Full Arch verification for the terraphim-clients-bin split package.
#
# Intended to run inside an Arch Linux container (see README.md):
# docker run --rm -v "$PWD/..":/mnt -w /mnt archlinux:base-devel \
# bash -lc 'pacman -Sy --noconfirm namcap >/dev/null && ./pkgbuilds/terraphim-clients-bin/verify.sh'
#
# When run as root it builds as an unprivileged \`builder\` user (makepkg
# refuses to run as root) and installs/removes with pacman.
set -euo pipefail
cd "$(dirname "$0")"

PKGVER="$(sed -n 's/^pkgver=//p' PKGBUILD)"
echo "== pkgver: $PKGVER =="

if [ "$(id -u)" -eq 0 ]; then
id builder >/dev/null 2>&1 || useradd -m builder
chown -R builder:builder .
run_makepkg() { runuser -u builder -- makepkg "$@"; }
else
run_makepkg() { makepkg "$@"; }
fi

echo "== .SRCINFO drift =="
run_makepkg --printsrcinfo > /tmp/.SRCINFO.generated
if ! diff -u .SRCINFO /tmp/.SRCINFO.generated; then
echo "ERROR: .SRCINFO is stale; regenerate with 'makepkg --printsrcinfo > .SRCINFO'" >&2
exit 1
fi

echo "== build =="
rm -f ./*.pkg.tar.zst
run_makepkg --force --noconfirm

agent="$(ls terraphim-agent-bin-"$PKGVER"-1-*.pkg.tar.zst)"
grep_pkg="$(ls terraphim-grep-bin-"$PKGVER"-1-*.pkg.tar.zst)"
echo "artifacts: $agent $grep_pkg"

echo "== namcap =="
namcap "$agent" "$grep_pkg"

echo "== split ownership =="
list_agent="$(bsdtar -tf "$agent" | sort)"
list_grep="$(bsdtar -tf "$grep_pkg" | sort)"
printf '%s\n' "$list_agent"
printf '%s\n' "$list_grep"
for f in usr/bin/terraphim-agent usr/share/licenses/terraphim-agent-bin/LICENSE-Apache-2.0 usr/share/terraphim/package-manager.d/terraphim-agent; do
grep -qx "$f" <<<"$list_agent" || { echo "agent missing $f" >&2; exit 1; }
done
for f in usr/bin/terraphim-grep usr/share/licenses/terraphim-grep-bin/LICENSE-MIT usr/share/terraphim/package-manager.d/terraphim-grep; do
grep -qx "$f" <<<"$list_grep" || { echo "grep missing $f" >&2; exit 1; }
done
! grep -q 'terraphim-grep' <<<"$list_agent"
! grep -q 'terraphim-agent' <<<"$list_grep"

echo "== install / Qkk / smoke / receipt / remove =="
as_root() { if [ "$(id -u)" -eq 0 ]; then "$@"; else sudo "$@"; fi; }
as_root pacman -U --noconfirm "$agent" "$grep_pkg"
as_root pacman -Qkk terraphim-agent-bin terraphim-grep-bin
terraphim-agent --version | grep -F "$PKGVER"
terraphim-grep --version | grep -F "$PKGVER"
test "$(tr -d '\n' < /usr/share/terraphim/package-manager.d/terraphim-agent)" = pacman
test "$(tr -d '\n' < /usr/share/terraphim/package-manager.d/terraphim-grep)" = pacman
as_root pacman -R --noconfirm terraphim-agent-bin terraphim-grep-bin
test ! -e /usr/bin/terraphim-agent
test ! -e /usr/bin/terraphim-grep
test ! -e /usr/share/terraphim/package-manager.d/terraphim-agent

echo "ALL CHECKS PASSED"
Loading
Loading