|
9 | 9 | push: |
10 | 10 | branches: [main] |
11 | 11 | schedule: |
12 | | - # nightly full regression — exercises every workspace member regardless of diff |
13 | | - - cron: "0 6 * * *" |
| 12 | + # WEEKLY full regression — every workspace member, regardless of diff. |
| 13 | + # |
| 14 | + # This is the safety net for the one thing selective testing structurally |
| 15 | + # cannot see: two changes that are each green on their own and break each |
| 16 | + # other once both have landed. Neither PR's diff names the member that |
| 17 | + # breaks, so neither PR selects it. |
| 18 | + # |
| 19 | + # Weekly rather than nightly because a full run is no longer cheap — with |
| 20 | + # the second linux toolchain leg it is ~11 hours of runner time — and the |
| 21 | + # net catches the same interactions whether it is cast every day or every |
| 22 | + # seven. Sunday 06:00 UTC. |
| 23 | + - cron: "0 6 * * 0" |
14 | 24 | workflow_dispatch: |
15 | 25 | inputs: |
16 | 26 | cache: |
@@ -326,21 +336,57 @@ jobs: |
326 | 336 | # package. Map changed files → affected members and test only those: |
327 | 337 | # pkgs/<x>/<lib>.lua → members whose mcpp.toml references <lib> |
328 | 338 | # tests/examples/<m>/** → member <m> |
329 | | - # Run the FULL workspace when the change can affect everything: |
330 | | - # non-PR events (push to main, the nightly cron, dispatch), this |
331 | | - # workflow file (it carries the mcpp version pins, so a version bump |
332 | | - # always re-validates every package), a non-member edit to the |
333 | | - # workspace manifest, or shared test scripts. Docs-only and tools/-only |
334 | | - # changes select nothing. |
| 339 | + # A push to main is mapped the same way — the merge's own diff — so a |
| 340 | + # merge costs what its PR cost. Run the FULL workspace when the change |
| 341 | + # can affect everything: the weekly cron and manual dispatch (which mean |
| 342 | + # "check everything" by definition), this workflow file (it carries the |
| 343 | + # mcpp version pins, so a version bump always re-validates every |
| 344 | + # package), a non-member edit to the workspace manifest, or shared test |
| 345 | + # scripts. Docs-only and tools/-only changes select nothing. |
335 | 346 | # Note: bash 3.2 on macOS runners — no associative arrays here. |
336 | 347 | - name: Select affected workspace members |
337 | 348 | id: plan |
338 | 349 | shell: bash |
339 | 350 | run: | |
340 | 351 | full() { echo "MEMBERS=__ALL__" >> "$GITHUB_ENV"; echo "full run: $1"; exit 0; } |
341 | | - [ "${{ github.event_name }}" = "pull_request" ] || full "event=${{ github.event_name }}" |
342 | | - base="origin/${{ github.base_ref }}" |
343 | | - changed=$(git diff --name-only "$base"...HEAD) |
| 352 | +
|
| 353 | + # A push to main has a diff too — it was just never asked for. |
| 354 | + # |
| 355 | + # This used to be `event != pull_request -> full`, so every merge |
| 356 | + # re-tested all 67 members on all three platforms: ~11 hours of |
| 357 | + # runner time to re-confirm what the PR had already gone green on |
| 358 | + # minutes earlier. The premise was that a push has no base to diff |
| 359 | + # against, and that is not true: merges here are squashes, so |
| 360 | + # `github.event.before` is the previous main and |
| 361 | + # `before..HEAD` reproduces exactly the file list the PR saw |
| 362 | + # (verified on 698b95ee — same ten paths). |
| 363 | + # |
| 364 | + # schedule and workflow_dispatch stay full. They are not "a change |
| 365 | + # landed", they are "check everything", which is the whole point of |
| 366 | + # the weekly net above. |
| 367 | + # |
| 368 | + # Two-dot for push, three-dot for pull_request, deliberately: a PR |
| 369 | + # wants its own commits against the merge base, while a push wants |
| 370 | + # what actually landed on this branch. |
| 371 | + case "${{ github.event_name }}" in |
| 372 | + pull_request) |
| 373 | + base="origin/${{ github.base_ref }}"; range="$base...HEAD" ;; |
| 374 | + push) |
| 375 | + base="${{ github.event.before }}" |
| 376 | + # All-zero on branch creation; absent object after a |
| 377 | + # force-push that dropped it. Either way there is nothing to |
| 378 | + # diff against, and guessing is worse than re-testing. |
| 379 | + case "$base" in |
| 380 | + ""|0000000000000000000000000000000000000000) |
| 381 | + full "push with no predecessor" ;; |
| 382 | + esac |
| 383 | + git cat-file -e "$base^{commit}" 2>/dev/null \ |
| 384 | + || full "push predecessor $base not in history" |
| 385 | + range="$base..HEAD" ;; |
| 386 | + *) |
| 387 | + full "event=${{ github.event_name }}" ;; |
| 388 | + esac |
| 389 | + changed=$(git diff --name-only $range) |
344 | 390 | printf 'changed files vs %s:\n%s\n' "$base" "$changed" |
345 | 391 | sel="" |
346 | 392 | add() { case " $sel " in *" $1 "*) ;; *) sel="$sel $1" ;; esac; } |
|
0 commit comments