diff --git a/.github/workflows/docker-gradle-build-push.yml b/.github/workflows/docker-gradle-build-push.yml index 8e59f1d..1e639af 100644 --- a/.github/workflows/docker-gradle-build-push.yml +++ b/.github/workflows/docker-gradle-build-push.yml @@ -36,14 +36,15 @@ jobs: # happened to grounds-forge 4.3.0 in its migrate init container. Building # an amd64 image on an arm64 runner would mean QEMU for the whole build. # Public fork PRs remain on GitHub-hosted runners; private repositories - # use the shared self-hosted pool `grounds-runners` (org-level ARC; the - # org's Default runner group refuses public repositories). Missing + # use RunsOn, an ephemeral 4 vCPU / 16 GB spot instance in our AWS account + # (eu-central-1). Missing # repository payloads safely fall back to GitHub-hosted. runs-on: >- ${{ inputs.runner != '' && inputs.runner || (github.event.repository.visibility == 'public' && 'ubuntu-24.04') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=4/ram=16/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64/extras=s3-cache', github.run_id)) || 'ubuntu-24.04' }} # Cold ARC builds can exceed 30m downloading builder/runtime base images # even after Gradle succeeds. Keep the default repo-ARC path bounded at @@ -56,6 +57,13 @@ jobs: env: TAG_TYPE: ${{ github.ref_type == 'tag' && 'release' || 'edge' }} steps: + # RunsOn (AWS) runners: routes the Actions cache, and with it the Buildx + # `type=gha` layer cache, to RunsOn's S3-backed Magic Cache. Needs + # `extras=s3-cache` in the runner label. + - name: Enable RunsOn Magic Cache + if: startsWith(runner.name, 'runs-on--') + uses: runs-on/action@v2 + - name: Checkout uses: actions/checkout@v7 @@ -69,8 +77,9 @@ jobs: # median in service-moderation, a third of the job, to read one # version string. Hosted runners only: from the self-hosted ARC runners # the GitHub Actions cache stalled at 0 bytes for minutes and crawled at - # ~1 MB/s (2026-09-30), slower than resolving from scratch. - cache: ${{ runner.environment == 'github-hosted' && 'gradle' || '' }} + # ~1 MB/s (2026-09-30), slower than resolving from scratch. RunsOn runners + # use it through the Magic Cache. + cache: ${{ (runner.environment == 'github-hosted' || startsWith(runner.name, 'runs-on--')) && 'gradle' || '' }} - name: Configure GitHub Packages credentials run: | @@ -108,7 +117,8 @@ jobs: echo "DOCKER_CONFIG=${docker_config}" >> "$GITHUB_ENV" # Where BuildKit keeps its layer cache, decided on the runner: - # - GitHub-hosted: the repository-scoped GHA cache. + # - GitHub-hosted, or RunsOn with its Magic Cache: the repository-scoped + # GHA cache. # - self-hosted with BUILDKIT_CACHE_REGISTRY: that registry. The hbr1 ARC # runners advertise one next to them (plain HTTP, cluster-internal), # the same way they advertise GRADLE_BUILD_CACHE_URL. The GHA cache is @@ -123,7 +133,7 @@ jobs: set -euo pipefail repo="${GITHUB_REPOSITORY#*/}" from=""; to=""; config="" - if [ "${RUNNER_ENVIRONMENT:-}" = "github-hosted" ]; then + if [ "${RUNNER_ENVIRONMENT:-}" = "github-hosted" ] || [[ "${RUNNER_NAME:-}" == runs-on--* ]]; then from="type=gha,scope=${GITHUB_REPOSITORY}-amd64" to="type=gha,scope=${GITHUB_REPOSITORY}-amd64,mode=max" elif [ -n "${BUILDKIT_CACHE_REGISTRY:-}" ]; then diff --git a/.github/workflows/gradle-ci.yml b/.github/workflows/gradle-ci.yml index b4fe9b3..fa86571 100644 --- a/.github/workflows/gradle-ci.yml +++ b/.github/workflows/gradle-ci.yml @@ -7,10 +7,10 @@ on: description: > Runner label. Leave unset and the job picks one by repository visibility: GitHub's arm64 hosted runner in public repos, where it - is free and has 4 vCPUs, and the shared self-hosted `grounds-runners` - pool (amd64) in private repos, where GitHub-hosted arm64 is not - offered. Set it explicitly to override, e.g. `grounds-runners-large` - for a build that needs more memory than the shared pool gives. + is free and has 4 vCPUs, and a RunsOn spot instance (amd64, 4 vCPU, + 16 GB) in private repos, where GitHub-hosted arm64 is not offered. + Set it explicitly to override, e.g. a RunsOn label with + `cpu=8/ram=32` for a build that needs more memory. required: false type: string default: "" @@ -33,11 +33,10 @@ concurrency: jobs: build: # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. @@ -45,10 +44,17 @@ jobs: ${{ inputs.runner != '' && inputs.runner || (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=4/ram=16/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64/extras=s3-cache', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 30 steps: + # RunsOn (AWS) runners: routes the Actions cache to RunsOn's S3-backed + # Magic Cache. Needs `extras=s3-cache` in the runner label. + - name: Enable RunsOn Magic Cache + if: startsWith(runner.name, 'runs-on--') + uses: runs-on/action@v2 + - name: Check out uses: actions/checkout@v7 @@ -60,13 +66,14 @@ jobs: # The GitHub Actions cache is a Azure-hosted download: from the self-hosted # runners on hbr1 it stalled at 0 bytes for minutes and crawled at ~1 MB/s # (2026-09-30), slower than resolving the dependencies from scratch. Hosted - # runners keep it; self-hosted ones use the Gradle build cache node. - cache: ${{ runner.environment == 'github-hosted' && 'gradle' || '' }} + # runners keep it; other self-hosted ones use the Gradle build cache node. + # RunsOn runners use the Actions cache through the Magic Cache. + cache: ${{ (runner.environment == 'github-hosted' || startsWith(runner.name, 'runs-on--')) && 'gradle' || '' }} - name: Set up Gradle uses: gradle/actions/setup-gradle@v6 with: - cache-disabled: ${{ runner.environment != 'github-hosted' }} + cache-disabled: ${{ runner.environment != 'github-hosted' && !startsWith(runner.name, 'runs-on--') }} - name: Use the Maven mirror uses: groundsgg/.github/.github/actions/maven-mirror@main diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 3740421..aaf6fbf 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -7,10 +7,10 @@ on: description: > Runner label. Leave unset and the job picks one by repository visibility: GitHub's arm64 hosted runner in public repos, where it - is free and has 4 vCPUs, and the shared self-hosted `grounds-runners` - pool (amd64) in private repos, where GitHub-hosted arm64 is not - offered. Set it explicitly to override, e.g. `grounds-runners-large` - for a build that needs more memory than the shared pool gives. + is free and has 4 vCPUs, and a RunsOn spot instance (amd64, 4 vCPU, + 16 GB) in private repos, where GitHub-hosted arm64 is not offered. + Set it explicitly to override, e.g. a RunsOn label with + `cpu=8/ram=32` for a build that needs more memory. required: false type: string default: "" @@ -33,11 +33,10 @@ concurrency: jobs: release: # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. @@ -45,10 +44,17 @@ jobs: ${{ inputs.runner != '' && inputs.runner || (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=4/ram=16/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64/extras=s3-cache', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 30 steps: + # RunsOn (AWS) runners: routes the Actions cache to RunsOn's S3-backed + # Magic Cache. Needs `extras=s3-cache` in the runner label. + - name: Enable RunsOn Magic Cache + if: startsWith(runner.name, 'runs-on--') + uses: runs-on/action@v2 + - name: Checkout uses: actions/checkout@v7 @@ -61,12 +67,13 @@ jobs: # runners on hbr1 it stalled at 0 bytes for minutes and crawled at ~1 MB/s # (2026-09-30), slower than resolving the dependencies from scratch. Hosted # runners keep it; self-hosted ones use the Gradle build cache node. - cache: ${{ runner.environment == 'github-hosted' && 'gradle' || '' }} + # RunsOn runners use the Actions cache through the Magic Cache. + cache: ${{ (runner.environment == 'github-hosted' || startsWith(runner.name, 'runs-on--')) && 'gradle' || '' }} - name: Set up Gradle uses: gradle/actions/setup-gradle@v6 with: - cache-disabled: ${{ runner.environment != 'github-hosted' }} + cache-disabled: ${{ runner.environment != 'github-hosted' && !startsWith(runner.name, 'runs-on--') }} - name: Use the Maven mirror uses: groundsgg/.github/.github/actions/maven-mirror@main diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml index 18b1f05..553502c 100644 --- a/.github/workflows/label-sync.yml +++ b/.github/workflows/label-sync.yml @@ -9,24 +9,24 @@ concurrency: jobs: sync-labels: - # Free GitHub-hosted runner in public repos; `grounds-runners` in private ones, + # Free GitHub-hosted runner in public repos; a small RunsOn instance in private ones, # where GitHub-hosted arm64 is not offered. Tests `visibility` rather than # `repository.private` because GitHub coerces `==` operands to numbers, so # an absent `private` field would compare equal to false and hand a private # repo a label that does not exist there. # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=2/ram=8/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 10 steps: diff --git a/.github/workflows/platform-test-preview-slashcmd.yml b/.github/workflows/platform-test-preview-slashcmd.yml index d935228..faa3984 100644 --- a/.github/workflows/platform-test-preview-slashcmd.yml +++ b/.github/workflows/platform-test-preview-slashcmd.yml @@ -53,18 +53,18 @@ jobs: # here because reusable workflows shouldn't trust their callers. if: github.event.issue.pull_request != null # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=2/ram=8/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 10 permissions: diff --git a/.github/workflows/platform-test-preview.yml b/.github/workflows/platform-test-preview.yml index f7d8d29..61b9ee8 100644 --- a/.github/workflows/platform-test-preview.yml +++ b/.github/workflows/platform-test-preview.yml @@ -82,12 +82,13 @@ jobs: # amd64 on purpose: the preview image is deployed onto the amd64 UKS # node pools. An arm64-only image pulls fine and then dies at exec with # "exec format error". Building amd64 on an arm64 runner would mean QEMU. - # Keep public PRs on hosted runners and private repositories on ARC. + # Keep public PRs on hosted runners and private repositories on RunsOn. # Missing event payloads fall back to a hosted runner, not Blacksmith. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=4/ram=16/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64/extras=s3-cache', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 30 outputs: @@ -97,6 +98,10 @@ jobs: packages: write id-token: write steps: + # RunsOn: routes the Buildx `type=gha` cache to the S3-backed Magic Cache. + - name: Enable RunsOn Magic Cache + if: startsWith(runner.name, 'runs-on--') + uses: runs-on/action@v2 - uses: actions/checkout@v7 with: ref: ${{ github.event.pull_request.head.sha }} @@ -185,18 +190,18 @@ jobs: if: github.event.action != 'closed' needs: build # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=2/ram=8/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 20 permissions: @@ -398,18 +403,18 @@ jobs: evict: if: github.event.action == 'closed' # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=2/ram=8/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 10 steps: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 6579baf..7f10ef8 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -14,24 +14,24 @@ concurrency: jobs: release-please: name: Create Release - # Free GitHub-hosted runner in public repos; `grounds-runners` in private ones, + # Free GitHub-hosted runner in public repos; a small RunsOn instance in private ones, # where GitHub-hosted arm64 is not offered. Tests `visibility` rather than # `repository.private` because GitHub coerces `==` operands to numbers, so # an absent `private` field would compare equal to false and hand a private # repo a label that does not exist there. # Read the three branches in order. A public repo keeps a GitHub-hosted - # runner: on a self-hosted pool a fork PR would run arbitrary code on - # hbr1, which also hosts production containers (the org's Default runner - # group refuses public repositories as a second line). A private repo goes - # to `grounds-runners`, the shared self-hosted ARC pool (org-level, on - # hbr1 today). And if `repository` is missing from the event payload, the + # runner: on a self-hosted runner a fork PR would run arbitrary code on + # our own infrastructure. A private repo goes to RunsOn, an ephemeral + # spot instance (m8a, m7a or m8i) in our AWS account (eu-central-1), sized per job in + # the label. And if `repository` is missing from the event payload, the # job lands on hosted amd64 `ubuntu-24.04`, which exists for public and # private repos alike -- hosted arm64 does not exist for private ones, and # a label no runner matches queues until someone cancels the job. runs-on: >- ${{ (github.event.repository.visibility == 'public' && 'ubuntu-24.04-arm') - || (github.event.repository.name && 'grounds-runners') + || (github.event.repository.name + && format('runs-on={0}/cpu=2/ram=8/family=m8a+m7a+m8i/spot=capacity-optimized/image=ubuntu24-full-x64', github.run_id)) || 'ubuntu-24.04' }} timeout-minutes: 10 steps: