From d08ff8209f5027a9bb04bbe3980c5ce8779208fc Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 29 Apr 2026 14:49:25 +0200 Subject: [PATCH 1/4] ci(workflows): open SSH breakpoint on E2E failure for debug-labeled PRs When a PR carries the `debug` label and the E2E job fails, pause the workflow and expose an SSH endpoint via the self-hosted breakpoint rendezvous server. Maintainers can attach to the live sandbox to inspect Talos and Cozystack state before teardown. Inspired by squat/kilo's CI setup. Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index d9898616..e669d42f 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -313,6 +313,17 @@ jobs: name: image-list path: /tmp/${{ env.SANDBOX_NAME }}/_out/images.txt + # ▸ Open an SSH breakpoint to the failing sandbox (opt-in via `debug` label). + # Maintainers can SSH into the live runner, inspect Talos/Cozystack state + # and resume the workflow with `breakpoint resume`. Times out after 30m. + - name: Breakpoint on E2E failure + if: failure() && contains(github.event.pull_request.labels.*.name, 'debug') + uses: namespacelabs/breakpoint-action@v0 + with: + duration: 30m + endpoint: 158.101.126.45:5000 + authorized-users: kvaps, gecube, kingdonb, lllamnyp, aobort, tym83, klinch0, nbykov0, matthieu-robin, mattia-eleuteri + # ▸ Tear down environment (always runs) - name: Tear down sandbox if: always() From 39d8ed90dc559c0f35367fb08c45eed35d3acc83 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 29 Apr 2026 14:59:44 +0200 Subject: [PATCH 2/4] ci(workflows): always open breakpoint on E2E failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the `debug` label gating — open the SSH breakpoint on every E2E failure, not only debug-labeled PRs. Maintainers can release the sandbox immediately with `breakpoint resume` if they don't need it. Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index e669d42f..3aa3a2c3 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -313,11 +313,11 @@ jobs: name: image-list path: /tmp/${{ env.SANDBOX_NAME }}/_out/images.txt - # ▸ Open an SSH breakpoint to the failing sandbox (opt-in via `debug` label). - # Maintainers can SSH into the live runner, inspect Talos/Cozystack state - # and resume the workflow with `breakpoint resume`. Times out after 30m. + # ▸ Open an SSH breakpoint to the failing sandbox so maintainers can attach + # to the live runner, inspect Talos/Cozystack state and resume with + # `breakpoint resume`. Times out after 30m. - name: Breakpoint on E2E failure - if: failure() && contains(github.event.pull_request.labels.*.name, 'debug') + if: failure() uses: namespacelabs/breakpoint-action@v0 with: duration: 30m From fc5197045293ead7df628f9d5f938fc790c393d8 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 29 Apr 2026 17:48:19 +0200 Subject: [PATCH 3/4] ci(workflows): gate breakpoint step behind BREAKPOINT_ENABLED secret Fork PRs do not receive repository secrets, so referencing secrets.BREAKPOINT_ENABLED in the step env makes the if condition evaluate to false on forks and the step is skipped. Internal PRs keep the breakpoint behavior. This prevents fork PR runs from exposing the self-hosted rendezvous server endpoint. Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 3aa3a2c3..6c1e43c6 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -316,8 +316,13 @@ jobs: # ▸ Open an SSH breakpoint to the failing sandbox so maintainers can attach # to the live runner, inspect Talos/Cozystack state and resume with # `breakpoint resume`. Times out after 30m. + # Gated by the BREAKPOINT_ENABLED secret — in fork PRs the secret is + # not exposed, so the step is skipped and forks cannot reach the + # self-hosted rendezvous server. - name: Breakpoint on E2E failure - if: failure() + if: failure() && env.BREAKPOINT_ENABLED == 'true' + env: + BREAKPOINT_ENABLED: ${{ secrets.BREAKPOINT_ENABLED }} uses: namespacelabs/breakpoint-action@v0 with: duration: 30m From 74c102ee7178b6bf2b79b7d0063dcf2d56def5f1 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 29 Apr 2026 17:52:44 +0200 Subject: [PATCH 4/4] ci(workflows): drive breakpoint via BREAKPOINT_ENDPOINT repo variable Move both the gating signal and the rendezvous server address into a single `vars.BREAKPOINT_ENDPOINT` repository variable. Fork PRs do not see repository variables, so the if-condition evaluates to false and the step is skipped on forks. Internal PRs run the breakpoint against whatever endpoint is configured in the variable, which keeps the address out of the workflow source. Co-Authored-By: Claude Signed-off-by: Andrei Kvapil --- .github/workflows/pull-requests.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 6c1e43c6..a2c09b32 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -316,17 +316,15 @@ jobs: # ▸ Open an SSH breakpoint to the failing sandbox so maintainers can attach # to the live runner, inspect Talos/Cozystack state and resume with # `breakpoint resume`. Times out after 30m. - # Gated by the BREAKPOINT_ENABLED secret — in fork PRs the secret is - # not exposed, so the step is skipped and forks cannot reach the - # self-hosted rendezvous server. + # Configured via the BREAKPOINT_ENDPOINT repository variable — in fork + # PRs repository variables are not exposed, so the step is skipped and + # forks cannot reach the self-hosted rendezvous server. - name: Breakpoint on E2E failure - if: failure() && env.BREAKPOINT_ENABLED == 'true' - env: - BREAKPOINT_ENABLED: ${{ secrets.BREAKPOINT_ENABLED }} + if: failure() && vars.BREAKPOINT_ENDPOINT != '' uses: namespacelabs/breakpoint-action@v0 with: duration: 30m - endpoint: 158.101.126.45:5000 + endpoint: ${{ vars.BREAKPOINT_ENDPOINT }} authorized-users: kvaps, gecube, kingdonb, lllamnyp, aobort, tym83, klinch0, nbykov0, matthieu-robin, mattia-eleuteri # ▸ Tear down environment (always runs)