gitdataai/scripts/build.js
ZhenYi 7e42139989
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
feat(frontend): embed SPA assets into app binary at compile time
- Add libs/frontend crate: build.rs runs pnpm build, copies dist/ to
  OUT_DIR/dist_blobs/, generates frontend.rs with lazy_static! map
- libs/api/dist.rs serves embedded assets via serve_frontend handler
- Register /{path:.*} SPA fallback in route.rs (after /api/*)
- Remove frontend container from deploy: docker/frontend.Dockerfile,
  deploy/templates/frontend-*.yaml, values.yaml frontend section
- Update ingress: gitdata.ai root now routes to app service
- Update scripts: build.js removes frontend step, deploy.js removes frontend
2026-04-17 12:04:34 +08:00

98 lines
3.1 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, outputs to dist/)
* 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: git short SHA)
* 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 GIT_SHA_SHORT = execSync('git rev-parse --short HEAD', {encoding: 'utf8'}).trim();
const TAG = process.env.TAG || GIT_SHA_SHORT;
const BUILD_TARGET = process.env.TARGET || 'x86_64-unknown-linux-gnu';
const RUST_SERVICES = ['app', 'gitserver', 'email-worker', 'git-hook', 'operator', 'static'];
const ALL_SERVICES = RUST_SERVICES;
const args = process.argv.slice(2);
const targets = args.length > 0 ? args : ALL_SERVICES;
const rustTargets = targets;
const rootDir = path.join(__dirname, '..');
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: rootDir }
);
console.log(` [OK] Rust binaries built`);
} catch (error) {
console.error(` [FAIL] Rust build failed`);
process.exit(1);
}
}
// Step 2: Build Docker images (frontend is embedded in app at compile time via libs/frontend)
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: rootDir }
);
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('');