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
48 changes: 46 additions & 2 deletions .github/workflows/kanban-archive.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,23 @@ jobs:
# under suspicion here -- reading the baseline with it would put both
# sides of the comparison back inside one view.
GH_TOKEN: ${{ github.token }}
# `gh run download` TAKES NO --repo AND THIS JOB HAS NO CHECKOUT, so it
# resolved the repository from the git remote, found no `.git`, and died
# before making any API call (backend#2802). That is why the artifacts
# LISTING above worked -- it puts the repo in the URL path -- while the
# fetch failed, and the run went red having archived successfully.
#
# Reproduced outside Actions, gh 2.98.0:
# $ cd /tmp/empty && gh run download <id> -n board-baseline
# failed to run git: fatal: not a git repository
# $ GH_REPO=tracebloc/.github gh run download <id> -n board-baseline
# $ cat prev/board.total -> 574
#
# `gh` does NOT read `GITHUB_REPOSITORY` (tested), so being on a runner
# does not supply it. GH_REPO is the variable it does read, and it is
# cheaper and narrower than adding a checkout to a job that needs no
# source.
GH_REPO: ${{ github.repository }}
run: |
set -uo pipefail
: > prev.total
Expand Down Expand Up @@ -313,7 +330,27 @@ jobs:
else
rid=$(printf '%s' "$arts" \
| jq -sr '[.[] | select(.expired == false)] | sort_by(.created_at) | last | .workflow_run.id')
if gh run download "$rid" -n board-baseline -D prev >/dev/null 2>&1 && [ -s prev/board.total ]; then
# KEEP THE DOWNLOAD'S STDERR. `>/dev/null 2>&1` is the reason this
# failure was diagnosable only by reproducing it by hand: the step
# reported "could not be downloaded" and threw away the one line
# that said why ("failed to run git: fatal: not a git repository").
# Stdout still goes to /dev/null -- it is progress noise -- but the
# error text is captured and echoed by the refusal below.
# STDERR TO A SCRATCH FILE, PROMOTED TO prev.error ONLY ON FAILURE
# (Bugbot, High -- on my own fix). Writing straight into prev.error
# couples the two: the assert step at the bottom treats ANY non-empty
# prev.error as an unreadable baseline (`if [ -s prev.error ]`), so a
# SUCCESSFUL download that printed anything at all would mark the
# baseline unreadable and keep the job red after a good archive --
# the exact failure this PR fixes, arriving from the other side.
#
# MEASURED, and stated honestly: `gh run download` writes 0 bytes to
# stderr on success on a non-TTY (tested, gh 2.98.0), so the finding
# as described does not reproduce today. The COUPLING is real
# regardless, and one deprecation notice on stderr in a future gh is
# all it would take. Decoupled unconditionally because it costs
# nothing: only the failure branch can now populate prev.error.
if gh run download "$rid" -n board-baseline -D prev >/dev/null 2>prev.stderr && [ -s prev/board.total ]; then
cp prev/board.total prev.total
echo "Baseline: run $rid saw $(cat prev.total) item(s)."
# IS THIS JOB THE ONLY ARCHIVER SINCE? It is not, and assuming
Expand Down Expand Up @@ -353,7 +390,14 @@ jobs:
# this is a broken read, not an empty history. Refusing is the
# whole point of having asked the two questions separately.
# selftest:unreadable-path
printf 'a live board-baseline artifact exists (run %s) but could not be downloaded\n' "$rid" > prev.error
# APPEND, DO NOT CLOBBER. `gh run download`'s stderr is already in
# prev.error at this point, and it holds the only line that says
# WHY -- overwriting it with this summary is what made the last
# five red runs undiagnosable from their own logs. The summary
# goes first because it names the run; the tool's own words follow.
reason=$(tr '\n' ' ' < prev.stderr 2>/dev/null | cut -c1-300)
printf 'a live board-baseline artifact exists (run %s) but could not be downloaded. gh said: %s\n' \
"$rid" "${reason:-<no stderr captured>}" > prev.error
echo "::warning::the baseline exists but could not be read; the assert step will refuse."
fi
fi
Expand Down
Loading
Loading