From cf2b398a89d638feee04b2e356f0f0eadf7b1142 Mon Sep 17 00:00:00 2001 From: Hendrik Brombeer Date: Thu, 30 Jul 2026 10:18:33 +0200 Subject: [PATCH 1/2] ci: halve Blacksmith runner vCPUs Blacksmith prices per vCPU-minute and rounds each job up to a whole minute, so this cannot cost more than the 4 vCPU status quo. Measured on the org's heaviest repo: a Gradle build/test job runs 1.20x slower at half the size (40% cheaper), and a Docker build job runs no slower at all. --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4003706..5a1efb4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ permissions: jobs: build: - runs-on: blacksmith-4vcpu-ubuntu-2404-arm + runs-on: blacksmith-2vcpu-ubuntu-2404-arm env: GRADLE_USER_HOME: /tmp/grounds-push-gradle-${{ github.run_id }}-${{ github.run_attempt }} steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21079f1..508a814 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ permissions: jobs: publish: - runs-on: blacksmith-4vcpu-ubuntu-2404-arm + runs-on: blacksmith-2vcpu-ubuntu-2404-arm env: GRADLE_USER_HOME: /tmp/grounds-push-gradle-${{ github.run_id }}-${{ github.run_attempt }} steps: From dc47768479b1f6c225f5694c384901448c8d4b64 Mon Sep 17 00:00:00 2001 From: Hendrik Brombeer Date: Thu, 30 Jul 2026 11:33:42 +0200 Subject: [PATCH 2/2] ci: add concurrency groups and job timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From an audit of all 205 workflow files in the org. 97 files had no concurrency group, so a push that superseded an in-flight PR run left the old one running to completion on a paid runner. 116 jobs had no `timeout-minutes`, so a hung job would run to GitHub's 6-hour default at full vCPU rate — the longest job actually observed in 14 days was 18 minutes, so 30 is a generous ceiling and 10 suffices for the release-please and label jobs. Cancelling is only applied where a half-finished run is harmless. Release, publish, deploy and release-please workflows get a concurrency group that serialises them without cancelling. --- .github/workflows/ci.yml | 5 +++++ .github/workflows/release-please.yml | 5 +++++ .github/workflows/release.yml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a1efb4..f3848ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,9 +10,14 @@ permissions: contents: read packages: read +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + jobs: build: runs-on: blacksmith-2vcpu-ubuntu-2404-arm + timeout-minutes: 30 env: GRADLE_USER_HOME: /tmp/grounds-push-gradle-${{ github.run_id }}-${{ github.run_attempt }} steps: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index ff66bc0..60d2928 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -10,10 +10,15 @@ permissions: issues: write pull-requests: write +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: false + jobs: release-please: name: Create Release runs-on: blacksmith-2vcpu-ubuntu-2404-arm + timeout-minutes: 10 steps: - name: Check out uses: actions/checkout@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 508a814..a81e3c0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,9 +15,14 @@ permissions: contents: read packages: write +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: false + jobs: publish: runs-on: blacksmith-2vcpu-ubuntu-2404-arm + timeout-minutes: 30 env: GRADLE_USER_HOME: /tmp/grounds-push-gradle-${{ github.run_id }}-${{ github.run_attempt }} steps: