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
22 changes: 15 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
name: CI

# Unfiltered `push` as well as `pull_request` on purpose. The artifacts the build produces exist
# so a change can be tried on a Pi or a Mac without building it there, and that only works if
# every branch push produces them -- not just the ones that have a pull request open. The cost
# is that a PR raised from a branch in this repo builds twice.
# Every branch `push` as well as `pull_request` on purpose. The artifacts the build produces
# exist so a change can be tried on a Pi or a Mac without building it there, and that only works
# if every branch push produces them -- not just the ones that have a pull request open. The
# cost is that a PR raised from a branch in this repo builds twice.
#
# Except tags, which belong to release.yml. Both workflows call the same build, and the
# `concurrency` group below is keyed by workflow name, so nothing would collapse the pair: a
# `v*` push would otherwise run the matrix twice over and report two statuses for one tag.
# `tags-ignore` rather than a positive `branches` filter, so the sentence above stays "every
# branch push, except --" instead of a list a reader has to check is exhaustive.
#
# The `branches` filter is what excludes them, and the rule behind it cuts both ways. A `push`
# naming only branch filters does not fire for tags at all -- that is the whole of how a tag is
# left to release.yml -- and the mirror of that rule is a trap worth naming: a `push` naming only
# `tags` or `tags-ignore` does not fire for *branches*, so `tags-ignore: '**'` reads like
# "everything except tags" and means "nothing at all".
#
# `'**'` and not `'*'`, because only the doubled form matches a `/`, and the branches here carry
# two apiece. `'*'` would be this same bug wearing a better disguise: main would build and no
# task branch would.
on:
push:
tags-ignore:
branches:
- '**'
pull_request:

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: Release

# A human tags; this publishes what that tag builds. Nothing here creates a tag, and there is
# no second trigger -- no branch push, no pull request, no schedule, no `workflow_dispatch` --
# so the only way to reach `gh release create` is to have pushed a `v*` tag. `ci.yml` ignores
# tags for the same reason, leaving one workflow to answer for one tag.
# so the only way to reach `gh release create` is to have pushed a `v*` tag. `ci.yml` filters on
# branches and so never fires for a tag, leaving one workflow to answer for one tag.
on:
push:
tags:
Expand Down
17 changes: 9 additions & 8 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -1046,13 +1046,14 @@ operator to choose between `Type=simple` and `Type=forking` and write the unit t
tee` returns 0 on a failed configure, and the assertion after it greps a truncated log —
both callers green on a build that never configured. A fail-open gate is worse than no gate,
which is the argument the shellcheck job at the top of `ci.yml` already makes.
- **`ci.yml` gained a `tags-ignore`, and that is the whole of its *behavioural* change** —
the rest of its diff is the matrix moving out to `build.yml`. Its `push` was
- **`ci.yml` gained a ref filter on its `push`, and that is the whole of its *behavioural*
change** — the rest of its diff is the matrix moving out to `build.yml`. Its `push` was
unfiltered on purpose, and a `v*` push would otherwise have run the matrix twice over and
reported two statuses for one tag — the `concurrency` group is keyed by workflow name, so
nothing collapses the pair. `tags-ignore` rather than a positive `branches: ['**']` filter,
so the existing "every branch push, on purpose" comment stays true with an exception named
rather than being rewritten as a list a reader has to check is exhaustive.
nothing collapses the pair. The filter is `branches: ['**']`, which is what excludes tags: a
`push` filtered on one kind of ref does not fire for the other kind at all. The inverse
spelling, `tags-ignore: ['**']`, reads like the same sentence but is that rule the other way
around, and stops branch pushes firing at all.
- **Fail closed, in two places, because `needs:` only covers one of them.** `needs: build`
catches a leg that went red. What it does not catch is a leg that went green *while
publishing nothing* — `Upload` is `if: matrix.publish`, and `if-no-files-found: error`
Expand Down Expand Up @@ -1374,9 +1375,9 @@ on a null-sink-only, mDNS-less binary. The three platform legs additionally run
test and upload the binary they built, kept 14 days.

The matrix itself lives in `.github/workflows/build.yml`, called by `ci.yml` and by item 10's
`release.yml` alike, so one definition answers for both paths; `ci.yml` carries a
`tags-ignore` so a tag push builds once rather than twice. See item 10 for why that split is
a reusable workflow rather than a composite action.
`release.yml` alike, so one definition answers for both paths; `ci.yml` filters its `push` to
`branches: ['**']`, which excludes tags, so a tag push builds once rather than twice. See item
10 for why that split is a reusable workflow rather than a composite action.

The unit harness is item 1's and unchanged: GoogleTest via `FetchContent` pinned to a tag,
wired to CTest with `gtest_discover_tests()`, defaulting ON only when this is the top-level
Expand Down