Skip to content
Bitcoin Roots

v29.4-roots.1 · Commit 7: [PATCH 07/13] release: establish Roots maintenance and assurance

ci/release/prepare-release.sh

Before: /dev/null · After: ci/release/prepare-release.sh

File metadata
new file mode 100755
index 0000000000000000000000000000000000000000..782832f4099d78b2edc19bf366629e9ad4eace0e

Download original patch · Release notes

Diff rows 1–100 of 100. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

ci/release/prepare-release.sh ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2026-present The Bitcoin Roots developers
3
+ # Distributed under the MIT software license, see the accompanying
4
+ # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+
6
+ export LC_ALL=C
7
+ set -Eeuo pipefail
8
+
9
+ if [[ "$#" -ne 5 ]]; then
10
+ printf 'Usage: %s DOWNLOAD_DIR OUTPUT_DIR PUBLIC_KEY_FILE RELEASE_NAME EXPECTED_PACKAGE_COUNT\n' "$0" >&2
11
+ exit 2
12
+ fi
13
+
14
+ download_dir=$1
15
+ output_dir=$2
16
+ public_key_file=$3
17
+ release_name=$4
18
+ expected_package_count=$5
19
+ script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
20
+ archive_tool="$script_dir/archive.py"
21
+
22
+ if [[ ! -d "$download_dir" ]]; then
23
+ printf 'Download directory does not exist: %s\n' "$download_dir" >&2
24
+ exit 1
25
+ fi
26
+ if [[ ! -f "$public_key_file" ]]; then
27
+ printf 'Public key does not exist: %s\n' "$public_key_file" >&2
28
+ exit 1
29
+ fi
30
+ if [[ ! "$expected_package_count" =~ ^[1-9][0-9]*$ ]]; then
31
+ printf 'Expected package count must be a positive integer: %s\n' "$expected_package_count" >&2
32
+ exit 1
33
+ fi
34
+
35
+ mkdir -p "$output_dir"
36
+ if find "$output_dir" -mindepth 1 -print -quit | grep -q .; then
37
+ printf 'Output directory is not empty: %s\n' "$output_dir" >&2
38
+ exit 1
39
+ fi
40
+
41
+ mapfile -d '' package_paths < <(
42
+ find "$download_dir" -type f \( -name '*.tar.gz' -o -name '*.zip' \) -print0 | sort -z
43
+ )
44
+ if [[ "${#package_paths[@]}" -ne "$expected_package_count" ]]; then
45
+ printf 'Expected %s release packages, found %s\n' "$expected_package_count" "${#package_paths[@]}" >&2
46
+ exit 1
47
+ fi
48
+
49
+ declare -A package_names=()
50
+ for package_path in "${package_paths[@]}"; do
51
+ package_name=${package_path##*/}
52
+ if [[ "$package_name" == *$'\n'* ]]; then
53
+ printf 'Release package names must not contain newlines\n' >&2
54
+ exit 1
55
+ fi
56
+ if [[ -n "${package_names[$package_name]:-}" ]]; then
57
+ printf 'Duplicate release package name: %s\n' "$package_name" >&2
58
+ exit 1
59
+ fi
60
+ package_names[$package_name]=1
61
+ done
62
+
63
+ mapfile -d '' patch_paths < <(find "$download_dir" -type f -name '*.patch' -print0 | sort -z)
64
+ if [[ "${#patch_paths[@]}" -ne 1 ]]; then
65
+ printf 'Expected one release patch series, found %s\n' "${#patch_paths[@]}" >&2
66
+ exit 1
67
+ fi
68
+ patch_path=${patch_paths[0]}
69
+ patch_name=${patch_path##*/}
70
+ if [[ "$patch_name" == *$'\n'* || -n "${package_names[$patch_name]:-}" ]]; then
71
+ printf 'Invalid or duplicate release patch name: %s\n' "$patch_name" >&2
72
+ exit 1
73
+ fi
74
+ if [[ ! -s "$patch_path" ]]; then
75
+ printf 'Release patch series is empty: %s\n' "$patch_path" >&2
76
+ exit 1
77
+ fi
78
+ package_names[$patch_name]=1
79
+
80
+ archive_root="$(RELEASE_TAG="$release_name" python3 "$archive_tool" root-name)"
81
+ for package_path in "${package_paths[@]}"; do
82
+ package_name=${package_path##*/}
83
+ python3 "$archive_tool" validate "$package_path" "$archive_root"
84
+ cp -- "$package_path" "$output_dir/$package_name"
85
+ done
86
+ cp -- "$patch_path" "$output_dir/$patch_name"
87
+
88
+ mapfile -d '' package_names_sorted < <(printf '%s\0' "${!package_names[@]}" | sort -z)
89
+ manifest="$output_dir/SHA512SUMS"
90
+ {
91
+ printf '# Bitcoin Roots release: %s\n' "$release_name"
92
+ printf '# This manifest is signed using the following OpenPGP public key:\n'
93
+ while IFS= read -r line || [[ -n "$line" ]]; do
94
+ printf '# %s\n' "$line"
95
+ done < "$public_key_file"
96
+ printf '#\n'
97
+ for package_name in "${package_names_sorted[@]}"; do
98
+ (cd "$output_dir" && sha512sum -- "$package_name")
99
+ done
100
+ } > "$manifest"