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"
|