Skip to content

Commit 9875fe8

Browse files
authored
chore: block amplitude in playwright ci (#4107)
* chore: block amplitude in playwright ci * update artifact download logic * fix download script * add debug step * fix naming mismatch * docs: push test result * update playwright fixture * fix: revert blob-report upload to fix merge and add debug
1 parent dac1c3c commit 9875fe8

5 files changed

Lines changed: 121 additions & 15 deletions

File tree

.github/workflows/visual-comparison.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ jobs:
151151
id: download-references
152152
env:
153153
GITHUB_REPOSITORY: ${{ github.repository }}
154+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
154155
continue-on-error: true
155156
run: |
156157
if ./static/scripts/screenshot-artifacts.sh ./screenshots; then
@@ -160,10 +161,32 @@ jobs:
160161
echo "⚠️ No reference screenshots found. This will create new baselines instead of comparing."
161162
fi
162163
164+
- name: Debug - List downloaded screenshots
165+
run: |
166+
echo "=== Contents of ./screenshots ==="
167+
ls -la ./screenshots || echo "Directory doesn't exist"
168+
echo ""
169+
echo "=== First level subdirectories ==="
170+
find ./screenshots -maxdepth 2 -type d || echo "No subdirectories"
171+
echo ""
172+
echo "=== Sample files (first 10) ==="
173+
find ./screenshots -type f -name "*.png" | head -10 || echo "No PNG files found"
174+
echo ""
175+
echo "=== Total PNG count ==="
176+
find ./screenshots -type f -name "*.png" | wc -l
177+
echo ""
178+
echo "=== Check specific files ==="
179+
ls -la ./screenshots/screenshot.doc.spec.ts/Docs-screenshots-pathname-cli-cmd-options*.png 2>&1 || echo "cli-cmd-options file not found"
180+
echo ""
181+
echo "=== Check if paths contain -1.png suffix ==="
182+
find ./screenshots -name "*-1.png" | head -5
183+
163184
- name: Take screenshots with Playwright
164185
env:
165186
PLAYWRIGHT_SNAPSHOT_DIR: ${{ github.workspace }}/screenshots
166187
run: |
188+
echo "PLAYWRIGHT_SNAPSHOT_DIR is set to: ${PLAYWRIGHT_SNAPSHOT_DIR}"
189+
echo "Workspace directory: ${{ github.workspace }}"
167190
if [ "${{ steps.download-references.outputs.has_references }}" = "false" ]; then
168191
echo "Creating new baseline screenshots..."
169192
npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --update-snapshots || exit 0
@@ -174,6 +197,7 @@ jobs:
174197
175198
- name: Upload blob report
176199
uses: actions/upload-artifact@v4
200+
if: ${{ !cancelled() }}
177201
with:
178202
name: blob-report-${{ matrix.shardIndex }}
179203
path: blob-report
@@ -210,6 +234,14 @@ jobs:
210234
pattern: blob-report-*
211235
merge-multiple: true
212236

237+
- name: Debug - Check downloaded reports
238+
run: |
239+
echo "=== Contents of all-blob-reports ==="
240+
ls -laR all-blob-reports/ || echo "Directory doesn't exist or is empty"
241+
echo ""
242+
echo "=== File count ==="
243+
find all-blob-reports -type f | wc -l
244+
213245
- name: Merge into HTML report
214246
run: npx playwright merge-reports --reporter html ./all-blob-reports
215247

static/scripts/screenshot-artifacts.sh

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,40 @@ fi
3636
ARTIFACTS=$(api "actions/runs/${RUN_ID}/artifacts?per_page=100")
3737
COUNT=$(echo "${ARTIFACTS}" | jq '.total_count')
3838

39+
# Filter out expired artifacts
40+
VALID_ARTIFACTS=$(echo "${ARTIFACTS}" | jq '.artifacts | map(select(.expired == false))')
41+
VALID_COUNT=$(echo "${VALID_ARTIFACTS}" | jq 'length')
42+
3943
if [[ "${COUNT}" -eq 0 ]]; then
4044
echo "No artifacts available for run ${RUN_ID}." >&2
4145
exit 1
4246
fi
4347

44-
echo "Downloading ${COUNT} artifact(s) from run ${RUN_ID}..."
48+
if [[ "${VALID_COUNT}" -eq 0 ]]; then
49+
echo "All ${COUNT} artifact(s) from run ${RUN_ID} have expired." >&2
50+
exit 1
51+
fi
52+
53+
echo "Found ${VALID_COUNT} valid (non-expired) artifact(s) from run ${RUN_ID} (${COUNT} total)..."
4554

4655
INDEX=0
56+
DOWNLOADED=0
4757
while IFS= read -r artifact; do
4858
NAME=$(echo "${artifact}" | jq -r '.name')
59+
60+
# Only download the merged screenshots artifact, skip individual shards and build
61+
if [[ "${NAME}" =~ ^screenshots-[0-9]+$ ]]; then
62+
echo "Skipping shard artifact ${NAME} (merged artifact preferred)"
63+
continue
64+
fi
65+
66+
if [[ "${NAME}" == "build" ]]; then
67+
echo "Skipping build artifact ${NAME} (not needed for references)"
68+
continue
69+
fi
70+
71+
echo "Processing artifact ${NAME}..."
72+
4973
URL=$(echo "${artifact}" | jq -r '.archive_download_url')
5074
if [[ -z "${URL}" || "${URL}" == "null" ]]; then
5175
echo "Skipping artifact ${NAME} with no download URL" >&2
@@ -54,23 +78,56 @@ while IFS= read -r artifact; do
5478

5579
TMP_ZIP="$(mktemp)"
5680
TMP_DIR="$(mktemp -d)"
57-
curl -sSL -H "Authorization: Bearer ${TOKEN}" -H "Accept: application/vnd.github+json" "${URL}" -o "${TMP_ZIP}"
81+
82+
echo "Downloading ${NAME} from ${URL}..."
83+
if ! curl -fsSL -H "Authorization: Bearer ${TOKEN}" -H "Accept: application/vnd.github+json" "${URL}" -o "${TMP_ZIP}"; then
84+
echo "Failed to download artifact ${NAME}" >&2
85+
rm -rf "${TMP_ZIP}" "${TMP_DIR}"
86+
continue
87+
fi
88+
89+
# Verify the download produced a valid zip file
90+
if [[ ! -s "${TMP_ZIP}" ]]; then
91+
echo "Downloaded file is empty for artifact ${NAME}" >&2
92+
rm -rf "${TMP_ZIP}" "${TMP_DIR}"
93+
continue
94+
fi
95+
96+
if ! unzip -tq "${TMP_ZIP}" >/dev/null 2>&1; then
97+
echo "Downloaded file is not a valid zip for artifact ${NAME}" >&2
98+
rm -rf "${TMP_ZIP}" "${TMP_DIR}"
99+
continue
100+
fi
101+
58102
unzip -oq "${TMP_ZIP}" -d "${TMP_DIR}"
59103

60104
if [[ -d "${TMP_DIR}/screenshots" ]]; then
105+
# Artifact contains a screenshots/ subdirectory - extract its contents
61106
shopt -s dotglob
62107
mkdir -p "${TARGET_DIR}"
63108
cp -R "${TMP_DIR}/screenshots"/* "${TARGET_DIR}/" 2>/dev/null || true
64109
shopt -u dotglob
110+
elif [[ "${NAME}" == "screenshots" ]]; then
111+
# Merged screenshots artifact extracts directly to target
112+
shopt -s dotglob
113+
mkdir -p "${TARGET_DIR}"
114+
cp -R "${TMP_DIR}"/* "${TARGET_DIR}/" 2>/dev/null || true
115+
shopt -u dotglob
65116
else
117+
# Other artifacts go to subdirectories
66118
DEST_DIR="${TARGET_DIR}/${NAME}"
67119
mkdir -p "${DEST_DIR}"
68120
cp -R "${TMP_DIR}"/* "${DEST_DIR}/" 2>/dev/null || true
69121
fi
70122

71123
rm -rf "${TMP_ZIP}" "${TMP_DIR}"
72-
INDEX=$((INDEX + 1))
73-
echo "Downloaded artifact ${NAME}"
74-
done < <(echo "${ARTIFACTS}" | jq -c '.artifacts[]')
124+
DOWNLOADED=$((DOWNLOADED + 1))
125+
echo "Successfully downloaded artifact ${NAME}"
126+
done < <(echo "${VALID_ARTIFACTS}" | jq -c '.[]')
127+
128+
if [[ "${DOWNLOADED}" -eq 0 ]]; then
129+
echo "No artifacts were downloaded successfully" >&2
130+
exit 1
131+
fi
75132

76-
echo "Downloaded ${INDEX} artifact(s) to ${TARGET_DIR}".
133+
echo "Successfully downloaded ${DOWNLOADED} artifact(s) to ${TARGET_DIR}"

tests/playwright/cookbook-home.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { expect, test } from '@playwright/test';
1+
import { expect, test } from './fixtures';
22
import type { Locator } from '@playwright/test';
33

44
const collectTileData = async (locator: Locator) => {

tests/playwright/fixtures.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { test as base } from '@playwright/test';
2+
3+
/**
4+
* Custom test with auto-fixture that blocks analytics requests.
5+
* This ensures consistent behavior across all tests and prevents
6+
* amplitude tracking from interfering with visual comparisons.
7+
*
8+
* The auto fixture runs before every test automatically.
9+
*/
10+
export const test = base.extend<{ blockAnalytics: void }>({
11+
blockAnalytics: [async ({ context }, use) => {
12+
// Block all Amplitude and analytics requests by fulfilling with empty responses
13+
// This prevents timeouts that would occur if we abort the requests
14+
await context.route('**/*amplitude*/**', route => route.fulfill({ status: 200, body: '' }));
15+
await context.route('**/comms', route => route.fulfill({ status: 200, body: '' }));
16+
await context.route('**/*.amplitude.com/**', route => route.fulfill({ status: 200, body: '' }));
17+
await context.route('**/api.amplitude.com/**', route => route.fulfill({ status: 200, body: '' }));
18+
await context.route('**/api2.amplitude.com/**', route => route.fulfill({ status: 200, body: '' }));
19+
20+
await use();
21+
}, { auto: true }], // Automatically runs for every test
22+
});
23+
24+
export { expect } from '@playwright/test';

tests/playwright/screenshot.doc.spec.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import fs from 'fs';
22
import path from 'path';
3-
import { expect, test } from '@playwright/test';
3+
import { expect, test } from './fixtures';
44
import { extractSitemapPathnames, WaitForDocusaurusHydration } from './utils';
55

66
const siteUrl = process.env.PLAYWRIGHT_BASE_URL ?? 'http://localhost:3000';
@@ -28,11 +28,6 @@ function isVersionedDocsPathname(pathname: string, list: string[]): boolean {
2828
return true;
2929
}
3030

31-
function sanitizePathname(pathname: string): string {
32-
const cleaned = pathname.replace(/^\/+/, '').replace(/[^a-zA-Z0-9]+/g, '_');
33-
return cleaned === '' ? 'home' : cleaned;
34-
}
35-
3631
test.beforeAll(async () => {
3732
console.log('Excluded pages: ', excludeList);
3833
console.log('Total pages: ', extractSitemapPathnames(sitemapPath).length);
@@ -53,10 +48,8 @@ function screenshotPathname(pathname: string) {
5348

5449
await page.waitForTimeout(1_000);
5550

56-
const snapshotName = `${sanitizePathname(pathname)}.png`;
5751
await expect(page).toHaveScreenshot({
5852
fullPage: true,
59-
path: testInfo.snapshotPath(snapshotName),
6053
timeout: 10_000,
6154
});
6255
});

0 commit comments

Comments
 (0)