@@ -4,12 +4,18 @@ permissions:
44 contents : read
55
66on :
7+ # #1967: GitHub Pages, Vendor Update and Conda Update run eight hours
8+ # apart on Saturdays, so each runs `head`'s test gate alone, mostly on a
9+ # commit of its own, and `vendor-update` and `conda-update` do not queue
10+ # on `repository-maintenance` together. None reads another's output, and
11+ # Conda Update comes last so its upload finds the release Create Release
12+ # made after Vendor Update (#1634). workflows.rst gives the evidence.
713 schedule :
8- - cron : ' 0 10 * * 6' # Saturdays at 10 :00 UTC
14+ - cron : ' 0 18 * * 6' # Saturdays at 18 :00 UTC
915 # No `push: branches: [main]` here. `unit-tests.yml`'s own push trigger
10- # already runs the full matrix for this commit; calling it again below with
11- # `gate-only: true` re-ran the single-version "Gate" job a second time for
12- # the same tree (#715). Chaining off `Unit Tests`' completion means the gate
16+ # already runs the full matrix for this commit; calling it again on every push
17+ # with `gate-only: true` re-ran the single-version "Gate" job a second time
18+ # for the same tree (#715). Chaining off `Unit Tests`' completion means the gate
1319 # never runs twice, and `conda-update` below just reads the verdict that
1420 # already exists. `.event == 'push'` is checked in that job's `if` rather
1521 # than here, because `workflow_run` fires for a pull request's completion
2531#
2632# A `workflow_run` is keyed on the commit `Unit Tests` verified instead (#1643).
2733# Each `Unit Tests` completion raises a run here, and one whose verdict is for an
28- # older commit only runs `verdict ` and skips -- but in a shared group it would
34+ # older commit only runs `head ` and skips -- but in a shared group it would
2935# still displace a pending run whose verdict matches, since "any existing pending
3036# job or workflow in the same concurrency group will be canceled" (GitHub,
3137# "Control the concurrency of workflows and jobs").
@@ -38,53 +44,14 @@ concurrency:
3844 cancel-in-progress : false
3945
4046jobs :
41- # Only earns its runners on the schedule trigger: `Unit Tests` has no
42- # schedule trigger of its own, so Saturday's cron run is the one case left
43- # where nothing else has already verified this tree. `workflow_run` carries
44- # its own verdict instead -- see `conda-update` below.
45- unit-tests :
46- name : Conda test gate
47- if : ${{ github.event_name != 'workflow_run' }}
47+ # #1967: the test gate, on the schedule only, and the `verdict` on a
48+ # `workflow_run`, shared with Vendor Update and GitHub Pages. cron-head.yml
49+ # says when each runs.
50+ head :
51+ name : Conda gate
4852 permissions :
4953 contents : read
50- uses : ./.github/workflows/unit-tests.yml
51- with :
52- gate-only : true
53-
54- # #1643: `github.sha`, which every checkout here takes, is main's tip when the
55- # `workflow_run` was raised -- not the commit the completed `Unit Tests` run
56- # verified, and in a merge wave the two differ. This job compares them with
57- # util/verdict_covers_checkout.py, whose docstring gives the rule, and the job
58- # below acts on a `workflow_run` only when `verified` is 'true'. Its `if:` is
59- # that job's `workflow_run` clause, so a run raised by a pull request's or a
60- # failed `Unit Tests` run still concludes `skipped`, as before.
61- verdict :
62- name : Verdict covers this commit
63- if : >-
64- github.event_name == 'workflow_run' &&
65- github.event.workflow_run.conclusion == 'success' &&
66- github.event.workflow_run.event == 'push' &&
67- github.event.workflow_run.head_branch == 'main'
68- runs-on : ubuntu-latest
69- timeout-minutes : 5
70- permissions :
71- contents : read
72- outputs :
73- verified : ${{ steps.verdict.outputs.verified }}
74- steps :
75- # The default ref, as the job below uses, so both see the same `github.sha`.
76- # Twenty commits leaves room for the bot commits the rule accepts; a verdict
77- # further back is not found, and so not accepted.
78- - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
79- with :
80- fetch-depth : 20
81- persist-credentials : false
82-
83- - name : Compare the verified commit with this checkout
84- id : verdict
85- env :
86- VERDICT_SHA : ${{ github.event.workflow_run.head_sha }}
87- run : python3 util/verdict_covers_checkout.py
54+ uses : ./.github/workflows/cron-head.yml
8855
8956 conda-update :
9057 name : Update requirements.txt
@@ -93,27 +60,27 @@ jobs:
9360 # a job naming the environment can read it. Keep that environment free of
9461 # required reviewers, or every scheduled bump waits for an approval.
9562 environment : conda-tag
96- needs : [ unit-tests, verdict ]
97- # `needs` cannot itself be conditional, so a skipped gate (`workflow_run`)
98- # has to be accepted explicitly -- by default this job would inherit the
99- # skip. `!cancelled()` rather than ` always()` so that cancelling the run
100- # still cancels the update; a gate that actually failed still blocks.
63+ needs : [ head ]
64+ # `needs` cannot itself be conditional, and `head`'s jobs skip on every
65+ # path, so this job must not inherit a skip. `!cancelled()` rather than
66+ # ` always()` so that cancelling the run still cancels the update; a gate
67+ # that actually failed still blocks.
10168 #
10269 # The `workflow_run` clause is the real gate for a push to main: it
10370 # reads the verdict `Unit Tests` already reached instead of re-running it,
104- # and `verdict` says whether that verdict covers the commit checked out
105- # below (#1643). `.event == 'push'` and `.head_branch == 'main'`
71+ # and `head`'s `verified` says whether that verdict covers the commit
72+ # checked out below (#1643). `.event == 'push'` and `.head_branch == 'main'`
10673 # both matter -- `workflow_run` fires for *every* completion of that
10774 # workflow, including one triggered by a pull request, and without this
10875 # check a green PR would upload a conda distribution built from that PR's
10976 # tree.
11077 if : >-
111- !cancelled() && needs.unit-tests .result != 'failure' &&
78+ !cancelled() && needs.head .result != 'failure' &&
11279 (github.event_name != 'workflow_run' || (
11380 github.event.workflow_run.conclusion == 'success' &&
11481 github.event.workflow_run.event == 'push' &&
11582 github.event.workflow_run.head_branch == 'main' &&
116- needs.verdict .outputs.verified == 'true'
83+ needs.head .outputs.verified == 'true'
11784 ))
11885 concurrency :
11986 group : repository-maintenance
@@ -140,7 +107,7 @@ jobs:
140107 # onto main's actual tip before writing, or does not write at all, so
141108 # pinning to the exact tested sha would have bought nothing here
142109 # either. Whether this commit is one that verdict covers is
143- # `verdict `'s question (#1643); whether what lands after it is, Push
110+ # `head `'s question (#1643); whether what lands after it is, Push
144111 # Changes' (#1632).
145112 #
146113 # The push below re-points `origin` at an SSH remote and authenticates
@@ -232,10 +199,11 @@ jobs:
232199 # Writes `pushed` and `commit`, which `CONDA_CHANGED` and `CONDA_COMMIT`
233200 # below hand to `conda-tag` and `conda-dist` (#1632).
234201 #
235- # The verdict this run acted on -- `verdict`'s, or on the schedule the
236- # gate's -- covers `$GITHUB_SHA`, the checkout, and nothing after it. A
237- # commit that lands on `main` during the run would otherwise be rebased
238- # under the bump, pushed, tagged and uploaded with no verdict of its own.
202+ # The verdict this run acted on -- `head`'s `verdict`, or on the schedule
203+ # its test gate's -- covers `$GITHUB_SHA`, the checkout, and nothing after
204+ # it. A commit that lands on `main` during the run would otherwise be
205+ # rebased under the bump, pushed, tagged and uploaded with no verdict of
206+ # its own.
239207 # So the tip is fetched first and the commits a rebase onto it would bring
240208 # in are put to #1643's rule, util/verdict_covers_checkout.py, run from
241209 # this checkout and not from the tip it is judging. If they are not
@@ -351,11 +319,14 @@ jobs:
351319 # required reviewers, or every scheduled bump waits for an approval.
352320 environment : conda-tag
353321 needs : [ conda-update ]
354- # `!cancelled()` is what makes this job reachable at all on the
355- # `workflow_run` path (#1632). `unit-tests` above skips on that event, and
356- # "a default status check of `success()` is applied unless you include one
357- # of these functions" (GitHub, "Evaluate expressions in workflows and
358- # actions", Status check functions). The skip it reacts to is not only a
322+ # `!cancelled()` is what made this job reachable at all on the
323+ # `workflow_run` path (#1632), when the test gate was a job of this file and
324+ # skipped on that event. It is kept now that the gate is in `head` (#1967):
325+ # a job of `head` skips on every path, and this job must not hinge on how
326+ # Actions reports such a call. Without a status-check function, "a default
327+ # status check of `success()` is applied unless you include one of these
328+ # functions" (GitHub, "Evaluate expressions in workflows and actions",
329+ # Status check functions). The skip it reacts to is not only a
359330 # direct `needs:` entry's: "If a run contains a series of jobs that need
360331 # each other, a failure or skip applies to all jobs in the dependency chain
361332 # from the point of failure or skip onwards" (GitHub, "Workflow syntax for
0 commit comments