mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 19:01:54 +00:00
The workflows pin `runs-on: ubuntu-NN.NN`, so no job moves to a new Ubuntu release behind our back, but nothing raised the pin either. A sixth job of `🔄 Update versions` closes that: `utils/update/runner.py` reads the image table of actions/runner-images, takes the newest x64 Ubuntu label whose image carries no preview or beta badge, and raises every older bare `runs-on: ubuntu-NN.NN` to it; arch-suffixed labels stay untouched. The job opens the change as one PR over `.github/workflows`, so its CI run tests the new image before it reaches main. This commit carries the updater's first result: every job now runs on ubuntu-26.04 (49 `runs-on`). actionlint 1.7.12, the newest release, does not know `ubuntu-26.04` yet (rhysd/actionlint#682, fix proposed in rhysd/actionlint#743), so `.github/actionlint.yaml` declares the label until a release knows it. act maps each `ubuntu-NN.NN` label the workflows use to the local platform image, derived from `.github/workflows`, instead of a fixed list that did not know ubuntu-26.04. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
"""Bump the pinned GitHub-hosted Ubuntu runner label of every workflow job.
|
|
|
|
GitHub lists its hosted images in the runner-images README; the newest x64
|
|
Ubuntu label whose image carries no preview or beta badge is the target.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
IMAGES_README = "https://raw.githubusercontent.com/actions/runner-images/main/README.md"
|
|
|
|
_LABEL = re.compile(r"`ubuntu-(\d{2})\.(\d{2})`")
|
|
_RUNS_ON = re.compile(r"(runs-on:\s*)ubuntu-(\d{2})\.(\d{2})(?![\w.-])")
|
|
_PRERELEASE = re.compile(r"preview|beta", re.IGNORECASE)
|
|
|
|
|
|
def newest_ubuntu_label(readme: str) -> str | None:
|
|
"""Return the newest GA x64 Ubuntu label listed in the images table.
|
|
|
|
Args:
|
|
readme: text of the runner-images README.
|
|
"""
|
|
versions: list[tuple[int, int]] = []
|
|
for row in readme.splitlines():
|
|
cells = [cell.strip() for cell in row.split("|")]
|
|
if len(cells) < 5 or not cells[1].startswith("Ubuntu"):
|
|
continue
|
|
if _PRERELEASE.search(cells[1]) or cells[2] != "x64":
|
|
continue
|
|
versions += [
|
|
(int(major), int(minor)) for major, minor in _LABEL.findall(cells[3])
|
|
]
|
|
if not versions:
|
|
return None
|
|
major, minor = max(versions)
|
|
return f"ubuntu-{major:02d}.{minor:02d}"
|
|
|
|
|
|
def bump_text(text: str, label: str) -> str:
|
|
"""Raise every older ``runs-on: ubuntu-NN.NN`` in *text* to *label*.
|
|
|
|
Args:
|
|
text: workflow source.
|
|
label: target label, ``ubuntu-NN.NN``.
|
|
"""
|
|
target = tuple(int(part) for part in label.removeprefix("ubuntu-").split("."))
|
|
|
|
def _raise(match: re.Match[str]) -> str:
|
|
if (int(match.group(2)), int(match.group(3))) < target:
|
|
return match.group(1) + label
|
|
return match.group(0)
|
|
|
|
return _RUNS_ON.sub(_raise, text)
|
|
|
|
|
|
def bump_workflows(workflows_dir: Path, label: str) -> list[Path]:
|
|
"""Rewrite the workflows under *workflows_dir* to *label*; return the changed files.
|
|
|
|
Args:
|
|
workflows_dir: directory holding the workflow YAML files.
|
|
label: target label, ``ubuntu-NN.NN``.
|
|
"""
|
|
changed: list[Path] = []
|
|
for path in sorted(workflows_dir.glob("*.y*ml")):
|
|
text = path.read_text( # nocheck: cache-read — read-then-write of the same file; cached read would go stale
|
|
encoding="utf-8"
|
|
)
|
|
bumped = bump_text(text, label)
|
|
if bumped != text:
|
|
path.write_text(bumped, encoding="utf-8")
|
|
changed.append(path)
|
|
return changed
|