Skip to content
Merged
13 changes: 12 additions & 1 deletion .github/workflows/nightly-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,12 @@ jobs:
license-evidence:
name: License compliance evidence
needs: [build-artifacts, python-compliance]
# !cancelled(): the implicit success() also inspects the transitively
# needed manual-approval job, which is skipped on scheduled runs.
if: >-
!cancelled() &&
needs.build-artifacts.result == 'success' &&
needs.python-compliance.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
Expand Down Expand Up @@ -754,7 +760,12 @@ jobs:
fpe-support-matrix:
name: FPE Support Matrix (main)
needs: [changes-guard, build-artifacts]
if: needs.changes-guard.outputs.should-build == 'true'
# !cancelled(): the implicit success() also inspects the transitively
# needed manual-approval job, which is skipped on scheduled runs.
if: >-
!cancelled() &&
needs.changes-guard.outputs.should-build == 'true' &&
needs.build-artifacts.result == 'success'
permissions:
contents: read
uses: ./.github/workflows/fpe-support-matrix.yml
Expand Down
20 changes: 18 additions & 2 deletions tests/test_ci_workflow_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -1776,7 +1776,7 @@ def test_release_artifact_handoffs_cannot_mix_versions():
assert fnmatch.fnmatchcase(name, selected_pattern) == (version == selected)


def _nightly_condition(job: str, **overrides) -> bool:
def _nightly_condition(job: str, *, cancelled: bool = False, **overrides) -> bool:
"""Evaluate the checked-in predicate with explicit Actions context values."""
values = {
"github.event_name": "schedule",
Expand All @@ -1794,10 +1794,26 @@ def _nightly_condition(job: str, **overrides) -> bool:
}
expression = _workflow("nightly-ci.yml")["jobs"][job]["if"]
expression = re.sub(r"(?:github|needs|vars)\.[\w.-]+", lambda match: repr(values[match[0]]), expression)
expression = expression.replace("!cancelled()", "True").replace("&&", " and ").replace("||", " or ")
expression = expression.replace("!cancelled()", repr(not cancelled)).replace("&&", " and ").replace("||", " or ")
return eval(expression, {"__builtins__": {}})


@pytest.mark.parametrize("job", ["license-evidence", "fpe-support-matrix"])
def test_nightly_validation_survives_skipped_approval_but_requires_successful_inputs(job):
configuration = _workflow("nightly-ci.yml")["jobs"][job]
# A status function overrides Actions' implicit success(), which would
# otherwise reject the skipped approval ancestor of a scheduled first run.
assert "!cancelled()" in configuration["if"]
assert _nightly_condition(job)
assert not _nightly_condition(job, cancelled=True)
for dependency in configuration["needs"]:
if dependency == "changes-guard":
assert not _nightly_condition(job, **{"needs.changes-guard.outputs.should-build": "false"})
continue
for result in ("failure", "skipped", "cancelled"):
assert not _nightly_condition(job, **{f"needs.{dependency}.result": result})


@pytest.mark.parametrize("job", ["build-artifacts", "trigger-gitlab-security"])
def test_nightly_retries_require_approval_from_the_current_attempt(job):
assert _nightly_condition(job)
Expand Down