-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeb-push
More file actions
executable file
·115 lines (104 loc) · 4.76 KB
/
Copy pathdeb-push
File metadata and controls
executable file
·115 lines (104 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env bash
#
# deb-push — push active distro branches to origin (which triggers the CI builds).
#
# Usage: ./deb-push <repo> [--no-wait] [<branch-glob>...]
#
# <repo> managed checkout directory (e.g. oxen-mq)
# <branch-glob> which branches to push; globs match against the active distro
# list, e.g. debian/sid, 'debian/*', 'ubuntu/*'. A bare codename
# (sid, trixie, noble, …) expands to its full branch. Quote globs
# so the shell doesn't expand them. Multiple are accepted either
# space- or comma-separated (debian/sid forky, or sid,forky).
# Default: 'debian/*' 'ubuntu/*'.
# --no-wait just push; don't watch the resulting CI builds.
#
# If any glob matches no active branch, nothing is pushed. Before pushing, a
# dependency pre-check verifies that every "ours" build-dependency of each branch
# is available at the required version in that branch's target reprepro repo, for
# every architecture that branch builds (its .drone.jsonnet deb_pipeline debarches,
# not just amd64); if any is missing on any built arch, nothing is pushed.
#
# It then watches the CI builds for the selected branches (at their current commit)
# to completion — live per-branch status, refreshing, with links to each build —
# and exits non-zero if any fails. This happens whether or not this run actually
# pushed anything, so re-running deb-push just re-attaches to the in-flight builds.
# Skipped by --no-wait, or if the drone CLI / DRONE_SERVER+DRONE_TOKEN aren't set.
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib.bash"
[ $# -ge 1 ] || usage
case "$1" in -h|--help) usage 0 ;; esac
repo="$1"; shift
resolve_repo "$repo"
# Pull --no-wait out of the args; the rest are branch globs.
NOWAIT=0
args=()
for a in "$@"; do
case "$a" in --no-wait) NOWAIT=1 ;; *) args+=("$a") ;; esac
done
# Accept space- and comma-separated globs, and bare codenames (sid, trixie, …),
# which expand_distro_spec turns into full branches.
mapfile -t globs < <(expand_distro_spec ${args[@]+"${args[@]}"})
[ "${#globs[@]}" -gt 0 ] || globs=('debian/*' 'ubuntu/*')
# Expand globs against the active distro list; fail fast on a non-matching glob.
selected=()
for g in "${globs[@]}"; do
hits=()
for b in "${distros[@]}"; do
# shellcheck disable=SC2254
case "$b" in $g) hits+=("$b") ;; esac
done
[ "${#hits[@]}" -gt 0 ] || die "no active branch matches '$g' — nothing pushed"
selected+=("${hits[@]}")
done
# De-duplicate, preserving order.
mapfile -t selected < <(printf '%s\n' "${selected[@]}" | awk '!seen[$0]++')
msg "Fetching origin..."
git fetch -q origin
# Drop active branches that don't exist yet (e.g. a distro deb-version-bump will
# create later). This is what lets the default "all branches" invocation work even
# when the configured distro set is ahead of what's actually been created. A glob
# that matched *no* active distro already failed above, so typos are still caught.
present=()
for b in "${selected[@]}"; do
if branch_exists "$b"; then present+=("$b")
else msg ">> $(cpkg "$b") $C_DIM doesn't exist yet — skipping$C_RESET"; fi
done
selected=("${present[@]}")
[ "${#selected[@]}" -gt 0 ] || { msg "No selected branches exist — nothing to push."; exit 0; }
msg "Checking dependencies for: $(cpkg "${selected[*]}")"
fail=0
for b in "${selected[@]}"; do
dep_check "$b" || fail=1
done
[ "$fail" = 0 ] || die "dependency pre-check failed (see above) — nothing pushed"
pushed=()
for b in "${selected[@]}"; do
# origin was fetched above, so local == origin/<b> means nothing to push
if [ "$(git rev-parse "$b")" = "$(git rev-parse -q --verify "refs/remotes/origin/$b" || true)" ]; then
msg ">> $(cpkg "$b") $C_DIM already up to date$C_RESET"
continue
fi
msg ">> pushing $(cpkg "$b")"
git push origin "$b"
pushed+=("$b")
done
if [ "${#pushed[@]}" -gt 0 ]; then
msg "${C_OK}Pushed:${C_RESET} $(cpkg "${pushed[*]}")"
else
msg "Nothing to push — all selected branches were already up to date."
fi
# Watch the CI builds for every selected branch at its current commit — not just
# the ones pushed this run — so re-running deb-push (with nothing new to push)
# still reports on the in-flight builds. --no-wait / no drone skips it.
[ "$NOWAIT" = 1 ] && exit 0
have_drone || { warn "drone CLI / DRONE_SERVER+DRONE_TOKEN not available — not watching CI"; exit 0; }
slug="$(origin_slug)"
[ -n "$slug" ] || { warn "couldn't determine the origin slug — not watching CI"; exit 0; }
MON_ITEMS=()
for b in "${selected[@]}"; do
MON_ITEMS+=("$b|$slug|$b|$(git rev-parse "$b")|0")
done
monitor_ci
[ "${#MON_FAILED[@]}" -eq 0 ] || die "CI failed for: $(cpkg "${MON_FAILED[*]}")"
msg "${C_OK}All CI builds passed.${C_RESET}"