diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a27e2ed..092ddc05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -266,7 +266,10 @@ env: jobs: build: name: build and verify - runs-on: ubuntu-latest + # EVERY UBUNTU RUNNER IS ON 24.04: `ubuntu-latest` became Ubuntu 26.04 on + # 2026-10-21. There setup-python has no Python 3.9 and the `[host]` case of + # the TERM-ignoring kill test fails. Pinned until 26.04 support is decided. + runs-on: ubuntu-24.04 timeout-minutes: 30 permissions: contents: read # the checkout and its submodule, the tag, and the forge's compare and tree listing @@ -1032,7 +1035,7 @@ jobs: # (their deployment limit is the tags v*). With no status function in # it, `if:` also requires the build to have succeeded. if: startsWith(github.ref, 'refs/tags/v') && needs.build.outputs.to-testpypi == 'true' - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 30 environment: name: testpypi @@ -1254,11 +1257,11 @@ jobs: fail-fast: false matrix: include: - - os: ubuntu-latest + - os: ubuntu-24.04 python: '3.x' - os: macos-latest python: '3.x' - - os: ubuntu-latest + - os: ubuntu-24.04 python: '3.9' env: WHEEL: ${{ needs.build.outputs.wheel }} @@ -1557,7 +1560,7 @@ jobs: # opensoft/openRepoTools-code alone (FR-048), so in an rc rehearsal # this job is skipped and never asks for the `pypi` approval. if: startsWith(github.ref, 'refs/tags/v') && needs.build.outputs.to-pypi == 'true' - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 30 environment: name: pypi diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2cfa173f..46feb68a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -52,7 +52,10 @@ jobs: # lane-helper suite runs. Each GitHub job has its own workstation runner; # the canonical wrapper still serializes any pytest processes on that runner. guard-launch-mode: - runs-on: ubuntu-latest + # EVERY UBUNTU RUNNER IS ON 24.04: `ubuntu-latest` became Ubuntu 26.04 on + # 2026-10-21. There setup-python has no Python 3.9 and the `[host]` case of + # the TERM-ignoring kill test fails. Pinned until 26.04 support is decided. + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -72,7 +75,7 @@ jobs: run: bash tests/run.sh -k 'guard_launch_mode or repo_hygiene' tests: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: # PINNED BY COMMIT, not by tag — openRepoShape's own rule, and the same # two commits every job here pins. A tag can be moved and a commit @@ -128,7 +131,7 @@ jobs: # the assertion; `-rs` prints the skip reasons, which is what a person # reading this job wants to see. tests-no-submodule: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -173,7 +176,7 @@ jobs: # hatchling and pipx reaches it for its shared pip; the `--install` run # reaches nothing. package: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: # The same two commits the other jobs pin. - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 diff --git a/specs/006-release-pypi/contracts/workflows.md b/specs/006-release-pypi/contracts/workflows.md index 706fe50b..8b46eece 100644 --- a/specs/006-release-pypi/contracts/workflows.md +++ b/specs/006-release-pypi/contracts/workflows.md @@ -265,8 +265,10 @@ this run's approvals, and `contents` for the tag, read again. - It needs `build` and `testpypi`. It runs on a tag after `testpypi` succeeded, and on a branch when `testpypi` was skipped. This is the model's condition. -- The matrix is `ubuntu-latest` on `3.x`, `macos-latest` on `3.x`, and - `ubuntu-latest` on `3.9`. There is no Windows leg. +- The matrix is `ubuntu-24.04` on `3.x`, `macos-latest` on `3.x`, and + `ubuntu-24.04` on `3.9`. There is no Windows leg. The ubuntu legs are + pinned because `ubuntu-latest` became Ubuntu 26.04 on 2026-10-21, where + setup-python has no Python `3.9`. - `PIP_INDEX_URL` is PyPI's, as the model has it. The steps: @@ -359,8 +361,10 @@ These are the model's grants (`release.yml:1133-1136` at v1.1.0). version and `run:` commands. These are asserted from the file's text, not from history, because CI checks out one commit at `fetch-depth: 1`. The pull request's diff review confirms the rest of "unchanged". -- The `package` job runs on `ubuntu-latest` with Python `3.9` and - `submodules: true`, and carries steps 4 to 11 in order. +- The `package` job runs on `ubuntu-24.04` with Python `3.9` and + `submodules: true`, and carries steps 4 to 11 in order. The runner is + pinned because `ubuntu-latest` became Ubuntu 26.04 on 2026-10-21, where + setup-python has no Python `3.9`. - Its `tomli` comes from the build lock's own entry, and the job holds no `--hash` of its own. - Its wheel-check heredoc (step 6) is run on the same four synthetic wheels diff --git a/specs/006-release-pypi/plan.md b/specs/006-release-pypi/plan.md index 18d6972d..73a21e6d 100644 --- a/specs/006-release-pypi/plan.md +++ b/specs/006-release-pypi/plan.md @@ -99,8 +99,9 @@ this plan. - **Runs on**: Linux and macOS, and WSL2 on Windows. Python 3.9 or later; bash 3.2 or later. -- **CI**: `ubuntu-latest`. The release install check adds `macos-latest`, - run under `/bin/bash` 3.2. +- **CI**: `ubuntu-24.04`, pinned because `ubuntu-latest` became Ubuntu 26.04 + on 2026-10-21, where setup-python has no Python 3.9. The release install + check adds `macos-latest`, run under `/bin/bash` 3.2. **Project Type**: a command-line toolset, the bash installer and the commands it places, published as one Python wheel, with CI and release diff --git a/tests/test_release_workflow.py b/tests/test_release_workflow.py index 8273f400..34ae79af 100644 --- a/tests/test_release_workflow.py +++ b/tests/test_release_workflow.py @@ -192,8 +192,11 @@ "(needs.testpypi.result == 'success' || " "(needs.testpypi.result == 'skipped' && " "!startsWith(github.ref, 'refs/tags/'))) }}") -INSTALL_LEGS = [("ubuntu-latest", "3.x"), ("macos-latest", "3.x"), - ("ubuntu-latest", "3.9")] + +#: The two ubuntu legs are pinned to 24.04, and macOS is not: `ubuntu-latest` +#: became Ubuntu 26.04 on 2026-10-21, where setup-python has no Python 3.9. +INSTALL_LEGS = [("ubuntu-24.04", "3.x"), ("macos-latest", "3.x"), + ("ubuntu-24.04", "3.9")] #: THE BUILD'S STEPS ADAPTED FROM THE MODEL, BY THE MODEL'S OWN NAMES, each #: a prefix the step's `name:` begins with (contracts/workflows.md's build diff --git a/tests/test_tests_workflow.py b/tests/test_tests_workflow.py index 33a1f6b0..030880c7 100644 --- a/tests/test_tests_workflow.py +++ b/tests/test_tests_workflow.py @@ -855,7 +855,7 @@ def test_tests_yml_existing_job_keeps_todays_runner_checkout_python_and_runs( assert isinstance(job, dict), f"tests.yml has no `{job_id}` job" want = EXISTING_JOBS[job_id] steps = job.get("steps") or [] - assert job.get("runs-on") == "ubuntu-latest", job.get("runs-on") + assert job.get("runs-on") == "ubuntu-24.04", job.get("runs-on") assert len(steps) >= 2, f"`{job_id}` has {len(steps)} steps" assert steps[0].get("uses") == CHECKOUT, steps[0] assert steps[0].get("with") == want["checkout"], steps[0].get("with") @@ -910,7 +910,7 @@ def test_tests_yml_package_runs_on_ubuntu_python_3_9_with_the_submodule( Python the package supports, on ubuntu.""" job = package_job(workflow) steps = job["steps"] - assert job.get("runs-on") == "ubuntu-latest", job.get("runs-on") + assert job.get("runs-on") == "ubuntu-24.04", job.get("runs-on") assert len(steps) >= 2, f"the package job has {len(steps)} steps" assert steps[0].get("uses") == CHECKOUT, steps[0] assert steps[0].get("with") == {"submodules": True, "fetch-depth": 1}, \