1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
name: Coverage (main)
# Main owns both persistent coverage outputs: the CodeScene upload and the
# ratchet baseline. Pull requests generate coverage only for their own local
# ratchet check, in `ci.yml`; they neither publish a report nor contact
# CodeScene.
#
# The split is not only hygiene. CodeScene accepts `cs-coverage upload` for an
# analysed branch, which a pull request head is not, and a pull request from a
# fork cannot read `secrets.CS_ACCESS_TOKEN` at all, so the upload step this
# workflow inherits was inert for forks and unnecessary everywhere else. Caches
# and baselines written on `main` are readable by every pull-request run, so the
# baseline written here is the one those ratchet checks compare against.
'on':
push:
branches:
# A dispatch reads the baseline without advancing it: the shared action
# publishes a new baseline only on a push to `refs/heads/main`, so a manual
# run can measure this lane without moving the figure it is measuring.
workflow_dispatch:
# A run in progress is never cancelled. A cancelled publisher abandons both its
# upload and its ratchet baseline write, so a burst of merges could leave `main`
# with no complete run at all. With cancellation off, a newer push waits for
# the running one and replaces any run still pending, so the newest baseline
# wins. The pull-request lanes cancel superseded runs; this one must not, and
# `tests/coverage_workflows.rs` refuses it.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
coverage-upload:
# Ubicloud's cache proxy is scoped by ref, so a pull request's Ubicloud
# build-test reads a warm main scope only if a main job on Ubicloud
# writes it. This is that writer. The fork arm never applies on push or
# dispatch; it is kept so every Ubicloud lane reads the same way.
# standard-4, not standard-2: on two vCPUs two trybuild compile tests
# (`compile.rs`) exceed nextest's 180 s allowance, cold and warm (runs
# 36556931315 and 36558819122); on four they pass.
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubicloud-standard-4' }}
# An Ubicloud runner is a self-hosted just-in-time runner with no
# six-hour hosted cap. Provisional: sized for the first, cold run on
# Ubicloud; tightened to twice a measured warm Ubicloud run once one
# exists.
timeout-minutes: 30
# The CodeScene token lives in this environment, whose deployment policy
# admits `main` alone; the codescene environment contract holds it to
# this job.
environment: codescene
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
BUILD_PROFILE: debug
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@6dea5677a84fec60ca51b07202570e3af12ffdb4
- name: Install ripgrep
# The suite shells out to `rg`, and `make check-ripgrep` refuses to run
# without it, so the instrumented run needs the same tool the merge
# gate installs and at the same pin: a baseline measured with a
# different ripgrep is not comparable with what the ratchet checks.
run: cargo binstall --no-confirm --locked ripgrep@15.2.0
- name: Test and Measure Coverage
# The same action, format and output path as the pull-request lane, and
# the same default baseline files, so the figure written here is the
# figure a pull request is measured against. `with-ratchet` is set on
# both sides for that reason: this lane is the writer and the
# pull-request lane the reader, and the action decides which by the
# event rather than by an input.
uses: leynos/shared-actions/.github/actions/generate-coverage@a5765019912a8ab6882b12db049c7cde635f3a85
with:
output-path: lcov.info
format: lcov
with-ratchet: 'true'
- name: Upload coverage data to CodeScene
env:
CS_ACCESS_TOKEN: ${{ secrets.CS_ACCESS_TOKEN }}
# An unset secret leaves the upload out rather than failing the lane,
# which is what lets a fork of this repository run the workflow at all.
# The ref conjunct is what keeps the dispatch trigger above from
# uploading a branch CodeScene does not analyse: the push trigger is
# restricted to `main`, but a dispatch may name any branch.
if: ${{ env.CS_ACCESS_TOKEN != '' && github.ref == 'refs/heads/main' }}
uses: leynos/shared-actions/.github/actions/upload-codescene-coverage@a5765019912a8ab6882b12db049c7cde635f3a85
with:
path: lcov.info
format: lcov
mode: upload
access-token: ${{ env.CS_ACCESS_TOKEN }}