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
73 changes: 73 additions & 0 deletions .github/workflows/action-degrades.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: upload-coverage degrades on an absent report

# THE TEST #83 DID NOT HAVE, and the reason it was closed:
#
# "This repository is public, so its storage is free and its own CI cannot reach the
# absent-artifact state by accident — it has to be constructed."
#
# So it is constructed here. `upload-coverage` is asked for an artifact that cannot exist, and the
# job must come back GREEN with the absence annotated. An absent report is not a coverage bug:
# coverage is a REPORT, `Every unit ran, exactly once` is a CORRECTNESS CLAIM, and only the second
# should be able to fail a suite.
#
# Without this, the degrade path ships untested and is exercised for the first time on a private
# consumer whose org has run out of Actions storage — which is exactly where it was needed and
# exactly where nobody can watch it.

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
absent:
name: an artifact that cannot exist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

# No artifact of this name is produced by any job in this run, so the download finds nothing.
# `name:` would hard-fail here; `pattern:` is what makes the difference the action now relies
# on, and this step is what keeps that true.
- id: run
uses: ./actions/upload-coverage
with:
artifact: no-such-artifact-${{ github.run_id }}
codecov-token: ''

- name: the job survived, and said why
run: |
set -euo pipefail
echo "reached the step after upload-coverage — the action did not abort the job"

present:
name: a report that does exist still uploads-or-degrades cleanly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

# THE POSITIVE CONTROL. Without it, an action that did nothing at all would pass the job
# above, and "degrades on absence" would be indistinguishable from "never works".
- name: Build a real lcov and publish it
run: |
set -euo pipefail
printf 'SF:src/Fake.jl\nDA:1,1\nDA:2,0\nend_of_record\n' > lcov.info
grep -c '^SF:' lcov.info

- uses: actions/upload-artifact@v7
with:
name: degrade-probe-lcov
path: lcov.info
retention-days: 1

- uses: ./actions/upload-coverage
with:
artifact: degrade-probe-lcov
codecov-token: ''

- name: it found the report
run: echo "the present-report path ran to completion"
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "TestShards"
uuid = "acceef1d-f5e0-4fe4-a546-818dc56ce7b2"
version = "0.3.38"
version = "0.3.39"
authors = ["sota shimozono <shimozono-sota631@g.ecc.u-tokyo.ac.jp>"]

[deps]
Expand Down
29 changes: 25 additions & 4 deletions actions/upload-coverage/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,39 @@ runs:
with:
submodules: ${{ inputs.submodules }}

# BY PATTERN, NOT BY NAME, and the difference is the whole fix. `download-artifact` by `name:`
# HARD-FAILS when the artifact is absent; by `pattern:` it succeeds with zero results. That
# asymmetry is why `collect` reaches its completeness gate under a full artifact quota while
# this job used to die at step two — same missing artifact, two different outcomes.
#
# An absent report is not a coverage BUG. Coverage is a report; "every unit ran exactly once" is
# a correctness claim, and only the second should be able to fail a suite. A private consumer
# whose org has run out of Actions storage was getting a red required check for a run whose
# tests were all green — for days, because storage is accrued in GigabyteHours and does not fall
# when artifacts are deleted, so it does not recover until the billing period rolls over.
- uses: actions/download-artifact@v8
id: fetch
with:
name: ${{ inputs.artifact }}
pattern: ${{ inputs.artifact }}
merge-multiple: true

- shell: bash
- id: report
shell: bash
run: |
set -euo pipefail
[ -s lcov.info ] || { echo "::error::${{ inputs.artifact }} contained no lcov.info — did the sharded run finish with coverage on?"; exit 1; }
if [ ! -s lcov.info ]; then
# LOUD, and not fatal. The absence is annotated and summarised; what it must not do is
# gate a suite on a report.
echo "::warning::no ${{ inputs.artifact }} to upload — the sharded run produced no merged report. Coverage is NOT being sent; the tests themselves are unaffected."
echo "Coverage **not uploaded**: no \`${{ inputs.artifact }}\` artifact. Under a full Actions storage quota this is expected and says nothing about the tests." >> "$GITHUB_STEP_SUMMARY"
echo "have=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Merged report: $(grep -c '^SF:' lcov.info) source files."
echo "have=true" >> "$GITHUB_OUTPUT"

- uses: codecov/codecov-action@v7
if: ${{ steps.token.outputs.have == 'true' }}
if: ${{ steps.token.outputs.have == 'true' && steps.report.outputs.have == 'true' }}
continue-on-error: ${{ inputs.fail-on-error != 'true' }}
with:
files: lcov.info
Expand Down
Loading