#!/usr/bin/env node /** * Build Docker images for C-----code * * Step 1: Build Rust binaries locally via cargo * Step 2: Build Docker images copying the pre-built binaries * * 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 REGISTRY = process.env.REGISTRY || 'harbor.gitdata.me/gta_team'; const TAG = process.env.TAG || 'latest'; const BUILD_TARGET = process.env.TARGET || 'x86_64-unknown-linux-gnu'; // Services that need Rust binary built externally const RUST_SERVICES = ['app', 'gitserver', 'email-worker', 'git-hook', 'migrate', 'operator', 'static']; // Package name → binary name const RUST_BINARIES = { 'app': 'app', 'gitserver': 'gitserver', 'email-worker': 'email-server', 'git-hook': 'git-hook', 'migrate': 'migrate', 'operator': 'operator', 'static': 'static-server', }; // Services that build Docker images // frontend uses Node.js in Docker (keeps its own build) const ALL_SERVICES = [...RUST_SERVICES, 'frontend']; const args = process.argv.slice(2); const targets = args.length > 0 ? args : ALL_SERVICES; // Determine which rust services are in targets const rustTargets = targets.filter(s => RUST_SERVICES.includes(s)); const dockerTargets = targets; 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 binaries = rustTargets.map(s => `--package ${Object.keys(RUST_BINARIES).includes(s) ? Object.entries(RUST_BINARIES).find(([k]) => k === s)[1] : s}`).join(' '); try { execSync( `cargo build --release ` + `--target ${BUILD_TARGET} ` + rustTargets.map(s => `--package ${RUST_BINARIES[s]}`).join(' ') + ` -j ${require('os').cpus().length}`, { 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 Docker images // --------------------------------------------------------------------------- console.log(`\n=== Step 2: Building Docker images ===`); for (const service of dockerTargets) { 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(`\n==> Building ${image}`); console.log(` Dockerfile: ${dockerfile}`); 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 dockerTargets) { console.log(` ${REGISTRY}/${service}:${TAG}`); } console.log('');