mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 19:56:53 +00:00
feat(ci): keep GitHub-hosted runner labels current through the updater
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>
This commit is contained in:
1 parent
52ad8549e0
commit
b055eece05
36 files changed
+307
-55
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
self-hosted-runner:
|
||||||
|
labels:
|
||||||
|
- ubuntu-26.04
|
||||||
@@ -43,7 +43,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: 💿 Image
|
name: 💿 Image
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
sync:
|
sync:
|
||||||
name: 🪞 Mirror
|
name: 🪞 Mirror
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
name: 🧹 Lint
|
name: 🧹 Lint
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
env:
|
env:
|
||||||
INFINITO_LINT_RUNNER: host
|
INFINITO_LINT_RUNNER: host
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ jobs:
|
|||||||
- test-deploy-chunk-2
|
- test-deploy-chunk-2
|
||||||
- test-deploy-chunk-3
|
- test-deploy-chunk-3
|
||||||
if: ${{ always() && github.ref == 'refs/heads/main' && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
|
if: ${{ always() && github.ref == 'refs/heads/main' && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
actions: read
|
actions: read
|
||||||
@@ -374,7 +374,7 @@ jobs:
|
|||||||
- lint
|
- lint
|
||||||
- security-codeql
|
- security-codeql
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: 🛑 Fail if any upstream job failed or was cancelled
|
- name: 🛑 Fail if any upstream job failed or was cancelled
|
||||||
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
check-ci-images:
|
check-ci-images:
|
||||||
name: 🔎 Check CI images
|
name: 🔎 Check CI images
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
missing: ${{ steps.check.outputs.missing }}
|
missing: ${{ steps.check.outputs.missing }}
|
||||||
ci_tag: ${{ steps.citag.outputs.ci_tag }}
|
ci_tag: ${{ steps.citag.outputs.ci_tag }}
|
||||||
@@ -123,7 +123,7 @@ jobs:
|
|||||||
needs.build-ci-images-if-missing.result == 'success' ||
|
needs.build-ci-images-if-missing.result == 'success' ||
|
||||||
needs.build-ci-images-if-missing.result == 'skipped'
|
needs.build-ci-images-if-missing.result == 'skipped'
|
||||||
)
|
)
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
discover:
|
discover:
|
||||||
name: 🔍 Chunk ${{ inputs.index }}${{ inputs.marker }}
|
name: 🔍 Chunk ${{ inputs.index }}${{ inputs.marker }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
outputs:
|
outputs:
|
||||||
apps: ${{ steps.discover.outputs.apps }}
|
apps: ${{ steps.discover.outputs.apps }}
|
||||||
@@ -251,7 +251,7 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
name: "${{ matrix.label }}"
|
name: "${{ matrix.label }}"
|
||||||
if: needs.discover.outputs.apps != '' && needs.discover.outputs.apps != '[]'
|
if: needs.discover.outputs.apps != '' && needs.discover.outputs.apps != '[]'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 355
|
timeout-minutes: 355
|
||||||
needs: discover
|
needs: discover
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
dns:
|
dns:
|
||||||
name: 🌐 DNS
|
name: 🌐 DNS
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- name: 🧹 Free disk space
|
- name: 🧹 Free disk space
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
test-install-make:
|
test-install-make:
|
||||||
name: 🛠️ Makefile
|
name: 🛠️ Makefile
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
env:
|
env:
|
||||||
NIX_CONFIG: |
|
NIX_CONFIG: |
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
test-install-pkgmgr:
|
test-install-pkgmgr:
|
||||||
name: 📦 PKGMGR
|
name: 📦 PKGMGR
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
env:
|
env:
|
||||||
NIX_CONFIG: |
|
NIX_CONFIG: |
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
prepare:
|
prepare:
|
||||||
name: 🧑💻 Workspace Matrix
|
name: 🧑💻 Workspace Matrix
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
outputs:
|
outputs:
|
||||||
matrix: ${{ steps.matrix.outputs.matrix }}
|
matrix: ${{ steps.matrix.outputs.matrix }}
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
|
|
||||||
test-workspace:
|
test-workspace:
|
||||||
name: ${{ matrix.icon }} Workspace (${{ matrix.label }})
|
name: ${{ matrix.icon }} Workspace (${{ matrix.label }})
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 345
|
timeout-minutes: 345
|
||||||
needs: prepare
|
needs: prepare
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: 🧪 Test
|
name: 🧪 Test
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
env:
|
env:
|
||||||
INFINITO_TEST_RUNNER: host
|
INFINITO_TEST_RUNNER: host
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
validation:
|
validation:
|
||||||
name: ✅ Validation
|
name: ✅ Validation
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout the calling ref for its tooling
|
- name: ⬇️ Checkout the calling ref for its tooling
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -148,7 +148,7 @@ jobs:
|
|||||||
wait-fork-prereq-run:
|
wait-fork-prereq-run:
|
||||||
name: ⏳ Wait for fork run
|
name: ⏳ Wait for fork run
|
||||||
if: ${{ inputs.fork_prereqs }}
|
if: ${{ inputs.fork_prereqs }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
env:
|
env:
|
||||||
WAIT_REQUIRED: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && !inputs.trusted_pr }}
|
WAIT_REQUIRED: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && !inputs.trusted_pr }}
|
||||||
steps:
|
steps:
|
||||||
@@ -194,7 +194,7 @@ jobs:
|
|||||||
name: 🚦 Gate Dependencies
|
name: 🚦 Gate Dependencies
|
||||||
needs: wait-fork-prereq-run
|
needs: wait-fork-prereq-run
|
||||||
if: ${{ !cancelled() && inputs.fork_prereqs }}
|
if: ${{ !cancelled() && inputs.fork_prereqs }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7.0.0
|
- uses: actions/checkout@v7.0.0
|
||||||
- name: ✅ Assert privileged prerequisites are ready
|
- name: ✅ Assert privileged prerequisites are ready
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
name: 🏷️ Close inactive issues and pull requests
|
name: 🏷️ Close inactive issues and pull requests
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
|
|
||||||
delete-stale-branches:
|
delete-stale-branches:
|
||||||
name: 🌿 Delete inactive branches
|
name: 🌿 Delete inactive branches
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
issues: write
|
issues: write
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
|
|
||||||
cleanup-ghcr-ci-images:
|
cleanup-ghcr-ci-images:
|
||||||
name: 📦 Delete old GHCR CI images
|
name: 📦 Delete old GHCR CI images
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
benchmark-collection-sources:
|
benchmark-collection-sources:
|
||||||
name: ⚖️ Time Galaxy against the git fallback
|
name: ⚖️ Time Galaxy against the git fallback
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
env:
|
env:
|
||||||
HISTORY_PATH: build/collection-source-history.json
|
HISTORY_PATH: build/collection-source-history.json
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
cleanup:
|
cleanup:
|
||||||
name: 🧹 Delete old ci-* image versions
|
name: 🧹 Delete old ci-* image versions
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
sync:
|
sync:
|
||||||
name: 🪞 Mirror
|
name: 🪞 Mirror
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
check-and-trigger:
|
check-and-trigger:
|
||||||
name: 🔎 Backfill highest missing release tag
|
name: 🔎 Backfill highest missing release tag
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: read
|
packages: read
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
# - https://gh.io/supported-runners-and-hardware-resources
|
# - https://gh.io/supported-runners-and-hardware-resources
|
||||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
security-events: write
|
security-events: write
|
||||||
packages: read
|
packages: read
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
fuzz-yaml-bootstrap:
|
fuzz-yaml-bootstrap:
|
||||||
name: 🧬 Fuzz the bootstrap YAML reader
|
name: 🧬 Fuzz the bootstrap YAML reader
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ permissions: read-all
|
|||||||
jobs:
|
jobs:
|
||||||
analysis:
|
analysis:
|
||||||
name: 🔍 Scorecard analysis
|
name: 🔍 Scorecard analysis
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
||||||
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
update-docker-image-versions:
|
update-docker-image-versions:
|
||||||
name: 🐳 Update Docker image versions
|
name: 🐳 Update Docker image versions
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -68,7 +68,7 @@ jobs:
|
|||||||
update-version-sources:
|
update-version-sources:
|
||||||
name: 🔖 Update declared version sources
|
name: 🔖 Update declared version sources
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
update-pip-pins:
|
update-pip-pins:
|
||||||
name: 🐍 Update pinned pip requirements
|
name: 🐍 Update pinned pip requirements
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -162,7 +162,7 @@ jobs:
|
|||||||
update-galaxy-pins:
|
update-galaxy-pins:
|
||||||
name: 🌌 Update pinned Ansible collections
|
name: 🌌 Update pinned Ansible collections
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -209,7 +209,7 @@ jobs:
|
|||||||
update-repository-refs:
|
update-repository-refs:
|
||||||
name: 🌿 Update repository refs
|
name: 🌿 Update repository refs
|
||||||
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Checkout
|
- name: ⬇️ Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.0
|
||||||
@@ -252,3 +252,45 @@ jobs:
|
|||||||
UPDATE_PR_BODY: "Automated update of semver-based git `ref:` values in `roles/*/meta/services.yml`. Upstream tags resolved via `git ls-remote --tags`."
|
UPDATE_PR_BODY: "Automated update of semver-based git `ref:` values in `roles/*/meta/services.yml`. Upstream tags resolved via `git ls-remote --tags`."
|
||||||
UPDATE_BASE_BRANCH: main
|
UPDATE_BASE_BRANCH: main
|
||||||
run: bash scripts/github/update/open/role_prs.sh roles
|
run: bash scripts/github/update/open/role_prs.sh roles
|
||||||
|
|
||||||
|
update-runner-labels:
|
||||||
|
name: 🏃 Update GitHub-hosted runner labels
|
||||||
|
if: vars.CI_ENABLE_AUTO_UPDATES == 'true'
|
||||||
|
runs-on: ubuntu-26.04
|
||||||
|
steps:
|
||||||
|
- name: ⬇️ Checkout
|
||||||
|
uses: actions/checkout@v7.0.0
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
|
||||||
|
- name: 🔧 Set up Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: 🔄 Update runner labels
|
||||||
|
run: bash scripts/github/update/runner_labels.sh
|
||||||
|
|
||||||
|
- name: 🔎 Check for changes
|
||||||
|
id: diff
|
||||||
|
run: bash scripts/github/resolve/check_git_changes.sh .github/workflows
|
||||||
|
|
||||||
|
- name: ⚙️ Generate app token
|
||||||
|
if: steps.diff.outputs.changed == 'true'
|
||||||
|
id: app-token
|
||||||
|
uses: actions/create-github-app-token@v3
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.BOT_APP_CLIENT_ID }}
|
||||||
|
private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: 📂 Open PR if runner labels changed
|
||||||
|
if: steps.diff.outputs.changed == 'true'
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
|
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
|
||||||
|
UPDATE_BRANCH_PREFIX: update/runner-labels
|
||||||
|
UPDATE_COMMIT_MESSAGE: "update(ci): raise GitHub-hosted runner labels"
|
||||||
|
UPDATE_PR_TITLE: "update(ci): raise GitHub-hosted runner labels"
|
||||||
|
UPDATE_PR_BODY: "Automated raise of every `runs-on: ubuntu-NN.NN` in `.github/workflows/` to the newest GA x64 Ubuntu image listed in https://github.com/actions/runner-images. Its CI run is the proof that the stack works on the new image."
|
||||||
|
UPDATE_BASE_BRANCH: main
|
||||||
|
run: bash scripts/github/update/open/pr.sh .github/workflows
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
cancel-branch-runs:
|
cancel-branch-runs:
|
||||||
name: 🚫 Cancel superseded branch runs
|
name: 🚫 Cancel superseded branch runs
|
||||||
if: ${{ github.event_name == 'push' && (github.ref_name != 'main' || (github.ref_name == 'main' && startsWith(github.event.head_commit.message, 'Release version '))) }}
|
if: ${{ github.event_name == 'push' && (github.ref_name != 'main' || (github.ref_name == 'main' && startsWith(github.event.head_commit.message, 'Release version '))) }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
contents: read
|
contents: read
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
cancel-pull-request-runs:
|
cancel-pull-request-runs:
|
||||||
name: 🚫 Cancel superseded pull request runs
|
name: 🚫 Cancel superseded pull request runs
|
||||||
if: ${{ github.event_name == 'pull_request_target' }}
|
if: ${{ github.event_name == 'pull_request_target' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
cancel-branch-runs:
|
cancel-branch-runs:
|
||||||
if: ${{ github.event.ref_type == 'branch' }}
|
if: ${{ github.event.ref_type == 'branch' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
cleanup:
|
cleanup:
|
||||||
name: 🗑️ Delete private GHCR mirror packages
|
name: 🗑️ Delete private GHCR mirror packages
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
detect-pr-scope:
|
detect-pr-scope:
|
||||||
name: 🔎 Detect PR scope
|
name: 🔎 Detect PR scope
|
||||||
if: ${{ github.event.pull_request.draft == false && (github.event_name == 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository) }}
|
if: ${{ github.event.pull_request.draft == false && (github.event_name == 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
scope: ${{ steps.resolve.outputs.scope }}
|
scope: ${{ steps.resolve.outputs.scope }}
|
||||||
run_ci_orchestrator: ${{ steps.resolve.outputs.run_ci_orchestrator }}
|
run_ci_orchestrator: ${{ steps.resolve.outputs.run_ci_orchestrator }}
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
- detect-pr-scope
|
- detect-pr-scope
|
||||||
- validation
|
- validation
|
||||||
if: ${{ needs.detect-pr-scope.outputs.run_ci_orchestrator == 'false' }}
|
if: ${{ needs.detect-pr-scope.outputs.run_ci_orchestrator == 'false' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ✅ Confirm lightweight PR scope
|
- name: ✅ Confirm lightweight PR scope
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
- detect-pr-scope
|
- detect-pr-scope
|
||||||
- validation
|
- validation
|
||||||
if: ${{ needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }}
|
if: ${{ needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
whitelist: ${{ steps.resolve.outputs.whitelist }}
|
whitelist: ${{ steps.resolve.outputs.whitelist }}
|
||||||
steps:
|
steps:
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
- detect-pr-scope
|
- detect-pr-scope
|
||||||
- validation
|
- validation
|
||||||
if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }}
|
if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
checkout_ref: ${{ steps.out.outputs.checkout_ref }}
|
checkout_ref: ${{ steps.out.outputs.checkout_ref }}
|
||||||
image_tag: ${{ steps.out.outputs.image_tag }}
|
image_tag: ${{ steps.out.outputs.image_tag }}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cancel-pr-runs:
|
cancel-pr-runs:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
close-when-disabled:
|
close-when-disabled:
|
||||||
name: 🚫 Close Dependabot PR while gated
|
name: 🚫 Close Dependabot PR while gated
|
||||||
if: github.event.pull_request.user.login == 'dependabot[bot]' && vars.CI_ENABLE_AUTO_UPDATES != 'true'
|
if: github.event.pull_request.user.login == 'dependabot[bot]' && vars.CI_ENABLE_AUTO_UPDATES != 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: 📪 Close PR
|
- name: 📪 Close PR
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
run-policy:
|
run-policy:
|
||||||
name: 🧭 Decide CI policy
|
name: 🧭 Decide CI policy
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: read
|
pull-requests: read
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
name: ⏭️ Skip CI
|
name: ⏭️ Skip CI
|
||||||
needs: run-policy
|
needs: run-policy
|
||||||
if: needs.run-policy.outputs.should_run != 'true'
|
if: needs.run-policy.outputs.should_run != 'true'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- name: ⏭️ Explain skip
|
- name: ⏭️ Explain skip
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
if: needs.run-policy.outputs.should_run == 'true'
|
if: needs.run-policy.outputs.should_run == 'true'
|
||||||
needs: run-policy
|
needs: run-policy
|
||||||
name: 🏷️ Detect release tag
|
name: 🏷️ Detect release tag
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
is_version: ${{ steps.pick.outputs.is_version }}
|
is_version: ${{ steps.pick.outputs.is_version }}
|
||||||
version_tag: ${{ steps.pick.outputs.version_tag }}
|
version_tag: ${{ steps.pick.outputs.version_tag }}
|
||||||
@@ -91,7 +91,7 @@ jobs:
|
|||||||
if: needs.run-policy.outputs.should_run == 'true'
|
if: needs.run-policy.outputs.should_run == 'true'
|
||||||
name: ⭐ Resolve new-role priority
|
name: ⭐ Resolve new-role priority
|
||||||
needs: run-policy
|
needs: run-policy
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
priority: ${{ steps.resolve.outputs.priority }}
|
priority: ${{ steps.resolve.outputs.priority }}
|
||||||
steps:
|
steps:
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
- run-policy
|
- run-policy
|
||||||
- detect-release
|
- detect-release
|
||||||
- ci-orchestrator
|
- ci-orchestrator
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-26.04
|
||||||
outputs:
|
outputs:
|
||||||
allowed: ${{ steps.guard.outputs.allowed }}
|
allowed: ${{ steps.guard.outputs.allowed }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
"""CLI entry point package for the GitHub-hosted runner label update."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
PROJECT_ROOT: Path = Path(__file__).resolve().parents[4]
|
||||||
Executable
+46
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from utils.update.fetch import document
|
||||||
|
from utils.update.runner import IMAGES_README, bump_workflows, newest_ubuntu_label
|
||||||
|
|
||||||
|
from . import PROJECT_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description=(
|
||||||
|
"Raise every workflow's runs-on Ubuntu label to the newest GA "
|
||||||
|
"GitHub-hosted x64 image."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--repo-root",
|
||||||
|
type=Path,
|
||||||
|
default=PROJECT_ROOT,
|
||||||
|
help="Repository root whose .github/workflows are updated",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
label = newest_ubuntu_label(document(IMAGES_README))
|
||||||
|
if label is None:
|
||||||
|
print(f"No GA x64 Ubuntu label found in {IMAGES_README}.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
repo_root = args.repo_root.resolve()
|
||||||
|
changed = bump_workflows(repo_root / ".github" / "workflows", label)
|
||||||
|
if not changed:
|
||||||
|
print(f"Every workflow already runs on {label} or newer.")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(f"Raised runs-on to {label} in:")
|
||||||
|
for path in changed:
|
||||||
|
print(f"- {path.relative_to(repo_root)}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -49,11 +49,11 @@ Some CI failures (most notably OOM-kills such as [#162](https://github.com/infin
|
|||||||
|
|
||||||
### GitHub-Hosted Runner Specs
|
### GitHub-Hosted Runner Specs
|
||||||
|
|
||||||
All [workflows](../../../../.github/workflows/) target `runs-on: ubuntu-24.04`, the GitHub-hosted standard Linux runner pinned to one Ubuntu release. GitHub still refreshes that image weekly; moving to the next release is a deliberate change of the label, and `tests/lint/repository/test_workflow_runner_pinned.py` rejects `*-latest` labels. The effective ceiling depends on the repository's visibility and plan:
|
All [workflows](../../../../.github/workflows/) target `runs-on: ubuntu-26.04`, the GitHub-hosted standard Linux runner pinned to one Ubuntu release. GitHub still refreshes that image weekly. The `🏃 Update GitHub-hosted runner labels` job of [cron-update.yml](../../../../.github/workflows/cron-update.yml) opens a pull request when a newer GA x64 Ubuntu image is listed in [actions/runner-images](https://github.com/actions/runner-images), and `tests/lint/repository/test_workflow_runner_pinned.py` rejects `*-latest` labels. The effective ceiling depends on the repository's visibility and plan:
|
||||||
|
|
||||||
| Repository / plan | vCPU | RAM | SSD |
|
| Repository / plan | vCPU | RAM | SSD |
|
||||||
|------------------------------------------|------|--------|-------|
|
|------------------------------------------|------|--------|-------|
|
||||||
| Public repo (this repo, `ubuntu-24.04`) | 4 | 16 GB | 14 GB |
|
| Public repo (this repo, `ubuntu-26.04`) | 4 | 16 GB | 14 GB |
|
||||||
| Private repo on Free / Pro / Team | 2 | 7 GB | 14 GB |
|
| Private repo on Free / Pro / Team | 2 | 7 GB | 14 GB |
|
||||||
| Private repo on Enterprise | 4 | 16 GB | 14 GB |
|
| Private repo on Enterprise | 4 | 16 GB | 14 GB |
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ For the authoritative specs, see the upstream docs for [standard hosted runners]
|
|||||||
Pick the profile that matches the runner you want to mimic:
|
Pick the profile that matches the runner you want to mimic:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Public repo runner (ubuntu-24.04, 4 vCPU / 16 GB): the default CI target
|
# Public repo runner (ubuntu-26.04, 4 vCPU / 16 GB): the default CI target
|
||||||
INFINITO_MEM_LIMIT=16g INFINITO_MEMSWAP_LIMIT=16g INFINITO_CPUS=4 make <target>
|
INFINITO_MEM_LIMIT=16g INFINITO_MEMSWAP_LIMIT=16g INFINITO_CPUS=4 make <target>
|
||||||
|
|
||||||
# Private repo runner on Free/Pro/Team (2 vCPU / 7 GB)
|
# Private repo runner on Free/Pro/Team (2 vCPU / 7 GB)
|
||||||
|
|||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." && pwd)"
|
||||||
|
|
||||||
|
cd "${REPO_ROOT}"
|
||||||
|
python3 -m cli.contributing.update.runner "$@"
|
||||||
@@ -54,10 +54,10 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cmd=(act "${ACT_EVENT}" -W "${_act_workflow}")
|
cmd=(act "${ACT_EVENT}" -W "${_act_workflow}")
|
||||||
cmd+=(-P "ubuntu-latest=${ACT_PLATFORM_IMAGE}")
|
_act_workflows_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)/.github/workflows"
|
||||||
cmd+=(-P "ubuntu-24.04=${ACT_PLATFORM_IMAGE}")
|
while read -r _act_label; do
|
||||||
cmd+=(-P "ubuntu-22.04=${ACT_PLATFORM_IMAGE}")
|
cmd+=(-P "${_act_label}=${ACT_PLATFORM_IMAGE}")
|
||||||
cmd+=(-P "ubuntu-20.04=${ACT_PLATFORM_IMAGE}")
|
done < <(grep -rhE 'runs-on:' "${_act_workflows_dir}" | grep -oE 'ubuntu-[0-9]+\.[0-9]+' | sort -u)
|
||||||
|
|
||||||
if [[ -n "${ACT_JOB}" ]]; then
|
if [[ -n "${ACT_JOB}" ]]; then
|
||||||
cmd+=(-j "${ACT_JOB}")
|
cmd+=(-j "${ACT_JOB}")
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from utils.cache.files import read_text
|
||||||
|
from utils.update.runner import bump_text, bump_workflows, newest_ubuntu_label
|
||||||
|
|
||||||
|
_BADGE = "<br>"
|
||||||
|
_PREVIEW = "[](https://x)"
|
||||||
|
_README = "\n".join(
|
||||||
|
[
|
||||||
|
"| Image | Architecture | YAML Label | Included Software |",
|
||||||
|
"| --------------------|--------------|---------------------|------------------|",
|
||||||
|
f"| Ubuntu 28.04 {_PREVIEW}{_BADGE} | x64 | `ubuntu-28.04` | [ubuntu-28.04] |",
|
||||||
|
f"| Ubuntu 26.04{_BADGE} | x64 | `ubuntu-26.04` | [ubuntu-26.04] |",
|
||||||
|
f"| Ubuntu 26.04 Arm64{_BADGE} | arm64 | `ubuntu-26.04-arm` | [x] |",
|
||||||
|
f"| Ubuntu 24.04{_BADGE} | x64 | `ubuntu-latest` or `ubuntu-24.04` | [x] |",
|
||||||
|
f"| Ubuntu Slim{_BADGE} | x64 | `ubuntu-slim` | [ubuntu-slim] |",
|
||||||
|
f"| macOS 26 Arm64{_BADGE} | arm64 | `macos-26` | [macOS-26-arm64] |",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestNewestUbuntuLabel(unittest.TestCase):
|
||||||
|
def test_picks_newest_ga_x64_label(self) -> None:
|
||||||
|
self.assertEqual("ubuntu-26.04", newest_ubuntu_label(_README))
|
||||||
|
|
||||||
|
def test_none_without_an_ubuntu_row(self) -> None:
|
||||||
|
self.assertIsNone(newest_ubuntu_label("| Image | x |\n| macOS | arm64 |"))
|
||||||
|
|
||||||
|
|
||||||
|
class TestBumpText(unittest.TestCase):
|
||||||
|
def test_raises_older_and_keeps_newer(self) -> None:
|
||||||
|
text = (
|
||||||
|
"jobs:\n"
|
||||||
|
" a:\n runs-on: ubuntu-22.04\n"
|
||||||
|
" b:\n runs-on: ubuntu-24.04\n"
|
||||||
|
" c:\n runs-on: ubuntu-28.04\n"
|
||||||
|
" d:\n runs-on: ubuntu-24.04-arm\n"
|
||||||
|
"# runs on ubuntu-24.04 elsewhere\n"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
"jobs:\n"
|
||||||
|
" a:\n runs-on: ubuntu-26.04\n"
|
||||||
|
" b:\n runs-on: ubuntu-26.04\n"
|
||||||
|
" c:\n runs-on: ubuntu-28.04\n"
|
||||||
|
" d:\n runs-on: ubuntu-24.04-arm\n"
|
||||||
|
"# runs on ubuntu-24.04 elsewhere\n",
|
||||||
|
bump_text(text, "ubuntu-26.04"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBumpWorkflows(unittest.TestCase):
|
||||||
|
def test_rewrites_only_changed_files(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
|
root = Path(tmp)
|
||||||
|
(root / "old.yml").write_text("runs-on: ubuntu-24.04\n", encoding="utf-8")
|
||||||
|
(root / "new.yml").write_text("runs-on: ubuntu-26.04\n", encoding="utf-8")
|
||||||
|
|
||||||
|
changed = bump_workflows(root, "ubuntu-26.04")
|
||||||
|
|
||||||
|
self.assertEqual([root / "old.yml"], changed)
|
||||||
|
self.assertEqual(
|
||||||
|
"runs-on: ubuntu-26.04\n", read_text(str(root / "old.yml"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
"""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
|
||||||
Reference in new issue
Block a user