diff --git a/.drone.yml b/.drone.yml index 6932ecc..32335db 100644 --- a/.drone.yml +++ b/.drone.yml @@ -38,6 +38,19 @@ steps: commands: - cd apps/frontend && pnpm build + - name: cargo-build + image: rust:1.94-bookworm + commands: + - cargo fetch + - cargo build --release --target ${BUILD_TARGET} -j $(nproc) \ + --package app \ + --package gitserver \ + --package email-server \ + --package git-hook \ + --package migrate-cli \ + --package operator \ + --package static-server + - name: docker-build image: gcr.io/kaniko-project/executor:latest environment: @@ -47,16 +60,16 @@ steps: - | TAG="${DRONE_TAG:-${DRONE_COMMIT_SHA:0:8}}" echo "==> Building images with tag: ${TAG}" - /kaniko/executor --context . --dockerfile docker/app.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/app:${TAG} --destination ${REGISTRY}/app:latest - /kaniko/executor --context . --dockerfile docker/gitserver.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/gitserver:${TAG} --destination ${REGISTRY}/gitserver:latest - /kaniko/executor --context . --dockerfile docker/email-worker.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/email-worker:${TAG} --destination ${REGISTRY}/email-worker:latest - /kaniko/executor --context . --dockerfile docker/git-hook.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/git-hook:${TAG} --destination ${REGISTRY}/git-hook:latest - /kaniko/executor --context . --dockerfile docker/migrate.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/migrate:${TAG} --destination ${REGISTRY}/migrate:latest - /kaniko/executor --context . --dockerfile docker/operator.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/operator:${TAG} --destination ${REGISTRY}/operator:latest - /kaniko/executor --context . --dockerfile docker/static.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/static:${TAG} --destination ${REGISTRY}/static:latest - /kaniko/executor --context . --dockerfile docker/frontend.Dockerfile --build-arg BUILD_TARGET=${BUILD_TARGET} --destination ${REGISTRY}/frontend:${TAG} --destination ${REGISTRY}/frontend:latest + /kaniko/executor --context . --dockerfile docker/app.Dockerfile --destination ${REGISTRY}/app:${TAG} --destination ${REGISTRY}/app:latest + /kaniko/executor --context . --dockerfile docker/gitserver.Dockerfile --destination ${REGISTRY}/gitserver:${TAG} --destination ${REGISTRY}/gitserver:latest + /kaniko/executor --context . --dockerfile docker/email-worker.Dockerfile --destination ${REGISTRY}/email-worker:${TAG} --destination ${REGISTRY}/email-worker:latest + /kaniko/executor --context . --dockerfile docker/git-hook.Dockerfile --destination ${REGISTRY}/git-hook:${TAG} --destination ${REGISTRY}/git-hook:latest + /kaniko/executor --context . --dockerfile docker/migrate.Dockerfile --destination ${REGISTRY}/migrate:${TAG} --destination ${REGISTRY}/migrate:latest + /kaniko/executor --context . --dockerfile docker/operator.Dockerfile --destination ${REGISTRY}/operator:${TAG} --destination ${REGISTRY}/operator:latest + /kaniko/executor --context . --dockerfile docker/static.Dockerfile --destination ${REGISTRY}/static:${TAG} --destination ${REGISTRY}/static:latest + /kaniko/executor --context . --dockerfile docker/frontend.Dockerfile --destination ${REGISTRY}/frontend:${TAG} --destination ${REGISTRY}/frontend:latest echo "==> All images pushed" - depends_on: [ frontend-build ] + depends_on: [ cargo-build, frontend-build ] - name: prepare-kubeconfig image: alpine:latest diff --git a/docker/app.Dockerfile b/docker/app.Dockerfile index c972cb6..d130fa3 100644 --- a/docker/app.Dockerfile +++ b/docker/app.Dockerfile @@ -1,38 +1,12 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -# Build dependencies: OpenSSL, libgit2, zlib, clang for sea-orm codegen -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -# Copy workspace manifests -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -# Pre-build dependencies only -RUN cargo fetch - -# Build the binary -RUN cargo build --release --package app --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- -FROM debian:bookworm-slim AS runtime +# Runtime only — binary built externally via cargo +FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates libssl3 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/app /app/app +COPY target/x86_64-unknown-linux-gnu/release/app /app/app -# All config via environment variables (APP_* prefix) ENV APP_LOG_LEVEL=info ENTRYPOINT ["/app/app"] diff --git a/docker/email-worker.Dockerfile b/docker/email-worker.Dockerfile index 3185b39..efd349b 100644 --- a/docker/email-worker.Dockerfile +++ b/docker/email-worker.Dockerfile @@ -1,24 +1,4 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -RUN cargo fetch -RUN cargo build --release --package email-server --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- +# Runtime only — binary built externally via cargo FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -26,7 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/email-server /app/email-worker +COPY target/x86_64-unknown-linux-gnu/release/email-server /app/email-worker ENV APP_LOG_LEVEL=info ENTRYPOINT ["/app/email-worker"] diff --git a/docker/git-hook.Dockerfile b/docker/git-hook.Dockerfile index fa3ef04..3ae23b3 100644 --- a/docker/git-hook.Dockerfile +++ b/docker/git-hook.Dockerfile @@ -1,24 +1,4 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libgit2-dev zlib1g-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -RUN cargo fetch -RUN cargo build --release --package git-hook --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- +# Runtime only — binary built externally via cargo FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -26,7 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/git-hook /app/git-hook +COPY target/x86_64-unknown-linux-gnu/release/git-hook /app/git-hook ENV APP_LOG_LEVEL=info ENTRYPOINT ["/app/git-hook"] diff --git a/docker/gitserver.Dockerfile b/docker/gitserver.Dockerfile index 35c4da0..fa6539d 100644 --- a/docker/gitserver.Dockerfile +++ b/docker/gitserver.Dockerfile @@ -1,37 +1,16 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libgit2-dev zlib1g-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -RUN cargo fetch -RUN cargo build --release --package gitserver --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- -FROM debian:bookworm-slim AS runtime +# Runtime only — binary built externally via cargo +FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates libssl3 openssh-server \ && rm -rf /var/lib/apt/lists/* -# SSH requires host keys and proper permissions RUN mkdir -p /run/sshd && \ ssh-keygen -A && \ chmod 755 /etc/ssh WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/gitserver /app/gitserver +COPY target/x86_64-unknown-linux-gnu/release/gitserver /app/gitserver ENV APP_LOG_LEVEL=info ENTRYPOINT ["/app/gitserver"] diff --git a/docker/migrate.Dockerfile b/docker/migrate.Dockerfile index 8d10ad3..0a824fb 100644 --- a/docker/migrate.Dockerfile +++ b/docker/migrate.Dockerfile @@ -1,24 +1,4 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -RUN cargo fetch -RUN cargo build --release --package migrate-cli --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- +# Runtime only — binary built externally via cargo FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -26,7 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/migrate /app/migrate +COPY target/x86_64-unknown-linux-gnu/release/migrate /app/migrate # Run migrations via: docker run --rm myapp/migrate up ENTRYPOINT ["/app/migrate"] diff --git a/docker/operator.Dockerfile b/docker/operator.Dockerfile index cb60c71..fc5fecc 100644 --- a/docker/operator.Dockerfile +++ b/docker/operator.Dockerfile @@ -1,32 +1,12 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev libclang-dev \ - gcc g++ make \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /build - -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/ apps/ - -RUN cargo fetch -RUN cargo build --release --package operator --target ${TARGET} -j $(nproc) - -# ---- Stage 2: Runtime ---- +# Runtime only — binary built externally via cargo FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates libssl3 \ + ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/operator /app/operator +COPY target/x86_64-unknown-linux-gnu/release/operator /app/operator # The operator reads POD_NAMESPACE and OPERATOR_IMAGE_PREFIX from env. # It connects to the in-cluster Kubernetes API via the service account token. diff --git a/docker/static.Dockerfile b/docker/static.Dockerfile index e01efdb..7fe5df2 100644 --- a/docker/static.Dockerfile +++ b/docker/static.Dockerfile @@ -1,34 +1,12 @@ -# ---- Stage 1: Build ---- -FROM rust:1.94.0-bookworm AS builder - -ARG BUILD_TARGET=x86_64-unknown-linux-gnu -ENV TARGET=${BUILD_TARGET} - -WORKDIR /build - -# Copy workspace manifests -COPY Cargo.toml Cargo.lock ./ -COPY libs/ libs/ -COPY apps/static/ apps/static/ - -# Pre-build dependencies only -RUN cargo fetch - -# Build the binary -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - --mount=type=cache,target=target \ - cargo build --release --package static-server --target ${TARGET} - -# ---- Stage 2: Runtime ---- -FROM debian:bookworm-slim AS runtime +# Runtime only — binary built externally via cargo +FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /app -COPY --from=builder /build/target/${TARGET}/release/static-server /app/static-server +COPY target/x86_64-unknown-linux-gnu/release/static-server /app/static-server ENV RUST_LOG=info ENV STATIC_LOG_LEVEL=info @@ -37,5 +15,4 @@ ENV STATIC_ROOT=/data ENV STATIC_CORS=true EXPOSE 8081 - ENTRYPOINT ["/app/static-server"] diff --git a/scripts/build.js b/scripts/build.js index 5eb5db3..464972a 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -2,10 +2,12 @@ /** * 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 - * node scripts/build.js app gitserver * * Environment: * REGISTRY - Docker registry (default: harbor.gitdata.me/gta_team) @@ -20,10 +22,29 @@ 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'; -const SERVICES = ['app', 'gitserver', 'email-worker', 'git-hook', 'migrate', 'operator', 'static', 'frontend']; +// 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 : SERVICES; +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}`); @@ -31,10 +52,37 @@ console.log(`Tag: ${TAG}`); console.log(`Target: ${BUILD_TARGET}`); console.log(`Services: ${targets.join(', ')}\n`); -for (const service of targets) { - if (!SERVICES.includes(service)) { +// --------------------------------------------------------------------------- +// 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: ${SERVICES.join(', ')}`); + console.error(`Available: ${ALL_SERVICES.join(', ')}`); process.exit(1); } @@ -47,7 +95,6 @@ for (const service of targets) { try { execSync( `docker build ` + - `--build-arg BUILD_TARGET=${BUILD_TARGET} ` + `-f "${dockerfile}" ` + `-t "${image}" ` + `.`, @@ -61,7 +108,7 @@ for (const service of targets) { } console.log(`\n=== Build Complete ===`); -for (const service of targets) { +for (const service of dockerTargets) { console.log(` ${REGISTRY}/${service}:${TAG}`); } console.log('');