mirror of
https://github.com/PostHog/posthog.git
synced 2026-10-26 09:51:43 +08:00
77 lines
2.8 KiB
JavaScript
77 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// Sizes the PR jest matrix from the count of tests related to the changed files: lists them the
|
|
// way the jest job will, then writes the matrix and the counts to GITHUB_OUTPUT.
|
|
//
|
|
// Run with: CHANGED_FILES="src/a.ts ../products/b.ts" node .github/scripts/jest-select.js
|
|
|
|
const { execFileSync } = require('node:child_process')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
const FRONTEND_DIR = path.resolve(__dirname, '../../frontend')
|
|
|
|
// Initial limit from the probes documented in docs/internal/ci-things-already-tried.md.
|
|
// File counts approximate runtime; tune this from observed shard durations.
|
|
const TEST_FILES_PER_SHARD = 342
|
|
const MAX_SHARDS = 8
|
|
const SEGMENT = 'app'
|
|
|
|
function listRelatedTests(changedFiles) {
|
|
if (changedFiles.length === 0) {
|
|
return []
|
|
}
|
|
// The package's `jest` script runs build:products first, like the jest job does.
|
|
const args = ['jest', '--listTests', '--findRelatedTests', ...changedFiles]
|
|
const output = execFileSync('pnpm', args, {
|
|
cwd: FRONTEND_DIR,
|
|
encoding: 'utf8',
|
|
timeout: 2 * 60 * 1000,
|
|
maxBuffer: 256 * 1024 * 1024,
|
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
})
|
|
return output.split('\n').filter((line) => line.startsWith('/'))
|
|
}
|
|
|
|
function planShards(testCount) {
|
|
return Math.min(MAX_SHARDS, Math.ceil(testCount / TEST_FILES_PER_SHARD))
|
|
}
|
|
|
|
function planOutputs({ changedFiles, changedFileCount, testCount }) {
|
|
const shardCount = planShards(testCount)
|
|
return {
|
|
mode: 'selective',
|
|
matrix: JSON.stringify({
|
|
include: Array.from({ length: shardCount }, (_, i) => ({
|
|
segment: SEGMENT,
|
|
chunk: i + 1,
|
|
shard_count: shardCount,
|
|
})),
|
|
}),
|
|
should_run: String(shardCount > 0),
|
|
changed_files: changedFiles.join(' '),
|
|
changed_file_count: String(changedFileCount),
|
|
selected_file_count: String(changedFiles.length),
|
|
related_test_count: String(testCount),
|
|
shard_count: String(shardCount),
|
|
full_run_reason_category: '',
|
|
full_run_reason_detail: '',
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const changedFiles = (process.env.CHANGED_FILES ?? '').split(' ').filter(Boolean)
|
|
const testCount = listRelatedTests(changedFiles).length
|
|
const outputs = planOutputs({ changedFiles, changedFileCount: process.env.CHANGED_FILE_COUNT ?? '', testCount })
|
|
const lines = Object.entries(outputs).map(([key, value]) => `${key}=${value}\n`)
|
|
fs.appendFileSync(process.env.GITHUB_OUTPUT ?? '/dev/stdout', lines.join(''))
|
|
console.log(
|
|
`Selective mode: ${changedFiles.length} changed files, ${testCount} related tests, ${outputs.shard_count} shards`
|
|
)
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main()
|
|
}
|
|
|
|
module.exports = { planShards, planOutputs, TEST_FILES_PER_SHARD, MAX_SHARDS }
|