From 4d8adedec834fd3000575de4acf1d47b960c25c3 Mon Sep 17 00:00:00 2001 From: Peder Schmedling <24737456+Laffs2k5@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:08:32 +0200 Subject: [PATCH 1/2] feat(ci-cd)!: default runs-on to the GitHub-hosted runner The 'runs-on' input defaulted to an empty string, which each job resolved to the self-hosted pool ["self-hosted", "dsb-builder", "linux", "x64"] via a fromJSON fallback. That pool is being decommissioned, so the fallback is about to point at a runner group with no runners: a caller that omits the input would queue indefinitely instead of failing, with nothing in the run to explain why. Every caller in the org set the input explicitly during the migration (72/72 as of 2026-10-05), so flipping the default changes no existing pipeline. It does change what a *new* repo gets when it omits the line, which is the point. Remove the fromJSON fallback from all nine job-level expressions rather than re-point it, so the dead pool is not referenced anywhere. Per-app overrides via an 'apps' entry are unaffected and still win over the global input. BREAKING CHANGE: callers that relied on the empty default to reach the self-hosted pool must now pass runs-on explicitly. No such caller exists in dsb-norge; external consumers of this public repo could never have used the old default, since the pool was DSB-internal. Co-Authored-By: Claude Opus 5 --- .../ci-cd-build-deploy-maven-lib.yml | 24 ++++++++-------- .github/workflows/ci-cd-default.yml | 28 +++++++++---------- .github/workflows/maven-artifacts-pruner.yml | 16 +++++------ 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci-cd-build-deploy-maven-lib.yml b/.github/workflows/ci-cd-build-deploy-maven-lib.yml index f66b7d7e..a2d6160f 100644 --- a/.github/workflows/ci-cd-build-deploy-maven-lib.yml +++ b/.github/workflows/ci-cd-build-deploy-maven-lib.yml @@ -38,16 +38,16 @@ on: runs-on: type: string required: false - # Empty (default) = the historical self-hosted pool, kept inside the workflow as a fromJSON - # fallback so callers that don't set this are unaffected. Any non-empty value is used as-is - # (like the terraform actions), so opting in is just a plain string — no JSON. - default: "" + # Default = the GitHub-hosted larger runner. The self-hosted 'dsb-builder' pool is being + # decommissioned (every caller migrated by 2026-10), so there is deliberately no fallback + # to it any more: an unset input would otherwise queue forever against a pool with no + # runners. Any value is used as-is (like the terraform actions): a plain string, no JSON. + default: "builder-app-platform-ghr-ubuntu-large" description: | Global runner for all jobs, as a plain string: a single GitHub-hosted larger runner name - (matched by name), e.g. 'builder-app-platform-ghr-ubuntu-large'. Empty (default) uses the - self-hosted pool [self-hosted, dsb-builder, linux, x64]. Can be overridden per application - with a 'runs-on' field on an entry in 'apps'. The final 'ci-cd-conclusion' gate always - runs on ubuntu-latest. + (matched by name). Defaults to 'builder-app-platform-ghr-ubuntu-large'. Can be overridden + per application with a 'runs-on' field on an entry in 'apps'. The final + 'ci-cd-conclusion' gate always runs on ubuntu-latest. # below are repo-specific settings, not app specific and thus does not belong in 'apps' # for explanation of maven artifact pruning configuration see inputs of 'ci-cd/prune-maven-artifacts-in-repo/action.yml' # sane defaults are defined but can be overridden pr. repo @@ -79,7 +79,7 @@ on: jobs: create-matrix: name: Create build matrix - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash @@ -105,8 +105,8 @@ jobs: build-and-deploy: name: Build and deploy to artifact repo needs: create-matrix - # per-app 'runs-on' wins, else the global input, else the self-hosted default - runs-on: ${{ matrix.app-vars.runs-on || inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + # per-app 'runs-on' wins, else the global input (which has a default) + runs-on: ${{ matrix.app-vars.runs-on || inputs.runs-on }} strategy: matrix: ${{ fromJSON(needs.create-matrix.outputs.app-vars-matrix) }} defaults: @@ -262,7 +262,7 @@ jobs: && ( github.event_name != 'pull_request' || github.event.action == 'closed' ) needs: [create-matrix, build-and-deploy] - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash diff --git a/.github/workflows/ci-cd-default.yml b/.github/workflows/ci-cd-default.yml index e78f98c4..f3d1020b 100644 --- a/.github/workflows/ci-cd-default.yml +++ b/.github/workflows/ci-cd-default.yml @@ -44,16 +44,16 @@ on: runs-on: type: string required: false - # Empty (default) = the historical self-hosted pool, kept inside the workflow as a fromJSON - # fallback so callers that don't set this are unaffected. Any non-empty value is used as-is - # (like the terraform actions), so opting in is just a plain string — no JSON. - default: "" + # Default = the GitHub-hosted larger runner. The self-hosted 'dsb-builder' pool is being + # decommissioned (every caller migrated by 2026-10), so there is deliberately no fallback + # to it any more: an unset input would otherwise queue forever against a pool with no + # runners. Any value is used as-is (like the terraform actions): a plain string, no JSON. + default: "builder-app-platform-ghr-ubuntu-large" description: | Global runner for all jobs, as a plain string: a single GitHub-hosted larger runner name - (matched by name), e.g. 'builder-app-platform-ghr-ubuntu-large'. Empty (default) uses the - self-hosted pool [self-hosted, dsb-builder, linux, x64]. Can be overridden per application - with a 'runs-on' field on an entry in 'apps'. The final 'ci-cd-conclusion' gate always - runs on ubuntu-latest. + (matched by name). Defaults to 'builder-app-platform-ghr-ubuntu-large'. Can be overridden + per application with a 'runs-on' field on an entry in 'apps'. The final + 'ci-cd-conclusion' gate always runs on ubuntu-latest. # below are repo-specific settings, not app specific and thus does not belong in 'apps' # for explanation of maven artifact pruning configuration see inputs of 'ci-cd/prune-maven-artifacts-in-repo/action.yml' # sane defaults are defined but can be overridden pr. repo @@ -85,7 +85,7 @@ on: jobs: check-docker-disk-space: name: Check Docker Disk Space & Prune if Needed - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash @@ -105,7 +105,7 @@ jobs: create-matrix: name: Create build matrix needs: check-docker-disk-space - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash @@ -147,8 +147,8 @@ jobs: build-deploy: name: Build and deploy needs: create-matrix - # per-app 'runs-on' wins, else the global input, else the self-hosted default - runs-on: ${{ matrix.app-vars.runs-on || inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + # per-app 'runs-on' wins, else the global input (which has a default) + runs-on: ${{ matrix.app-vars.runs-on || inputs.runs-on }} strategy: matrix: ${{ fromJSON(needs.create-matrix.outputs.app-vars-matrix) }} fail-fast: false @@ -562,7 +562,7 @@ jobs: if: | (github.event_name == 'push' || github.event_name == 'workflow_dispatch' ) needs: [create-matrix, build-deploy] - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash @@ -640,7 +640,7 @@ jobs: && ( github.event_name != 'pull_request' || github.event.action == 'closed' ) needs: [create-matrix, build-deploy] - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash diff --git a/.github/workflows/maven-artifacts-pruner.yml b/.github/workflows/maven-artifacts-pruner.yml index 86ebe6e1..0cde1ce1 100644 --- a/.github/workflows/maven-artifacts-pruner.yml +++ b/.github/workflows/maven-artifacts-pruner.yml @@ -9,15 +9,15 @@ on: runs-on: type: string required: false - # Empty (default) = the historical self-hosted pool, kept inside the workflow as a fromJSON - # fallback so callers that don't set this are unaffected. Any non-empty value is used as-is - # (like the terraform actions), so opting in is just a plain string — no JSON. - default: "" + # Default = the GitHub-hosted larger runner. The self-hosted 'dsb-builder' pool is being + # decommissioned (every caller migrated by 2026-10), so there is deliberately no fallback + # to it any more: an unset input would otherwise queue forever against a pool with no + # runners. Any value is used as-is (like the terraform actions): a plain string, no JSON. + default: "builder-app-platform-ghr-ubuntu-large" description: | Runner for the prune job, as a plain string: a single GitHub-hosted larger runner name - (matched by name), e.g. 'builder-app-platform-ghr-ubuntu-large'. Empty (default) uses the - self-hosted pool [self-hosted, dsb-builder, linux, x64]. The 'ci-cd-conclusion' gate - always runs on ubuntu-latest. + (matched by name). Defaults to 'builder-app-platform-ghr-ubuntu-large'. The + 'ci-cd-conclusion' gate always runs on ubuntu-latest. # for explanation of maven artifact pruning configuration see inputs of 'ci-cd/prune-maven-artifacts-in-repo/action.yml' # sane defaults are defined but can be overridden pr. repo release-prune-keep-min-count: @@ -57,7 +57,7 @@ jobs: prune-maven-artifacts: name: Prune maven artifacts # This job handles pruning of maven artifacts published in the calling repo - runs-on: ${{ inputs.runs-on || fromJSON('["self-hosted", "dsb-builder", "linux", "x64"]') }} + runs-on: ${{ inputs.runs-on }} defaults: run: shell: bash From 7acf1f4206fd480905e5374c1280a2a0224b8831 Mon Sep 17 00:00:00 2001 From: Peder Schmedling <24737456+Laffs2k5@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:08:39 +0200 Subject: [PATCH 2/2] docs(claude): describe the GitHub-hosted runner as the default Keeps the AI-assistant context in step with the runs-on default flip. Separate commit because this is assistant configuration, not part of the functional change. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 09c206f1..3ebf20c9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,10 +67,10 @@ When developing changes that need to be tried from a real consumer repo, follow The reusable workflows assume: -- Self-hosted runners labeled `self-hosted, dsb-builder, linux, x64`. +- Jobs run on the GitHub-hosted larger runner `builder-app-platform-ghr-ubuntu-large` (the `runs-on` input's default). The self-hosted `dsb-builder` pool it replaced is being decommissioned; there is no fallback to it. - A GitHub App (`dsb-norge-cicd-access`) is installed in the caller org; `get-github-app-installation-token` mints an installation token from `ORG_CICD_APP_ID` / `ORG_CICD_APP_INSTALLATION_ID` / `ORG_CICD_APP_PRIVATE_KEY`. - Permissions required on the caller workflow are listed at the top of `.github/workflows/ci-cd-default.yml` and in `ci-cd/README.md`. -- Build provenance + CycloneDX SBOM attestations are produced for Docker images, Maven artifacts, and npm builds (see `ci-cd/README.md` → **Artifact attestation** for verification commands and the Sigstore endpoint list self-hosted runners need outbound 443 access to). +- Build provenance + CycloneDX SBOM attestations are produced for Docker images, Maven artifacts, and npm builds (see `ci-cd/README.md` → **Artifact attestation** for verification commands and the Sigstore endpoint list the runners need outbound 443 access to). ## Conventions worth knowing before editing