mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
feda2c8e31
We already attest to the relevant dist-archive in inputs.SHA256SUMS, which is recorded at build-time. We use a SKIPATTEST.TAG file to indicate output directories which do not require attestation (much like the CACHEDIR.TAG specification). Generally, it's better to have build scripts declare properties of directories instead of introducing name-based special cases in attest scripts since build scripts have a more detailed context of what is going on.
202 lines
5.2 KiB
Bash
Executable file
202 lines
5.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
export LC_ALL=C
|
|
set -e -o pipefail
|
|
|
|
# Source the common prelude, which:
|
|
# 1. Checks if we're at the top directory of the Bitcoin Core repository
|
|
# 2. Defines a few common functions and variables
|
|
#
|
|
# shellcheck source=libexec/prelude.bash
|
|
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
|
|
|
|
|
|
###################
|
|
## Sanity Checks ##
|
|
###################
|
|
|
|
################
|
|
# Required non-builtin commands should be invokable
|
|
################
|
|
|
|
check_tools cat env basename mkdir xargs find
|
|
if [ -z "$NO_SIGN" ]; then
|
|
check_tools gpg
|
|
fi
|
|
|
|
################
|
|
# Required env vars should be non-empty
|
|
################
|
|
|
|
cmd_usage() {
|
|
cat <<EOF
|
|
Synopsis:
|
|
|
|
env GUIX_SIGS_REPO=<path/to/guix.sigs> \\
|
|
SIGNER=GPG_KEY_NAME[=SIGNER_NAME] \\
|
|
[ NO_SIGN=1 ]
|
|
./contrib/guix/guix-attest
|
|
|
|
Example w/o overriding signing name:
|
|
|
|
env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\
|
|
SIGNER=achow101 \\
|
|
./contrib/guix/guix-attest
|
|
|
|
Example overriding signing name:
|
|
|
|
env GUIX_SIGS_REPO=/home/dongcarl/guix.sigs \\
|
|
SIGNER=0x96AB007F1A7ED999=dongcarl \\
|
|
./contrib/guix/guix-attest
|
|
|
|
Example w/o signing, just creating SHA256SUMS:
|
|
|
|
env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\
|
|
SIGNER=achow101 \\
|
|
NO_SIGN=1 \\
|
|
./contrib/guix/guix-attest
|
|
|
|
EOF
|
|
}
|
|
|
|
if [ -z "$GUIX_SIGS_REPO" ] || [ -z "$SIGNER" ]; then
|
|
cmd_usage
|
|
exit 1
|
|
fi
|
|
|
|
################
|
|
# GUIX_SIGS_REPO should exist as a directory
|
|
################
|
|
|
|
if [ ! -d "$GUIX_SIGS_REPO" ]; then
|
|
cat << EOF
|
|
ERR: The specified GUIX_SIGS_REPO is not an existent directory:
|
|
|
|
'$GUIX_SIGS_REPO'
|
|
|
|
Hint: Please clone the guix.sigs repository and point to it with the
|
|
GUIX_SIGS_REPO environment variable.
|
|
|
|
EOF
|
|
cmd_usage
|
|
exit 1
|
|
fi
|
|
|
|
################
|
|
# The key specified in SIGNER should be usable
|
|
################
|
|
|
|
IFS='=' read -r gpg_key_name signer_name <<< "$SIGNER"
|
|
if [ -z "${signer_name}" ]; then
|
|
signer_name="$gpg_key_name"
|
|
fi
|
|
|
|
if [ -z "$NO_SIGN" ] && ! gpg --dry-run --list-secret-keys "${gpg_key_name}" >/dev/null 2>&1; then
|
|
echo "ERR: GPG can't seem to find any key named '${gpg_key_name}'"
|
|
exit 1
|
|
fi
|
|
|
|
################
|
|
# We should be able to find at least one output
|
|
################
|
|
|
|
echo "Looking for build output directories in ${OUTDIR_BASE}"
|
|
|
|
shopt -s nullglob
|
|
OUTDIRS=( "${OUTDIR_BASE}"/* ) # This expands to an array of directories...
|
|
shopt -u nullglob
|
|
|
|
if (( ${#OUTDIRS[@]} )); then
|
|
echo "Found build output directories:"
|
|
for outdir in "${OUTDIRS[@]}"; do
|
|
echo " '$outdir'"
|
|
done
|
|
echo
|
|
else
|
|
echo "ERR: Could not find any build output directories in ${OUTDIR_BASE}"
|
|
exit 1
|
|
fi
|
|
|
|
|
|
##############
|
|
## Attest ##
|
|
##############
|
|
|
|
# Usage: out_name $outdir
|
|
#
|
|
# HOST: The output directory being attested
|
|
#
|
|
out_name() {
|
|
basename "$1"
|
|
}
|
|
|
|
# Usage: out_sig_dir $outdir
|
|
#
|
|
# outdir: The output directory being attested
|
|
#
|
|
out_sig_dir() {
|
|
echo "$GUIX_SIGS_REPO/$VERSION/$(out_name "$1")/$signer_name"
|
|
}
|
|
|
|
# Accumulate a list of signature directories that already exist...
|
|
outdirs_already_attested_to=()
|
|
|
|
echo "Attesting to build outputs for version: '${VERSION}'"
|
|
echo ""
|
|
|
|
# MAIN LOGIC: Loop through each output for VERSION and attest to output in
|
|
# GUIX_SIGS_REPO as SIGNER, if attestation does not exist
|
|
for outdir in "${OUTDIRS[@]}"; do
|
|
if [ -e "${outdir}/SKIPATTEST.TAG" ]; then
|
|
echo "${outname}: SKIPPING: Output directory marked with SKIPATTEST.TAG file"
|
|
continue
|
|
fi
|
|
outname="$(out_name "$outdir")"
|
|
outsigdir="$(out_sig_dir "$outdir")"
|
|
if [ -e "$outsigdir" ]; then
|
|
echo "${outname}: SKIPPING: Signature directory already exists in the specified guix.sigs repository"
|
|
outdirs_already_attested_to+=("$outdir")
|
|
else
|
|
mkdir -p "$outsigdir"
|
|
|
|
(
|
|
cd "$outdir"
|
|
|
|
if [ -e inputs.SHA256SUMS ]; then
|
|
echo "${outname}: Including existent input SHA256SUMS"
|
|
cat inputs.SHA256SUMS >> "$outsigdir"/SHA256SUMS
|
|
fi
|
|
|
|
echo "${outname}: Hashing build outputs to produce SHA256SUMS"
|
|
files="$(find -L . -type f ! -iname '*.SHA256SUMS')"
|
|
if [ -n "$files" ]; then
|
|
cut -c3- <<< "$files" | env LC_ALL=C sort | xargs sha256sum >> "$outsigdir"/SHA256SUMS
|
|
else
|
|
echo "ERR: ${outname}: No outputs found in '${outdir}'"
|
|
exit 1
|
|
fi
|
|
)
|
|
if [ -z "$NO_SIGN" ]; then
|
|
echo "${outname}: Signing SHA256SUMS to produce SHA256SUMS.asc"
|
|
gpg --detach-sign --local-user "$gpg_key_name" --armor --output "$outsigdir"/SHA256SUMS.asc "$outsigdir"/SHA256SUMS
|
|
else
|
|
echo "${outname}: Not signing SHA256SUMS as \$NO_SIGN is not empty"
|
|
fi
|
|
echo ""
|
|
fi
|
|
done
|
|
|
|
if (( ${#outdirs_already_attested_to[@]} )); then
|
|
# ...so that we can print them out nicely in a warning message
|
|
cat << EOF
|
|
|
|
WARN: Signature directories from '$signer_name' already exist in the specified
|
|
guix.sigs repository for the following output directories and were
|
|
skipped:
|
|
|
|
EOF
|
|
for outdir in "${outdirs_already_attested_to[@]}"; do
|
|
echo " '${outdir}'"
|
|
echo " Corresponds to: '$(out_sig_dir "$outdir")'"
|
|
echo ""
|
|
done
|
|
fi
|