From b2976537bea565f29b2238f7c2715d7e2e8c4634 Mon Sep 17 00:00:00 2001 From: Michael Yankelev Date: Wed, 4 Mar 2026 00:06:07 +0100 Subject: [PATCH 1/3] chore(ci): extract reusable verify-e2e workflow Unify E2E verification logic used by release-gate and tag-staging into a single reusable workflow (verify-e2e.yml). This ensures both workflows use the same robust checks (polling, run_executed_tests, fallback range search) instead of tag-staging having a weaker version. Co-Authored-By: Claude Opus 4.6 Entire-Checkpoint: ee51045241e7 --- .github/workflows/release-gate.yml | 263 ++--------------------------- .github/workflows/tag-staging.yml | 67 +++----- .github/workflows/verify-e2e.yml | 263 +++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+), 286 deletions(-) create mode 100644 .github/workflows/verify-e2e.yml diff --git a/.github/workflows/release-gate.yml b/.github/workflows/release-gate.yml index c806f29283..9697d36b02 100644 --- a/.github/workflows/release-gate.yml +++ b/.github/workflows/release-gate.yml @@ -6,258 +6,27 @@ on: types: [opened, synchronize, reopened] jobs: - detect-changes: - name: Detect Changes Since Last Release + get-main-sha: + name: Get Main SHA if: startsWith(github.head_ref, 'release-please--') runs-on: ubuntu-latest outputs: - desktop: ${{ steps.check.outputs.desktop }} - prev_tag: ${{ steps.check.outputs.prev_tag }} + sha: ${{ steps.sha.outputs.sha }} steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for desktop-related changes since last release - id: check - run: | - # Find the latest non-staging release tag - PREV_TAG=$(git tag --list 'v*' --sort=-v:refname \ - | grep -v 'staging' \ - | head -1) - - if [ -z "$PREV_TAG" ]; then - echo "No previous release tag found — assuming desktop changed" - echo "desktop=true" >> "$GITHUB_OUTPUT" - echo "prev_tag=" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "Previous release tag: ${PREV_TAG}" - echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT" - echo "Diffing ${PREV_TAG}..HEAD" - - # Desktop-related path patterns (mirrored from e2e-desktop.yml) - DESKTOP_PATTERNS=( - 'apps/desktop/src/' - 'apps/desktop/src-tauri/src/' - 'apps/desktop/src-tauri/vendor/' - 'apps/desktop/src-tauri/capabilities/' - 'apps/desktop/src-tauri/resources/' - 'apps/desktop/src-tauri/Cargo.toml' - 'apps/desktop/src-tauri/Cargo.lock' - 'apps/desktop/src-tauri/build.rs' - 'apps/desktop/src-tauri/rust-toolchain.toml' - 'apps/desktop/index.html' - 'apps/desktop/vite.config.' - 'apps/desktop/tsconfig' - 'packages/crypto/src/' - 'packages/crypto/tsconfig' - '.github/workflows/e2e-desktop.yml' - ) - - CHANGED_FILES=$(git diff --name-only "${PREV_TAG}..HEAD") - DESKTOP_CHANGED=false - - for pattern in "${DESKTOP_PATTERNS[@]}"; do - if echo "$CHANGED_FILES" | grep -Fq "$pattern"; then - echo "Desktop change detected matching pattern: ${pattern}" - DESKTOP_CHANGED=true - break - fi - done - - echo "desktop=${DESKTOP_CHANGED}" >> "$GITHUB_OUTPUT" - echo "Desktop changes detected: ${DESKTOP_CHANGED}" - - verify-e2e: - name: Verify E2E Passed - needs: detect-changes - if: startsWith(github.head_ref, 'release-please--') - runs-on: ubuntu-latest - timeout-minutes: 40 - steps: - - name: Wait for Web E2E and verify it passed - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Get the latest commit on main (the base the release PR targets) - MAIN_SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') - echo "Latest main commit: ${MAIN_SHA}" - - # Poll for the Web E2E run to complete (it triggers on the same push) - MAX_ATTEMPTS=30 - POLL_INTERVAL=30 - echo "Waiting for Web E2E run to complete (polling every ${POLL_INTERVAL}s, max ${MAX_ATTEMPTS} attempts)..." - - for attempt in $(seq 1 $MAX_ATTEMPTS); do - E2E_CONCLUSION=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e.yml --branch=main --limit=10 \ - --json headSha,conclusion,status \ - --jq "[.[] | select(.headSha == \"${MAIN_SHA}\")][0].conclusion // empty") - - if [ -n "$E2E_CONCLUSION" ]; then - echo "Web E2E completed with conclusion: ${E2E_CONCLUSION}" - break - fi - - if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then - echo "::error::Web E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes for main (${MAIN_SHA})." - exit 1 - fi - - echo "Attempt ${attempt}/${MAX_ATTEMPTS}: E2E still running, waiting ${POLL_INTERVAL}s..." - sleep $POLL_INTERVAL - done - - if [ "$E2E_CONCLUSION" != "success" ]; then - echo "::error::E2E Tests did not pass on main (conclusion: ${E2E_CONCLUSION})" - exit 1 - fi - echo "Web E2E: passed" - - - name: Verify Desktop E2E (if desktop changed) - if: needs.detect-changes.outputs.desktop == 'true' + - name: Get latest main commit + id: sha env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PREV_TAG: ${{ needs.detect-changes.outputs.prev_tag }} run: | - MAIN_SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') - echo "Desktop changes detected since ${PREV_TAG} — verifying Desktop E2E" - - # Helper: check if a workflow run actually executed e2e-desktop jobs - # (not skipped due to change detection). Returns 0 if tests ran, 1 if skipped, 2 on API error. - run_executed_tests() { - local run_id=$1 - local executed - if ! executed=$(gh api "repos/${{ github.repository }}/actions/runs/${run_id}/jobs" \ - --jq '[.jobs[] | select(.name | startswith("Desktop E2E")) | select(.conclusion == "success")] | length'); then - echo "::error::Failed to query jobs for run ${run_id} (API error or rate limit)" - return 2 - fi - [ "${executed:-0}" -gt 0 ] - } - - # First check if there's a desktop E2E run for HEAD (may still be running) - HEAD_RUN=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e-desktop.yml --branch=main --limit=50 \ - --json headSha,conclusion,status,databaseId \ - --jq "[.[] | select(.headSha == \"${MAIN_SHA}\")][0]") - - HEAD_STATUS=$(echo "$HEAD_RUN" | jq -r '.status // empty') - - if [ -n "$HEAD_STATUS" ]; then - HEAD_RUN_ID=$(echo "$HEAD_RUN" | jq -r '.databaseId') - echo "Desktop E2E run exists for HEAD (run ${HEAD_RUN_ID}) — polling until complete..." - MAX_ATTEMPTS=40 - POLL_INTERVAL=30 - - for attempt in $(seq 1 $MAX_ATTEMPTS); do - CONCLUSION=$(gh run view "$HEAD_RUN_ID" --repo ${{ github.repository }} \ - --json conclusion \ - --jq '.conclusion // empty') - - if [ -n "$CONCLUSION" ]; then - if [ "$CONCLUSION" != "success" ]; then - echo "::error::Desktop E2E Tests did not pass on main (conclusion: ${CONCLUSION})" - exit 1 - fi - # Verify the e2e-desktop jobs actually ran (not skipped) - run_executed_tests "$HEAD_RUN_ID" && rc=0 || rc=$? - if [ "$rc" -eq 2 ]; then - exit 1 - elif [ "$rc" -eq 0 ]; then - echo "Desktop E2E: passed (at HEAD, tests executed)" - exit 0 - else - echo "Desktop E2E run at HEAD succeeded but tests were skipped (no desktop changes detected by workflow)." - echo "Falling through to search for a run that actually executed tests..." - break - fi - fi - - if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then - echo "::error::Desktop E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes." - exit 1 - fi - - echo "Attempt ${attempt}/${MAX_ATTEMPTS}: Desktop E2E still running, waiting ${POLL_INTERVAL}s..." - sleep $POLL_INTERVAL - done - fi - - # No desktop E2E run for HEAD (or HEAD run skipped tests) — find the - # most recent run in the release range that actually executed tests - echo "Searching for a Desktop E2E run that executed tests since ${PREV_TAG}..." - - if [ -z "$PREV_TAG" ]; then - echo "::error::No previous release tag and no Desktop E2E run for HEAD. Cannot verify desktop changes." - exit 1 - fi + SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') + echo "sha=${SHA}" >> "$GITHUB_OUTPUT" + echo "Latest main commit: ${SHA}" - # Get commit SHAs in the release range - RANGE_COMMITS=$(gh api "repos/${{ github.repository }}/compare/${PREV_TAG}...${MAIN_SHA}" \ - --jq '[.commits[].sha] | join("\n")' 2>/dev/null || echo "") - - if [ -z "$RANGE_COMMITS" ]; then - echo "::error::Could not determine commits in range ${PREV_TAG}..${MAIN_SHA}" - exit 1 - fi - - # Get recent completed desktop E2E runs (newest first) and find the - # most recent one whose commit is within the release range AND whose - # e2e-desktop jobs actually ran (not skipped) - RUNS=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e-desktop.yml --branch=main --limit=50 \ - --json headSha,conclusion,status,databaseId \ - --jq '.[] | select(.status == "completed") | "\(.headSha) \(.conclusion) \(.databaseId)"') - - LATEST_IN_RANGE_SHA="" - LATEST_IN_RANGE_CONCLUSION="" - - while IFS=" " read -r sha conclusion run_id; do - if [ -z "$sha" ]; then - continue - fi - if echo "$RANGE_COMMITS" | grep -Fq "$sha"; then - if [ "$conclusion" != "success" ]; then - # Found a failed run in range — report it immediately - LATEST_IN_RANGE_SHA="$sha" - LATEST_IN_RANGE_CONCLUSION="$conclusion" - break - fi - # Success run — verify tests actually executed - run_executed_tests "$run_id" && rc=0 || rc=$? - if [ "$rc" -eq 2 ]; then - exit 1 - elif [ "$rc" -eq 0 ]; then - LATEST_IN_RANGE_SHA="$sha" - LATEST_IN_RANGE_CONCLUSION="$conclusion" - LATEST_IN_RANGE_RUN_ID="$run_id" - break - else - echo "Skipping run ${run_id} at ${sha} — tests were skipped (no desktop changes detected by workflow)" - fi - fi - done <> "$GITHUB_OUTPUT" + echo "Resolved ${RELEASE_TAG} to ${SHA}" - - name: Verify E2E tests passed - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RELEASE_TAG: ${{ inputs.release_tag }} - run: | - COMMIT_SHA=$(git rev-parse "refs/tags/${RELEASE_TAG}") - echo "Checking test status for commit ${COMMIT_SHA}" - - # Web E2E runs on every push to main — must exist and pass - E2E_CONCLUSION=$(gh run list --workflow=e2e.yml --branch=main --limit=10 \ - --json headSha,conclusion --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0].conclusion") - if [ -z "$E2E_CONCLUSION" ]; then - echo "::error::No E2E test run found for ${RELEASE_TAG} (${COMMIT_SHA})" - exit 1 - fi - if [ "$E2E_CONCLUSION" != "success" ]; then - echo "::error::E2E Tests did not pass for ${RELEASE_TAG} (conclusion: ${E2E_CONCLUSION})" - exit 1 - fi - echo "Web E2E: passed" + verify-e2e: + name: Verify E2E + needs: resolve-sha + uses: ./.github/workflows/verify-e2e.yml + with: + commit_sha: ${{ needs.resolve-sha.outputs.commit_sha }} + secrets: inherit - # Desktop E2E may be skipped if no desktop files changed — only block if it ran and failed - DESKTOP_CONCLUSION=$(gh run list --workflow=e2e-desktop.yml --branch=main --limit=10 \ - --json headSha,conclusion --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0].conclusion") - if [ -n "$DESKTOP_CONCLUSION" ] && [ "$DESKTOP_CONCLUSION" != "success" ]; then - echo "::error::Desktop E2E Tests did not pass for ${RELEASE_TAG} (conclusion: ${DESKTOP_CONCLUSION})" - exit 1 - fi - if [ -z "$DESKTOP_CONCLUSION" ]; then - echo "Desktop E2E: no run for this commit (skipped — no desktop changes)" - else - echo "Desktop E2E: passed" - fi + tag-staging: + name: Create Staging Tag + needs: [resolve-sha, verify-e2e] + runs-on: ubuntu-latest + environment: staging-approval + permissions: + contents: write + outputs: + staging_tag: ${{ steps.rc.outputs.staging_tag }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Calculate next RC number id: rc diff --git a/.github/workflows/verify-e2e.yml b/.github/workflows/verify-e2e.yml new file mode 100644 index 0000000000..9b6032fb7c --- /dev/null +++ b/.github/workflows/verify-e2e.yml @@ -0,0 +1,263 @@ +name: Verify E2E + +on: + workflow_call: + inputs: + commit_sha: + description: 'Commit SHA to verify E2E tests for' + required: true + type: string + +jobs: + detect-changes: + name: Detect Changes Since Last Release + runs-on: ubuntu-latest + outputs: + desktop: ${{ steps.check.outputs.desktop }} + prev_tag: ${{ steps.check.outputs.prev_tag }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for desktop-related changes since last release + id: check + run: | + # Find the latest non-staging release tag + PREV_TAG=$(git tag --list 'v*' --sort=-v:refname \ + | grep -v 'staging' \ + | head -1) + + if [ -z "$PREV_TAG" ]; then + echo "No previous release tag found — assuming desktop changed" + echo "desktop=true" >> "$GITHUB_OUTPUT" + echo "prev_tag=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Previous release tag: ${PREV_TAG}" + echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT" + echo "Diffing ${PREV_TAG}..${{ inputs.commit_sha }}" + + # Desktop-related path patterns (mirrored from e2e-desktop.yml) + DESKTOP_PATTERNS=( + 'apps/desktop/src/' + 'apps/desktop/src-tauri/src/' + 'apps/desktop/src-tauri/vendor/' + 'apps/desktop/src-tauri/capabilities/' + 'apps/desktop/src-tauri/resources/' + 'apps/desktop/src-tauri/Cargo.toml' + 'apps/desktop/src-tauri/Cargo.lock' + 'apps/desktop/src-tauri/build.rs' + 'apps/desktop/src-tauri/rust-toolchain.toml' + 'apps/desktop/index.html' + 'apps/desktop/vite.config.' + 'apps/desktop/tsconfig' + 'packages/crypto/src/' + 'packages/crypto/tsconfig' + '.github/workflows/e2e-desktop.yml' + ) + + CHANGED_FILES=$(git diff --name-only "${PREV_TAG}..${{ inputs.commit_sha }}") + DESKTOP_CHANGED=false + + for pattern in "${DESKTOP_PATTERNS[@]}"; do + if echo "$CHANGED_FILES" | grep -Fq "$pattern"; then + echo "Desktop change detected matching pattern: ${pattern}" + DESKTOP_CHANGED=true + break + fi + done + + echo "desktop=${DESKTOP_CHANGED}" >> "$GITHUB_OUTPUT" + echo "Desktop changes detected: ${DESKTOP_CHANGED}" + + verify-e2e: + name: Verify E2E Passed + needs: detect-changes + runs-on: ubuntu-latest + timeout-minutes: 40 + steps: + - name: Wait for Web E2E and verify it passed + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMIT_SHA: ${{ inputs.commit_sha }} + run: | + echo "Verifying E2E for commit: ${COMMIT_SHA}" + + # Poll for the Web E2E run to complete + MAX_ATTEMPTS=30 + POLL_INTERVAL=30 + echo "Waiting for Web E2E run to complete (polling every ${POLL_INTERVAL}s, max ${MAX_ATTEMPTS} attempts)..." + + for attempt in $(seq 1 $MAX_ATTEMPTS); do + E2E_CONCLUSION=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e.yml --branch=main --limit=10 \ + --json headSha,conclusion,status \ + --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0].conclusion // empty") + + if [ -n "$E2E_CONCLUSION" ]; then + echo "Web E2E completed with conclusion: ${E2E_CONCLUSION}" + break + fi + + if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then + echo "::error::Web E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes for commit ${COMMIT_SHA}." + exit 1 + fi + + echo "Attempt ${attempt}/${MAX_ATTEMPTS}: E2E still running, waiting ${POLL_INTERVAL}s..." + sleep $POLL_INTERVAL + done + + if [ "$E2E_CONCLUSION" != "success" ]; then + echo "::error::E2E Tests did not pass (conclusion: ${E2E_CONCLUSION})" + exit 1 + fi + echo "Web E2E: passed" + + - name: Verify Desktop E2E (if desktop changed) + if: needs.detect-changes.outputs.desktop == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMIT_SHA: ${{ inputs.commit_sha }} + PREV_TAG: ${{ needs.detect-changes.outputs.prev_tag }} + run: | + echo "Desktop changes detected since ${PREV_TAG} — verifying Desktop E2E" + + # Helper: check if a workflow run actually executed e2e-desktop jobs + # (not skipped due to change detection). Returns 0 if tests ran, 1 if skipped, 2 on API error. + run_executed_tests() { + local run_id=$1 + local executed + if ! executed=$(gh api "repos/${{ github.repository }}/actions/runs/${run_id}/jobs" \ + --jq '[.jobs[] | select(.name | startswith("Desktop E2E")) | select(.conclusion == "success")] | length'); then + echo "::error::Failed to query jobs for run ${run_id} (API error or rate limit)" + return 2 + fi + [ "${executed:-0}" -gt 0 ] + } + + # First check if there's a desktop E2E run for this commit (may still be running) + HEAD_RUN=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e-desktop.yml --branch=main --limit=50 \ + --json headSha,conclusion,status,databaseId \ + --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0]") + + HEAD_STATUS=$(echo "$HEAD_RUN" | jq -r '.status // empty') + + if [ -n "$HEAD_STATUS" ]; then + HEAD_RUN_ID=$(echo "$HEAD_RUN" | jq -r '.databaseId') + echo "Desktop E2E run exists for commit (run ${HEAD_RUN_ID}) — polling until complete..." + MAX_ATTEMPTS=40 + POLL_INTERVAL=30 + + for attempt in $(seq 1 $MAX_ATTEMPTS); do + CONCLUSION=$(gh run view "$HEAD_RUN_ID" --repo ${{ github.repository }} \ + --json conclusion \ + --jq '.conclusion // empty') + + if [ -n "$CONCLUSION" ]; then + if [ "$CONCLUSION" != "success" ]; then + echo "::error::Desktop E2E Tests did not pass (conclusion: ${CONCLUSION})" + exit 1 + fi + # Verify the e2e-desktop jobs actually ran (not skipped) + run_executed_tests "$HEAD_RUN_ID" && rc=0 || rc=$? + if [ "$rc" -eq 2 ]; then + exit 1 + elif [ "$rc" -eq 0 ]; then + echo "Desktop E2E: passed (at target commit, tests executed)" + exit 0 + else + echo "Desktop E2E run at target commit succeeded but tests were skipped (no desktop changes detected by workflow)." + echo "Falling through to search for a run that actually executed tests..." + break + fi + fi + + if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then + echo "::error::Desktop E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes." + exit 1 + fi + + echo "Attempt ${attempt}/${MAX_ATTEMPTS}: Desktop E2E still running, waiting ${POLL_INTERVAL}s..." + sleep $POLL_INTERVAL + done + fi + + # No desktop E2E run for target commit (or it skipped tests) — find the + # most recent run in the release range that actually executed tests + echo "Searching for a Desktop E2E run that executed tests since ${PREV_TAG}..." + + if [ -z "$PREV_TAG" ]; then + echo "::error::No previous release tag and no Desktop E2E run for target commit. Cannot verify desktop changes." + exit 1 + fi + + # Get commit SHAs in the release range + RANGE_COMMITS=$(gh api "repos/${{ github.repository }}/compare/${PREV_TAG}...${COMMIT_SHA}" \ + --jq '[.commits[].sha] | join("\n")' 2>/dev/null || echo "") + + if [ -z "$RANGE_COMMITS" ]; then + echo "::error::Could not determine commits in range ${PREV_TAG}..${COMMIT_SHA}" + exit 1 + fi + + # Get recent completed desktop E2E runs (newest first) and find the + # most recent one whose commit is within the release range AND whose + # e2e-desktop jobs actually ran (not skipped) + RUNS=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e-desktop.yml --branch=main --limit=50 \ + --json headSha,conclusion,status,databaseId \ + --jq '.[] | select(.status == "completed") | "\(.headSha) \(.conclusion) \(.databaseId)"') + + LATEST_IN_RANGE_SHA="" + LATEST_IN_RANGE_CONCLUSION="" + + while IFS=" " read -r sha conclusion run_id; do + if [ -z "$sha" ]; then + continue + fi + if echo "$RANGE_COMMITS" | grep -Fq "$sha"; then + if [ "$conclusion" != "success" ]; then + # Found a failed run in range — report it immediately + LATEST_IN_RANGE_SHA="$sha" + LATEST_IN_RANGE_CONCLUSION="$conclusion" + break + fi + # Success run — verify tests actually executed + run_executed_tests "$run_id" && rc=0 || rc=$? + if [ "$rc" -eq 2 ]; then + exit 1 + elif [ "$rc" -eq 0 ]; then + LATEST_IN_RANGE_SHA="$sha" + LATEST_IN_RANGE_CONCLUSION="$conclusion" + LATEST_IN_RANGE_RUN_ID="$run_id" + break + else + echo "Skipping run ${run_id} at ${sha} — tests were skipped (no desktop changes detected by workflow)" + fi + fi + done < Date: Wed, 4 Mar 2026 00:31:15 +0100 Subject: [PATCH 2/3] chore(ci): run full E2E suites in tag-staging workflow Instead of verifying previous E2E runs passed, tag-staging now calls the actual e2e.yml and e2e-desktop.yml workflows directly. Both run in parallel at the release tag ref before the staging tag is created. - Add workflow_call trigger with optional ref input to e2e.yml and e2e-desktop.yml so they can be called as reusable workflows - Replace tag-staging's inline verification with direct calls to both E2E workflows - Revert release-gate.yml to its original inline form (no need for a separate reusable workflow when only one caller exists) - Remove verify-e2e.yml (superseded by this approach) Co-Authored-By: Claude Opus 4.6 Entire-Checkpoint: 8e8faf6e56bf --- .github/workflows/e2e-desktop.yml | 8 + .github/workflows/e2e.yml | 8 + .github/workflows/release-gate.yml | 263 +++++++++++++++++++++++++++-- .github/workflows/tag-staging.yml | 33 ++-- .github/workflows/verify-e2e.yml | 263 ----------------------------- 5 files changed, 281 insertions(+), 294 deletions(-) delete mode 100644 .github/workflows/verify-e2e.yml diff --git a/.github/workflows/e2e-desktop.yml b/.github/workflows/e2e-desktop.yml index 086ecd15cf..4a280dcdc1 100644 --- a/.github/workflows/e2e-desktop.yml +++ b/.github/workflows/e2e-desktop.yml @@ -4,6 +4,12 @@ on: push: branches: [main] workflow_dispatch: + workflow_call: + inputs: + ref: + description: 'Git ref to checkout (tag, branch, or SHA)' + required: false + type: string jobs: changes: @@ -68,6 +74,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || '' }} # --- Install FUSE driver (needed for both build and test) --- diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 43937703ce..6eb6c61269 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -4,6 +4,12 @@ on: push: branches: [main] workflow_dispatch: + workflow_call: + inputs: + ref: + description: 'Git ref to checkout (tag, branch, or SHA)' + required: false + type: string jobs: e2e: @@ -51,6 +57,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || '' }} - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.github/workflows/release-gate.yml b/.github/workflows/release-gate.yml index 9697d36b02..c806f29283 100644 --- a/.github/workflows/release-gate.yml +++ b/.github/workflows/release-gate.yml @@ -6,27 +6,258 @@ on: types: [opened, synchronize, reopened] jobs: - get-main-sha: - name: Get Main SHA + detect-changes: + name: Detect Changes Since Last Release if: startsWith(github.head_ref, 'release-please--') runs-on: ubuntu-latest outputs: - sha: ${{ steps.sha.outputs.sha }} + desktop: ${{ steps.check.outputs.desktop }} + prev_tag: ${{ steps.check.outputs.prev_tag }} steps: - - name: Get latest main commit - id: sha + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for desktop-related changes since last release + id: check + run: | + # Find the latest non-staging release tag + PREV_TAG=$(git tag --list 'v*' --sort=-v:refname \ + | grep -v 'staging' \ + | head -1) + + if [ -z "$PREV_TAG" ]; then + echo "No previous release tag found — assuming desktop changed" + echo "desktop=true" >> "$GITHUB_OUTPUT" + echo "prev_tag=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Previous release tag: ${PREV_TAG}" + echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT" + echo "Diffing ${PREV_TAG}..HEAD" + + # Desktop-related path patterns (mirrored from e2e-desktop.yml) + DESKTOP_PATTERNS=( + 'apps/desktop/src/' + 'apps/desktop/src-tauri/src/' + 'apps/desktop/src-tauri/vendor/' + 'apps/desktop/src-tauri/capabilities/' + 'apps/desktop/src-tauri/resources/' + 'apps/desktop/src-tauri/Cargo.toml' + 'apps/desktop/src-tauri/Cargo.lock' + 'apps/desktop/src-tauri/build.rs' + 'apps/desktop/src-tauri/rust-toolchain.toml' + 'apps/desktop/index.html' + 'apps/desktop/vite.config.' + 'apps/desktop/tsconfig' + 'packages/crypto/src/' + 'packages/crypto/tsconfig' + '.github/workflows/e2e-desktop.yml' + ) + + CHANGED_FILES=$(git diff --name-only "${PREV_TAG}..HEAD") + DESKTOP_CHANGED=false + + for pattern in "${DESKTOP_PATTERNS[@]}"; do + if echo "$CHANGED_FILES" | grep -Fq "$pattern"; then + echo "Desktop change detected matching pattern: ${pattern}" + DESKTOP_CHANGED=true + break + fi + done + + echo "desktop=${DESKTOP_CHANGED}" >> "$GITHUB_OUTPUT" + echo "Desktop changes detected: ${DESKTOP_CHANGED}" + + verify-e2e: + name: Verify E2E Passed + needs: detect-changes + if: startsWith(github.head_ref, 'release-please--') + runs-on: ubuntu-latest + timeout-minutes: 40 + steps: + - name: Wait for Web E2E and verify it passed env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') - echo "sha=${SHA}" >> "$GITHUB_OUTPUT" - echo "Latest main commit: ${SHA}" + # Get the latest commit on main (the base the release PR targets) + MAIN_SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') + echo "Latest main commit: ${MAIN_SHA}" - verify: - name: Verify E2E - needs: get-main-sha - if: startsWith(github.head_ref, 'release-please--') - uses: ./.github/workflows/verify-e2e.yml - with: - commit_sha: ${{ needs.get-main-sha.outputs.sha }} - secrets: inherit + # Poll for the Web E2E run to complete (it triggers on the same push) + MAX_ATTEMPTS=30 + POLL_INTERVAL=30 + echo "Waiting for Web E2E run to complete (polling every ${POLL_INTERVAL}s, max ${MAX_ATTEMPTS} attempts)..." + + for attempt in $(seq 1 $MAX_ATTEMPTS); do + E2E_CONCLUSION=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e.yml --branch=main --limit=10 \ + --json headSha,conclusion,status \ + --jq "[.[] | select(.headSha == \"${MAIN_SHA}\")][0].conclusion // empty") + + if [ -n "$E2E_CONCLUSION" ]; then + echo "Web E2E completed with conclusion: ${E2E_CONCLUSION}" + break + fi + + if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then + echo "::error::Web E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes for main (${MAIN_SHA})." + exit 1 + fi + + echo "Attempt ${attempt}/${MAX_ATTEMPTS}: E2E still running, waiting ${POLL_INTERVAL}s..." + sleep $POLL_INTERVAL + done + + if [ "$E2E_CONCLUSION" != "success" ]; then + echo "::error::E2E Tests did not pass on main (conclusion: ${E2E_CONCLUSION})" + exit 1 + fi + echo "Web E2E: passed" + + - name: Verify Desktop E2E (if desktop changed) + if: needs.detect-changes.outputs.desktop == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PREV_TAG: ${{ needs.detect-changes.outputs.prev_tag }} + run: | + MAIN_SHA=$(gh api repos/${{ github.repository }}/git/ref/heads/main --jq '.object.sha') + echo "Desktop changes detected since ${PREV_TAG} — verifying Desktop E2E" + + # Helper: check if a workflow run actually executed e2e-desktop jobs + # (not skipped due to change detection). Returns 0 if tests ran, 1 if skipped, 2 on API error. + run_executed_tests() { + local run_id=$1 + local executed + if ! executed=$(gh api "repos/${{ github.repository }}/actions/runs/${run_id}/jobs" \ + --jq '[.jobs[] | select(.name | startswith("Desktop E2E")) | select(.conclusion == "success")] | length'); then + echo "::error::Failed to query jobs for run ${run_id} (API error or rate limit)" + return 2 + fi + [ "${executed:-0}" -gt 0 ] + } + + # First check if there's a desktop E2E run for HEAD (may still be running) + HEAD_RUN=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e-desktop.yml --branch=main --limit=50 \ + --json headSha,conclusion,status,databaseId \ + --jq "[.[] | select(.headSha == \"${MAIN_SHA}\")][0]") + + HEAD_STATUS=$(echo "$HEAD_RUN" | jq -r '.status // empty') + + if [ -n "$HEAD_STATUS" ]; then + HEAD_RUN_ID=$(echo "$HEAD_RUN" | jq -r '.databaseId') + echo "Desktop E2E run exists for HEAD (run ${HEAD_RUN_ID}) — polling until complete..." + MAX_ATTEMPTS=40 + POLL_INTERVAL=30 + + for attempt in $(seq 1 $MAX_ATTEMPTS); do + CONCLUSION=$(gh run view "$HEAD_RUN_ID" --repo ${{ github.repository }} \ + --json conclusion \ + --jq '.conclusion // empty') + + if [ -n "$CONCLUSION" ]; then + if [ "$CONCLUSION" != "success" ]; then + echo "::error::Desktop E2E Tests did not pass on main (conclusion: ${CONCLUSION})" + exit 1 + fi + # Verify the e2e-desktop jobs actually ran (not skipped) + run_executed_tests "$HEAD_RUN_ID" && rc=0 || rc=$? + if [ "$rc" -eq 2 ]; then + exit 1 + elif [ "$rc" -eq 0 ]; then + echo "Desktop E2E: passed (at HEAD, tests executed)" + exit 0 + else + echo "Desktop E2E run at HEAD succeeded but tests were skipped (no desktop changes detected by workflow)." + echo "Falling through to search for a run that actually executed tests..." + break + fi + fi + + if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then + echo "::error::Desktop E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes." + exit 1 + fi + + echo "Attempt ${attempt}/${MAX_ATTEMPTS}: Desktop E2E still running, waiting ${POLL_INTERVAL}s..." + sleep $POLL_INTERVAL + done + fi + + # No desktop E2E run for HEAD (or HEAD run skipped tests) — find the + # most recent run in the release range that actually executed tests + echo "Searching for a Desktop E2E run that executed tests since ${PREV_TAG}..." + + if [ -z "$PREV_TAG" ]; then + echo "::error::No previous release tag and no Desktop E2E run for HEAD. Cannot verify desktop changes." + exit 1 + fi + + # Get commit SHAs in the release range + RANGE_COMMITS=$(gh api "repos/${{ github.repository }}/compare/${PREV_TAG}...${MAIN_SHA}" \ + --jq '[.commits[].sha] | join("\n")' 2>/dev/null || echo "") + + if [ -z "$RANGE_COMMITS" ]; then + echo "::error::Could not determine commits in range ${PREV_TAG}..${MAIN_SHA}" + exit 1 + fi + + # Get recent completed desktop E2E runs (newest first) and find the + # most recent one whose commit is within the release range AND whose + # e2e-desktop jobs actually ran (not skipped) + RUNS=$(gh run list --repo ${{ github.repository }} \ + --workflow=e2e-desktop.yml --branch=main --limit=50 \ + --json headSha,conclusion,status,databaseId \ + --jq '.[] | select(.status == "completed") | "\(.headSha) \(.conclusion) \(.databaseId)"') + + LATEST_IN_RANGE_SHA="" + LATEST_IN_RANGE_CONCLUSION="" + + while IFS=" " read -r sha conclusion run_id; do + if [ -z "$sha" ]; then + continue + fi + if echo "$RANGE_COMMITS" | grep -Fq "$sha"; then + if [ "$conclusion" != "success" ]; then + # Found a failed run in range — report it immediately + LATEST_IN_RANGE_SHA="$sha" + LATEST_IN_RANGE_CONCLUSION="$conclusion" + break + fi + # Success run — verify tests actually executed + run_executed_tests "$run_id" && rc=0 || rc=$? + if [ "$rc" -eq 2 ]; then + exit 1 + elif [ "$rc" -eq 0 ]; then + LATEST_IN_RANGE_SHA="$sha" + LATEST_IN_RANGE_CONCLUSION="$conclusion" + LATEST_IN_RANGE_RUN_ID="$run_id" + break + else + echo "Skipping run ${run_id} at ${sha} — tests were skipped (no desktop changes detected by workflow)" + fi + fi + done <> "$GITHUB_OUTPUT" - echo "Resolved ${RELEASE_TAG} to ${SHA}" + echo "Tag ${RELEASE_TAG} validated" + + web-e2e: + name: Web E2E + needs: validate-tag + uses: ./.github/workflows/e2e.yml + with: + ref: ${{ inputs.release_tag }} + secrets: inherit - verify-e2e: - name: Verify E2E - needs: resolve-sha - uses: ./.github/workflows/verify-e2e.yml + desktop-e2e: + name: Desktop E2E + needs: validate-tag + uses: ./.github/workflows/e2e-desktop.yml with: - commit_sha: ${{ needs.resolve-sha.outputs.commit_sha }} + ref: ${{ inputs.release_tag }} secrets: inherit tag-staging: name: Create Staging Tag - needs: [resolve-sha, verify-e2e] + needs: [web-e2e, desktop-e2e] runs-on: ubuntu-latest environment: staging-approval permissions: diff --git a/.github/workflows/verify-e2e.yml b/.github/workflows/verify-e2e.yml deleted file mode 100644 index 9b6032fb7c..0000000000 --- a/.github/workflows/verify-e2e.yml +++ /dev/null @@ -1,263 +0,0 @@ -name: Verify E2E - -on: - workflow_call: - inputs: - commit_sha: - description: 'Commit SHA to verify E2E tests for' - required: true - type: string - -jobs: - detect-changes: - name: Detect Changes Since Last Release - runs-on: ubuntu-latest - outputs: - desktop: ${{ steps.check.outputs.desktop }} - prev_tag: ${{ steps.check.outputs.prev_tag }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for desktop-related changes since last release - id: check - run: | - # Find the latest non-staging release tag - PREV_TAG=$(git tag --list 'v*' --sort=-v:refname \ - | grep -v 'staging' \ - | head -1) - - if [ -z "$PREV_TAG" ]; then - echo "No previous release tag found — assuming desktop changed" - echo "desktop=true" >> "$GITHUB_OUTPUT" - echo "prev_tag=" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "Previous release tag: ${PREV_TAG}" - echo "prev_tag=${PREV_TAG}" >> "$GITHUB_OUTPUT" - echo "Diffing ${PREV_TAG}..${{ inputs.commit_sha }}" - - # Desktop-related path patterns (mirrored from e2e-desktop.yml) - DESKTOP_PATTERNS=( - 'apps/desktop/src/' - 'apps/desktop/src-tauri/src/' - 'apps/desktop/src-tauri/vendor/' - 'apps/desktop/src-tauri/capabilities/' - 'apps/desktop/src-tauri/resources/' - 'apps/desktop/src-tauri/Cargo.toml' - 'apps/desktop/src-tauri/Cargo.lock' - 'apps/desktop/src-tauri/build.rs' - 'apps/desktop/src-tauri/rust-toolchain.toml' - 'apps/desktop/index.html' - 'apps/desktop/vite.config.' - 'apps/desktop/tsconfig' - 'packages/crypto/src/' - 'packages/crypto/tsconfig' - '.github/workflows/e2e-desktop.yml' - ) - - CHANGED_FILES=$(git diff --name-only "${PREV_TAG}..${{ inputs.commit_sha }}") - DESKTOP_CHANGED=false - - for pattern in "${DESKTOP_PATTERNS[@]}"; do - if echo "$CHANGED_FILES" | grep -Fq "$pattern"; then - echo "Desktop change detected matching pattern: ${pattern}" - DESKTOP_CHANGED=true - break - fi - done - - echo "desktop=${DESKTOP_CHANGED}" >> "$GITHUB_OUTPUT" - echo "Desktop changes detected: ${DESKTOP_CHANGED}" - - verify-e2e: - name: Verify E2E Passed - needs: detect-changes - runs-on: ubuntu-latest - timeout-minutes: 40 - steps: - - name: Wait for Web E2E and verify it passed - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMMIT_SHA: ${{ inputs.commit_sha }} - run: | - echo "Verifying E2E for commit: ${COMMIT_SHA}" - - # Poll for the Web E2E run to complete - MAX_ATTEMPTS=30 - POLL_INTERVAL=30 - echo "Waiting for Web E2E run to complete (polling every ${POLL_INTERVAL}s, max ${MAX_ATTEMPTS} attempts)..." - - for attempt in $(seq 1 $MAX_ATTEMPTS); do - E2E_CONCLUSION=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e.yml --branch=main --limit=10 \ - --json headSha,conclusion,status \ - --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0].conclusion // empty") - - if [ -n "$E2E_CONCLUSION" ]; then - echo "Web E2E completed with conclusion: ${E2E_CONCLUSION}" - break - fi - - if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then - echo "::error::Web E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes for commit ${COMMIT_SHA}." - exit 1 - fi - - echo "Attempt ${attempt}/${MAX_ATTEMPTS}: E2E still running, waiting ${POLL_INTERVAL}s..." - sleep $POLL_INTERVAL - done - - if [ "$E2E_CONCLUSION" != "success" ]; then - echo "::error::E2E Tests did not pass (conclusion: ${E2E_CONCLUSION})" - exit 1 - fi - echo "Web E2E: passed" - - - name: Verify Desktop E2E (if desktop changed) - if: needs.detect-changes.outputs.desktop == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COMMIT_SHA: ${{ inputs.commit_sha }} - PREV_TAG: ${{ needs.detect-changes.outputs.prev_tag }} - run: | - echo "Desktop changes detected since ${PREV_TAG} — verifying Desktop E2E" - - # Helper: check if a workflow run actually executed e2e-desktop jobs - # (not skipped due to change detection). Returns 0 if tests ran, 1 if skipped, 2 on API error. - run_executed_tests() { - local run_id=$1 - local executed - if ! executed=$(gh api "repos/${{ github.repository }}/actions/runs/${run_id}/jobs" \ - --jq '[.jobs[] | select(.name | startswith("Desktop E2E")) | select(.conclusion == "success")] | length'); then - echo "::error::Failed to query jobs for run ${run_id} (API error or rate limit)" - return 2 - fi - [ "${executed:-0}" -gt 0 ] - } - - # First check if there's a desktop E2E run for this commit (may still be running) - HEAD_RUN=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e-desktop.yml --branch=main --limit=50 \ - --json headSha,conclusion,status,databaseId \ - --jq "[.[] | select(.headSha == \"${COMMIT_SHA}\")][0]") - - HEAD_STATUS=$(echo "$HEAD_RUN" | jq -r '.status // empty') - - if [ -n "$HEAD_STATUS" ]; then - HEAD_RUN_ID=$(echo "$HEAD_RUN" | jq -r '.databaseId') - echo "Desktop E2E run exists for commit (run ${HEAD_RUN_ID}) — polling until complete..." - MAX_ATTEMPTS=40 - POLL_INTERVAL=30 - - for attempt in $(seq 1 $MAX_ATTEMPTS); do - CONCLUSION=$(gh run view "$HEAD_RUN_ID" --repo ${{ github.repository }} \ - --json conclusion \ - --jq '.conclusion // empty') - - if [ -n "$CONCLUSION" ]; then - if [ "$CONCLUSION" != "success" ]; then - echo "::error::Desktop E2E Tests did not pass (conclusion: ${CONCLUSION})" - exit 1 - fi - # Verify the e2e-desktop jobs actually ran (not skipped) - run_executed_tests "$HEAD_RUN_ID" && rc=0 || rc=$? - if [ "$rc" -eq 2 ]; then - exit 1 - elif [ "$rc" -eq 0 ]; then - echo "Desktop E2E: passed (at target commit, tests executed)" - exit 0 - else - echo "Desktop E2E run at target commit succeeded but tests were skipped (no desktop changes detected by workflow)." - echo "Falling through to search for a run that actually executed tests..." - break - fi - fi - - if [ "$attempt" -eq "$MAX_ATTEMPTS" ]; then - echo "::error::Desktop E2E run did not complete within $(( MAX_ATTEMPTS * POLL_INTERVAL / 60 )) minutes." - exit 1 - fi - - echo "Attempt ${attempt}/${MAX_ATTEMPTS}: Desktop E2E still running, waiting ${POLL_INTERVAL}s..." - sleep $POLL_INTERVAL - done - fi - - # No desktop E2E run for target commit (or it skipped tests) — find the - # most recent run in the release range that actually executed tests - echo "Searching for a Desktop E2E run that executed tests since ${PREV_TAG}..." - - if [ -z "$PREV_TAG" ]; then - echo "::error::No previous release tag and no Desktop E2E run for target commit. Cannot verify desktop changes." - exit 1 - fi - - # Get commit SHAs in the release range - RANGE_COMMITS=$(gh api "repos/${{ github.repository }}/compare/${PREV_TAG}...${COMMIT_SHA}" \ - --jq '[.commits[].sha] | join("\n")' 2>/dev/null || echo "") - - if [ -z "$RANGE_COMMITS" ]; then - echo "::error::Could not determine commits in range ${PREV_TAG}..${COMMIT_SHA}" - exit 1 - fi - - # Get recent completed desktop E2E runs (newest first) and find the - # most recent one whose commit is within the release range AND whose - # e2e-desktop jobs actually ran (not skipped) - RUNS=$(gh run list --repo ${{ github.repository }} \ - --workflow=e2e-desktop.yml --branch=main --limit=50 \ - --json headSha,conclusion,status,databaseId \ - --jq '.[] | select(.status == "completed") | "\(.headSha) \(.conclusion) \(.databaseId)"') - - LATEST_IN_RANGE_SHA="" - LATEST_IN_RANGE_CONCLUSION="" - - while IFS=" " read -r sha conclusion run_id; do - if [ -z "$sha" ]; then - continue - fi - if echo "$RANGE_COMMITS" | grep -Fq "$sha"; then - if [ "$conclusion" != "success" ]; then - # Found a failed run in range — report it immediately - LATEST_IN_RANGE_SHA="$sha" - LATEST_IN_RANGE_CONCLUSION="$conclusion" - break - fi - # Success run — verify tests actually executed - run_executed_tests "$run_id" && rc=0 || rc=$? - if [ "$rc" -eq 2 ]; then - exit 1 - elif [ "$rc" -eq 0 ]; then - LATEST_IN_RANGE_SHA="$sha" - LATEST_IN_RANGE_CONCLUSION="$conclusion" - LATEST_IN_RANGE_RUN_ID="$run_id" - break - else - echo "Skipping run ${run_id} at ${sha} — tests were skipped (no desktop changes detected by workflow)" - fi - fi - done < Date: Wed, 4 Mar 2026 00:40:27 +0100 Subject: [PATCH 3/3] fix(ci): address PR review comments for workflow_call support - Use github.sha as ref fallback instead of empty string in e2e.yml and e2e-desktop.yml checkout steps - Change e2e-desktop.yml change detection to only run on push events (more explicit than excluding workflow_dispatch) - Update e2e-desktop job condition to run for all non-push events (covers both workflow_dispatch and workflow_call callers) Co-Authored-By: Claude Opus 4.6 Entire-Checkpoint: 5296a75e2f2b --- .github/workflows/e2e-desktop.yml | 8 ++++---- .github/workflows/e2e.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/e2e-desktop.yml b/.github/workflows/e2e-desktop.yml index 4a280dcdc1..23919d8a2b 100644 --- a/.github/workflows/e2e-desktop.yml +++ b/.github/workflows/e2e-desktop.yml @@ -14,8 +14,8 @@ on: jobs: changes: name: Detect Changes - # Skip change detection for workflow_dispatch (always run) - if: github.event_name != 'workflow_dispatch' + # Only run change detection for push events (skip for workflow_dispatch and workflow_call) + if: github.event_name == 'push' runs-on: ubuntu-latest outputs: desktop: ${{ steps.filter.outputs.desktop }} @@ -49,7 +49,7 @@ jobs: if: >- always() && !cancelled() && ( - github.event_name == 'workflow_dispatch' || + github.event_name != 'push' || needs.changes.outputs.desktop == 'true' ) runs-on: ${{ matrix.os }} @@ -75,7 +75,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - ref: ${{ inputs.ref || '' }} + ref: ${{ inputs.ref || github.sha }} # --- Install FUSE driver (needed for both build and test) --- diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6eb6c61269..56df77d02e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -58,7 +58,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ inputs.ref || '' }} + ref: ${{ inputs.ref || github.sha }} - name: Setup pnpm uses: pnpm/action-setup@v4