hack/backport-batch-scheduled.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# The scheduled backport batch (docs/release/backports.md): for each line the
# batch runs for, newest first, continue the open batch pull request or open
# one, check the line, and report what waits on the batch. This is what
# .github/workflows/backport-batch.yaml runs; a maintainer can run it by hand
# from a clean worktree of the repository.
#
# Usage: backport-batch-scheduled.sh [--dry-run] [--no-workflow-files]
#
# --dry-run builds and checks each batch in this worktree and prints what it
# would report, but pushes nothing, opens or edits no pull request and writes
# no comment. Its check sees the line without the batch it just built, so it
# can exit 1 where the real run's check passes. Without --dry-run the batch's
# token has to be in BACKPORT_BATCH_TOKEN, and it is the only token gh sees:
# the job's own GITHUB_TOKEN is never a fallback, because a push made with it
# starts no CI on the batch pull request. The workflow passes the cozystack-ci
# App's token; a maintainer running this by hand passes their own.
#
# --no-workflow-files goes to run: an original that changes .github/workflows/
# is left on the batch pull request for a maintainer instead of picked, for a
# token that may not push such a commit, as the workflow's is.
#
# Environment:
# BACKPORT_BATCH the backport-batch binary (default: built from this tree)
# BACKPORT_BATCH_TOKEN the token the batch pushes, opens and comments with
# BACKPORT_BATCH_BOT the bot the scheduled batch writes as, <app>[bot],
# whose batch pull request and comment are trusted;
# cozystack-ci[bot] when unset
# BACKPORT_ALERT_TEAM the team or person the batch's comment mentions,
# org/team or a login; nobody is mentioned when it is
# unset
# GITHUB_STEP_SUMMARY when set, each finding is appended to it as a line
#
# Exits 0 when every line ran and its check passed, 1 when a line's run,
# check or report failed, and 2 on a usage or setup error.
set -euo pipefail
die() {
echo "backport-batch-scheduled: $*" >&2
exit 2
}
usage="usage: backport-batch-scheduled.sh [--dry-run] [--no-workflow-files]"
dry_run=false
# An empty array expands under set -u only as ${a[@]+"${a[@]}"} on bash before
# 4.4, which is what macOS ships.
workflows=()
for arg in "$@"; do
case "$arg" in
--dry-run) dry_run=true ;;
--no-workflow-files) workflows=(--no-workflow-files) ;;
*) die "$usage" ;;
esac
done
push=()
if ! $dry_run; then
[ -n "${BACKPORT_BATCH_TOKEN:-}" ] ||
die "BACKPORT_BATCH_TOKEN is empty; the workflow sets it to the cozystack-ci App's token, a run by hand to your own (docs/release/backports.md#the-scheduled-run). The job's GITHUB_TOKEN is not used: its pushes start no CI."
export GH_TOKEN="$BACKPORT_BATCH_TOKEN"
unset GITHUB_TOKEN
push=(--push)
fi
mention=()
if [ -n "${BACKPORT_ALERT_TEAM:-}" ]; then
mention=(--mention "$BACKPORT_ALERT_TEAM")
fi
top=$(git rev-parse --show-toplevel) || die "not in a worktree of the repository"
cd "$top"
out=$(mktemp -d)
bin=${BACKPORT_BATCH:-}
if [ -z "$bin" ]; then
# Built before the first run switches this tree to a batch branch, whose
# line may not have the tool at all.
bin="$out/backport-batch"
go build -o "$bin" ./cmd/backport-batch
fi
report() {
echo "$1"
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
printf -- '- %s\n' "$1" >> "$GITHUB_STEP_SUMMARY"
fi
}
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
printf '## Backport batch\n\n' >> "$GITHUB_STEP_SUMMARY"
fi
lines=$("$bin" lines) || die "cannot list the release lines"
[ -n "$lines" ] || die "no release line to run the batch for"
status=0
for line in $lines; do
echo "::group::$line"
rc=0
"$bin" run --line "$line" --continue ${workflows[@]+"${workflows[@]}"} ${push[@]+"${push[@]}"} > "$out/$line.md" || rc=$?
if [ "$rc" -ne 0 ]; then
report "$line: the run failed with exit $rc"
status=1
elif $dry_run; then
report "$line: the batch is built in this tree, its body in $out/$line.md"
fi
rc=0
"$bin" check --line "$line" || rc=$?
if [ "$rc" -ne 0 ]; then
report "$line: the check exited $rc; see its output above"
status=1
fi
rc=0
notes=$("$bin" notify --line "$line" ${mention[@]+"${mention[@]}"} ${push[@]+"${push[@]}"}) || rc=$?
while IFS= read -r note; do
[ -z "$note" ] || report "$note"
done <<< "$notes"
if [ "$rc" -ne 0 ]; then
report "$line: reporting what waits on the batch failed with exit $rc"
status=1
fi
echo "::endgroup::"
done
exit "$status"