# --- WASM build stage --- # Builds solitaire_server/web/pkg/ (replay viewer + Bevy canvas app) from # source. The artifacts are not committed to the repo (issue #156); this # stage is their single source of truth for deployment. FROM rust:1.95-slim AS wasm-builder WORKDIR /build RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN rustup target add wasm32-unknown-unknown # Pinned wasm toolchain — keep versions in sync with # .gitea/workflows/web-e2e.yml and build_wasm.sh prerequisites. RUN curl -sSL https://github.com/rustwasm/wasm-bindgen/releases/download/0.2.120/wasm-bindgen-0.2.120-x86_64-unknown-linux-musl.tar.gz \ | tar xz -C /opt \ && ln -s /opt/wasm-bindgen-0.2.120-x86_64-unknown-linux-musl/wasm-bindgen /usr/local/bin/wasm-bindgen \ && curl -sSL https://github.com/rustwasm/wasm-pack/releases/download/v0.14.0/wasm-pack-v0.14.0-x86_64-unknown-linux-musl.tar.gz \ | tar xz -C /opt \ && ln -s /opt/wasm-pack-v0.14.0-x86_64-unknown-linux-musl/wasm-pack /usr/local/bin/wasm-pack \ && curl -sSL https://github.com/WebAssembly/binaryen/releases/download/version_130/binaryen-version_130-x86_64-linux.tar.gz \ | tar xz -C /opt \ && ln -s /opt/binaryen-version_130/bin/wasm-opt /usr/local/bin/wasm-opt # Manifests first so the dependency-fetch layer caches across source changes # (same pattern as the server build stage below). COPY .cargo/config.toml ./.cargo/config.toml COPY Cargo.toml Cargo.lock ./ COPY solitaire_core/Cargo.toml ./solitaire_core/Cargo.toml COPY solitaire_sync/Cargo.toml ./solitaire_sync/Cargo.toml COPY solitaire_data/Cargo.toml ./solitaire_data/Cargo.toml COPY solitaire_engine/Cargo.toml ./solitaire_engine/Cargo.toml COPY solitaire_server/Cargo.toml ./solitaire_server/Cargo.toml COPY solitaire_app/Cargo.toml ./solitaire_app/Cargo.toml COPY solitaire_assetgen/Cargo.toml ./solitaire_assetgen/Cargo.toml COPY solitaire_wasm/Cargo.toml ./solitaire_wasm/Cargo.toml COPY solitaire_web/Cargo.toml ./solitaire_web/Cargo.toml RUN for crate in solitaire_core solitaire_sync solitaire_data solitaire_engine \ solitaire_server solitaire_app solitaire_assetgen solitaire_wasm solitaire_web; do \ mkdir -p $crate/src && echo "pub fn _stub() {}" > $crate/src/lib.rs; \ done && \ echo "fn main() {}" > solitaire_server/src/main.rs && \ echo "fn main() {}" > solitaire_app/src/main.rs && \ echo "fn main() {}" > solitaire_assetgen/src/main.rs RUN cargo fetch --locked # Real source for the wasm-feeding crates. Whole crate directories (not just # src/) because solitaire_engine embeds theme/audio/font assets at compile # time from its own assets/ and the workspace assets/. COPY build_wasm.sh ./ # whats_new_plugin embeds the changelog at compile time # (include_str!("../../CHANGELOG.md")) — omit it and the engine build # fails inside this stage while full-checkout builds stay green. COPY CHANGELOG.md ./ COPY solitaire_core ./solitaire_core COPY solitaire_sync ./solitaire_sync COPY solitaire_data ./solitaire_data COPY solitaire_engine ./solitaire_engine COPY solitaire_wasm ./solitaire_wasm COPY solitaire_web ./solitaire_web COPY assets ./assets RUN ./build_wasm.sh # --- Build stage --- FROM rust:1.95-slim AS builder WORKDIR /build # Install musl tools for a fully static binary and sqlx-cli for compile-time # query checking (SQLX_OFFLINE=true skips the live-DB check at build time). RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ libssl-dev \ && rm -rf /var/lib/apt/lists/* # Copy only the files needed to build the server crate. # Layer order: workspace manifests first so dependency fetches are cached. COPY .cargo/config.toml ./.cargo/config.toml COPY Cargo.toml Cargo.lock ./ COPY solitaire_core/Cargo.toml ./solitaire_core/Cargo.toml COPY solitaire_sync/Cargo.toml ./solitaire_sync/Cargo.toml COPY solitaire_data/Cargo.toml ./solitaire_data/Cargo.toml COPY solitaire_engine/Cargo.toml ./solitaire_engine/Cargo.toml COPY solitaire_server/Cargo.toml ./solitaire_server/Cargo.toml COPY solitaire_app/Cargo.toml ./solitaire_app/Cargo.toml COPY solitaire_assetgen/Cargo.toml ./solitaire_assetgen/Cargo.toml COPY solitaire_wasm/Cargo.toml ./solitaire_wasm/Cargo.toml COPY solitaire_web/Cargo.toml ./solitaire_web/Cargo.toml # Stub every workspace crate so `cargo fetch --locked` resolves the full # dependency graph without requiring source files beyond Cargo.toml. RUN for crate in solitaire_core solitaire_sync solitaire_data solitaire_engine \ solitaire_server solitaire_app solitaire_assetgen solitaire_wasm solitaire_web; do \ mkdir -p $crate/src && echo "pub fn _stub() {}" > $crate/src/lib.rs; \ done && \ echo "fn main() {}" > solitaire_server/src/main.rs && \ echo "fn main() {}" > solitaire_app/src/main.rs && \ echo "fn main() {}" > solitaire_assetgen/src/main.rs # Registry config comes from .cargo/config.toml copied above. RUN cargo fetch --locked # Now copy real source and build in release mode. COPY solitaire_core/src ./solitaire_core/src COPY solitaire_sync/src ./solitaire_sync/src COPY solitaire_server/src ./solitaire_server/src COPY solitaire_server/web ./solitaire_server/web COPY solitaire_server/migrations ./solitaire_server/migrations # sqlx offline query cache — required when SQLX_OFFLINE=true so the # compile-time macros don't need a live database. COPY .sqlx ./.sqlx ENV SQLX_OFFLINE=true RUN cargo build --release --locked -p solitaire_server --bin solitaire_server # --- Runtime stage --- FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ libsqlite3-0 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /build/target/release/solitaire_server ./server # Migrations are embedded via sqlx::migrate!("./migrations") at compile time. # Static web assets are served via ServeDir at runtime from these paths: # /app/solitaire_server/web → /web route # /app/assets → /assets route # Card themes (dark + classic) are embedded in the binary; no theme files needed here. COPY solitaire_server/web ./solitaire_server/web # The wasm bundles are never in the repo — they come from the wasm-builder stage. COPY --from=wasm-builder /build/solitaire_server/web/pkg ./solitaire_server/web/pkg COPY assets ./assets ENV SERVER_PORT=8080 EXPOSE 8080 ENTRYPOINT ["./server"]