From c097dda3f4ed73a6cdb2b28fb2d04c5a833994af Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Tue, 16 Jun 2026 05:17:30 -0400 Subject: [PATCH] Default test legs to GitHub-hosted (pin ubuntu-24.04, not ubuntu-latest) The SciML self-hosted pool (demeter*/arctic*, ephemeral *-cxnps-*) is registered with the custom label `ubuntu-latest`, the same label GitHub-hosted runners answer. So every default test leg that requests `ubuntu-latest` is a coin-flip between GitHub-hosted and self-hosted scheduling. The persistent demeter*/arctic* runners lack passwordless sudo, so the apt-packages provisioning step (`sudo apt-get`) intermittently fails with "sudo: a terminal is required to read the password" whenever a leg lands on one of them (ChrisRackauckas/InternalJunk#52). Evidence: across 205 jobs in 4 recent OrdinaryDiffEq.jl runs (CI / Sublibrary CI / Downgrade / Downgrade Sublibraries), `ubuntu-latest` was answered by BOTH github-hosted runners (runner group "GitHub Actions") AND self-hosted runners (demeter*/arctic*/*-cxnps-*, group "default"). The self-hosted runners' only assigned labels are {self-hosted, Linux, X64, gpu, high-memory, ubuntu-latest} -- none carry the pinned `ubuntu-24.04`/`ubuntu-22.04` labels. A github-hosted job's setup log shows `ubuntu-latest` currently resolves to image `ubuntu-24.04`, so pinning to `ubuntu-24.04` keeps the identical environment while removing the self-hosted pool from the candidate set. Change: set the DEFAULT test-leg runner to the pinned `ubuntu-24.04` label, which only GitHub-hosted runners answer, forcing default legs onto GitHub-hosted (where `sudo apt-get` works via passwordless sudo). Applied to the per-group `runner` default in compute_affected_sublibraries.jl (the source for grouped-tests.yml / sublibrary-project-tests.yml matrices), the `os` default in tests.yml and downgrade.yml, and the hardcoded `runs-on` in sublibrary-downgrade.yml plus the detect/discover helper jobs. GPU / self-hosted groups are intentionally PRESERVED: any group that sets an explicit `runner` (e.g. ["self-hosted","Linux","X64","gpu"]) in its test_groups.toml overrides the default and is left untouched; the OS-axis overrides (os = ["ubuntu-latest", ...]) are likewise unchanged. Needs a v1 retag to take effect fleet-wide. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/downgrade.yml | 4 ++-- .github/workflows/grouped-tests.yml | 4 +++- .github/workflows/sublibrary-downgrade.yml | 9 +++++++-- .github/workflows/sublibrary-project-tests.yml | 4 +++- .github/workflows/tests.yml | 4 ++-- scripts/compute_affected_sublibraries.jl | 16 ++++++++++++---- test/runtests.jl | 7 +++++-- 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/.github/workflows/downgrade.yml b/.github/workflows/downgrade.yml index a2fe16c..abbbf3a 100644 --- a/.github/workflows/downgrade.yml +++ b/.github/workflows/downgrade.yml @@ -39,8 +39,8 @@ on: required: false type: boolean os: - description: "The machine configuration on which the job needs to be run" - default: "ubuntu-latest" + description: "The machine configuration on which the job needs to be run. Defaults to the pinned label ubuntu-24.04 (NOT ubuntu-latest) so the downgrade leg lands on a GitHub-hosted runner: the SciML self-hosted demeter*/arctic* pool squats the ubuntu-latest label, but not the pinned ubuntu-24.04 label, so pinning forces GitHub-hosted (which has passwordless sudo for apt-packages provisioning)." + default: "ubuntu-24.04" required: false type: string apt-packages: diff --git a/.github/workflows/grouped-tests.yml b/.github/workflows/grouped-tests.yml index f1fd8e6..cd8cc65 100644 --- a/.github/workflows/grouped-tests.yml +++ b/.github/workflows/grouped-tests.yml @@ -77,7 +77,9 @@ on: jobs: detect: - runs-on: ubuntu-latest + # Pinned label ubuntu-24.04 (NOT ubuntu-latest) forces GitHub-hosted; the + # self-hosted demeter*/arctic* pool squats ubuntu-latest but not this label. + runs-on: ubuntu-24.04 outputs: matrix: ${{ steps.compute.outputs.matrix }} steps: diff --git a/.github/workflows/sublibrary-downgrade.yml b/.github/workflows/sublibrary-downgrade.yml index 28a6128..defe185 100644 --- a/.github/workflows/sublibrary-downgrade.yml +++ b/.github/workflows/sublibrary-downgrade.yml @@ -50,7 +50,9 @@ on: jobs: discover: - runs-on: ubuntu-latest + # Pinned label ubuntu-24.04 (NOT ubuntu-latest) forces GitHub-hosted; the + # self-hosted demeter*/arctic* pool squats ubuntu-latest but not this label. + runs-on: ubuntu-24.04 outputs: projects: ${{ steps.list.outputs.projects }} has_any: ${{ steps.list.outputs.has_any }} @@ -89,8 +91,11 @@ jobs: test: needs: discover + # Pinned label ubuntu-24.04 (NOT ubuntu-latest) forces GitHub-hosted: the + # self-hosted demeter*/arctic* pool squats ubuntu-latest but not the pinned + # label, and GitHub-hosted has passwordless sudo for apt-packages. if: needs.discover.outputs.has_any == 'true' - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 container: ${{ inputs.container }} strategy: fail-fast: false diff --git a/.github/workflows/sublibrary-project-tests.yml b/.github/workflows/sublibrary-project-tests.yml index 0a1190a..1718762 100644 --- a/.github/workflows/sublibrary-project-tests.yml +++ b/.github/workflows/sublibrary-project-tests.yml @@ -69,7 +69,9 @@ on: jobs: detect: - runs-on: ubuntu-latest + # Pinned label ubuntu-24.04 (NOT ubuntu-latest) forces GitHub-hosted; the + # self-hosted demeter*/arctic* pool squats ubuntu-latest but not this label. + runs-on: ubuntu-24.04 outputs: matrix: ${{ steps.compute.outputs.matrix }} has_changes: ${{ steps.compute.outputs.has_changes }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 15fb960..a8f018d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,8 +33,8 @@ on: required: false type: boolean os: - description: "The machine configuration on which the job needs to be run" - default: "ubuntu-latest" + description: "The machine configuration on which the job needs to be run. Defaults to the pinned label ubuntu-24.04 (NOT ubuntu-latest) so default legs land on GitHub-hosted runners: the SciML self-hosted demeter*/arctic* pool squats the ubuntu-latest label, but not the pinned ubuntu-24.04 label, so pinning forces GitHub-hosted (which has passwordless sudo for apt-packages provisioning). Pass a self-hosted label array via `runner` to opt back into self-hosted (e.g. GPU groups)." + default: "ubuntu-24.04" required: false type: string cache: diff --git a/scripts/compute_affected_sublibraries.jl b/scripts/compute_affected_sublibraries.jl index 7fb18dc..cf96f59 100644 --- a/scripts/compute_affected_sublibraries.jl +++ b/scripts/compute_affected_sublibraries.jl @@ -21,7 +21,15 @@ # runner = ["self-hosted", "Linux", "X64", "gpu"] # # Optional fields per group: -# runner — string or array of labels (default: "ubuntu-latest") +# runner — string or array of labels (default: "ubuntu-24.04"). The +# default is the PINNED ubuntu-24.04 label (NOT ubuntu-latest) +# so default groups (Core/QA/…) land on GitHub-hosted runners: +# the SciML self-hosted demeter*/arctic* pool squats the +# ubuntu-latest label but not the pinned ubuntu-24.04 label, so +# pinning forces GitHub-hosted (which has passwordless sudo for +# apt provisioning). A group that needs self-hosted (e.g. GPU) +# sets `runner` explicitly to a self-hosted label array, which +# overrides this default and is preserved unchanged. # os — array of OS runners for an OS matrix (root matrix only; the # group runs once per OS, e.g. ["ubuntu-latest","windows-latest", # "macos-latest"]). Empty -> use `runner`. Don't combine with a @@ -153,7 +161,7 @@ end function parse_test_group(config::AbstractDict) versions = convert(Vector{String}, config["versions"]) - runner_raw = get(config, "runner", "ubuntu-latest") + runner_raw = get(config, "runner", "ubuntu-24.04") runner = runner_raw isa Vector ? convert(Vector{String}, runner_raw) : runner_raw::String timeout = Int(get(config, "timeout", 120)) num_threads = Int(get(config, "num_threads", 1)) @@ -170,7 +178,7 @@ function load_test_groups(lib_dir::String, pkg::String) return Dict{String, TestGroupConfig}(name => parse_test_group(config) for (name, config) in toml) end return Dict{String, TestGroupConfig}( - k => TestGroupConfig(v, "ubuntu-latest", 120, 1, false, false, String[]) for (k, v) in DEFAULT_TEST_GROUPS + k => TestGroupConfig(v, "ubuntu-24.04", 120, 1, false, false, String[]) for (k, v) in DEFAULT_TEST_GROUPS ) end @@ -192,7 +200,7 @@ function load_root_test_groups(repo_root::String) isempty(groups) || return groups end return Dict{String, TestGroupConfig}( - k => TestGroupConfig(v, "ubuntu-latest", 120, 1, false, false, String[]) for (k, v) in DEFAULT_ROOT_GROUPS + k => TestGroupConfig(v, "ubuntu-24.04", 120, 1, false, false, String[]) for (k, v) in DEFAULT_ROOT_GROUPS ) end diff --git a/test/runtests.jl b/test/runtests.jl index 0b042f5..1af3a05 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -177,6 +177,9 @@ end @test Set((e.group, e.version) for e in build_root_matrix(d)) == Set([("Core", "lts"), ("Core", "1"), ("Core", "pre")]) @test all(e -> e.continue_on_error == false, build_root_matrix(d)) + # Default runner is the pinned GitHub-hosted label (forces GitHub-hosted off + # the self-hosted pool that squats ubuntu-latest), NOT ubuntu-latest. + @test all(e -> e.runner == "ubuntu-24.04", build_root_matrix(d)) mkpath(joinpath(d, "test")) write( @@ -236,9 +239,9 @@ end @test length(core) == 6 @test Set((e.version, e.runner) for e in core) == Set((v, o) for v in ["lts", "1"] for o in ["ubuntu-latest", "windows-latest", "macos-latest"]) - # QA: no os -> single default ubuntu runner. + # QA: no os -> single default GitHub-hosted runner (pinned ubuntu-24.04). qa = filter(e -> e.group == "QA", m) - @test length(qa) == 1 && only(qa).runner == "ubuntu-latest" + @test length(qa) == 1 && only(qa).runner == "ubuntu-24.04" # GPU: custom runner, no OS fan-out. gpu = filter(e -> e.group == "GPU", m) @test length(gpu) == 1 && only(gpu).runner == ["self-hosted", "Linux", "X64", "gpu"]