Files
guix-tribes/scripts/update-tribes-pin
self a8b9edcb5a scripts: add tribes pin update helper
Add a small helper that resolves a Tribes revision, exports a clean source tree from the local checkout, and asks pguix to compute the exact Guix fixed-output hashes for the source, raw Mix deps, prepared Mix deps, and npm deps.\n\nThe script updates tribes/packages/source.scm in one step, so bumping the pin no longer requires hand-running git archive, guix hash, and the mix/npm dependency hash pipeline separately.
2026-04-12 13:03:05 +02:00

219 lines
5.6 KiB
Bash
Executable File

#!/bin/sh
set -eu
usage() {
cat <<'EOF'
Usage: update-tribes-pin [options] [rev]
Pin guix-tribes to a Tribes commit and refresh all fixed-output hashes.
By default, REV is "master" resolved from the local Tribes checkout.
Options:
--tribes-repo PATH Local Tribes git checkout
--guix-repo PATH Local guix-tribes checkout
--pguix-host HOST SSH host used for Guix builds and hashing
-h, --help Show this help
EOF
}
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
default_guix_repo=$(CDPATH= cd -- "$script_dir/.." && pwd)
default_tribes_repo=$(CDPATH= cd -- "$default_guix_repo/../tribes" && pwd)
tribes_repo=$default_tribes_repo
guix_repo=$default_guix_repo
pguix_host=pguix
rev=master
while [ "$#" -gt 0 ]; do
case "$1" in
--tribes-repo)
tribes_repo=$2
shift 2
;;
--guix-repo)
guix_repo=$2
shift 2
;;
--pguix-host)
pguix_host=$2
shift 2
;;
-h|--help)
usage
exit 0
;;
--)
shift
break
;;
-*)
printf 'Unknown option: %s\n' "$1" >&2
usage >&2
exit 1
;;
*)
rev=$1
shift
;;
esac
done
if [ "$#" -gt 0 ]; then
printf 'Unexpected arguments: %s\n' "$*" >&2
usage >&2
exit 1
fi
source_file=$guix_repo/tribes/packages/source.scm
if [ ! -d "$tribes_repo/.git" ]; then
printf 'Tribes repo not found: %s\n' "$tribes_repo" >&2
exit 1
fi
if [ ! -f "$source_file" ]; then
printf 'guix-tribes source file not found: %s\n' "$source_file" >&2
exit 1
fi
require_tool() {
if ! command -v "$1" >/dev/null 2>&1; then
printf 'Missing required tool: %s\n' "$1" >&2
exit 1
fi
}
require_tool env
require_tool git
require_tool rsync
require_tool ssh
require_tool tar
require_tool perl
require_tool mktemp
commit=$(git -C "$tribes_repo" rev-parse "$rev^{commit}")
version=$(env LC_ALL=C perl -0ne 'print $1 if /\(git-version "([^"]+)"/' "$source_file")
if [ -z "$version" ]; then
printf 'Could not read Tribes version from %s\n' "$source_file" >&2
exit 1
fi
local_tmp=$(mktemp -d "${TMPDIR:-/tmp}/tribes-pin.XXXXXX")
remote_tmp=
cleanup() {
if [ -n "${remote_tmp:-}" ]; then
ssh "$pguix_host" "rm -rf '$remote_tmp'" >/dev/null 2>&1 || true
fi
rm -rf "$local_tmp"
}
trap cleanup EXIT INT TERM
mkdir -p "$local_tmp/tribes-source"
git -C "$tribes_repo" archive "$commit" | tar -x -C "$local_tmp/tribes-source"
remote_tmp=$(ssh "$pguix_host" 'mktemp -d /tmp/tribes-pin.XXXXXX')
rsync -az --delete --exclude .git "$guix_repo/" "$pguix_host:$remote_tmp/guix-tribes/"
rsync -az --delete "$local_tmp/tribes-source/" "$pguix_host:$remote_tmp/tribes-source/"
source_hash=$(ssh "$pguix_host" "guix hash -rx '$remote_tmp/tribes-source'" | tr -d '\r')
remote_run_scheme() {
name=$1
body=$2
ssh "$pguix_host" "cat > '$remote_tmp/$name.scm' <<'EOF'
$body
EOF"
ssh "$pguix_host" "guix build -L '$remote_tmp/guix-tribes' -f '$remote_tmp/$name.scm' --no-grafts 2>&1" || true
}
extract_hash() {
env LC_ALL=C perl -ne '
if (s/.*\bgot:\s*([0-9a-z]{52}).*/$1/) {
chomp;
$hash = $_;
} elsif (s/.*\bactual hash:\s*([0-9a-z]{52}).*/$1/) {
chomp;
$hash = $_;
}
END {
if (defined $hash) {
print $hash;
} else {
exit 1;
}
}
'
}
dummy_hash=0000000000000000000000000000000000000000000000000000
raw_output=$(remote_run_scheme raw-mix-deps "(use-modules (guix gexp) (tribes packages source))
(fetch-mix-deps
(local-file \"$remote_tmp/tribes-source\" #:recursive? #t)
#:name \"tribes-mix-deps-raw\"
#:version \"$version\"
#:sha256 \"$dummy_hash\")")
raw_mix_hash=$(printf '%s\n' "$raw_output" | extract_hash) || {
printf 'Failed to extract raw mix deps hash.\n%s\n' "$raw_output" >&2
exit 1
}
mix_output=$(remote_run_scheme mix-deps "(use-modules (guix gexp) (tribes packages source))
(tribes-mix-deps
(local-file \"$remote_tmp/tribes-source\" #:recursive? #t)
#:name \"tribes-mix-deps\"
#:version \"$version\"
#:raw-sha256 \"$raw_mix_hash\"
#:sha256 \"$dummy_hash\")")
mix_hash=$(printf '%s\n' "$mix_output" | extract_hash) || {
printf 'Failed to extract prepared mix deps hash.\n%s\n' "$mix_output" >&2
exit 1
}
npm_output=$(remote_run_scheme npm-deps "(use-modules (guix gexp) (tribes packages source))
(fetch-npm-deps
(local-file \"$remote_tmp/tribes-source\" #:recursive? #t)
#:mix-fod-deps
(tribes-mix-deps
(local-file \"$remote_tmp/tribes-source\" #:recursive? #t)
#:name \"tribes-mix-deps\"
#:version \"$version\"
#:raw-sha256 \"$raw_mix_hash\"
#:sha256 \"$mix_hash\")
#:name \"tribes-npm-deps\"
#:version \"$version\"
#:sha256 \"$dummy_hash\")")
npm_hash=$(printf '%s\n' "$npm_output" | extract_hash) || {
printf 'Failed to extract npm deps hash.\n%s\n' "$npm_output" >&2
exit 1
}
COMMIT=$commit \
SOURCE_HASH=$source_hash \
RAW_MIX_HASH=$raw_mix_hash \
MIX_HASH=$mix_hash \
NPM_HASH=$npm_hash \
env LC_ALL=C perl -0pi -e '
s/\(define %tribes-raw-mix-deps-sha256\n "[^"]+"\)/(define %tribes-raw-mix-deps-sha256\n "$ENV{RAW_MIX_HASH}")/;
s/\(define %tribes-mix-deps-sha256\n "[^"]+"\)/(define %tribes-mix-deps-sha256\n "$ENV{MIX_HASH}")/;
s/\(define %tribes-npm-deps-sha256\n "[^"]+"\)/(define %tribes-npm-deps-sha256\n "$ENV{NPM_HASH}")/;
s/\(define %tribes-commit\n "[^"]+"\)/(define %tribes-commit\n "$ENV{COMMIT}")/;
s/\(define %tribes-source-sha256\n "[^"]+"\)/(define %tribes-source-sha256\n "$ENV{SOURCE_HASH}")/;
' "$source_file"
printf 'Updated %s\n' "$source_file"
printf 'commit: %s\n' "$commit"
printf 'source sha256: %s\n' "$source_hash"
printf 'raw mix deps sha256: %s\n' "$raw_mix_hash"
printf 'mix deps sha256: %s\n' "$mix_hash"
printf 'npm deps sha256: %s\n' "$npm_hash"