From 9ad81de56a6c1cfeb9ed52a24e1b1235c3af604f Mon Sep 17 00:00:00 2001 From: Markus Becker Date: Thu, 16 Jul 2026 11:54:40 +0200 Subject: [PATCH 1/2] chore: skip SonarQube scan when Tailscale bring-up fails [CPONETOPS-1078] Follow-up to #320. Making the Tailscale step continue-on-error stops it from failing the job, but the SonarQube step then still ran against a dead VPN, failing ~30s later and logging a confusing error (job passed, but noisily). Gate the Sonar step on the Tailscale step's outcome so a failed VPN bring-up skips the scan entirely instead of running it doomed. Using `outcome != 'failure'` (rather than `== 'success'`) keeps the SonarCloud path working when Tailscale is skipped because no TAILSCALE_AUTHKEY is passed. Applied to both pull-request-kotlin.yml and sonar-cloud.yml. With sonar-non-blocking: false the Tailscale failure still hard-fails the job (the scan is a required gate, so an unreachable SonarQube should block). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_0134BvmGHE9QM5zwSAzfJJUv --- .github/workflows/pull-request-kotlin.yml | 6 +++++- .github/workflows/sonar-cloud.yml | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-kotlin.yml b/.github/workflows/pull-request-kotlin.yml index 3e29803..9c41cfa 100644 --- a/.github/workflows/pull-request-kotlin.yml +++ b/.github/workflows/pull-request-kotlin.yml @@ -195,6 +195,7 @@ jobs: # needs to join the tailnet before the scan step can reach it. Skipped # automatically for repos still on SonarCloud (no TAILSCALE_AUTHKEY passed). - name: Tailscale + id: tailscale if: ${{ !inputs.skip-sonar && env.TAILSCALE_AUTHKEY != '' }} continue-on-error: ${{ inputs.sonar-non-blocking }} uses: tailscale/github-action@6cae46e2d796f265265cfcf628b72a32b4d7cade # v3.3.0 @@ -202,8 +203,11 @@ jobs: authkey: ${{ env.TAILSCALE_AUTHKEY }} hostname: "github-${{ github.run_id }}" args: "--login-server https://headscale.monta.com --accept-routes" + # != 'failure' (not == 'success') so the SonarCloud path still runs when + # Tailscale is skipped (no TAILSCALE_AUTHKEY); only a failed VPN bring-up, + # which leaves SonarQube unreachable, skips the scan. - name: Upload results to SonarQube - if: ${{ !inputs.skip-sonar }} + if: ${{ !inputs.skip-sonar && steps.tailscale.outcome != 'failure' }} continue-on-error: ${{ inputs.sonar-non-blocking }} env: GHL_USERNAME: ${{ secrets.GHL_USERNAME }} diff --git a/.github/workflows/sonar-cloud.yml b/.github/workflows/sonar-cloud.yml index 9aa4e2a..03710fd 100644 --- a/.github/workflows/sonar-cloud.yml +++ b/.github/workflows/sonar-cloud.yml @@ -101,6 +101,7 @@ jobs: # needs to join the tailnet before the scan step can reach it. Skipped # automatically for repos still on SonarCloud (no TAILSCALE_AUTHKEY passed). - name: Tailscale + id: tailscale if: ${{ env.TAILSCALE_AUTHKEY != '' }} continue-on-error: ${{ inputs.sonar-non-blocking }} uses: tailscale/github-action@6cae46e2d796f265265cfcf628b72a32b4d7cade # v3.3.0 @@ -117,7 +118,11 @@ jobs: gradle-module: ${{ inputs.gradle-module }} gradle-tasks: 'test koverXmlReport' gradle-args: ${{ inputs.gradle-args }} + # != 'failure' (not == 'success') so the SonarCloud path still runs when + # Tailscale is skipped (no TAILSCALE_AUTHKEY); only a failed VPN bring-up, + # which leaves SonarQube unreachable, skips the scan. - name: Analyze with SonarQube + if: ${{ steps.tailscale.outcome != 'failure' }} continue-on-error: ${{ inputs.sonar-non-blocking }} env: GHL_USERNAME: ${{ secrets.GHL_USERNAME }} From c21aa27959ad582a45f392b8140d4f1978c86a7e Mon Sep 17 00:00:00 2001 From: Markus Becker Date: Thu, 16 Jul 2026 11:55:45 +0200 Subject: [PATCH 2/2] chore: trim comments on Sonar skip condition Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_0134BvmGHE9QM5zwSAzfJJUv --- .github/workflows/pull-request-kotlin.yml | 4 +--- .github/workflows/sonar-cloud.yml | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pull-request-kotlin.yml b/.github/workflows/pull-request-kotlin.yml index 9c41cfa..776a32d 100644 --- a/.github/workflows/pull-request-kotlin.yml +++ b/.github/workflows/pull-request-kotlin.yml @@ -203,9 +203,7 @@ jobs: authkey: ${{ env.TAILSCALE_AUTHKEY }} hostname: "github-${{ github.run_id }}" args: "--login-server https://headscale.monta.com --accept-routes" - # != 'failure' (not == 'success') so the SonarCloud path still runs when - # Tailscale is skipped (no TAILSCALE_AUTHKEY); only a failed VPN bring-up, - # which leaves SonarQube unreachable, skips the scan. + # != 'failure' (not == 'success') keeps the SonarCloud path when Tailscale is skipped. - name: Upload results to SonarQube if: ${{ !inputs.skip-sonar && steps.tailscale.outcome != 'failure' }} continue-on-error: ${{ inputs.sonar-non-blocking }} diff --git a/.github/workflows/sonar-cloud.yml b/.github/workflows/sonar-cloud.yml index 03710fd..d48af03 100644 --- a/.github/workflows/sonar-cloud.yml +++ b/.github/workflows/sonar-cloud.yml @@ -118,9 +118,7 @@ jobs: gradle-module: ${{ inputs.gradle-module }} gradle-tasks: 'test koverXmlReport' gradle-args: ${{ inputs.gradle-args }} - # != 'failure' (not == 'success') so the SonarCloud path still runs when - # Tailscale is skipped (no TAILSCALE_AUTHKEY); only a failed VPN bring-up, - # which leaves SonarQube unreachable, skips the scan. + # != 'failure' (not == 'success') keeps the SonarCloud path when Tailscale is skipped. - name: Analyze with SonarQube if: ${{ steps.tailscale.outcome != 'failure' }} continue-on-error: ${{ inputs.sonar-non-blocking }}