Add build testing and pre-commit hooks
- Add test-build.js script to verify standalone build locally - Add pre-commit hook with security, build, and test checks - Copy required-server-files.json to root of standalone for Amplify - Add husky for automatic pre-commit validation This ensures we test builds locally before pushing
This commit is contained in:
1
.husky/pre-commit
Executable file
1
.husky/pre-commit
Executable file
@@ -0,0 +1 @@
|
||||
./scripts/pre-commit.sh
|
||||
@@ -11,6 +11,7 @@ frontend:
|
||||
commands:
|
||||
- npm run build
|
||||
- cp -r .next/static .next/standalone/.next/
|
||||
- cp .next/standalone/.next/required-server-files.json .next/standalone/
|
||||
artifacts:
|
||||
baseDirectory: .next/standalone
|
||||
files:
|
||||
|
||||
17
package-lock.json
generated
17
package-lock.json
generated
@@ -28,6 +28,7 @@
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^30.0.0",
|
||||
"jest-environment-jsdom": "^30.0.0",
|
||||
"postcss": "^8.4.32",
|
||||
@@ -6043,6 +6044,22 @@
|
||||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.7",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
|
||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
"lint": "next lint",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"security:check": "node scripts/security-check.js"
|
||||
"security:check": "node scripts/security-check.js",
|
||||
"test:build": "node scripts/test-build.js",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/cheerio": "^0.22.35",
|
||||
@@ -32,6 +34,7 @@
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"husky": "^9.1.7",
|
||||
"jest": "^30.0.0",
|
||||
"jest-environment-jsdom": "^30.0.0",
|
||||
"postcss": "^8.4.32",
|
||||
|
||||
29
scripts/pre-commit.sh
Executable file
29
scripts/pre-commit.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🔍 Running pre-commit checks..."
|
||||
|
||||
# Run security check
|
||||
echo "🔐 Checking for credential leaks..."
|
||||
npm run security:check
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Security check failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run build test
|
||||
echo "🏗️ Testing build..."
|
||||
node scripts/test-build.js
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Build test failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
echo "🧪 Running tests..."
|
||||
npm test -- --passWithNoTests
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Tests failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All pre-commit checks passed!"
|
||||
69
scripts/test-build.js
Executable file
69
scripts/test-build.js
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
console.log('🧪 Testing build locally...\n');
|
||||
|
||||
// Clean previous build
|
||||
console.log('🧹 Cleaning previous build...');
|
||||
try {
|
||||
execSync('rm -rf .next', { stdio: 'inherit' });
|
||||
} catch (e) {
|
||||
// Ignore if doesn't exist
|
||||
}
|
||||
|
||||
// Run build
|
||||
console.log('\n🔨 Running build...');
|
||||
try {
|
||||
execSync('npm run build', { stdio: 'inherit' });
|
||||
} catch (e) {
|
||||
console.error('❌ Build failed!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check for required files
|
||||
console.log('\n🔍 Checking build output...');
|
||||
const checks = [
|
||||
{ path: '.next/standalone/server.js', name: 'Standalone server' },
|
||||
{ path: '.next/standalone/.next/required-server-files.json', name: 'Required server files' },
|
||||
{ path: '.next/static', name: 'Static directory' },
|
||||
];
|
||||
|
||||
let allPassed = true;
|
||||
for (const check of checks) {
|
||||
if (fs.existsSync(check.path)) {
|
||||
console.log(`✅ ${check.name}: Found`);
|
||||
} else {
|
||||
console.error(`❌ ${check.name}: Missing at ${check.path}`);
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the copy command
|
||||
console.log('\n📋 Testing copy command...');
|
||||
try {
|
||||
execSync('cp -r .next/static .next/standalone/.next/', { stdio: 'inherit' });
|
||||
console.log('✅ Copy command successful');
|
||||
} catch (e) {
|
||||
console.error('❌ Copy command failed');
|
||||
allPassed = false;
|
||||
}
|
||||
|
||||
// Check final structure
|
||||
console.log('\n📁 Final structure check...');
|
||||
const finalPath = '.next/standalone/.next/static';
|
||||
if (fs.existsSync(finalPath)) {
|
||||
console.log('✅ Static files copied successfully');
|
||||
} else {
|
||||
console.error('❌ Static files not in final location');
|
||||
allPassed = false;
|
||||
}
|
||||
|
||||
if (!allPassed) {
|
||||
console.error('\n❌ Build test failed! Do not push.');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('\n✅ All build tests passed!');
|
||||
}
|
||||
Reference in New Issue
Block a user