diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index c84a846895c..d827e4dfd9c 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -270,17 +270,17 @@ jobs: retention-days: 14 e2e-cleanup: - name: 'Cleanup current-run E2E apps' + name: 'Cleanup current-run E2E resources' needs: e2e-tests if: ${{ always() && needs.e2e-tests.result != 'skipped' }} runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 20 continue-on-error: true steps: - uses: actions/checkout@v6 with: - repository: ${{ github.event.pull_request.head.repo.full_name || github.event.repository.full_name }} - ref: ${{ github.event.pull_request.head.ref || github.event.merge_group.head_ref }} + repository: ${{ github.repository }} + ref: ${{ github.sha }} fetch-depth: 1 - name: Setup deps uses: ./.github/actions/setup-cli-deps @@ -295,6 +295,14 @@ jobs: E2E_ACCOUNT_PASSWORD: ${{ secrets.E2E_ACCOUNT_PASSWORD }} E2E_ORG_ID: ${{ secrets.E2E_ORG_ID }} run: pnpm --filter e2e exec tsx scripts/prime-browser-auth.ts + - name: Cleanup current-run E2E stores + env: + E2E_ACCOUNT_EMAIL: ${{ secrets.E2E_ACCOUNT_EMAIL }} + E2E_ACCOUNT_PASSWORD: ${{ secrets.E2E_ACCOUNT_PASSWORD }} + E2E_ORG_ID: ${{ secrets.E2E_ORG_ID }} + run: | + RUN_TOKEN=$(node -e "process.stdout.write(BigInt(process.env.GITHUB_RUN_ID).toString(36))") + pnpm --filter e2e exec tsx scripts/cleanup-stores.ts --pattern "r${RUN_TOKEN}a${GITHUB_RUN_ATTEMPT}" - name: Cleanup current-run E2E apps env: E2E_ACCOUNT_EMAIL: ${{ secrets.E2E_ACCOUNT_EMAIL }} diff --git a/packages/e2e/scripts/cleanup-stores.ts b/packages/e2e/scripts/cleanup-stores.ts index 550dcd84ae7..990e9e40b65 100644 --- a/packages/e2e/scripts/cleanup-stores.ts +++ b/packages/e2e/scripts/cleanup-stores.ts @@ -21,6 +21,7 @@ import {config} from 'dotenv' import * as path from 'path' +import * as fs from 'fs' import {fileURLToPath} from 'url' import {chromium} from '@playwright/test' import {BROWSER_TIMEOUT} from '../setup/constants.js' @@ -56,6 +57,28 @@ export interface CleanupStoresOptions { headed?: boolean /** Organization ID (default: from E2E_ORG_ID env) */ orgId?: string + /** Playwright browser storage state path (default: E2E_BROWSER_STATE_PATH or global-auth path) */ + storageStatePath?: string +} + +function isAccountsShopifyUrl(rawUrl: string): boolean { + try { + return new URL(rawUrl).hostname === 'accounts.shopify.com' + // eslint-disable-next-line no-catch-all/no-catch-all + } catch { + return false + } +} + +function defaultStorageStatePath(): string { + const tmpBase = process.env.E2E_TEMP_DIR ?? path.resolve(__dirname, '../../../.e2e-tmp') + return path.join(tmpBase, 'global-auth', 'browser-storage-state.json') +} + +function existingStorageStatePath(candidate?: string): string | undefined { + return [candidate, process.env.E2E_BROWSER_STATE_PATH, defaultStorageStatePath()].find( + (storageStatePath): storageStatePath is string => Boolean(storageStatePath && fs.existsSync(storageStatePath)), + ) } export async function cleanupStores(opts: CleanupStoresOptions = {}): Promise { @@ -64,6 +87,7 @@ export async function cleanupStores(opts: CleanupStoresOptions = {}): Promise false)) { + const accountButton = email ? page.locator(`text=${email}`).first() : undefined + if (accountButton && (await accountButton.isVisible({timeout: BROWSER_TIMEOUT.long}).catch(() => false))) { await accountButton.click() await page.waitForTimeout(BROWSER_TIMEOUT.medium) }