Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions commit-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,27 @@ sys.stderr.write(f"{len(additions)} addition(s), {len(deletions)} deletion(s)\n"

log "committing to $BRANCH, $(wc -c < "$payload") byte payload"

curl -sS --fail-with-body -X POST "$API/graphql" \
# --fail-with-body writes the body and exits non-zero, and under set -e that
# exit skipped the reporting below and the trap deleted the file: an auth
# failure or a 502 showed curl's generic "returned error: NNN" and nothing
# GitHub actually said. The body is printed here instead, where it is still on
# disk.
#
# --retry covers the transient half. This runs after the archive has already
# been published to R2, so failing here leaves the bucket ahead of the state
# branches until the next ingest repairs it. A retry is safe rather than
# merely convenient: expectedHeadOid makes the mutation conditional, so if the
# first attempt did land, the retry is refused for the right reason instead of
# committing twice.
if ! curl -sS --fail-with-body -X POST "$API/graphql" \
--max-time 120 --retry 3 --retry-connrefused --retry-all-errors \
-H "Authorization: bearer $GITHUB_TOKEN" \
-H 'Content-Type: application/json' \
--data @"$payload" > "$response"
--data @"$payload" > "$response"; then
log "FATAL: the GraphQL request to $API failed. What it returned:"
cat "$response" >&2
exit 1
fi

python3 - "$response" <<'PY'
import json, sys
Expand Down
43 changes: 42 additions & 1 deletion tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ eq() { # label expected actual
# assertions vanish rather than fail -- which is exactly what happened when
# these groups were first lifted out of pkghaus/apt: eq() was left behind and
# the suite still printed "all tests passed". Bump this when adding one.
EXPECTED_ASSERTIONS=5
EXPECTED_ASSERTIONS=8

echo "the signed-commit payload describes every change, deletions included"
(
Expand Down Expand Up @@ -139,6 +139,47 @@ echo "a tree with no changes makes no commit"
exit $((fail > 0))
) || fail=$((fail + 1))

echo "an HTTP failure reports what GitHub said, not just curl's exit code"
(
work="$(mktemp -d)"
export GITHUB_TOKEN=fake GITHUB_REPOSITORY=pkghaus/apt

repo="$work/repo"; mkdir -p "$repo"; cd "$repo"
git init -q -b archive .
printf 'one\n' > keep.txt
git add -A
git -c user.name=t -c user.email=t@example.invalid commit -qm base
printf 'two\n' > keep.txt

# curl as --fail-with-body behaves on an HTTP error: the body is written
# to the output AND the exit status is non-zero. That combination is what
# used to lose the message -- set -e took the exit before anything printed
# the body, and the trap then deleted the file.
mkdir -p "$work/bin"
cat > "$work/bin/curl" <<'FAKE'
#!/bin/sh
printf '{"message":"Bad credentials","documentation_url":"https://docs.github.com/graphql"}'
exit 22
FAKE
chmod +x "$work/bin/curl"

out="$(PATH="$work/bin:$PATH" "$ROOT/commit-branch.sh" "$repo" archive "test" 2>&1)" \
&& rc=0 || rc=$?

eq "the run fails" "1" "${rc:-0}"
case "$out" in
*"Bad credentials"*) ok "GitHub's own message reaches the log" ;;
*) no "GitHub's own message reaches the log" "got [$out]" ;;
esac
case "$out" in
*FATAL*) ok "and it is labelled as the failure it is" ;;
*) no "and it is labelled as the failure it is" "got [$out]" ;;
esac

cd /; rm -rf "$work"
exit $((fail > 0))
) || fail=$((fail + 1))

echo
ran="$(wc -l < "$TALLY")"
if [ "$ran" -ne "$EXPECTED_ASSERTIONS" ]; then
Expand Down