Sync config from arch
- hypr/apps.lua - hypr/autostart.lua - hypr/envs.lua - hypr/hyprland.lua - hypr/hyprsunset.conf - hypr/input.lua - hypr/looknfeel.lua - hypr/omasettings.lua - hypr/xdph.conf - omarchy/branding/about.txt - omarchy/branding/screensaver.txt - omarchy/extensions/omarchy-menu.jsonc - omarchy/hooks/battery-low.d/play-warning-sound.sample - omarchy/hooks/font-set.d/show-font-notification.sample - omarchy/hooks/post-boot.d/weather.sample - omarchy/hooks/post-update.d/install-voxtype.hook - omarchy/hooks/post-update.d/setup-agent.hook - omarchy/hooks/post-update.d/setup-fingerprint.hook - omarchy/hooks/post-update.d/show-update-notification.sample - omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample - omarchy/hooks/theme-set.d/show-theme-notification.sample - omarchy/shell.json - omarchy/shell.toml - omarchy/theme.name - omarchy/themes/azure-glow/README.md - omarchy/themes/azure-glow/alacritty.toml - omarchy/themes/azure-glow/btop.theme - omarchy/themes/azure-glow/hyprland.conf - omarchy/themes/azure-glow/hyprlock.conf - omarchy/themes/azure-glow/icons.theme - … 269 more
This commit is contained in:
@@ -0,0 +1,351 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the SSH agent helper reproducibly.
|
||||
#
|
||||
# The compiled helper is committed to this repository. That is only defensible
|
||||
# if anyone can rebuild it from the committed source and get the same bytes --
|
||||
# otherwise the binary is an unauditable blob that happens to sit next to some
|
||||
# source code. This script is the one entry point that produces it, locally and
|
||||
# in CI, so there is a single definition of what "the release build" means.
|
||||
#
|
||||
# What fixes the output bytes:
|
||||
#
|
||||
# Cargo.lock the exact dependency set (committed)
|
||||
# rust-toolchain.toml the exact compiler (committed)
|
||||
# --target the ABI (below)
|
||||
# --remap-path-prefix build paths, which otherwise leak (below)
|
||||
# the container image glibc, ld and strip (PINNED_IMAGE)
|
||||
#
|
||||
# The last one is why a bare runner is not enough. A GNU-linked binary carries
|
||||
# symbol version requirements from the glibc it built against, and `strip`
|
||||
# output differs between binutils releases -- so `ubuntu-latest` drifting
|
||||
# forward would change the bytes with nothing in the repository having changed.
|
||||
#
|
||||
# rustc does not consume SOURCE_DATE_EPOCH and embeds no build timestamp, so
|
||||
# that variable is deliberately not part of this. The git commit is likewise
|
||||
# not embedded: a binary tracked by the same commit that names it cannot be
|
||||
# reproduced from that commit.
|
||||
|
||||
set -o pipefail
|
||||
set -u
|
||||
|
||||
# The pinned build environment. Changing it means regenerating the binary and
|
||||
# its checksum in the same commit.
|
||||
#
|
||||
# Pinned by digest rather than tag: a tag is a moving pointer, and
|
||||
# `rust:1.98.0-bookworm` is rebuilt on new Debian base images, which changes
|
||||
# glibc and binutils underneath an unchanged Rust version. This is the
|
||||
# multi-arch manifest digest published 2026-08-25.
|
||||
PINNED_IMAGE="rust:1.98.0-bookworm@sha256:82150a52ec202c1b14d7817e14516c392bb7f5cfebd88f1ed531cb37ebd39922"
|
||||
SUPPORTED_TARGET="x86_64-unknown-linux-gnu"
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
# Architecture-scoped from the start. v1 ships x86_64 only, but a flat bin/
|
||||
# would have to be restructured the day a second target appears, and the
|
||||
# checksum file would have to change shape with it.
|
||||
OUTPUT_ARCH="x86_64-linux"
|
||||
OUTPUT_DIR="$REPO_ROOT/bin/$OUTPUT_ARCH"
|
||||
OUTPUT_NAME="qs-bitwarden-ssh-agent"
|
||||
# One SHA256SUMS covering every tracked artifact, in the format `sha256sum -c`
|
||||
# reads, rather than a sidecar file per binary.
|
||||
SUMS_FILE="$REPO_ROOT/bin/SHA256SUMS"
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: scripts/build-agent.sh [--verify-reproducible] [--compare-tracked]
|
||||
[--allow-unpinned] [--explain]
|
||||
|
||||
(no flags) Build the release helper into bin/<arch>/ and write
|
||||
bin/SHA256SUMS.
|
||||
--verify-reproducible Build twice from two different absolute paths and
|
||||
require byte-identical output. Writes nothing.
|
||||
--compare-tracked Report whether the tracked binary matches a fresh build
|
||||
of this source, without modifying the repository.
|
||||
Exit 1 on drift.
|
||||
--allow-unpinned Permit a host-toolchain build when no container runtime
|
||||
is available. The result is NOT reproducible and is
|
||||
refused by --verify-reproducible.
|
||||
--explain Say which build environment this would use and stop.
|
||||
Runs nothing, pulls nothing, writes nothing.
|
||||
USAGE
|
||||
}
|
||||
|
||||
fail() { printf 'build-agent: %s\n' "$1" >&2; exit 1; }
|
||||
note() { printf 'build-agent: %s\n' "$1" >&2; }
|
||||
|
||||
# --- preconditions ---------------------------------------------------------
|
||||
|
||||
require_lockfile() {
|
||||
[ -f "$REPO_ROOT/agent/Cargo.lock" ] \
|
||||
|| fail "agent/Cargo.lock is missing; a release build has no dependency set without it"
|
||||
[ -f "$REPO_ROOT/agent/rust-toolchain.toml" ] \
|
||||
|| fail "agent/rust-toolchain.toml is missing; the compiler is not pinned"
|
||||
}
|
||||
|
||||
# A target other than the one the committed binary is for would produce bytes
|
||||
# nobody can compare against it.
|
||||
require_target() {
|
||||
local target="${1:-$SUPPORTED_TARGET}"
|
||||
[ "$target" = "$SUPPORTED_TARGET" ] \
|
||||
|| fail "unsupported target '$target'; this release builds only $SUPPORTED_TARGET"
|
||||
}
|
||||
|
||||
# Are we already running inside the pinned build environment?
|
||||
#
|
||||
# This is the question that matters, and it is not the same as "can I start a
|
||||
# container". CI runs this script *inside* the pinned image, where no
|
||||
# container runtime exists and none is wanted -- an earlier version conflated
|
||||
# the two and refused to build in the one environment it was written for.
|
||||
#
|
||||
# QSBW_PINNED_BUILD is the claim, set by the release workflow and by this
|
||||
# script when it re-executes itself in a container. The compiler check below
|
||||
# is the part that does not take that claim on trust: if the environment says
|
||||
# it is pinned but carries a different rustc than rust-toolchain.toml names,
|
||||
# the claim is wrong and the build stops.
|
||||
in_pinned_environment() {
|
||||
[ "${QSBW_PINNED_BUILD:-}" = "1" ] || return 1
|
||||
local pinned actual
|
||||
pinned="$(grep -oP 'channel\s*=\s*"\K[^"]+' "$REPO_ROOT/agent/rust-toolchain.toml" 2>/dev/null)"
|
||||
actual="$(rustc --version 2>/dev/null | cut -d' ' -f2)"
|
||||
[ -n "$pinned" ] && [ "$pinned" = "$actual" ] \
|
||||
|| fail "this environment claims to be the pinned one but carries rustc ${actual:-unknown}, not $pinned"
|
||||
|
||||
# The compiler check alone is too weak: a host may happen to carry the same
|
||||
# rustc while its glibc and binutils -- the things the image exists to pin --
|
||||
# are entirely different. The pinned image is Debian bookworm, so verify
|
||||
# that too. It is cheap, and it catches the case of a developer setting the
|
||||
# variable on a machine that merely has the right Rust.
|
||||
local os_id os_codename
|
||||
os_id="$(. /etc/os-release 2>/dev/null && printf '%s' "${ID:-}")"
|
||||
os_codename="$(. /etc/os-release 2>/dev/null && printf '%s' "${VERSION_CODENAME:-}")"
|
||||
[ "$os_id" = "debian" ] && [ "$os_codename" = "bookworm" ] \
|
||||
|| fail "this environment claims to be the pinned one but is ${os_id:-unknown}/${os_codename:-unknown},
|
||||
not debian/bookworm. The image pins glibc and binutils, not just the compiler."
|
||||
return 0
|
||||
}
|
||||
|
||||
# A runtime we could use to *enter* the pinned environment from outside it.
|
||||
container_runtime() {
|
||||
# Omarchy's own convention is `sudo docker`: it does not put users in the
|
||||
# docker group, because that group is equivalent to passwordless root. A
|
||||
# repository whose purpose is guarding private keys should not require that
|
||||
# to build.
|
||||
if docker info >/dev/null 2>&1; then echo "docker"; return 0; fi
|
||||
if sudo -n docker info >/dev/null 2>&1; then echo "sudo docker"; return 0; fi
|
||||
if podman info >/dev/null 2>&1; then echo "podman"; return 0; fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Re-run this script inside the pinned image, so a local reproduction uses the
|
||||
# same glibc, linker and strip that produced the committed bytes.
|
||||
reexec_in_container() {
|
||||
local runtime="$1"
|
||||
shift
|
||||
note "entering the pinned image with: $runtime"
|
||||
# shellcheck disable=SC2086
|
||||
$runtime run --rm \
|
||||
-e QSBW_PINNED_BUILD=1 \
|
||||
-v "$REPO_ROOT:/work" -w /work \
|
||||
"$PINNED_IMAGE" \
|
||||
/work/scripts/build-agent.sh "$@"
|
||||
}
|
||||
|
||||
# --- the build itself ------------------------------------------------------
|
||||
|
||||
# Compose the flags that remove build-path variance. The registry path is the
|
||||
# one that usually leaks: dependency source paths end up in panic messages and
|
||||
# debug sections, and $CARGO_HOME differs per machine and per CI runner.
|
||||
rustflags_for() {
|
||||
local src="$1" cargo_home="${2:-${CARGO_HOME:-$HOME/.cargo}}"
|
||||
printf -- '--remap-path-prefix=%s=/src --remap-path-prefix=%s/registry=/registry' \
|
||||
"$src" "$cargo_home"
|
||||
}
|
||||
|
||||
# One cargo invocation, with everything that affects output stated explicitly.
|
||||
#
|
||||
# The target directory must live *inside* the source root. It is remapped
|
||||
# along with everything else under it, and build-script output paths reach the
|
||||
# binary: a target directory somewhere else is an unremapped path that changes
|
||||
# the bytes. That is not hypothetical -- the release build used a separate
|
||||
# temporary directory and produced a different digest from the two builds
|
||||
# --verify-reproducible had just declared identical.
|
||||
build_into() {
|
||||
local src="$1"
|
||||
( cd "$src/agent" \
|
||||
&& CARGO_TARGET_DIR="$src/target" \
|
||||
RUSTFLAGS="$(rustflags_for "$src")" \
|
||||
cargo build --locked --release --target "$SUPPORTED_TARGET" >&2 )
|
||||
}
|
||||
|
||||
# Export the committed tree somewhere clean and build it there.
|
||||
#
|
||||
# Every mode goes through this, so a release, a reproducibility check and a
|
||||
# drift comparison are literally the same procedure. They diverged once, and
|
||||
# the divergence was invisible until two digests of the same source disagreed.
|
||||
#
|
||||
# HEAD rather than the working tree: a release artifact should not contain
|
||||
# uncommitted changes, and the comparison modes have to build what the
|
||||
# repository actually says.
|
||||
build_clean_copy() {
|
||||
local dest="$1"
|
||||
mkdir -p "$dest" || return 1
|
||||
git -C "$REPO_ROOT" archive HEAD | tar -x -C "$dest" || return 1
|
||||
build_into "$dest" || return 1
|
||||
printf '%s/target/%s/release/%s' "$dest" "$SUPPORTED_TARGET" "$OUTPUT_NAME"
|
||||
}
|
||||
|
||||
digest() { sha256sum "$1" | cut -d' ' -f1; }
|
||||
|
||||
# --- modes -----------------------------------------------------------------
|
||||
|
||||
# Build twice from genuinely different absolute paths. Copying the source to a
|
||||
# second location is the point: a path that leaked into the binary shows up
|
||||
# here as a digest mismatch and nowhere else.
|
||||
verify_reproducible() {
|
||||
if ! in_pinned_environment; then
|
||||
local runtime
|
||||
if runtime="$(container_runtime)"; then
|
||||
reexec_in_container "$runtime" --verify-reproducible
|
||||
return $?
|
||||
fi
|
||||
fail "not in the pinned build environment and no container runtime to enter one, so the
|
||||
system toolchain is unpinned and the result would not be reproducible. This check
|
||||
refuses to report success it cannot support. It runs in CI, which executes it inside
|
||||
the pinned image. See --allow-unpinned for a plain build that makes no such claim."
|
||||
fi
|
||||
note "building in the pinned environment"
|
||||
|
||||
local work first second
|
||||
work="$(mktemp -d)" || fail "could not create a work directory"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$work'" EXIT
|
||||
first="$work/path-one"
|
||||
second="$work/a-considerably-longer-second-path"
|
||||
|
||||
local a b binary
|
||||
binary="$(build_clean_copy "$first")" || fail "the first build failed"
|
||||
a="$(digest "$binary")"
|
||||
binary="$(build_clean_copy "$second")" || fail "the second build failed"
|
||||
b="$(digest "$binary")"
|
||||
|
||||
printf 'path one: %s\npath two: %s\n' "$a" "$b"
|
||||
if [ "$a" != "$b" ]; then
|
||||
fail "the two builds differ, so something in the build path reached the binary"
|
||||
fi
|
||||
note "identical across both paths: $a"
|
||||
}
|
||||
|
||||
# Report drift without touching the repository, so it is safe in a PR gate.
|
||||
compare_tracked() {
|
||||
local committed="$OUTPUT_DIR/$OUTPUT_NAME"
|
||||
[ -f "$committed" ] || fail "no tracked binary at bin/$OUTPUT_ARCH/$OUTPUT_NAME"
|
||||
|
||||
# The comparison is only worth anything from inside the pinned environment.
|
||||
# The tracked bytes were produced there, and the image pins glibc and
|
||||
# binutils as well as the compiler -- so a host build with the right rustc
|
||||
# and a different libc reports drift that does not exist. This mode is the
|
||||
# PR gate: it was the one mode that could fail for a reason having nothing
|
||||
# to do with the source it was asked about.
|
||||
if ! in_pinned_environment; then
|
||||
local runtime
|
||||
if runtime="$(container_runtime)"; then
|
||||
reexec_in_container "$runtime" --compare-tracked
|
||||
return $?
|
||||
fi
|
||||
fail "not in the pinned build environment and no container runtime to enter one. A build
|
||||
here would use the host toolchain, whose output differs from the tracked bytes for
|
||||
reasons that are not drift -- so this check refuses to report a mismatch it cannot
|
||||
stand behind. It runs in CI, which executes it inside the pinned image."
|
||||
fi
|
||||
note "comparing in the pinned environment"
|
||||
|
||||
local work
|
||||
work="$(mktemp -d)" || fail "could not create a work directory"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$work'" EXIT
|
||||
local fresh binary
|
||||
binary="$(build_clean_copy "$work/source")" || fail "the comparison build failed"
|
||||
fresh="$(digest "$binary")"
|
||||
local have
|
||||
have="$(digest "$committed")"
|
||||
printf 'tracked: %s\nfresh: %s\n' "$have" "$fresh"
|
||||
[ "$have" = "$fresh" ] \
|
||||
|| fail "bin/$OUTPUT_ARCH/$OUTPUT_NAME does not match a build of this source"
|
||||
note "the tracked binary matches this source"
|
||||
}
|
||||
|
||||
build_release() {
|
||||
local allow_unpinned="$1"
|
||||
if ! in_pinned_environment; then
|
||||
local runtime
|
||||
if runtime="$(container_runtime)"; then
|
||||
reexec_in_container "$runtime"
|
||||
return $?
|
||||
fi
|
||||
[ "$allow_unpinned" = "yes" ] || fail "not in the pinned build environment and no container runtime
|
||||
to enter one, so the system toolchain would be unpinned. Pass --allow-unpinned to build
|
||||
anyway, understanding the result is not the release artifact."
|
||||
note "WARNING: building with the host toolchain. These bytes are not reproducible"
|
||||
note " and must not be committed as the release binary."
|
||||
fi
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
local work
|
||||
work="$(mktemp -d)" || fail "could not create a work directory"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$work'" EXIT
|
||||
local binary
|
||||
binary="$(build_clean_copy "$work/source")" || fail "the build failed"
|
||||
install -m 0755 "$binary" "$OUTPUT_DIR/$OUTPUT_NAME"
|
||||
# Paths relative to bin/, so `sha256sum -c SHA256SUMS` works from there
|
||||
# whatever the checkout is called.
|
||||
( cd "$REPO_ROOT/bin" && sha256sum "$OUTPUT_ARCH/$OUTPUT_NAME" > "$SUMS_FILE" )
|
||||
note "wrote bin/$OUTPUT_ARCH/$OUTPUT_NAME and bin/SHA256SUMS"
|
||||
}
|
||||
|
||||
# Report the decision without acting on it. Useful for a person wondering why
|
||||
# a build refused, and for tests that need to check the decision logic without
|
||||
# pulling an image and running two full builds to find out.
|
||||
explain() {
|
||||
if in_pinned_environment; then
|
||||
printf 'environment: pinned (building here directly)\n'
|
||||
return 0
|
||||
fi
|
||||
local runtime
|
||||
if runtime="$(container_runtime)"; then
|
||||
printf 'environment: not pinned, but reachable via %s\n' "$runtime"
|
||||
printf 'image: %s\n' "$PINNED_IMAGE"
|
||||
return 0
|
||||
fi
|
||||
printf 'environment: not pinned and no container runtime to enter one\n'
|
||||
printf 'consequence: a build here would not be reproducible; --verify-reproducible refuses\n'
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- entry point -----------------------------------------------------------
|
||||
|
||||
main() {
|
||||
local mode="build" allow_unpinned="no"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--verify-reproducible) mode="verify" ;;
|
||||
--explain) mode="explain" ;;
|
||||
--compare-tracked) mode="compare" ;;
|
||||
--allow-unpinned) allow_unpinned="yes" ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) usage >&2; fail "unknown argument '$1'" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
require_lockfile
|
||||
require_target "${CARGO_BUILD_TARGET:-$SUPPORTED_TARGET}"
|
||||
command -v cargo >/dev/null 2>&1 || fail "cargo is not on PATH"
|
||||
|
||||
case "$mode" in
|
||||
explain) explain ;;
|
||||
verify) verify_reproducible ;;
|
||||
compare) compare_tracked ;;
|
||||
build) build_release "$allow_unpinned" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user