- frontend.Dockerfile: runtime-only, COPY apps/frontend/dist instead of building in Docker - build.js: add frontend build step (pnpm build) before docker build - drone.yml: remove obsolete frontend-deps/frontend-build steps
118 lines
3.8 KiB
JavaScript
118 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Build Docker images for C-----code
|
|
*
|
|
* Workflow:
|
|
* 1. cargo build --release --target x86_64-unknown-linux-gnu (compile Rust binaries)
|
|
* 2. pnpm build (build frontend SPA)
|
|
* 3. docker build (copy pre-built artifacts into minimal runtime images)
|
|
*
|
|
* Usage:
|
|
* node scripts/build.js # Build all images
|
|
* node scripts/build.js app # Build specific service
|
|
*
|
|
* Environment:
|
|
* REGISTRY - Docker registry (default: harbor.gitdata.me/gta_team)
|
|
* TAG - Image tag (default: latest)
|
|
* TARGET - Rust build target (default: x86_64-unknown-linux-gnu)
|
|
*/
|
|
|
|
const { execSync } = require('child_process');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
const REGISTRY = process.env.REGISTRY || 'harbor.gitdata.me/gta_team';
|
|
const TAG = process.env.TAG || new Date().toISOString().slice(0, 13).replace('T', '-');
|
|
const BUILD_TARGET = process.env.TARGET || 'x86_64-unknown-linux-gnu';
|
|
|
|
const RUST_SERVICES = ['app', 'gitserver', 'email-worker', 'git-hook', 'operator', 'static'];
|
|
const FRONTEND_SERVICE = 'frontend';
|
|
const ALL_SERVICES = [...RUST_SERVICES, FRONTEND_SERVICE];
|
|
|
|
const args = process.argv.slice(2);
|
|
const targets = args.length > 0 ? args : ALL_SERVICES;
|
|
|
|
const rustTargets = targets.filter(s => RUST_SERVICES.includes(s));
|
|
const needsFrontend = targets.includes(FRONTEND_SERVICE);
|
|
|
|
console.log(`\n=== Build Configuration ===`);
|
|
console.log(`Registry: ${REGISTRY}`);
|
|
console.log(`Tag: ${TAG}`);
|
|
console.log(`Target: ${BUILD_TARGET}`);
|
|
console.log(`Services: ${targets.join(', ')}\n`);
|
|
|
|
// Step 1: Build Rust binaries
|
|
if (rustTargets.length > 0) {
|
|
console.log(`\n==> Step 1: Building Rust binaries`);
|
|
const cpus = require('os').cpus().length;
|
|
try {
|
|
execSync(
|
|
`cargo build --release --target ${BUILD_TARGET} ${rustTargets.map(s => {
|
|
const pkgMap = {
|
|
'app': 'app', 'gitserver': 'gitserver', 'email-worker': 'email-server',
|
|
'git-hook': 'git-hook', 'operator': 'operator', 'static': 'static-server',
|
|
};
|
|
return `--package ${pkgMap[s]}`;
|
|
}).join(' ')} -j ${cpus}`,
|
|
{ stdio: 'inherit', cwd: path.join(__dirname, '..') }
|
|
);
|
|
console.log(` [OK] Rust binaries built`);
|
|
} catch (error) {
|
|
console.error(` [FAIL] Rust build failed`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Step 2: Build frontend (requires apps/frontend to exist locally)
|
|
if (needsFrontend) {
|
|
const frontendDir = path.join(__dirname, '..', 'apps', 'frontend');
|
|
if (!fs.existsSync(frontendDir)) {
|
|
console.error(`\n [FAIL] apps/frontend not found. Please ensure frontend source exists.`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`\n==> Step 2: Building frontend`);
|
|
try {
|
|
execSync(`corepack enable && corepack prepare pnpm@10 --activate && pnpm install --frozen-lockfile && pnpm build`, {
|
|
stdio: 'inherit',
|
|
cwd: frontendDir,
|
|
});
|
|
console.log(` [OK] Frontend built`);
|
|
} catch (error) {
|
|
console.error(` [FAIL] Frontend build failed`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Step 3: Build Docker images
|
|
console.log(`\n==> Step 3: Building Docker images`);
|
|
|
|
for (const service of targets) {
|
|
if (!ALL_SERVICES.includes(service)) {
|
|
console.error(`Unknown service: ${service}`);
|
|
console.error(`Available: ${ALL_SERVICES.join(', ')}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const dockerfile = path.join(__dirname, '..', 'docker', `${service}.Dockerfile`);
|
|
const image = `${REGISTRY}/${service}:${TAG}`;
|
|
|
|
console.log(` Building ${image}`);
|
|
|
|
try {
|
|
execSync(
|
|
`docker build -f "${dockerfile}" -t "${image}" .`,
|
|
{ stdio: 'inherit', cwd: path.join(__dirname, '..') }
|
|
);
|
|
console.log(` [OK] ${image}`);
|
|
} catch (error) {
|
|
console.error(` [FAIL] ${service}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
console.log(`\n=== Build Complete ===`);
|
|
for (const service of targets) {
|
|
console.log(` ${REGISTRY}/${service}:${TAG}`);
|
|
}
|
|
console.log('');
|