From 4717cfec4e1feef9d277ab890787b0053dcadc8c Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Fri, 18 Sep 2026 13:39:56 -0400 Subject: [PATCH] Publish record covers build failures, and says where each package came from When a package had no PR artifact and its build failed, the publish step never ran, no record was written, and the report job failed looking for it. The collect step now records each package's source (PR artifact, built here, or build-failed) and writes the record itself when a build fails, so the report can say plainly that nothing was published and why. --- .github/workflows/publish.yml | 44 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c34449e..dea7370 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -89,7 +89,12 @@ jobs: GH_TOKEN: ${{ github.token }} CONTAINER_ENGINE: docker run: | - set -euo pipefail + set -uo pipefail + # sources.jsonl: where each package's files came from, or that the + # build failed. A failed build ends the run before any publish, and + # the record says so instead of the report job finding nothing. + : > sources.jsonl + failed=0 while read -r package arch channels publish_arches; do hash=$(git rev-parse "HEAD:pkgbuilds/$package") label="$package-$arch-$hash" @@ -99,14 +104,31 @@ jobs: mkdir -p "build-output/edge/$arch" if [[ -n "$found" ]]; then echo "==> $label: PR artifact" - curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" - unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch" + if curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -o /tmp/artifact.zip "$found" && unzip -oq /tmp/artifact.zip -d "build-output/edge/$arch"; then + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"pr-artifact"}' >> sources.jsonl + else + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"artifact-download-failed"}' >> sources.jsonl; failed=1; break + fi else echo "==> $label: no artifact for this tree, building" - OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package" + if OMARCHY_KEEP_BUILD_WORKSPACE=1 bin/build --mirror edge --arch "$arch" --package "$package"; then + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"built"}' >> sources.jsonl + else + jq -nc --arg p "$package" --arg a "$arch" '{package:$p, arch:$a, source:"build-failed"}' >> sources.jsonl; failed=1; break + fi fi done < plan.txt - ls -1 build-output/edge/*/*.pkg.tar.zst + ls -1 build-output/edge/*/*.pkg.tar.zst 2>/dev/null || true + if (( failed )); then + # Write the record now; the publish step will not run. + jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ + --slurpfile sources sources.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], sources:$sources, slots:[]}' \ + > publish-record.json + cat publish-record.json + exit 1 + fi - name: Publish env: @@ -184,8 +206,8 @@ jobs: done jq -n --arg sha "${{ github.sha }}" --arg run "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ --arg prefix "${OMARCHY_PUBLISH_PREFIX:-}" --arg event "${{ github.event_name }}" \ - --slurpfile slots slots.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ - '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], slots:$slots}' \ + --slurpfile slots slots.jsonl --slurpfile sources sources.jsonl --slurpfile plan <(jq -c '.include[]' <<<'${{ needs.changes.outputs.matrix }}' | jq -sc .) \ + '{time: (now|todate), commit:$sha, run:$run, event:$event, target: (if $prefix=="" then "live" else $prefix end), plan:$plan[0], sources:$sources, slots:$slots}' \ > publish-record.json cat publish-record.json exit $status @@ -219,12 +241,16 @@ jobs: run: | jq -r --arg outcome "${{ needs.publish.result }}" ' def pkgs: [.packages[] | select(test("-debug-")|not)] | join(", "); + def src: if .source=="pr-artifact" then "PR artifact" elif .source=="built" then "built here" else "**" + .source + "**" end; "### Publish " + (if $outcome=="success" then "succeeded" else "FAILED" end) + " → **" + .target + "**" + (if .target!="live" then " (proof prefix, not live)" else "" end), "", - (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs), + "Packages: " + ([.sources[] | .package + " (" + .arch + ", " + src + ")"] | join("; ")), "", - (if (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), + (if (.slots|length) > 0 then (.slots[] | "- `" + .mirror + "/" + .arch + "`: " + (if .status=="published" then "" else "**" + .status + "** " end) + pkgs) else "_Nothing was published._" end), + "", + (if ([.sources[] | select(.source|test("failed"))] | length) > 0 then "_A build failed, so no channel was touched._\n" + elif (.plan|length) > (.slots|length) then "_Some planned slots did not run because an earlier slot failed._\n" else "" end), "Commit " + .commit[0:7] + " · [run](" + .run + ")" ' publish-record.json > comment.md cat comment.md