bitchat-android/tools/reproducible-builds/verify-github-release.sh
2026-07-29 02:06:43 +02:00

95 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TAG="${1:?usage: verify-github-release.sh TAG [--no-rebuild]}"
MODE="${2:-}"
REPOSITORY="${BITCHAT_GITHUB_REPOSITORY:-permissionlesstech/bitchat-android}"
TEMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TEMP_DIR"' EXIT
if ! [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
echo "error: release tag must look like vX.Y.Z" >&2
exit 1
fi
if [ -n "$MODE" ] && [ "$MODE" != "--no-rebuild" ]; then
echo "error: unknown option: $MODE" >&2
exit 1
fi
if ! command -v gh >/dev/null 2>&1; then
echo "error: gh is required" >&2
exit 1
fi
if command -v sha256sum >/dev/null 2>&1; then
SHA256=(sha256sum)
elif command -v shasum >/dev/null 2>&1; then
SHA256=(shasum -a 256)
else
echo "error: sha256sum or shasum is required" >&2
exit 1
fi
DOWNLOAD_DIR="$TEMP_DIR/github"
mkdir -p "$DOWNLOAD_DIR"
gh release download "$TAG" \
--repo "$REPOSITORY" \
--dir "$DOWNLOAD_DIR" \
--pattern 'BITCHAT_BUILDINFO.json' \
--pattern 'BITCHAT_SHA256SUMS' \
--pattern 'BITCHAT_SHA256SUMS.unsigned' \
--pattern 'bitchat-android-*.apk' \
--pattern 'bitchat-android-*.aab'
attested_artifacts=(
BITCHAT_BUILDINFO.json
BITCHAT_SHA256SUMS.unsigned
bitchat-android-arm64-unsigned.apk
bitchat-android-armv7-unsigned.apk
bitchat-android-release-unsigned.aab
bitchat-android-universal-unsigned.apk
bitchat-android-x86-unsigned.apk
bitchat-android-x86_64-unsigned.apk
)
for artifact in "${attested_artifacts[@]}"; do
if [ ! -f "$DOWNLOAD_DIR/$artifact" ]; then
echo "error: attested canonical artifact missing: $artifact" >&2
exit 1
fi
gh attestation verify "$DOWNLOAD_DIR/$artifact" --repo "$REPOSITORY" >/dev/null
done
echo "GitHub provenance attestations for the canonical unsigned build verified."
(
cd "$DOWNLOAD_DIR"
"${SHA256[@]}" -c BITCHAT_SHA256SUMS
)
echo "GitHub release checksums verified."
mv "$DOWNLOAD_DIR/BITCHAT_BUILDINFO.json" "$DOWNLOAD_DIR/BUILDINFO.json"
mv "$DOWNLOAD_DIR/BITCHAT_SHA256SUMS" "$DOWNLOAD_DIR/SHA256SUMS"
mv "$DOWNLOAD_DIR/BITCHAT_SHA256SUMS.unsigned" "$DOWNLOAD_DIR/SHA256SUMS.unsigned"
if [ "$MODE" = "--no-rebuild" ]; then
exit 0
fi
release_commit="$(sed -n 's/.*"sourceCommit": *"\([^"]*\)".*/\1/p' "$DOWNLOAD_DIR/BUILDINFO.json")"
local_commit="$(git -C "$PROJECT_ROOT" rev-parse HEAD)"
if [ "$release_commit" != "$local_commit" ]; then
echo "error: check out release commit $release_commit before rebuilding" >&2
exit 1
fi
LOCAL_DIR="$PROJECT_ROOT/.reproducible-build/verify-$TAG"
if [ -e "$LOCAL_DIR" ]; then
echo "error: local verification output already exists: $LOCAL_DIR" >&2
exit 1
fi
"$SCRIPT_DIR/build-in-container.sh" "$LOCAL_DIR"
"$SCRIPT_DIR/compare-release.sh" "$LOCAL_DIR" "$DOWNLOAD_DIR"
echo "GitHub release $TAG was reproduced successfully from source."