Stamp locally packaged macOS apps with their update identity

This commit is contained in:
FBukovina 2026-09-17 22:52:46 +02:00
commit b3130a8b0b
5 changed files with 139 additions and 2 deletions

View file

@ -6,6 +6,18 @@ set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
# An installed .app needs a source identity for the updater, including when
# packaged locally. CI can still supply COMMIT explicitly. Plain `make`
# builds keep their "dev" default.
if [[ -z "${COMMIT:-}" ]]; then
if [[ ! -e "$ROOT/.git" ]] ||
! COMMIT="$(git -C "$ROOT" rev-parse --verify HEAD 2>/dev/null)"; then
echo "error: cannot determine the source commit; set COMMIT when bundling without Git metadata" >&2
exit 1
fi
fi
export COMMIT
ARCH="$(uname -m)"
case "$ARCH" in
arm64|aarch64) ARCH_TAG=arm64 ;;

View file

@ -0,0 +1,114 @@
#!/usr/bin/env bash
# Exercise build identity at the real bundler entry point without building GTK.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TMP="$(mktemp -d "${TMPDIR:-/tmp}/maturita-bundle-commit.XXXXXX")"
trap 'rm -rf "$TMP"' EXIT
fail() {
echo "FAIL: $*" >&2
exit 1
}
mkdir -p "$TMP/bin"
cat > "$TMP/bin/make" <<'EOF'
#!/usr/bin/env bash
printf '%s\n' "${COMMIT-UNSET}" >> "$MATURITA_TEST_MAKE_LOG"
if [[ "$*" == *" clean" ]]; then
exit 0
fi
# Stop before packaging, after observing the real build's environment.
exit 97
EOF
cat > "$TMP/bin/brew" <<'EOF'
#!/bin/sh
echo /unused-homebrew
EOF
cat > "$TMP/bin/uname" <<'EOF'
#!/bin/sh
echo arm64
EOF
chmod +x "$TMP/bin/make" "$TMP/bin/brew" "$TMP/bin/uname"
new_fixture() {
mkdir -p "$1/scripts"
cp "$ROOT/scripts/bundle-macos.sh" "$1/scripts/bundle-macos.sh"
}
run_bundle() {
local fixture="$1" mode="$2" value="${3-}"
MAKE_LOG="$fixture/make.log"
OUTPUT_LOG="$fixture/output.log"
rm -f "$MAKE_LOG"
if (
unset COMMIT GIT_DIR GIT_WORK_TREE GIT_COMMON_DIR GIT_INDEX_FILE
export PATH="$TMP/bin:$PATH"
export MATURITA_TEST_MAKE_LOG="$MAKE_LOG"
# A source archive must not accidentally inherit an enclosing checkout.
export GIT_CEILING_DIRECTORIES="$TMP"
if [[ "$mode" == supplied ]]; then
export COMMIT="$value"
fi
bash "$fixture/scripts/bundle-macos.sh"
) > "$OUTPUT_LOG" 2>&1; then
STATUS=0
else
STATUS=$?
fi
}
expect_build_commit() {
local expected="$1" actual
[[ "$STATUS" -eq 97 ]] || {
cat "$OUTPUT_LOG" >&2
fail "expected the stubbed build to run (status $STATUS)"
}
[[ -f "$MAKE_LOG" ]] || fail "make was not called"
actual="$(cat "$MAKE_LOG")"
[[ "$actual" == "$expected"$'\n'"$expected" ]] ||
fail "clean/build did not both receive COMMIT=$expected (got '$actual')"
}
expect_missing_identity() {
[[ "$STATUS" -ne 0 ]] || fail 'missing identity unexpectedly succeeded'
[[ ! -e "$MAKE_LOG" ]] || fail 'missing identity reached make'
grep -q 'COMMIT' "$OUTPUT_LOG" || fail 'missing identity has no COMMIT guidance'
}
GIT_FIXTURE="$TMP/checkout with spaces"
new_fixture "$GIT_FIXTURE"
git init -q "$GIT_FIXTURE"
git -C "$GIT_FIXTURE" -c user.name='Bundle test' \
-c user.email='bundle-test@example.invalid' -c commit.gpgsign=false \
-c core.hooksPath=/dev/null commit --allow-empty -qm 'Fixture commit'
EXPECTED="$(git -C "$GIT_FIXTURE" rev-parse HEAD)"
run_bundle "$GIT_FIXTURE" unset
expect_build_commit "$EXPECTED"
echo 'PASS: Git checkout identity with spaces in its path'
run_bundle "$GIT_FIXTURE" supplied ''
expect_build_commit "$EXPECTED"
echo 'PASS: empty COMMIT falls back to checkout identity'
ARCHIVE_FIXTURE="$TMP/source archive"
new_fixture "$ARCHIVE_FIXTURE"
EXPLICIT=0123456789abcdef0123456789abcdef01234567
run_bundle "$ARCHIVE_FIXTURE" supplied "$EXPLICIT"
expect_build_commit "$EXPLICIT"
echo 'PASS: explicit COMMIT works without Git metadata'
run_bundle "$ARCHIVE_FIXTURE" supplied dev
expect_build_commit dev
echo 'PASS: explicit development identity is preserved'
run_bundle "$ARCHIVE_FIXTURE" unset
expect_missing_identity
echo 'PASS: source archive without COMMIT fails before building'
NESTED_FIXTURE="$GIT_FIXTURE/exported sources"
new_fixture "$NESTED_FIXTURE"
run_bundle "$NESTED_FIXTURE" unset
expect_missing_identity
echo 'PASS: source archive does not inherit an unrelated parent Git identity'