From b93ead0c9cd719708ba16c6b4ab5ea1405a3408d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Thu, 11 Apr 2024 09:44:47 +0200 Subject: [PATCH] chore: add test mapping script (#63757) ### What? This adds a script that first gets a list of changed files compared to our base branch (`canary`) in PRs and identifies related test files by looking them up from a `related-tests-manifest.json`, then runs them. ### Why? We would like to be able to run related E2E tests when certain files change, so we can test deployment stability. NOTE: We still want to run all E2E tests on PRs, but this script can be used to also test deployments for hot paths. Since these tests can take up to [3-4 hours](https://github.com/vercel/next.js/actions/workflows/test_e2e_deploy.yml), we aim to run a subset of these tests first. Closes NEXT-2947 --- scripts/run-related-test.mjs | 54 ++++++++++++++++++++++++++++++++ test/related-tests-manifest.json | 3 ++ 2 files changed, 57 insertions(+) create mode 100644 scripts/run-related-test.mjs create mode 100644 test/related-tests-manifest.json diff --git a/scripts/run-related-test.mjs b/scripts/run-related-test.mjs new file mode 100644 index 0000000000000..4dddae9b0e567 --- /dev/null +++ b/scripts/run-related-test.mjs @@ -0,0 +1,54 @@ +/** + * This script reads the 'test/realted-tests-manifest.json' file, which contains a list of test globs that maps source code files to test files. + * The script is used to find all related test cases for a given code change. + * Usage: `node scripts/run-related-test.mjs ...` + */ + +import { promisify } from 'node:util' +import { exec as execOrg } from 'node:child_process' +import { readFile } from 'node:fs/promises' +import { join } from 'node:path' + +const exec = promisify(execOrg) + +/** + * Get all changed files from git under the packages directory + * @returns {Promise} - List of changed files + */ +async function getChangedFilesFromPackages(baseBranch = 'canary') { + await exec('git config --global --add safe.directory /work') + await exec(`git remote set-branches --add origin ${baseBranch}`) + await exec(`git fetch origin ${baseBranch} --depth=20`) + const { stdout } = await exec(`git diff --name-only ${baseBranch}`) + return stdout + .trim() + .split('\n') + .filter((line) => line.startsWith('packages/')) +} + +export async function getRelatedTests(args = []) { + const relatedTestsManifest = join( + process.cwd(), + 'test', + 'related-tests-manifest.json' + ) + /** @type {Record} */ + const manifest = JSON.parse( + await readFile(relatedTestsManifest, 'utf-8').catch(() => '{}') + ) + const tests = [] + const paths = args.length ? args : await getChangedFilesFromPackages() + for (const path of paths) { + const relatedTestsKey = Object.keys(manifest).find((key) => + path.startsWith(key) + ) + if (relatedTestsKey) { + const lines = manifest[relatedTestsKey] + tests.push(...lines) + } + } + + return Array.from(new Set(tests)) +} + +// console.log(await getRelatedTests(process.argv.slice(2))) diff --git a/test/related-tests-manifest.json b/test/related-tests-manifest.json new file mode 100644 index 0000000000000..3803280f17274 --- /dev/null +++ b/test/related-tests-manifest.json @@ -0,0 +1,3 @@ +{ + "packages/next/src/server": ["e2e/app-dir/ppr-*"] +}