diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fdd6409a..4aae11dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,8 +14,8 @@ permissions: actions: read concurrency: - group: frontend-release-${{ github.event.workflow_run.head_branch }}-${{ github.event.workflow_run.head_sha }} - cancel-in-progress: false + group: frontend-release-${{ github.event.workflow_run.head_branch }} + cancel-in-progress: true jobs: build-upload-and-verify: @@ -40,38 +40,65 @@ jobs: fetch-depth: 0 ref: ${{ github.event.workflow_run.head_sha }} + - name: Check release commit is current + id: branch-head + run: | + latest_sha="$(git ls-remote origin "refs/heads/$RELEASE_BRANCH" | awk '{print $1}')" + if [[ -z "$latest_sha" ]]; then + echo "Could not resolve origin/$RELEASE_BRANCH." >&2 + exit 1 + fi + if [[ "$latest_sha" != "$RELEASE_EXPECTED_COMMIT" ]]; then + echo "current=false" >> "$GITHUB_OUTPUT" + echo "Skipping stale release for $RELEASE_EXPECTED_COMMIT; origin/$RELEASE_BRANCH is $latest_sha." + exit 0 + fi + echo "current=true" >> "$GITHUB_OUTPUT" + echo "Release commit is current for $RELEASE_BRANCH." + env: + RELEASE_BRANCH: ${{ github.event.workflow_run.head_branch }} + - name: Setup Node.js + if: steps.branch-head.outputs.current == 'true' uses: actions/setup-node@v5 with: node-version: 22 cache: npm - name: Install dependencies + if: steps.branch-head.outputs.current == 'true' run: npm ci --legacy-peer-deps - name: Check AI workflow sync + if: steps.branch-head.outputs.current == 'true' run: node scripts/sync-ai-workflow.mjs --check - name: Source and i18n checks + if: steps.branch-head.outputs.current == 'true' run: | npm run text:check-encoding npm run i18n:v2:source-check - name: Unit tests + if: steps.branch-head.outputs.current == 'true' run: npm run test:unit env: VITEST_BATCH_SIZE: 5 - name: Build release artifact + if: steps.branch-head.outputs.current == 'true' run: npm run build - name: Install Playwright Chromium + if: steps.branch-head.outputs.current == 'true' run: npx playwright install --with-deps chromium - name: Production Playwright gate + if: steps.branch-head.outputs.current == 'true' run: npm run test:e2e:prod - name: Upload dist artifact + if: steps.branch-head.outputs.current == 'true' continue-on-error: true uses: actions/upload-artifact@v4 with: @@ -80,25 +107,14 @@ jobs: retention-days: 3 - name: Request Release Manager auto sync + if: steps.branch-head.outputs.current == 'true' run: | test -n "$RELEASE_MANAGER_GATE_TOKEN" || (echo "RELEASE_MANAGER_GATE_TOKEN is required" >&2; exit 1) - response_file="$(mktemp)" - status_code="$(curl --show-error --silent \ - --output "$response_file" \ - --write-out "%{http_code}" \ + curl --fail --show-error --silent \ -X POST "$RELEASE_MANAGER_GATE_URL" \ -H "Authorization: Bearer $RELEASE_MANAGER_GATE_TOKEN" \ -H "Content-Type: application/json" \ - --data "{\"environment_url\":\"$RELEASE_BASE_URL\",\"channel_slug\":\"stable\",\"app\":\"frontend\",\"repository\":\"$RELEASE_REPOSITORY\",\"branch\":\"$RELEASE_BRANCH\",\"expected_commit\":\"$RELEASE_EXPECTED_COMMIT\",\"build_id\":\"$RELEASE_EXPECTED_BUILD_ID\",\"workflow_url\":\"$RELEASE_WORKFLOW_URL\",\"auto_sync\":true,\"wait_timeout_seconds\":300,\"poll_interval_seconds\":10,\"required_checks\":[\"api_gateway\"]}")" - if [[ "$status_code" =~ ^2 ]]; then - cat "$response_file" - elif [[ "$status_code" == "504" ]]; then - echo "Release Manager auto sync request reached the gateway timeout; continuing to artifact wait." - else - cat "$response_file" >&2 - echo "Release Manager auto sync request failed with HTTP $status_code." >&2 - exit 1 - fi + --data "{\"environment_url\":\"$RELEASE_BASE_URL\",\"channel_slug\":\"stable\",\"app\":\"frontend\",\"repository\":\"$RELEASE_REPOSITORY\",\"branch\":\"$RELEASE_BRANCH\",\"expected_commit\":\"$RELEASE_EXPECTED_COMMIT\",\"build_id\":\"$RELEASE_EXPECTED_BUILD_ID\",\"workflow_url\":\"$RELEASE_WORKFLOW_URL\",\"auto_sync\":true,\"wait_timeout_seconds\":300,\"poll_interval_seconds\":10,\"required_checks\":[\"api_gateway\"]}" env: RELEASE_MANAGER_GATE_URL: ${{ secrets.RELEASE_MANAGER_GATE_URL || 'https://api.truckwash.io/release/gate/test-runs' }} RELEASE_MANAGER_GATE_TOKEN: ${{ secrets.RELEASE_MANAGER_GATE_TOKEN }} @@ -107,14 +123,17 @@ jobs: RELEASE_WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - name: Wait for Coolify release artifact + if: steps.branch-head.outputs.current == 'true' run: npm run release:verify-upload - name: Public live Playwright gate + if: steps.branch-head.outputs.current == 'true' run: npm run test:e2e:live:public env: NODE_OPTIONS: --use-system-ca - name: Credentialed live Playwright gate + if: steps.branch-head.outputs.current == 'true' run: npm run test:e2e:live:roles env: NODE_OPTIONS: --use-system-ca @@ -127,6 +146,7 @@ jobs: PLAYWRIGHT_DEPARTMENT_ID: ${{ secrets.PLAYWRIGHT_DEPARTMENT_ID }} - name: Record Release Manager gate + if: steps.branch-head.outputs.current == 'true' run: | test -n "$RELEASE_MANAGER_GATE_TOKEN" || (echo "RELEASE_MANAGER_GATE_TOKEN is required" >&2; exit 1) release_gate_build_id="${RELEASE_VERIFIED_BUILD_ID:-$RELEASE_EXPECTED_BUILD_ID}" @@ -143,13 +163,14 @@ jobs: RELEASE_WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - name: Update server version after verification + if: steps.branch-head.outputs.current == 'true' run: npm run release:update-server-version env: SERVER_UPDATE_TOKEN: ${{ secrets.SERVER_UPDATE_TOKEN }} RELEASE_VERSION: ${{ github.event.workflow_run.head_sha }} - name: Upload Playwright report - if: failure() + if: failure() && steps.branch-head.outputs.current == 'true' continue-on-error: true uses: actions/upload-artifact@v4 with: