From 1a2702caea9fcb840e0c264f7433ff7b53358a3c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 22 Sep 2026 06:53:39 +0000 Subject: [PATCH 1/2] ci: fail e2e ref lookup unless the branch is missing git ls-remote --exit-code status 2 is a missing ref. Other statuses are transport failures and must not soft-fall back to main. migration-wallet-setup re-resolves that candidate immediately before checkout so a failed-job rerun does not reuse a deleted companion. Co-authored-by: piotr-iohk --- .github/actions/resolve-e2e-ref/action.yml | 51 ++++++++++++++------ .github/workflows/determine-e2e-branch.yml | 28 ++++++++++- .github/workflows/migration-wallet-setup.yml | 19 +++++++- AGENTS.md | 2 + 4 files changed, 80 insertions(+), 20 deletions(-) diff --git a/.github/actions/resolve-e2e-ref/action.yml b/.github/actions/resolve-e2e-ref/action.yml index e4e04a75..d97f39a3 100644 --- a/.github/actions/resolve-e2e-ref/action.yml +++ b/.github/actions/resolve-e2e-ref/action.yml @@ -6,6 +6,10 @@ description: "Re-validate the determined e2e branch immediately before checkout" # the companion may be deleted later, or "Re-run failed jobs" may reuse the # old determine output. Shard jobs (including macos) should call this right # before checking out synonymdev/bitkit-e2e-tests. +# +# git ls-remote --exit-code returns 2 when no ref matches. Any other nonzero +# status is a transport or lookup failure. Only status 2 may soft-fall back +# (default companion) or hard-fail (explicit custom branch). inputs: selected: @@ -35,14 +39,14 @@ runs: - name: Resolve e2e ref id: resolve shell: bash + env: + SELECTED: ${{ inputs.selected }} + E2E_BRANCH_INPUT: ${{ inputs.e2e_branch_input }} + FALLBACK: ${{ inputs.fallback }} + TEST_REPO: ${{ inputs.test_repo }} run: | set -euo pipefail - SELECTED="${{ inputs.selected }}" - E2E_BRANCH_INPUT="${{ inputs.e2e_branch_input }}" - FALLBACK="${{ inputs.fallback }}" - TEST_REPO="${{ inputs.test_repo }}" - echo "🧭 Selected: $SELECTED" echo "🧭 e2e_branch_input: $E2E_BRANCH_INPUT" echo "🧭 Fallback: $FALLBACK" @@ -51,18 +55,33 @@ runs: # 1. Empty or already the fallback — nothing to re-validate. if [[ -z "$SELECTED" || "$SELECTED" == "$FALLBACK" ]]; then REF="$FALLBACK" - # 2. Companion still exists — use it. - elif git ls-remote --exit-code https://github.com/$TEST_REPO.git "refs/heads/$SELECTED" >/dev/null 2>&1; then - REF="$SELECTED" - echo "✅ Found selected branch: $REF" - # 3. Explicit custom branch is gone — fail hard (do not silently switch). - elif [[ -n "$E2E_BRANCH_INPUT" && "$E2E_BRANCH_INPUT" != "main" && "$E2E_BRANCH_INPUT" != "default-feature-branch" ]]; then - echo "::error title=Invalid e2e_branch::Branch '$SELECTED' not found in $TEST_REPO" - exit 1 - # 4. Default companion path — soft-fallback (deleted after determine, or stale re-run). else - echo "::warning title=Missing e2e companion::Branch '$SELECTED' not found in $TEST_REPO, using '$FALLBACK'." - REF="$FALLBACK" + # --exit-code: 0 = ref exists, 2 = no matching ref. Anything else + # (DNS, auth, 128, …) failed to look the ref up. + LS_ERR="$(mktemp)" + LS_STATUS=0 + git ls-remote --exit-code "https://github.com/${TEST_REPO}.git" "refs/heads/${SELECTED}" >/dev/null 2>"$LS_ERR" || LS_STATUS=$? + if [[ "$LS_STATUS" -ne 0 && -s "$LS_ERR" ]]; then + echo "git ls-remote stderr:" + cat "$LS_ERR" + fi + rm -f "$LS_ERR" + + if [[ "$LS_STATUS" -eq 0 ]]; then + REF="$SELECTED" + echo "✅ Found selected branch: $REF" + elif [[ "$LS_STATUS" -ne 2 ]]; then + echo "::error title=E2E ref lookup failed::git ls-remote exited ${LS_STATUS} while checking '${SELECTED}' in ${TEST_REPO}. Refusing to fall back to '${FALLBACK}'." + exit 1 + # 3. Explicit custom branch is gone — fail hard (do not silently switch). + elif [[ -n "$E2E_BRANCH_INPUT" && "$E2E_BRANCH_INPUT" != "main" && "$E2E_BRANCH_INPUT" != "default-feature-branch" ]]; then + echo "::error title=Invalid e2e_branch::Branch '${SELECTED}' not found in ${TEST_REPO}" + exit 1 + # 4. Default companion path — soft-fallback only for a real miss (exit 2). + else + echo "::warning title=Missing e2e companion::Branch '${SELECTED}' not found in ${TEST_REPO}, using '${FALLBACK}'." + REF="$FALLBACK" + fi fi echo "🧭 Effective ref: $REF" diff --git a/.github/workflows/determine-e2e-branch.yml b/.github/workflows/determine-e2e-branch.yml index 26f2702f..a14101ae 100644 --- a/.github/workflows/determine-e2e-branch.yml +++ b/.github/workflows/determine-e2e-branch.yml @@ -54,10 +54,34 @@ jobs: echo "🧭 Base branch: $BASE_BRANCH" echo "🧭 Checking repo: $TEST_REPO" + # --exit-code: 0 = ref exists, 2 = no matching ref. + # Any other status is a transport/lookup failure. Falling back on + # that would run CI against the base branch after a bad lookup. + ref_status() { + local ref_name="$1" + local err_file + local status=0 + err_file="$(mktemp)" + git ls-remote --exit-code "https://github.com/${TEST_REPO}.git" "refs/heads/${ref_name}" >/dev/null 2>"$err_file" || status=$? + if [[ "$status" -ne 0 && -s "$err_file" ]]; then + echo "git ls-remote stderr:" + cat "$err_file" + fi + rm -f "$err_file" + if [[ "$status" -eq 0 ]]; then + return 0 + fi + if [[ "$status" -eq 2 ]]; then + return 2 + fi + echo "::error title=E2E ref lookup failed::git ls-remote exited ${status} while checking '${ref_name}' in ${TEST_REPO}. Refusing to treat this as a missing branch." + exit 1 + } + if [[ "$INPUT_BRANCH" == "main" ]]; then BRANCH="main" elif [[ "$INPUT_BRANCH" == "default-feature-branch" ]]; then - if git ls-remote --exit-code https://github.com/$TEST_REPO.git "refs/heads/$APP_BRANCH" >/dev/null 2>&1; then + if ref_status "$APP_BRANCH"; then BRANCH="$APP_BRANCH" echo "✅ Found matching branch: $BRANCH" else @@ -65,7 +89,7 @@ jobs: echo "⚠️ No '$APP_BRANCH' branch in $TEST_REPO, using '$BASE_BRANCH'." fi else - if git ls-remote --exit-code https://github.com/$TEST_REPO.git "refs/heads/$INPUT_BRANCH" >/dev/null 2>&1; then + if ref_status "$INPUT_BRANCH"; then BRANCH="$INPUT_BRANCH" else echo "::error title=Invalid e2e_branch::Branch '$INPUT_BRANCH' not found in $TEST_REPO" diff --git a/.github/workflows/migration-wallet-setup.yml b/.github/workflows/migration-wallet-setup.yml index e1711f3a..2dd9d002 100644 --- a/.github/workflows/migration-wallet-setup.yml +++ b/.github/workflows/migration-wallet-setup.yml @@ -4,9 +4,14 @@ on: workflow_call: inputs: e2e_branch: - description: "Branch of synonymdev/bitkit-e2e-tests to use" + description: "Candidate branch of synonymdev/bitkit-e2e-tests. Re-validated immediately before checkout. Callers may pass an already-resolved ref; a missing default companion falls back to main." required: true type: string + e2e_branch_input: + description: "Resolution mode (main | default-feature-branch | custom branch name). Empty inherits the caller workflow_dispatch input e2e_branch, then default-feature-branch. A custom name hard-fails when the branch is missing." + required: false + type: string + default: "" rn_version: description: "Legacy RN app version to use for setup (e.g., v1.1.6)" required: false @@ -30,12 +35,22 @@ jobs: runs-on: ubuntu-latest steps: + # Re-resolve in this job. "Re-run failed jobs" does not re-run a + # successful resolve job in the caller, so inputs.e2e_branch can name + # a companion that was deleted after that job finished. + - name: Resolve E2E tests ref + id: e2e-ref + uses: $/.github/actions/resolve-e2e-ref + with: + selected: ${{ inputs.e2e_branch }} + e2e_branch_input: ${{ inputs.e2e_branch_input || github.event.inputs.e2e_branch || 'default-feature-branch' }} + - name: Clone E2E tests uses: actions/checkout@v4 with: repository: synonymdev/bitkit-e2e-tests path: bitkit-e2e-tests - ref: ${{ inputs.e2e_branch }} + ref: ${{ steps.e2e-ref.outputs.ref }} - name: Enable KVM run: | diff --git a/AGENTS.md b/AGENTS.md index e1377c3c..a37c6dfe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -136,6 +136,8 @@ Resolution rules (from `determine-e2e-branch.yml`): - `e2e_branch_input=main` -> use `main`. - `e2e_branch_input=default-feature-branch` -> use the same branch name as the app repo _if it exists_ in `bitkit-e2e-tests`, otherwise fall back to `main`. - `e2e_branch_input=` -> use that branch only if it exists; otherwise the workflow fails. +- `git ls-remote --exit-code` status **2** means the ref is missing (soft-fallback or the custom hard-fail above). Any other nonzero status is a transport/lookup failure and fails the job; do not treat it as "branch missing". +- `migration-wallet-setup.yml` runs `resolve-e2e-ref` immediately before checkout. `e2e_branch` is the candidate (callers may pass an already-resolved name). Optional `e2e_branch_input` selects the mode; when omitted, the caller dispatch input `e2e_branch` is used, otherwise `default-feature-branch`. Implication for feature work: From 0977e6cbd67e51f71c3b6386989bf07a43396dd2 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 22 Sep 2026 06:56:18 +0000 Subject: [PATCH 2/2] ci: pin migration resolve-e2e-ref to this repo The wallet-setup workflow is called from the app repos, so the pre-checkout resolver must be synonymdev/bitkit-e2e-tests/...@main, matching the other callers. Co-authored-by: piotr-iohk --- .github/workflows/migration-wallet-setup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/migration-wallet-setup.yml b/.github/workflows/migration-wallet-setup.yml index 2dd9d002..2f9cae6d 100644 --- a/.github/workflows/migration-wallet-setup.yml +++ b/.github/workflows/migration-wallet-setup.yml @@ -40,7 +40,7 @@ jobs: # a companion that was deleted after that job finished. - name: Resolve E2E tests ref id: e2e-ref - uses: $/.github/actions/resolve-e2e-ref + uses: synonymdev/bitkit-e2e-tests/.github/actions/resolve-e2e-ref@main with: selected: ${{ inputs.e2e_branch }} e2e_branch_input: ${{ inputs.e2e_branch_input || github.event.inputs.e2e_branch || 'default-feature-branch' }}