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
30 changes: 15 additions & 15 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,31 @@
#
# Codecov configuration (https://docs.codecov.com/docs/codecov-yaml).
# The coverage job of .github/workflows/build-and-test-ci.yml merges the
# reports of all test legs and uploads them as a single report, so no
# upload count needs to be configured here.
# reports of the test legs that ran and uploads them as a single report, so
# no upload count needs to be configured here.
#
# Only the nightly scheduled run on main tests every leg; other runs skip
# the legs whose results they can reuse, so their reports cover only part of
# the tests. Codecov therefore compares nothing: no comment, no status
# checks, and no annotations of uncovered lines. A pull request links to its
# report through the "coverage" commit status that the coverage job sets.

codecov:
# Wait for CI to pass before posting coverage results: a failed test leg
# can leave the report incomplete, which would look like a regression.
require_ci_to_pass: true

coverage:
precision: 2
round: down
range: "20...80"
status:
# Report, but never fail, the project and patch checks.
project:
default:
informational: true
patch:
default:
informational: true
project: off
patch: off
changes: off

comment: false

comment:
layout: "header, diff, files, footer"
behavior: default
require_changes: false
github_checks:
annotations: false

# Only src/ is reported (see the gcovr --filter in build-and-test-ci.yml);
# keep the rest of the tree out of Codecov's view even if a report includes
Expand Down
84 changes: 72 additions & 12 deletions .github/workflows/build-and-test-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
# edg-docker-test --posture=extensive --non-interactive
#
# inside the ghcr.io/edgcpp/ci-runner image. Each toolchain runs
# ci-toolchain.yml, which builds its preset and then runs one test leg per
# configuration; a test leg waits only on its own toolchain's build:
# ci-toolchain.yml, which builds its preset (twice: instrumented, for the
# tests, and uninstrumented, for the test cache key) and then runs one test
# leg per configuration; a test leg waits only on its own toolchain's builds:
#
# prepare ─┬─► linux-gcc-debug: build ─► Test ×2 ─┬─► publish (on failure)
# └─► linux-i686-gcc-debug: build ─► Test ×2 ─┴─► coverage
# prepare ─┬─► linux-gcc-debug: build, hash ─► Test ×2 ─┬─► publish (on failure)
# └─► linux-i686-gcc-debug: build, hash ─► Test ×2 ─┴─► coverage
# bench (pull requests only; independent)
#
# The prepare job computes the shared run timestamp and test-input hash that
Expand All @@ -24,17 +25,22 @@
#
# The builds set EDG_BUILD_IDENTIFIER so that identical sources produce
# byte-identical build products. Each test leg keys a cache entry on the
# SHA-256 of the build products it downloaded, the test files its
# SHA-256 of the products of its toolchain's uninstrumented build (which
# leaves out line numbers, so that changes that merely move code don't change
# the key; see the hash job in ci-toolchain.yml), the test files its
# configuration can read (edg-test-inputs-hash, so re-recording a test for
# one configuration doesn't invalidate the others), and the git trees of the
# other inputs it reads from the checkout (bases/, include_c++/,
# util/eccp.sh, and the workflow files, computed once by the prepare job).
# When a leg passes, it saves that entry along with its coverage report; a
# later run on the same ref (a re-run, or a push that leaves the build
# products and test inputs unchanged) restores it, skips edgy, and reuses
# the coverage report.
# When a leg passes, it saves that entry; a later run on the same ref (a
# re-run, or a push that leaves the build products and test inputs
# unchanged) restores it and skips edgy, and so reports no coverage (the
# earlier run's coverage could point at lines that have since moved).
# Scheduled and manual runs reuse nothing (see reuse_results).
# actions/cache scopes entries to the ref that saved them (plus the default
# branch), so one pull request can never vouch for another's build.
# branch), so one pull request can never vouch for another's build. The
# merge queue's entries are saved again for main by promote-test-cache.yml
# once the commit they tested lands, so later pull requests can reuse them.
#
# The bench job runs the cachegrind benchmarks the way
# `edg-docker-bench --posture=release` does and uploads them as bench-results
Expand All @@ -44,15 +50,23 @@
# The debug builds are instrumented for gcov (EDG_CPFE_USE_GCOV) and ship
# their .gcno files with the build products. Each test leg turns the .gcda
# files its run produces into a gcovr JSON report for src/; the coverage job
# merges the reports of all test legs and uploads one report to Codecov
# (see .github/codecov.yml). The coverage steps never fail the run; only
# merges the reports of the test legs that ran and uploads one report to
# Codecov (see .github/codecov.yml), which compares nothing and posts
# nothing on pull requests; a pull request links to its report through a
# "coverage" commit status. The nightly scheduled run tests every leg, so it
# gives main complete coverage. The coverage steps never fail the run; only
# edgy's results do.

