diff --git a/.github/workflows/docker-gradle-build-push.yml b/.github/workflows/docker-gradle-build-push.yml index e92aeee..3f76081 100644 --- a/.github/workflows/docker-gradle-build-push.yml +++ b/.github/workflows/docker-gradle-build-push.yml @@ -67,8 +67,10 @@ jobs: # Without this the `./gradlew -q properties` step below resolves the # whole dependency graph from scratch on every run — measured at ~98s # median in service-moderation, a third of the job, to read one - # version string. - cache: "gradle" + # 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' || '' }} - name: Configure GitHub Packages credentials run: | diff --git a/.github/workflows/gradle-ci.yml b/.github/workflows/gradle-ci.yml index a7007ff..bc94e26 100644 --- a/.github/workflows/gradle-ci.yml +++ b/.github/workflows/gradle-ci.yml @@ -57,10 +57,16 @@ jobs: with: distribution: "temurin" java-version: "25" - cache: "gradle" + # 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' || '' }} - name: Set up Gradle uses: gradle/actions/setup-gradle@v6 + with: + cache-disabled: ${{ runner.environment != 'github-hosted' }} - name: Configure GitHub Packages credentials run: | diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 2330e7d..51158ef 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -57,10 +57,16 @@ jobs: with: distribution: "temurin" java-version: "25" - cache: "gradle" + # 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' || '' }} - name: Set up Gradle uses: gradle/actions/setup-gradle@v6 + with: + cache-disabled: ${{ runner.environment != 'github-hosted' }} - name: Configure GitHub Packages credentials for resolution run: | diff --git a/tests/test_docker_workflow.py b/tests/test_docker_workflow.py index d9cf7f1..b378d0a 100644 --- a/tests/test_docker_workflow.py +++ b/tests/test_docker_workflow.py @@ -177,6 +177,23 @@ def test_every_central_workflow_routes_private_repos_to_the_shared_pool(self): self.assertEqual(missing, 'ubuntu-24.04') self.assertEqual(checked, 9, 'every repo-routed job should target the shared pool') + def test_gradle_caches_are_used_on_hosted_runners_only(self): + """From hbr1 the GHA cache stalled at 0 bytes and crawled at ~1 MB/s (2026-09-30). + + A literal `cache: gradle` would send every self-hosted job back through it, so each + Gradle job must gate setup-java's cache -- and setup-gradle's -- on the runner. + """ + for name in ['gradle-ci.yml', 'gradle-publish.yml', 'docker-gradle-build-push.yml']: + job = next(iter(yaml.safe_load((WORKFLOW.parent / name).read_text())['jobs'].values())) + for step in job['steps']: + uses, with_ = step.get('uses', ''), step.get('with', {}) + with self.subTest(workflow=name, step=uses): + if uses.startswith('actions/setup-java'): + self.assertIn('runner.environment', str(with_['cache'])) + self.assertNotEqual(with_['cache'], 'gradle') + if uses.startswith('gradle/actions/setup-gradle'): + self.assertIn('runner.environment', str(with_['cache-disabled'])) + def test_runner_override_and_missing_event_payload(self): job = yaml.safe_load(WORKFLOW.read_text())['jobs']['docker-build-push'] context = {'inputs.runner': '', 'github.event.repository.visibility': '', 'github.event.repository.name': ''}