From 18be235d8ff8f50f5a519c952890d5f5cc6826ea Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 14 Oct 2026 16:57:58 +0200 Subject: [PATCH 1/2] ci(e2e): Run E2E tests without restoring the monorepo's node_modules E2E jobs restored the ~860 MB root dependency cache and the full build output only to run a few tsx scripts and to resolve the linked test-utils package. The scripts are now plain .mjs files without dependencies, and test-utils is installed from a tarball like the SDK packages. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 23 +-- dev-packages/e2e-tests/ciCopyToTemp.mjs | 20 +++ dev-packages/e2e-tests/ciCopyToTemp.ts | 26 --- dev-packages/e2e-tests/ciPnpmOverrides.mjs | 12 ++ dev-packages/e2e-tests/ciPnpmOverrides.ts | 20 --- .../lib/{copyToTemp.ts => copyToTemp.mjs} | 36 ++-- .../e2e-tests/lib/packedTarballUtils.mjs | 83 +++++++++ .../e2e-tests/lib/packedTarballUtils.ts | 64 ------- .../{pnpmOverrides.ts => pnpmOverrides.mjs} | 47 +++-- .../lib/{runtimeFiles.ts => runtimeFiles.mjs} | 9 +- .../lib/syncPackedTarballSymlinks.mjs | 38 ++++ .../lib/syncPackedTarballSymlinks.ts | 65 ------- dev-packages/e2e-tests/package.json | 8 +- dev-packages/e2e-tests/prepare.mjs | 4 + dev-packages/e2e-tests/prepare.ts | 15 -- dev-packages/e2e-tests/run.ts | 8 +- dev-packages/e2e-tests/tsconfig.json | 4 +- .../validate-packed-tarball-setup.mjs | 39 +++++ .../validate-packed-tarball-setup.ts | 42 ----- ...malize-e2e-test-dump-transaction-events.js | 162 +++++++++--------- 20 files changed, 363 insertions(+), 362 deletions(-) create mode 100644 dev-packages/e2e-tests/ciCopyToTemp.mjs delete mode 100644 dev-packages/e2e-tests/ciCopyToTemp.ts create mode 100644 dev-packages/e2e-tests/ciPnpmOverrides.mjs delete mode 100644 dev-packages/e2e-tests/ciPnpmOverrides.ts rename dev-packages/e2e-tests/lib/{copyToTemp.ts => copyToTemp.mjs} (69%) create mode 100644 dev-packages/e2e-tests/lib/packedTarballUtils.mjs delete mode 100644 dev-packages/e2e-tests/lib/packedTarballUtils.ts rename dev-packages/e2e-tests/lib/{pnpmOverrides.ts => pnpmOverrides.mjs} (71%) rename dev-packages/e2e-tests/lib/{runtimeFiles.ts => runtimeFiles.mjs} (81%) create mode 100644 dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.mjs delete mode 100644 dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.ts create mode 100644 dev-packages/e2e-tests/prepare.mjs delete mode 100644 dev-packages/e2e-tests/prepare.ts create mode 100644 dev-packages/e2e-tests/validate-packed-tarball-setup.mjs delete mode 100644 dev-packages/e2e-tests/validate-packed-tarball-setup.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5804e0b6ef6f..c752a89f3296 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1090,10 +1090,8 @@ jobs: uses: denoland/setup-deno@v2.0.5 with: deno-version: ${{ matrix.deno-version || 'v2.8.3' }} - - name: Restore caches - uses: ./.github/actions/restore-cache - with: - dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Install pnpm + uses: ./.github/actions/install-pnpm - name: Restore tarball artifacts uses: actions/download-artifact@v8 @@ -1114,6 +1112,13 @@ jobs: name: build-layer-output path: ${{ env.BUILD_LAYER_PATH }} + # The Lambda functions install the built workspace packages directly (see `src/stack.ts`). + - name: Restore build artifacts + uses: actions/download-artifact@v8 + if: matrix.test-application == 'aws-serverless' + with: + name: build-output + # Installs Playwright while the app builds. # Started after the artifact downloads: starting next to them made `download-artifact` fail to read the event file. - name: Install Playwright @@ -1172,7 +1177,7 @@ jobs: - name: Pre-process E2E Test Dumps if: failure() run: | - node ./scripts/normalize-e2e-test-dump-transaction-events.js + node ./scripts/normalize-e2e-test-dump-transaction-events.js ${{ runner.temp }}/test-application/event-dumps - name: Upload E2E Test Event Dumps uses: actions/upload-artifact@v7 @@ -1241,10 +1246,8 @@ jobs: uses: denoland/setup-deno@v2.0.5 with: deno-version: ${{ matrix.deno-version || 'v2.8.3' }} - - name: Restore caches - uses: ./.github/actions/restore-cache - with: - dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Install pnpm + uses: ./.github/actions/install-pnpm - name: Restore tarball artifacts uses: actions/download-artifact@v8 @@ -1303,7 +1306,7 @@ jobs: - name: Pre-process E2E Test Dumps if: failure() run: | - node ./scripts/normalize-e2e-test-dump-transaction-events.js + node ./scripts/normalize-e2e-test-dump-transaction-events.js ${{ runner.temp }}/test-application/event-dumps - name: Upload E2E Test Event Dumps uses: actions/upload-artifact@v7 diff --git a/dev-packages/e2e-tests/ciCopyToTemp.mjs b/dev-packages/e2e-tests/ciCopyToTemp.mjs new file mode 100644 index 000000000000..f257e00d12a7 --- /dev/null +++ b/dev-packages/e2e-tests/ciCopyToTemp.mjs @@ -0,0 +1,20 @@ +// @ts-check +/* eslint-disable no-console */ + +import { copyToTemp } from './lib/copyToTemp.mjs'; +import { applyRuntimeFiles } from './lib/runtimeFiles.mjs'; + +const originalPath = process.argv[2]; +const tmpDirPath = process.argv[3]; + +if (!originalPath || !tmpDirPath) { + throw new Error('Original path and tmp dir path are required'); +} + +console.log(`Copying ${originalPath} to ${tmpDirPath}...`); + +await copyToTemp(originalPath, tmpDirPath); + +if (process.env.RUNTIME) { + applyRuntimeFiles(tmpDirPath, process.env.RUNTIME); +} diff --git a/dev-packages/e2e-tests/ciCopyToTemp.ts b/dev-packages/e2e-tests/ciCopyToTemp.ts deleted file mode 100644 index 649fe01fed3f..000000000000 --- a/dev-packages/e2e-tests/ciCopyToTemp.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-disable no-console */ - -import { copyToTemp } from './lib/copyToTemp'; -import { applyRuntimeFiles } from './lib/runtimeFiles'; - -async function run(): Promise { - const originalPath = process.argv[2]; - const tmpDirPath = process.argv[3]; - - if (!originalPath || !tmpDirPath) { - throw new Error('Original path and tmp dir path are required'); - } - - console.log(`Copying ${originalPath} to ${tmpDirPath}...`); - - await copyToTemp(originalPath, tmpDirPath); - - if (process.env.RUNTIME) { - applyRuntimeFiles(tmpDirPath, process.env.RUNTIME); - } -} - -run().catch(error => { - console.error(error); - process.exit(1); -}); diff --git a/dev-packages/e2e-tests/ciPnpmOverrides.mjs b/dev-packages/e2e-tests/ciPnpmOverrides.mjs new file mode 100644 index 000000000000..a3d6d643c6fa --- /dev/null +++ b/dev-packages/e2e-tests/ciPnpmOverrides.mjs @@ -0,0 +1,12 @@ +// @ts-check +import * as path from 'node:path'; +import { addPnpmOverrides } from './lib/pnpmOverrides.mjs'; + +const tmpDirPath = process.argv[2]; +const packedDirPath = process.argv[3]; + +if (!tmpDirPath || !packedDirPath) { + throw new Error('Tmp dir path and packed dir path are required'); +} + +await addPnpmOverrides(path.resolve(tmpDirPath), path.resolve(packedDirPath)); diff --git a/dev-packages/e2e-tests/ciPnpmOverrides.ts b/dev-packages/e2e-tests/ciPnpmOverrides.ts deleted file mode 100644 index 909a59fa2e9d..000000000000 --- a/dev-packages/e2e-tests/ciPnpmOverrides.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable no-console */ - -import { addPnpmOverrides } from './lib/pnpmOverrides'; -import * as path from 'path'; - -async function run(): Promise { - const tmpDirPath = process.argv[2]; - const packedDirPath = process.argv[3]; - - if (!tmpDirPath || !packedDirPath) { - throw new Error('Tmp dir path and packed dir path are required'); - } - - await addPnpmOverrides(path.resolve(tmpDirPath), path.resolve(packedDirPath)); -} - -run().catch(error => { - console.error(error); - process.exit(1); -}); diff --git a/dev-packages/e2e-tests/lib/copyToTemp.ts b/dev-packages/e2e-tests/lib/copyToTemp.mjs similarity index 69% rename from dev-packages/e2e-tests/lib/copyToTemp.ts rename to dev-packages/e2e-tests/lib/copyToTemp.mjs index c45a5793e2fc..ae7f5e04d5fe 100644 --- a/dev-packages/e2e-tests/lib/copyToTemp.ts +++ b/dev-packages/e2e-tests/lib/copyToTemp.mjs @@ -1,22 +1,31 @@ +// @ts-check /* eslint-disable no-console */ -import { readFileSync, writeFileSync } from 'fs'; -import { cp } from 'fs/promises'; -import { isAbsolute, join, resolve } from 'path'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { cp } from 'node:fs/promises'; +import { dirname, isAbsolute, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; -export async function copyToTemp(originalPath: string, tmpDirPath: string): Promise { +const __dirname = dirname(fileURLToPath(import.meta.url)); + +/** + * @param {string} originalPath + * @param {string} tmpDirPath + * @returns {Promise} + */ +export async function copyToTemp(originalPath, tmpDirPath) { // copy files to tmp dir await cp(originalPath, tmpDirPath, { recursive: true }); fixPackageJson(tmpDirPath); } -function fixPackageJson(cwd: string): void { +/** + * @param {string} cwd + */ +function fixPackageJson(cwd) { const packageJsonPath = join(cwd, 'package.json'); - const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { - dependencies?: Record; - devDependencies?: Record; - volta?: Record; - }; + /** @type {{ dependencies?: Record; devDependencies?: Record; volta?: Record }} */ + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); // 1. Fix file dependencies if (packageJson.dependencies) { @@ -45,8 +54,11 @@ function fixPackageJson(cwd: string): void { writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); } -// Exported for pnpmOverrides as well -export function fixFileLinkDependencies(dependencyObj: Record): void { +/** + * Exported for pnpmOverrides as well + * @param {Record} dependencyObj + */ +export function fixFileLinkDependencies(dependencyObj) { for (const [key, value] of Object.entries(dependencyObj)) { const prefix = value.startsWith('link:') ? 'link:' : value.startsWith('file:') ? 'file:' : null; if (!prefix) { diff --git a/dev-packages/e2e-tests/lib/packedTarballUtils.mjs b/dev-packages/e2e-tests/lib/packedTarballUtils.mjs new file mode 100644 index 000000000000..c46a94ff9578 --- /dev/null +++ b/dev-packages/e2e-tests/lib/packedTarballUtils.mjs @@ -0,0 +1,83 @@ +// @ts-check +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const E2E_TESTS_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const REPOSITORY_ROOT = path.resolve(E2E_TESTS_ROOT, '../..'); + +// test-utils is not published, but test apps install it from its tarball too: with a `link:`, its dependencies would +// resolve from the monorepo's root `node_modules` instead of the app's. +const TARBALL_PACKAGE_DIRS = [ + ...fs.readdirSync(path.join(REPOSITORY_ROOT, 'packages')).map(dir => path.join(REPOSITORY_ROOT, 'packages', dir)), + path.join(REPOSITORY_ROOT, 'dev-packages', 'test-utils'), +]; + +/** + * Workspace @sentry and @sentry-internal packages that have a built tarball for the E2E version. + * @returns {{ name: string; tarballPath: string }[]} The package names and their tarball paths, sorted by name. + */ +export function getPackedTarballs() { + const version = getE2eTestsPackageVersion(); + const tarballs = []; + + for (const packageDir of TARBALL_PACKAGE_DIRS) { + const packageJsonPath = path.join(packageDir, 'package.json'); + if (!fs.existsSync(packageJsonPath)) { + continue; + } + + const name = readJson(packageJsonPath).name; + if (!name || (!name.startsWith('@sentry/') && !name.startsWith('@sentry-internal/'))) { + continue; + } + + const tarballPath = path.join(packageDir, versionedTarballFilename(name, version)); + if (fs.existsSync(tarballPath)) { + tarballs.push({ name, tarballPath }); + } + } + + return tarballs.sort((a, b) => a.name.localeCompare(b.name)); +} + +/** + * Stable symlink name in `packed/` (no version segment). + * @param {string} packageName + * @returns {string} + */ +export function packedSymlinkFilename(packageName) { + return `${npmPackBasename(packageName)}-packed.tgz`; +} + +/** + * Versioned tarball filename produced by `npm pack` in a package directory. + * @param {string} packageName + * @param {string} version + * @returns {string} + */ +function versionedTarballFilename(packageName, version) { + return `${npmPackBasename(packageName)}-${version}.tgz`; +} + +/** + * npm pack tarball basename (without version and .tgz), e.g. `@sentry/core` -> `sentry-core`. + * @param {string} packageName + * @returns {string} + */ +function npmPackBasename(packageName) { + return packageName.replace(/^@/, '').replace(/\//g, '-'); +} + +/** + * @param {string} filePath + * @returns {any} + */ +function readJson(filePath) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +/** @returns {string} */ +export function getE2eTestsPackageVersion() { + return readJson(path.join(E2E_TESTS_ROOT, 'package.json')).version; +} diff --git a/dev-packages/e2e-tests/lib/packedTarballUtils.ts b/dev-packages/e2e-tests/lib/packedTarballUtils.ts deleted file mode 100644 index d7bbeefcb8e7..000000000000 --- a/dev-packages/e2e-tests/lib/packedTarballUtils.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as path from 'path'; -import * as fs from 'fs'; -import { sync as globSync } from 'glob'; - -const E2E_TESTS_ROOT = path.resolve(__dirname, '..'); -const REPOSITORY_ROOT = path.resolve(E2E_TESTS_ROOT, '../..'); - -// test-utils is not published, but test apps install it from its tarball too: with a `link:`, its dependencies would -// resolve from the monorepo's root `node_modules` instead of the app's. -export const TARBALL_PACKAGE_JSON_GLOB = '{packages/*,dev-packages/test-utils}/package.json'; - -/** - * Workspace @sentry and @sentry-internal packages that have a built tarball for the E2E version. - * @returns The names of the Sentry tarball packages. - */ -export function getPublishedSentryTarballPackageNames(): string[] { - const version = getE2eTestsPackageVersion(); - const names: string[] = []; - - for (const packageJsonPath of globSync(TARBALL_PACKAGE_JSON_GLOB, { - cwd: REPOSITORY_ROOT, - absolute: true, - })) { - const pkg = readJson<{ name?: string }>(packageJsonPath); - const name = pkg.name; - if (!name || (!name.startsWith('@sentry/') && !name.startsWith('@sentry-internal/'))) { - continue; - } - const packageDir = path.dirname(packageJsonPath); - const tarball = path.join(packageDir, versionedTarballFilename(name, version)); - if (fs.existsSync(tarball)) { - names.push(name); - } - } - - return names.sort(); -} - -/** Stable symlink name in `packed/` (no version segment). */ -export function packedSymlinkFilename(packageName: string): string { - return `${npmPackBasename(packageName)}-packed.tgz`; -} - -/** - * Versioned tarball filename produced by `npm pack` in a package directory. - */ -export function versionedTarballFilename(packageName: string, version: string): string { - return `${npmPackBasename(packageName)}-${version}.tgz`; -} - -/** - * npm pack tarball basename (without version and .tgz), e.g. `@sentry/core` -> `sentry-core`. - */ -function npmPackBasename(packageName: string): string { - return packageName.replace(/^@/, '').replace(/\//g, '-'); -} - -function readJson(filePath: string): T { - return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T; -} - -function getE2eTestsPackageVersion(): string { - return readJson<{ version: string }>(path.join(E2E_TESTS_ROOT, 'package.json')).version; -} diff --git a/dev-packages/e2e-tests/lib/pnpmOverrides.ts b/dev-packages/e2e-tests/lib/pnpmOverrides.mjs similarity index 71% rename from dev-packages/e2e-tests/lib/pnpmOverrides.ts rename to dev-packages/e2e-tests/lib/pnpmOverrides.mjs index 9f5dd88a9ea8..8812886d9371 100644 --- a/dev-packages/e2e-tests/lib/pnpmOverrides.ts +++ b/dev-packages/e2e-tests/lib/pnpmOverrides.mjs @@ -1,7 +1,8 @@ -import { readFile, writeFile } from 'fs/promises'; -import * as path from 'path'; -import { getPublishedSentryTarballPackageNames, packedSymlinkFilename } from './packedTarballUtils'; -import { fixFileLinkDependencies } from './copyToTemp'; +// @ts-check +import { readFile, writeFile } from 'node:fs/promises'; +import * as path from 'node:path'; +import { fixFileLinkDependencies } from './copyToTemp.mjs'; +import { getPackedTarballs, packedSymlinkFilename } from './packedTarballUtils.mjs'; /** * For a given temp test application directory, add pnpm overrides to pin internal Sentry dependencies to their packed tarballs. @@ -10,12 +11,14 @@ import { fixFileLinkDependencies } from './copyToTemp'; * pnpm reads overrides only from pnpm-workspace.yaml. A fixture's existing overrides take precedence. * https://pnpm.io/settings/dependency-resolution#overrides * - * @param tmpDirPath - The temporary directory path of the test application. - * @param packedDirPath - The path to the packed tarballs. + * @param {string} tmpDirPath - The temporary directory path of the test application. + * @param {string} packedDirPath - The path to the packed tarballs. + * @returns {Promise} */ -export async function addPnpmOverrides(tmpDirPath: string, packedDirPath: string): Promise { +export async function addPnpmOverrides(tmpDirPath, packedDirPath) { const packageJsonPath = path.join(tmpDirPath, 'package.json'); - const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')) as { pnpm?: unknown; resolutions?: unknown }; + /** @type {{ pnpm?: unknown; resolutions?: unknown }} */ + const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')); // pnpm 11+ ignores these fields, so their settings would silently have no effect. if (packageJson.pnpm || packageJson.resolutions) { @@ -24,7 +27,7 @@ export async function addPnpmOverrides(tmpDirPath: string, packedDirPath: string ); } - const packageNames = getPublishedSentryTarballPackageNames(); + const packageNames = getPackedTarballs().map(({ name }) => name); const overrides = Object.fromEntries( packageNames.map(packageName => [packageName, `file:${packedDirPath}/${packedSymlinkFilename(packageName)}`]), ); @@ -48,7 +51,11 @@ export async function addPnpmOverrides(tmpDirPath: string, packedDirPath: string console.log(`Added ${packageNames.length} internal Sentry package overrides`); } -function parseWorkspaceOverrides(workspace: string): Record { +/** + * @param {string} workspace + * @returns {Record} + */ +function parseWorkspaceOverrides(workspace) { const overrides = /^overrides:\n((?:[ \t]+.*(?:\n|$))*)/m.exec(workspace)?.[1]; if (!overrides) { return {}; @@ -69,15 +76,27 @@ function parseWorkspaceOverrides(workspace: string): Record { ); } -function parseYamlString(quoted: string): string { - return quoted.startsWith("'") ? quoted.slice(1, -1).replace(/''/g, "'") : (JSON.parse(quoted) as string); +/** + * @param {string} quoted + * @returns {string} + */ +function parseYamlString(quoted) { + return quoted.startsWith("'") ? quoted.slice(1, -1).replace(/''/g, "'") : JSON.parse(quoted); } -function removeWorkspaceOverrides(workspace: string): string { +/** + * @param {string} workspace + * @returns {string} + */ +function removeWorkspaceOverrides(workspace) { return workspace.replace(/^overrides:\n(?:[ \t]+.*(?:\n|$))*/m, ''); } -function formatWorkspaceOverrides(overrides: Record): string { +/** + * @param {Record} overrides + * @returns {string} + */ +function formatWorkspaceOverrides(overrides) { return Object.entries(overrides) .map(([packageName, target]) => ` ${JSON.stringify(packageName)}: ${JSON.stringify(target)}`) .join('\n'); diff --git a/dev-packages/e2e-tests/lib/runtimeFiles.ts b/dev-packages/e2e-tests/lib/runtimeFiles.mjs similarity index 81% rename from dev-packages/e2e-tests/lib/runtimeFiles.ts rename to dev-packages/e2e-tests/lib/runtimeFiles.mjs index a29c0bc890d3..505d7309847b 100644 --- a/dev-packages/e2e-tests/lib/runtimeFiles.ts +++ b/dev-packages/e2e-tests/lib/runtimeFiles.mjs @@ -1,12 +1,15 @@ +// @ts-check /* eslint-disable no-console */ -import { copyFileSync, existsSync, readdirSync } from 'fs'; -import { join } from 'path'; +import { copyFileSync, existsSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; /** * Copies each file in `dir` that has `runtime` as a part of its name over the existing file without that part, for * example `app/entry.server.cloudflare.tsx` over `app/entry.server.tsx`. + * @param {string} dir + * @param {string} runtime */ -export function applyRuntimeFiles(dir: string, runtime: string): void { +export function applyRuntimeFiles(dir, runtime) { for (const entry of readdirSync(dir, { withFileTypes: true })) { if (entry.name === 'node_modules' || entry.name.startsWith('.')) { continue; diff --git a/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.mjs b/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.mjs new file mode 100644 index 000000000000..1045acea8e40 --- /dev/null +++ b/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.mjs @@ -0,0 +1,38 @@ +// @ts-check +/* eslint-disable no-console */ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getE2eTestsPackageVersion, getPackedTarballs, packedSymlinkFilename } from './packedTarballUtils.mjs'; + +const e2eTestsRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const repositoryRoot = path.resolve(e2eTestsRoot, '../..'); +const packedDir = path.join(e2eTestsRoot, 'packed'); + +/** + * Ensures `packed/-packed.tgz` symlinks point at the current versioned tarballs under `packages/*`. + * Run after `pnpm run build:tarball` at the repo root (or from CI after restoring the tarball cache). + */ +export function syncPackedTarballSymlinks() { + fs.mkdirSync(packedDir, { recursive: true }); + + for (const entry of fs.readdirSync(packedDir, { withFileTypes: true })) { + if (!entry.name.endsWith('-packed.tgz')) { + continue; + } + fs.rmSync(path.join(packedDir, entry.name), { recursive: true, force: true }); + } + + const tarballs = getPackedTarballs(); + if (tarballs.length === 0) { + throw new Error( + `No packed tarballs found for version ${getE2eTestsPackageVersion()} under packages/*/. Run "pnpm run build:tarball" at the repository root.`, + ); + } + + for (const { name, tarballPath } of tarballs) { + fs.symlinkSync(tarballPath, path.join(packedDir, packedSymlinkFilename(name))); + } + + console.log(`Linked ${tarballs.length} tarball symlinks in ${path.relative(repositoryRoot, packedDir) || 'packed'}.`); +} diff --git a/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.ts b/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.ts deleted file mode 100644 index 5d1d4cf45a6b..000000000000 --- a/dev-packages/e2e-tests/lib/syncPackedTarballSymlinks.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable no-console */ -import * as fs from 'fs'; -import * as path from 'path'; -import { sync as globSync } from 'glob'; -import { packedSymlinkFilename, TARBALL_PACKAGE_JSON_GLOB, versionedTarballFilename } from './packedTarballUtils'; - -const e2eTestsRoot = path.resolve(__dirname, '..'); -const repositoryRoot = path.resolve(e2eTestsRoot, '../..'); -const packedDir = path.join(e2eTestsRoot, 'packed'); - -function readJson(filePath: string): T { - return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T; -} - -/** - * Ensures `packed/-packed.tgz` symlinks point at the current versioned tarballs. - * Run after `pnpm run build:tarball` at the repo root (or from CI after restoring the tarball cache). - */ -export function syncPackedTarballSymlinks(): void { - const { version } = readJson<{ version: string }>(path.join(e2eTestsRoot, 'package.json')); - - fs.mkdirSync(packedDir, { recursive: true }); - - for (const entry of fs.readdirSync(packedDir, { withFileTypes: true })) { - if (!entry.name.endsWith('-packed.tgz')) { - continue; - } - fs.rmSync(path.join(packedDir, entry.name), { recursive: true, force: true }); - } - - const packageJsonPaths = globSync(TARBALL_PACKAGE_JSON_GLOB, { - cwd: repositoryRoot, - absolute: true, - }); - - let linked = 0; - for (const packageJsonPath of packageJsonPaths) { - const pkg = readJson<{ name?: string }>(packageJsonPath); - const name = pkg.name; - if (!name || (!name.startsWith('@sentry/') && !name.startsWith('@sentry-internal/'))) { - continue; - } - - const packageDir = path.dirname(packageJsonPath); - const expectedTarball = path.join(packageDir, versionedTarballFilename(name, version)); - - if (!fs.existsSync(expectedTarball)) { - continue; - } - - const linkName = packedSymlinkFilename(name); - const linkPath = path.join(packedDir, linkName); - - fs.symlinkSync(expectedTarball, linkPath); - linked++; - } - - if (linked === 0) { - throw new Error( - `No packed tarballs found for version ${version}. Run "pnpm run build:tarball" at the repository root.`, - ); - } - - console.log(`Linked ${linked} tarball symlinks in ${path.relative(repositoryRoot, packedDir) || 'packed'}.`); -} diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index f40846c63ed9..7de3fd9e3a66 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -9,13 +9,13 @@ "lint:ts": "tsc --noEmit", "test:e2e": "run-s test:prepare test:validate test:run", "test:run": "tsx run.ts", - "test:prepare": "tsx prepare.ts", - "test:validate": "tsx validate-packed-tarball-setup.ts", + "test:prepare": "node prepare.mjs", + "test:validate": "node validate-packed-tarball-setup.mjs", "clean": "rimraf tmp node_modules packed && pnpm run clean:test-applications && pnpm run clean:pnpm", "ci:build-matrix": "node ./lib/getTestMatrix.mjs", "ci:build-matrix-optional": "node ./lib/getTestMatrix.mjs --optional=true", - "ci:copy-to-temp": "tsx ./ciCopyToTemp.ts", - "ci:pnpm-overrides": "tsx ./ciPnpmOverrides.ts", + "ci:copy-to-temp": "node ./ciCopyToTemp.mjs", + "ci:pnpm-overrides": "node ./ciPnpmOverrides.mjs", "clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,.astro,.output,pnpm-lock.yaml,.last-run.json,test-results,.angular,event-dumps}", "clean:pnpm": "pnpm store prune" }, diff --git a/dev-packages/e2e-tests/prepare.mjs b/dev-packages/e2e-tests/prepare.mjs new file mode 100644 index 000000000000..bcaea94b2895 --- /dev/null +++ b/dev-packages/e2e-tests/prepare.mjs @@ -0,0 +1,4 @@ +// @ts-check +import { syncPackedTarballSymlinks } from './lib/syncPackedTarballSymlinks.mjs'; + +syncPackedTarballSymlinks(); diff --git a/dev-packages/e2e-tests/prepare.ts b/dev-packages/e2e-tests/prepare.ts deleted file mode 100644 index 049b727b1b21..000000000000 --- a/dev-packages/e2e-tests/prepare.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable no-console */ -import * as dotenv from 'dotenv'; -import { syncPackedTarballSymlinks } from './lib/syncPackedTarballSymlinks'; - -async function run(): Promise { - // Load environment variables from .env file locally - dotenv.config(); - - syncPackedTarballSymlinks(); -} - -run().catch(error => { - console.error(error); - process.exit(1); -}); diff --git a/dev-packages/e2e-tests/run.ts b/dev-packages/e2e-tests/run.ts index 964cc9c46e39..db41879c8f64 100644 --- a/dev-packages/e2e-tests/run.ts +++ b/dev-packages/e2e-tests/run.ts @@ -5,10 +5,10 @@ import { mkdir, mkdtemp, readFile, rm } from 'fs/promises'; import { sync as globSync } from 'glob'; import { tmpdir } from 'os'; import { delimiter, dirname, join, resolve } from 'path'; -import { copyToTemp } from './lib/copyToTemp'; -import { applyRuntimeFiles } from './lib/runtimeFiles'; -import { syncPackedTarballSymlinks } from './lib/syncPackedTarballSymlinks'; -import { addPnpmOverrides } from './lib/pnpmOverrides'; +import { copyToTemp } from './lib/copyToTemp.mjs'; +import { applyRuntimeFiles } from './lib/runtimeFiles.mjs'; +import { syncPackedTarballSymlinks } from './lib/syncPackedTarballSymlinks.mjs'; +import { addPnpmOverrides } from './lib/pnpmOverrides.mjs'; interface SentryTestVariant { 'build-command': string; diff --git a/dev-packages/e2e-tests/tsconfig.json b/dev-packages/e2e-tests/tsconfig.json index 026669f596c0..f3ef44daf268 100644 --- a/dev-packages/e2e-tests/tsconfig.json +++ b/dev-packages/e2e-tests/tsconfig.json @@ -2,6 +2,8 @@ "extends": "../../tsconfig.json", "exclude": ["node_modules", "test-applications"], "compilerOptions": { - "types": ["node"] + "types": ["node"], + "allowJs": true, + "noEmit": true } } diff --git a/dev-packages/e2e-tests/validate-packed-tarball-setup.mjs b/dev-packages/e2e-tests/validate-packed-tarball-setup.mjs new file mode 100644 index 000000000000..053ded13411b --- /dev/null +++ b/dev-packages/e2e-tests/validate-packed-tarball-setup.mjs @@ -0,0 +1,39 @@ +// @ts-check +import * as assert from 'node:assert'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getE2eTestsPackageVersion, getPackedTarballs } from './lib/packedTarballUtils.mjs'; + +const tarballs = getPackedTarballs(); + +assert.ok( + tarballs.length > 0, + `No tarballs found for version ${getE2eTestsPackageVersion()}. Run "pnpm run build:tarball" at the repository root.`, +); + +const packedDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'packed'); +const symlinkPaths = fs.existsSync(packedDir) + ? fs + .readdirSync(packedDir) + .filter(name => name.endsWith('-packed.tgz')) + .map(name => path.join(packedDir, name)) + : []; + +assert.ok( + symlinkPaths.length > 0, + 'No packed tarball symlinks found. Run "pnpm run test:prepare" in dev-packages/e2e-tests.', +); + +assert.strictEqual( + symlinkPaths.length, + tarballs.length, + `Tarball count (${tarballs.length}) does not match packed symlink count (${symlinkPaths.length}). Re-run "pnpm run test:prepare".`, +); + +for (const symlinkPath of symlinkPaths) { + const st = fs.lstatSync(symlinkPath); + assert.ok(st.isSymbolicLink(), `Expected ${symlinkPath} to be a symlink.`); + const target = path.resolve(path.dirname(symlinkPath), fs.readlinkSync(symlinkPath)); + assert.ok(fs.existsSync(target), `Symlink ${symlinkPath} points to missing file: ${target}`); +} diff --git a/dev-packages/e2e-tests/validate-packed-tarball-setup.ts b/dev-packages/e2e-tests/validate-packed-tarball-setup.ts deleted file mode 100644 index 933121f71cbe..000000000000 --- a/dev-packages/e2e-tests/validate-packed-tarball-setup.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as assert from 'assert'; -import * as fs from 'fs'; -import { sync as globSync } from 'glob'; -import * as path from 'path'; - -const repositoryRoot = path.resolve(__dirname, '../..'); - -const e2ePkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8')) as { version: string }; -const version = e2ePkg.version; - -const tarballPaths = globSync(`{packages/*,dev-packages/test-utils}/sentry-*-${version}.tgz`, { - cwd: repositoryRoot, - absolute: true, -}); - -assert.ok( - tarballPaths.length > 0, - `No tarballs found for version ${version}. Run "pnpm run build:tarball" at the repository root.`, -); - -const symlinkPaths = globSync('packed/*-packed.tgz', { - cwd: __dirname, - absolute: true, -}); - -assert.ok( - symlinkPaths.length > 0, - 'No packed tarball symlinks found. Run "pnpm run test:prepare" in dev-packages/e2e-tests.', -); - -assert.strictEqual( - symlinkPaths.length, - tarballPaths.length, - `Tarball count (${tarballPaths.length}) does not match packed symlink count (${symlinkPaths.length}). Re-run "pnpm run test:prepare".`, -); - -for (const symlinkPath of symlinkPaths) { - const st = fs.lstatSync(symlinkPath); - assert.ok(st.isSymbolicLink(), `Expected ${symlinkPath} to be a symlink.`); - const target = path.resolve(path.dirname(symlinkPath), fs.readlinkSync(symlinkPath)); - assert.ok(fs.existsSync(target), `Symlink ${symlinkPath} points to missing file: ${target}`); -} diff --git a/scripts/normalize-e2e-test-dump-transaction-events.js b/scripts/normalize-e2e-test-dump-transaction-events.js index e3459d52621d..376b86d2b413 100644 --- a/scripts/normalize-e2e-test-dump-transaction-events.js +++ b/scripts/normalize-e2e-test-dump-transaction-events.js @@ -3,93 +3,91 @@ const fs = require('fs'); const path = require('path'); -const glob = require('glob'); - -glob.glob( - '../dev-packages/e2e-tests/test-applications/*/event-dumps/*.dump', - { - cwd: __dirname, - absolute: true, - }, - (err, dumpPaths) => { - if (err) { - throw err; + +const dumpDir = process.argv[2]; +if (!dumpDir) { + throw new Error('Usage: node normalize-e2e-test-dump-transaction-events.js '); +} + +const dumpPaths = fs.existsSync(dumpDir) + ? fs + .readdirSync(dumpDir) + .filter(name => name.endsWith('.dump')) + .map(name => path.join(dumpDir, name)) + : []; + +dumpPaths.forEach(dumpPath => { + const fileContents = fs.readFileSync(dumpPath, 'utf8'); + + const transactionNodes = []; + + fileContents.split('\n').forEach(serializedEnvelope => { + let envelope; + try { + envelope = JSON.parse(serializedEnvelope); + } catch { + return; + // noop } - dumpPaths.forEach(dumpPath => { - const fileContents = fs.readFileSync(dumpPath, 'utf8'); - - const transactionNodes = []; - - fileContents.split('\n').forEach(serializedEnvelope => { - let envelope; - try { - envelope = JSON.parse(serializedEnvelope); - } catch { - return; - // noop - } - - const envelopeItems = envelope[1]; - - envelopeItems.forEach(([envelopeItemHeader, transaction]) => { - if (envelopeItemHeader.type === 'transaction') { - const rootNode = { - runtime: transaction.contexts.runtime?.name, - op: transaction.contexts.trace.op, - name: transaction.transaction, - children: [], - }; - - const spanMap = new Map(); - spanMap.set(transaction.contexts.trace.span_id, rootNode); - - transaction.spans.forEach(span => { - const node = { - op: span.data['sentry.op'], - name: span.description, - parent_span_id: span.parent_span_id, - children: [], - }; - spanMap.set(span.span_id, node); - }); - - transaction.spans.forEach(span => { - const node = spanMap.get(span.span_id); - if (node?.parent_span_id) { - const parentNode = spanMap.get(node.parent_span_id); - parentNode.children.push(node); - } - }); - - transactionNodes.push(rootNode); - } + const envelopeItems = envelope[1]; + + envelopeItems.forEach(([envelopeItemHeader, transaction]) => { + if (envelopeItemHeader.type === 'transaction') { + const rootNode = { + runtime: transaction.contexts.runtime?.name, + op: transaction.contexts.trace.op, + name: transaction.transaction, + children: [], + }; + + const spanMap = new Map(); + spanMap.set(transaction.contexts.trace.span_id, rootNode); + + transaction.spans.forEach(span => { + const node = { + op: span.data['sentry.op'], + name: span.description, + parent_span_id: span.parent_span_id, + children: [], + }; + spanMap.set(span.span_id, node); }); - }); - - const output = transactionNodes - .sort((a, b) => { - const aSerialized = serializeNode(a); - const bSerialized = serializeNode(b); - if (aSerialized < bSerialized) { - return -1; - } else if (aSerialized > bSerialized) { - return 1; - } else { - return 0; + + transaction.spans.forEach(span => { + const node = spanMap.get(span.span_id); + if (node?.parent_span_id) { + const parentNode = spanMap.get(node.parent_span_id); + parentNode.children.push(node); } - }) - .map(node => buildDeterministicStringFromNode(node)) - .join('\n\n-----------------------\n\n'); - - fs.writeFileSync( - path.join(path.dirname(dumpPath), `normalized-transactions-${path.basename(dumpPath, '.dump')}.txt`), - output, - 'utf-8', - ); + }); + + transactionNodes.push(rootNode); + } }); - }, -); + }); + + const output = transactionNodes + .sort((a, b) => { + const aSerialized = serializeNode(a); + const bSerialized = serializeNode(b); + if (aSerialized < bSerialized) { + return -1; + } else if (aSerialized > bSerialized) { + return 1; + } else { + return 0; + } + }) + .map(node => buildDeterministicStringFromNode(node)) + .join('\n\n-----------------------\n\n'); + + fs.writeFileSync( + path.join(path.dirname(dumpPath), `normalized-transactions-${path.basename(dumpPath, '.dump')}.txt`), + output, + 'utf-8', + ); +}); // ------- utility fns ---------- From 525339ca740c22b7a695a21060b1f3201087fb2f Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 14 Oct 2026 17:09:16 +0200 Subject: [PATCH 2/2] ref(e2e): Drop TypeScript and unused dependencies from e2e-tests With all scripts as plain .mjs files, the local runner no longer needs tsx, dotenv or glob. esbuild was unused. Type checking of this package was never run in CI, so it no longer has a tsconfig; the JSDoc types are kept for editors. Co-Authored-By: Claude Opus 5.5 --- dev-packages/e2e-tests/package.json | 10 +- dev-packages/e2e-tests/{run.ts => run.mjs} | 101 +++++++++++---------- dev-packages/e2e-tests/tsconfig.json | 9 -- pnpm-lock.yaml | 15 --- 4 files changed, 57 insertions(+), 78 deletions(-) rename dev-packages/e2e-tests/{run.ts => run.mjs} (80%) delete mode 100644 dev-packages/e2e-tests/tsconfig.json diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index 7de3fd9e3a66..1a228e59525d 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -6,9 +6,8 @@ "scripts": { "lint:fix": "oxlint . --fix --type-aware", "lint": "oxlint . --type-aware", - "lint:ts": "tsc --noEmit", "test:e2e": "run-s test:prepare test:validate test:run", - "test:run": "tsx run.ts", + "test:run": "node run.mjs", "test:prepare": "node prepare.mjs", "test:validate": "node validate-packed-tarball-setup.mjs", "clean": "rimraf tmp node_modules packed && pnpm run clean:test-applications && pnpm run clean:pnpm", @@ -20,13 +19,8 @@ "clean:pnpm": "pnpm store prune" }, "devDependencies": { - "@types/node": "^18.19.1", - "dotenv": "17.4.2", - "esbuild": "0.28.1", "eslint-plugin-regexp": "^3.1.0", - "glob": "^13.0.6", - "rimraf": "^6.1.3", - "tsx": "^4.23.0" + "rimraf": "^6.1.3" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/run.ts b/dev-packages/e2e-tests/run.mjs similarity index 80% rename from dev-packages/e2e-tests/run.ts rename to dev-packages/e2e-tests/run.mjs index db41879c8f64..0125ddd89179 100644 --- a/dev-packages/e2e-tests/run.ts +++ b/dev-packages/e2e-tests/run.mjs @@ -1,43 +1,41 @@ +// @ts-check /* eslint-disable no-console */ -import { execFileSync, spawn } from 'child_process'; -import * as dotenv from 'dotenv'; -import { mkdir, mkdtemp, readFile, rm } from 'fs/promises'; -import { sync as globSync } from 'glob'; -import { tmpdir } from 'os'; -import { delimiter, dirname, join, resolve } from 'path'; +import { execFileSync, spawn } from 'node:child_process'; +import { existsSync, readdirSync } from 'node:fs'; +import { mkdir, mkdtemp, readFile, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { delimiter, dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { copyToTemp } from './lib/copyToTemp.mjs'; +import { addPnpmOverrides } from './lib/pnpmOverrides.mjs'; import { applyRuntimeFiles } from './lib/runtimeFiles.mjs'; import { syncPackedTarballSymlinks } from './lib/syncPackedTarballSymlinks.mjs'; -import { addPnpmOverrides } from './lib/pnpmOverrides.mjs'; -interface SentryTestVariant { - 'build-command': string; - 'assert-command'?: string; - label?: string; - skip?: boolean; - /** Runtime of the variant (`bun`, `deno` or `cloudflare`). Sets `RUNTIME` and selects the runtime-specific files. */ - runtime?: string; -} +const __dirname = dirname(fileURLToPath(import.meta.url)); -interface PackageJson { - sentryTest?: { - variants?: SentryTestVariant[]; - optionalVariants?: SentryTestVariant[]; - }; -} +/** + * `runtime` is the runtime of the variant (`bun`, `deno` or `cloudflare`). It sets `RUNTIME` and selects the + * runtime-specific files. + * @typedef {{ 'build-command': string; 'assert-command'?: string; label?: string; skip?: boolean; runtime?: string }} SentryTestVariant + */ + +/** @typedef {{ sentryTest?: { variants?: SentryTestVariant[]; optionalVariants?: SentryTestVariant[] } }} PackageJson */ const DEFAULT_DSN = 'https://username@domain/123'; const DEFAULT_SENTRY_ORG_SLUG = 'sentry-javascript-sdks'; const DEFAULT_SENTRY_PROJECT = 'sentry-javascript-e2e-tests'; -function asyncExec( - command: string | string[], - options: { env: Record; cwd: string }, -): Promise { +/** + * @param {string | string[]} command + * @param {{ env: Record; cwd: string }} options + * @returns {Promise} + */ +function asyncExec(command, options) { return new Promise((resolve, reject) => { // If command is an array, use spawn with separate command and args (safer) // If command is a string, maintain backward compatibility with shell: true - let process: ReturnType; + /** @type {ReturnType} */ + let process; if (typeof command === 'string') { process = spawn(command, { ...options, shell: true }); } else { @@ -76,27 +74,28 @@ function asyncExec( }); } -function findMatchingVariant(variants: SentryTestVariant[], variantLabel: string): SentryTestVariant | undefined { +/** + * @param {SentryTestVariant[]} variants + * @param {string} variantLabel + * @returns {SentryTestVariant | undefined} + */ +function findMatchingVariant(variants, variantLabel) { const variantLabelLower = variantLabel.toLowerCase(); return variants.find(variant => variant.label?.toLowerCase().includes(variantLabelLower)); } -async function getVariantBuildCommand( - packageJsonPath: string, - variantLabel: string, - testAppPath: string, -): Promise<{ - buildCommand: string; - assertCommand: string; - testLabel: string; - matchedVariantLabel?: string; - skip?: boolean; - runtime?: string; -}> { +/** + * @param {string} packageJsonPath + * @param {string} variantLabel + * @param {string} testAppPath + * @returns {Promise<{ buildCommand: string; assertCommand: string; testLabel: string; matchedVariantLabel?: string; skip?: boolean; runtime?: string }>} + */ +async function getVariantBuildCommand(packageJsonPath, variantLabel, testAppPath) { try { const packageJsonContent = await readFile(packageJsonPath, 'utf-8'); - const packageJson: PackageJson = JSON.parse(packageJsonContent); + /** @type {PackageJson} */ + const packageJson = JSON.parse(packageJsonContent); const allVariants = [ ...(packageJson.sentryTest?.variants || []), @@ -132,12 +131,14 @@ async function getVariantBuildCommand( * The directory of the node version that the app pins. CI uses the same pin (see `node-version-file` in * .github/workflows/build.yml). Only node comes from Volta: Volta cannot run pnpm 12 * (https://github.com/volta-cli/volta/issues/2114), so the apps use the pnpm version that runs this script. + * @param {string} cwd + * @returns {string | undefined} */ -function getPinnedNodeDir(cwd: string): string | undefined { +function getPinnedNodeDir(cwd) { try { return dirname(execFileSync('volta', ['run', 'node', '-p', 'process.execPath'], { cwd, encoding: 'utf8' }).trim()); } catch (error) { - if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { + if (/** @type {NodeJS.ErrnoException} */ (error).code !== 'ENOENT') { throw error; } console.warn(`Volta is not installed, so ${cwd} runs on node ${process.version} instead of the version it pins.`); @@ -145,9 +146,12 @@ function getPinnedNodeDir(cwd: string): string | undefined { } } -async function run(): Promise { +async function run() { // Load environment variables from .env file locally - dotenv.config(); + const envFile = join(__dirname, '.env'); + if (existsSync(envFile)) { + process.loadEnvFile(envFile); + } // Allow to run a single app only via `pnpm run test:run ` const appName = process.argv[2] || ''; @@ -155,7 +159,8 @@ async function run(): Promise { const allTestFlags = process.argv.slice(3); // Check for --variant flag - let variantLabel: string | undefined; + /** @type {string | undefined} */ + let variantLabel; let skipNextFlag = false; const testFlags = allTestFlags.filter((flag, index) => { @@ -223,7 +228,11 @@ async function run(): Promise { await asyncExec('pnpm run clean:test-applications', { env, cwd: __dirname }); await asyncExec('pnpm cache delete "@sentry/*"', { env, cwd: __dirname }); - const testAppPaths = appName ? [appName.trim()] : globSync('*', { cwd: `${__dirname}/test-applications/` }); + const testAppPaths = appName + ? [appName.trim()] + : readdirSync(join(__dirname, 'test-applications'), { withFileTypes: true }) + .filter(entry => entry.isDirectory() && !entry.name.startsWith('.')) + .map(entry => entry.name); console.log(`Runnings tests for: ${testAppPaths.join(', ')}`); console.log(''); diff --git a/dev-packages/e2e-tests/tsconfig.json b/dev-packages/e2e-tests/tsconfig.json deleted file mode 100644 index f3ef44daf268..000000000000 --- a/dev-packages/e2e-tests/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "exclude": ["node_modules", "test-applications"], - "compilerOptions": { - "types": ["node"], - "allowJs": true, - "noEmit": true - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e21069427b5..2bb7ba85b3d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -691,27 +691,12 @@ importers: dev-packages/e2e-tests: devDependencies: - '@types/node': - specifier: ^18.19.1 - version: 18.19.130 - dotenv: - specifier: 17.4.2 - version: 17.4.2 - esbuild: - specifier: 0.28.1 - version: 0.28.1 eslint-plugin-regexp: specifier: ^3.1.0 version: 3.1.0 - glob: - specifier: ^13.0.6 - version: 13.0.6 rimraf: specifier: ^6.1.3 version: 6.1.3 - tsx: - specifier: ^4.23.0 - version: 4.23.0 dev-packages/external-contributor-gh-action: dependencies: