From 9024434bf0eaef0124ca693edc92f349d48c0040 Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Thu, 22 Oct 2026 16:57:09 -0400 Subject: [PATCH] ci(conda): drop the unreachable Windows conda steps (#1967) `windows-latest` has been commented out of the conda matrices since 2023, yet `conda` in create-release.yml and `conda-dist` in cron-conda.yml still carried `Install and Setup (Windows)`, `Setup Conda Distribution (Windows)`, the `matrix.os != 'windows-latest'` guards on their twins, and a `windows-latest` arm in each `case "${{ matrix.os }}"`. Remove them, and replace the commented matrix line with a note that adding the leg back means writing its steps. test_conda_no_windows_steps_1967 pins that no step's `if:` or `case` arm in either job names a runner its matrix lacks, and that no step is Windows-only while no leg is Windows. #1854's install-step count drops its Windows twin, and util/conda_vendor.py's note on `bld.bat` no longer says "commented out". --- .github/workflows/create-release.yml | 22 +--- .github/workflows/cron-conda.yml | 19 +-- ...test_conda_legs_install_no_pcapkit_1854.py | 2 +- .../test_conda_no_windows_steps_1967.py | 113 ++++++++++++++++++ util/conda_vendor.py | 2 +- 5 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 tests/project/test_conda_no_windows_steps_1967.py diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 0c724da0cf..fe4693187e 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -980,7 +980,8 @@ jobs: - macos-latest - macos-26-intel - ubuntu-latest - # - windows-latest # skip for now + # No Windows leg since 2023, and no Windows steps (#1967): adding the leg + # back means writing its steps, as test_conda_no_windows_steps_1967 pins. # #1633, #1660: the supported tier only. No KTLO 3.10 leg: the list # util/conda_vendor.py derives omits typing-extensions, which # pcapkit/utilities/compat.py imports below 3.11, and pins each @@ -1032,9 +1033,6 @@ jobs: ubuntu-latest) target_platform="linux-64" ;; - windows-latest) - target_platform="win-64" - ;; *) target_platform="" ;; @@ -1083,31 +1081,18 @@ jobs: # installed here: on ``macos-26-intel`` they resolve a cryptography with # no Intel wheel, which pip has to compile or fail on. - name: Install and Setup - if: ${{ matrix.os != 'windows-latest' }} run: | set -x python -m pip install -U pip setuptools wheel - - name: Install and Setup (Windows) - if: ${{ matrix.os == 'windows-latest' }} - run: | - python -m pip install -U pip setuptools wheel - - name: Setup Conda Distribution - if: ${{ matrix.os != 'windows-latest' }} run: | set -x mkdir -p conda/wheels python -m pip download -r conda/requirements.txt -d conda/wheels - - name: Setup Conda Distribution (Windows) - if: ${{ matrix.os == 'windows-latest' }} - run: | - mkdir -p conda/wheels - python -m pip download -r conda/requirements.txt -d conda/wheels - # With `activate-environment: base`, `python-version` installs that Python # into base, next to conda itself. conda-forge's conda has no py315 build # yet, so on 3.15 that fails with "RemoveError: Conda cannot remove @@ -1173,9 +1158,6 @@ jobs: ubuntu-latest) target_platform="linux-64" ;; - windows-latest) - target_platform="win-64" - ;; *) target_platform="" ;; diff --git a/.github/workflows/cron-conda.yml b/.github/workflows/cron-conda.yml index f80446122c..994fd94a88 100644 --- a/.github/workflows/cron-conda.yml +++ b/.github/workflows/cron-conda.yml @@ -415,7 +415,8 @@ jobs: - macos-latest - macos-26-intel - ubuntu-latest - # - windows-latest # skip for now + # No Windows leg since 2023, and no Windows steps (#1967): adding the leg + # back means writing its steps, as test_conda_no_windows_steps_1967 pins. # #1633: the supported tier, from .github/python-versions.toml through # `conda-update` (#1660); create-release.yml's ``conda`` job says why # there is no KTLO 3.10 leg. @@ -433,34 +434,21 @@ jobs: # #1854: pcapkit is not installed here; see create-release.yml's step of # the same name. - name: Install and Setup - if: ${{ matrix.os != 'windows-latest' }} run: | set -x python -m pip install -U pip setuptools wheel - - name: Install and Setup (Windows) - if: ${{ matrix.os == 'windows-latest' }} - run: | - python -m pip install -U pip setuptools wheel - # #1827: pip evaluates conda/requirements.txt's platform markers here, # on this leg's own runner, so Intel macOS fetches its own cryptography # pin; the recipe's build.sh installs whatever this downloaded. - name: Setup Conda Distribution - if: ${{ matrix.os != 'windows-latest' }} run: | set -x mkdir -p conda/wheels python -m pip download -r conda/requirements.txt -d conda/wheels - - name: Setup Conda Distribution (Windows) - if: ${{ matrix.os == 'windows-latest' }} - run: | - mkdir -p conda/wheels - python -m pip download -r conda/requirements.txt -d conda/wheels - # See create-release.yml's step of the same name for the 3.15 exception. - name: Conda environment creation and activation uses: conda-incubator/setup-miniconda@be893c923ea9cf1cf7cd510fbdde27c7e18cbdcb # v4.1.0 @@ -514,9 +502,6 @@ jobs: ubuntu-latest) target_platform="linux-64" ;; - windows-latest) - target_platform="win-64" - ;; *) target_platform="" ;; diff --git a/tests/project/test_conda_legs_install_no_pcapkit_1854.py b/tests/project/test_conda_legs_install_no_pcapkit_1854.py index c25b9e2e4d..a9af379342 100644 --- a/tests/project/test_conda_legs_install_no_pcapkit_1854.py +++ b/tests/project/test_conda_legs_install_no_pcapkit_1854.py @@ -88,7 +88,7 @@ def test_each_install_step_upgrades_the_build_tools_alone(self) -> None: steps = [step for found, job, step in self.steps() if (found, job) == (name, job_id) and str(step.get('name', '')).startswith('Install and Setup')] with self.subTest(workflow=name, job=job_id): - self.assertEqual(len(steps), 2, 'the Linux/macOS step and the Windows one') + self.assertEqual(len(steps), 1, 'one step for every leg, with no Windows twin (#1967)') for step in steps: with self.subTest(workflow=name, job=job_id, step=step['name']): self.assertEqual(installs(step), [BUILD_TOOLS]) diff --git a/tests/project/test_conda_no_windows_steps_1967.py b/tests/project/test_conda_no_windows_steps_1967.py new file mode 100644 index 0000000000..a4d6ac6245 --- /dev/null +++ b/tests/project/test_conda_no_windows_steps_1967.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +"""#1967: the conda jobs keep no step or ``case`` arm for a runner they have no leg on. + +``conda`` in :file:`.github/workflows/create-release.yml` and ``conda-dist`` in +:file:`.github/workflows/cron-conda.yml` have had no ``windows-latest`` leg since +2023, yet carried ``Install and Setup (Windows)``, ``Setup Conda Distribution +(Windows)``, the ``matrix.os != 'windows-latest'`` guards on their twins, and a +``windows-latest`` arm in each ``case "${{ matrix.os }}"``: code no run reached. + +* :class:`TestNoDeadRunnerCode` pins that no step's ``if:`` names a runner label + the job's matrix lacks, no ``case`` arm maps one, and, with no Windows leg, no + step is Windows-only. So adding a Windows leg back means adding its steps back + deliberately, rather than reviving ones nobody has run. +* :class:`TestTheCheckSeesDeadCode` feeds :func:`dead` the jobs as they stood + before, rebuilt from the current ones, so the pin cannot pass by reading nothing. + +""" + +from __future__ import annotations + +import copy +import re +import unittest +from typing import TYPE_CHECKING + +from tests import _workflows + +if TYPE_CHECKING: + from typing import Any + +#: Test tier (#1958): reads the workflow files, a question about the tree. +__tier__ = 'LATEST' + +#: The conda jobs, as (workflow, job). +JOBS = (('create-release.yml', 'conda'), ('cron-conda.yml', 'conda-dist')) +#: A ``matrix.os`` comparison in an ``if:``, capturing the label compared against. +GUARD = re.compile(r"matrix\.os\s*[!=]=\s*'([^']+)'") +#: A ``case "${{ matrix.os }}" in`` block of a step's ``run:``. +CASE = re.compile(r'case "\$\{\{ matrix\.os \}\}" in\n(.*?)\n\s*esac', re.DOTALL) +#: An arm of that block, capturing its pattern. +ARM = re.compile(r'^\s*([^\s()]+)\)\s*$', re.MULTILINE) +#: A Windows runner label, or the step name of a Windows-only step. +WINDOWS = re.compile(r'windows', re.IGNORECASE) +#: An ``if:`` that runs its step on Windows alone. +WINDOWS_ONLY = re.compile(r"(?:matrix|runner)\.os\s*==\s*'[^']*windows", re.IGNORECASE) + + +def dead(spec: 'dict[str, Any]') -> 'list[str]': + """What of ``spec``, a job, names a runner its matrix has no leg on.""" + labels = list(spec['strategy']['matrix']['os']) + windows_leg = any(WINDOWS.search(label) for label in labels) + found = [] + for step in spec['steps']: + name = str(step.get('name') or step.get('uses') or step.get('id')) + condition = str(step.get('if', '')) + for label in GUARD.findall(condition): + if label not in labels: + found.append(f'{name}: `if:` compares matrix.os with {label}, which is no leg') + if not windows_leg and (WINDOWS_ONLY.search(condition) or WINDOWS.search(str(step.get('name', '')))): + found.append(f'{name}: Windows-only, and no leg is Windows') + for block in CASE.findall(str(step.get('run', ''))): + for pattern in ARM.findall(block): + if pattern != '*' and pattern not in labels: + found.append(f'{name}: `case` arm {pattern}, which is no leg') + return found + + +class TestNoDeadRunnerCode(unittest.TestCase): + """Each conda job's steps and ``case`` arms cover its legs and nothing else.""" + + def test_no_step_or_arm_names_a_missing_leg(self) -> None: + for name, job_id in JOBS: + with self.subTest(workflow=name, job=job_id): + self.assertEqual(dead(_workflows.job(name, job_id)), []) + + +class TestTheCheckSeesDeadCode(unittest.TestCase): + """:func:`dead` reports each kind of dead code the jobs held before #1967.""" + + def test_it_reports_a_windows_step_guard_and_arm(self) -> None: + for name, job_id in JOBS: + spec = copy.deepcopy(_workflows.job(name, job_id)) + install = next(step for step in spec['steps'] if step.get('name') == 'Install and Setup') + install['if'] = "${{ matrix.os != 'windows-latest' }}" + spec['steps'].append({'name': 'Install and Setup (Windows)', + 'if': "${{ matrix.os == 'windows-latest' }}", + 'run': 'python -m pip install -U pip setuptools wheel\n'}) + spec['steps'].append({'name': 'Map the leg', 'run': ( + 'case "${{ matrix.os }}" in\n' + ' windows-latest)\n' + ' target_platform="win-64"\n' + ' ;;\n' + ' *)\n' + ' target_platform=""\n' + ' ;;\n' + 'esac\n')}) + with self.subTest(workflow=name, job=job_id): + self.assertEqual(dead(spec), [ + 'Install and Setup: `if:` compares matrix.os with windows-latest, which is no leg', + 'Install and Setup (Windows): `if:` compares matrix.os with windows-latest, which is no leg', + 'Install and Setup (Windows): Windows-only, and no leg is Windows', + 'Map the leg: `case` arm windows-latest, which is no leg', + ]) + + def test_a_windows_leg_allows_its_own_steps(self) -> None: + spec = {'strategy': {'matrix': {'os': ['ubuntu-latest', 'windows-latest']}}, + 'steps': [{'name': 'Setup (Windows)', 'if': "${{ matrix.os == 'windows-latest' }}", + 'run': 'case "${{ matrix.os }}" in\n windows-latest)\n x=1\n ;;\nesac\n'}]} + self.assertEqual(dead(spec), []) + + +if __name__ == '__main__': + unittest.main() diff --git a/util/conda_vendor.py b/util/conda_vendor.py index f94cc93840..3e64275cee 100644 --- a/util/conda_vendor.py +++ b/util/conda_vendor.py @@ -103,7 +103,7 @@ #: ``sys.platform``, ``platform.system()`` and ``platform.machine()`` read on its #: runner: ``ubuntu-latest``, the Intel ``macos-26-intel`` and the arm64 #: ``macos-latest``. Each leg publishes only its own runner's platform (#1822). -#: Their Windows legs are commented out, and with them the recipe's ``bld.bat``. +#: They have no Windows leg (#1967), so the recipe's ``bld.bat`` goes unused. PLATFORMS = { 'linux-64': ('linux', 'Linux', 'x86_64'), 'osx-64': ('darwin', 'Darwin', 'x86_64'),