name: Build & Test CI

on:
pull_request:
merge_group:
# The nightly run tests every leg (no reused results), for complete
# coverage of main.
schedule:
- cron: '17 6 * * *'
workflow_dispatch:

permissions:
contents: read
Expand Down Expand Up @@ -129,6 +143,9 @@ jobs:
configs: ${{ matrix.configs }}
run_timestamp: ${{ needs.prepare.outputs.run_timestamp }}
test_inputs: ${{ needs.prepare.outputs.test_inputs }}
reuse_results: >-
${{ github.event_name == 'pull_request' ||
github.event_name == 'merge_group' }}

publish-test-results:
name: Publish aggregated test results
Expand Down Expand Up @@ -185,6 +202,10 @@ jobs:
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
# To link a pull request to its coverage report.
statuses: write
steps:
- name: Check out repository
uses: actions/checkout@v7
Expand Down Expand Up @@ -226,11 +247,17 @@ jobs:
# gcov run (plugins: noop) and its "file fixes" pass, which opens every
# file git tracks and crashes on the dangling symlinks used as test
# inputs (e.g. tests/.../embed___has_embed/embed___has_embed.c).
#
# The report covers the commit tested, which for a pull request is the
# merge commit, not the head commit the action would otherwise report
# it under, so name the commit explicitly.
- name: Upload coverage to Codecov
id: upload
if: ${{ hashFiles('coverage.xml') != '' }}
continue-on-error: true
uses: codecov/codecov-action@v7
with:
override_commit: ${{ github.sha }}
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.xml
disable_search: true
Expand All @@ -240,6 +267,39 @@ jobs:
fail_ci_if_error: true
verbose: true

# Codecov posts no comment or checks (see .github/codecov.yml), so link
# the report from a commit status instead. The report is filed under
# the commit tested, but the status goes on the pull request's head
# commit, as the pull request shows only that commit's statuses. A pull
# request from a fork gets a read-only token and can't set the status;
# the job summary has the link either way.
- name: Link coverage report
if: ${{ !cancelled() }}
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
UPLOADED: ${{ steps.upload.outcome == 'success' }}
IS_PULL_REQUEST: ${{ github.event_name == 'pull_request' }}
TESTED_SHA: ${{ github.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
Comment thread
wchilders-nvidia marked this conversation as resolved.
Resolved
run: |
if [ "${UPLOADED}" != true ]; then
echo "No coverage report: every test leg reused an earlier" \
"run's results, or coverage failed (see above)." \
>> "${GITHUB_STEP_SUMMARY}"
exit 0
Comment thread
wchilders-nvidia marked this conversation as resolved.
Resolved
fi
url="https://app.codecov.io/gh/${GITHUB_REPOSITORY}/commit/${TESTED_SHA}"
echo "[Coverage report](${url}) of the test legs this run ran" \
"(legs that reused earlier results add none)." \
>> "${GITHUB_STEP_SUMMARY}"
if [ "${IS_PULL_REQUEST}" = true ]; then
gh api "repos/${GITHUB_REPOSITORY}/statuses/${HEAD_SHA}" \
-f state=success -f context=coverage \
-f description='Coverage of the tests this run ran' \
-f target_url="${url}" > /dev/null
fi

bench:
name: Benchmark linux-gcc-release
if: ${{ github.event_name == 'pull_request' }}
Expand Down
Loading
Loading