Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const createJestConfig = nextJest()
const customJestConfig = {
displayName: process.env.IS_WEBPACK_TEST ? 'webpack' : 'Turbopack',
testMatch: ['**/*.test.js', '**/*.test.ts', '**/*.test.jsx', '**/*.test.tsx'],
globalSetup: '<rootDir>/jest-global-setup.ts',
setupFilesAfterEnv: ['<rootDir>/jest-setup-after-env.ts'],
verbose: true,
rootDir: 'test',
Expand Down
10 changes: 10 additions & 0 deletions packages/next/taskfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2684,6 +2684,16 @@ export async function build(task, opts) {
['precompile', 'compile', 'check_error_codes', 'generate_types'],
opts
)
// Write git commit hash to dist for stale build detection during tests
try {
const { stdout: commitHash } = await execa('git', ['rev-parse', 'HEAD'])
await fs.writeFile(
join(__dirname, 'dist', '.build-commit'),
commitHash.trim()
)
} catch (err) {
console.warn(`Warning: Could not write build commit hash: ${err.message}`)
}
}

export async function generate_types(task, opts) {
Expand Down
4 changes: 4 additions & 0 deletions run-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const glob = promisify(_glob)
const exec = promisify(execOrig)
const core = require('@actions/core')
const { getTestFilter } = require('./test/get-test-filter')
const { checkBuildFreshness } = require('./test/lib/check-build-freshness')

// Do not rename or format. sync-react script relies on this line.
// prettier-ignore
Expand Down Expand Up @@ -219,6 +220,9 @@ async function main() {
// Ensure we have the arguments awaited from yargs.
argv = await argv

// Check for stale or missing build
await checkBuildFreshness()

// `.github/workflows/build_reusable.yml` sets this, we should use it unless
// it's overridden by an explicit `--concurrency` argument.
const envConcurrency =
Expand Down
5 changes: 5 additions & 0 deletions test/jest-global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { checkBuildFreshness } from './lib/check-build-freshness'

export default async function globalSetup() {
await checkBuildFreshness()
}
59 changes: 59 additions & 0 deletions test/lib/check-build-freshness.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { existsSync } = require('fs')
const fsp = require('fs/promises')
const path = require('path')
const { execSync } = require('child_process')

const YELLOW = '\x1b[33m'
const RESET = '\x1b[0m'

/**
* Check if the Next.js build is fresh (matches current git HEAD).
* Prints warnings to console if build is missing or stale.
* @returns {Promise<void>}
*/
async function checkBuildFreshness() {
const distPath = path.join(__dirname, '../../packages/next/dist')
const buildCommitPath = path.join(distPath, '.build-commit')

if (!existsSync(distPath)) {
console.warn(`${YELLOW}⚠️ WARNING: No build found!${RESET}`)
console.warn(
`${YELLOW} The packages/next/dist directory does not exist.${RESET}`
)
console.warn(
`${YELLOW} Run \`pnpm build\` before running tests.\n${RESET}`
)
return
}

if (!existsSync(buildCommitPath)) {
console.warn(`${YELLOW}⚠️ WARNING: Build may be stale!${RESET}`)
console.warn(
`${YELLOW} Unable to verify build freshness (no .build-commit marker).${RESET}`
)
console.warn(`${YELLOW} Run \`pnpm build\` to rebuild.\n${RESET}`)
return
}

try {
const buildCommit = (await fsp.readFile(buildCommitPath, 'utf8')).trim()
const currentCommit = execSync('git rev-parse HEAD', {
encoding: 'utf8',
}).trim()

if (buildCommit !== currentCommit) {
console.warn(`${YELLOW}⚠️ WARNING: Build is stale!${RESET}`)
console.warn(
`${YELLOW} Build was compiled at commit: ${buildCommit.slice(0, 8)}${RESET}`
)
console.warn(
`${YELLOW} Current HEAD is at commit: ${currentCommit.slice(0, 8)}${RESET}`
)
console.warn(`${YELLOW} Run \`pnpm build\` to rebuild.\n${RESET}`)
}
} catch (err) {
// Ignore errors (e.g., git not available)
}
}

module.exports = { checkBuildFreshness }
Loading