27de28a487
根目录统一管理九个 workspace 与唯一 lockfile 迁移 CI、Jenkins 和容器的根目录单次 npm ci 补齐 hoist 兼容、版本校验与 workspace 门禁 同步依赖边界方案、运维文档和长期记忆
232 lines
11 KiB
Docker
232 lines
11 KiB
Docker
ARG RUST_IMAGE=rust:1.96-bookworm@sha256:19817ead3289c8c631c73df281e18b59b172f6a31f4f563290f69cddd06c30e9
|
|
ARG RUNNER_IMAGE=docker.gitea.com/runner-images:ubuntu-latest@sha256:58ea92624c7c09582e05594d95488331045053d3a3f34cf09649f2a32313a614
|
|
|
|
FROM ${RUST_IMAGE} AS rust-toolchain
|
|
|
|
RUN rustup component add rustfmt \
|
|
&& rustc --version \
|
|
&& cargo --version \
|
|
&& rustfmt --version
|
|
|
|
FROM rust-toolchain AS rust-dependency-cache
|
|
|
|
ENV CARGO_HTTP_MULTIPLEXING=false \
|
|
CARGO_NET_RETRY=10
|
|
|
|
COPY server-rs /tmp/genarrative-cargo-cache/server-rs
|
|
COPY apps/desktop-shell/src-tauri /tmp/genarrative-cargo-cache/desktop-shell
|
|
COPY apps/ai-game-creator-shell/src-tauri /tmp/genarrative-cargo-cache/apps/ai-game-creator-shell/src-tauri
|
|
|
|
RUN find /tmp/genarrative-cargo-cache -name Cargo.toml -exec dirname {} \; \
|
|
| while IFS= read -r crate_dir; do \
|
|
mkdir -p "${crate_dir}/src"; \
|
|
: > "${crate_dir}/src/lib.rs"; \
|
|
: > "${crate_dir}/src/main.rs"; \
|
|
: > "${crate_dir}/src/active.rs"; \
|
|
done \
|
|
&& cargo_fetch_with_retry() { \
|
|
manifest_path="$1"; \
|
|
for attempt in 1 2 3 4 5; do \
|
|
if cargo fetch --locked \
|
|
--target x86_64-unknown-linux-gnu \
|
|
--manifest-path "${manifest_path}"; then \
|
|
return 0; \
|
|
fi; \
|
|
if [ "${attempt}" -eq 5 ]; then \
|
|
return 1; \
|
|
fi; \
|
|
sleep "$((attempt * 5))"; \
|
|
done; \
|
|
} \
|
|
&& cargo_fetch_with_retry /tmp/genarrative-cargo-cache/server-rs/Cargo.toml \
|
|
&& cargo_fetch_with_retry /tmp/genarrative-cargo-cache/desktop-shell/Cargo.toml \
|
|
&& cargo_fetch_with_retry /tmp/genarrative-cargo-cache/apps/ai-game-creator-shell/src-tauri/Cargo.toml \
|
|
&& CARGO_NET_OFFLINE=true cargo fetch --locked \
|
|
--target x86_64-unknown-linux-gnu \
|
|
--manifest-path /tmp/genarrative-cargo-cache/server-rs/Cargo.toml \
|
|
&& CARGO_NET_OFFLINE=true cargo fetch --locked \
|
|
--target x86_64-unknown-linux-gnu \
|
|
--manifest-path /tmp/genarrative-cargo-cache/desktop-shell/Cargo.toml \
|
|
&& CARGO_NET_OFFLINE=true cargo fetch --locked \
|
|
--target x86_64-unknown-linux-gnu \
|
|
--manifest-path /tmp/genarrative-cargo-cache/apps/ai-game-creator-shell/src-tauri/Cargo.toml \
|
|
&& rm -rf /tmp/genarrative-cargo-cache
|
|
|
|
FROM ${RUNNER_IMAGE}
|
|
|
|
ARG NODE_VERSION=22.23.1
|
|
ARG NODE_LINUX_X64_SHA256=9749e988f437343b7fa832c69ded82a312e41a03116d766797ac14f6f9eee578
|
|
ARG NPM_VERSION=10.9.7
|
|
ARG GOOGLE_CHROME_VERSION=150.0.7871.181-1
|
|
ARG GOOGLE_LINUX_SIGNING_KEY_FINGERPRINT=EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
|
|
|
|
LABEL org.opencontainers.image.title="Genarrative Gitea CI job image" \
|
|
org.opencontainers.image.description="Ubuntu 24.04 CI image with fixed toolchains and prewarmed npm/Cargo caches" \
|
|
org.opencontainers.image.version="2026.07.23.1"
|
|
|
|
RUN test "$(dpkg --print-architecture)" = "amd64" \
|
|
&& find /etc/apt/sources.list.d -maxdepth 1 -type f \
|
|
! -name ubuntu.sources -delete \
|
|
&& apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
bubblewrap \
|
|
build-essential \
|
|
ca-certificates \
|
|
clang \
|
|
cmake \
|
|
curl \
|
|
ffmpeg \
|
|
file \
|
|
libayatana-appindicator3-dev \
|
|
libclang-dev \
|
|
libcurl4-openssl-dev \
|
|
librsvg2-dev \
|
|
libssl-dev \
|
|
libwebkit2gtk-4.1-dev \
|
|
libxdo-dev \
|
|
lld \
|
|
patchelf \
|
|
pkg-config \
|
|
ripgrep \
|
|
wget \
|
|
xz-utils \
|
|
&& google_key="$(mktemp)" \
|
|
&& curl --retry 3 --retry-all-errors --retry-delay 2 \
|
|
--proto '=https' --tlsv1.2 -fsSL \
|
|
https://dl.google.com/linux/linux_signing_key.pub \
|
|
-o "${google_key}" \
|
|
&& test "$(gpg --batch --show-keys --with-colons "${google_key}" \
|
|
| awk -F: '$1 == "fpr" { print $10; exit }')" \
|
|
= "${GOOGLE_LINUX_SIGNING_KEY_FINGERPRINT}" \
|
|
&& install -d -m 0755 /etc/apt/keyrings \
|
|
&& install -m 0644 "${google_key}" /etc/apt/keyrings/google-chrome.asc \
|
|
&& printf '%s\n' \
|
|
'deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.asc] https://dl.google.com/linux/chrome/deb/ stable main' \
|
|
> /etc/apt/sources.list.d/google-chrome.list \
|
|
&& rm -f "${google_key}" \
|
|
&& apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
"google-chrome-stable=${GOOGLE_CHROME_VERSION}" \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
RUN node_archive="node-v${NODE_VERSION}-linux-x64.tar.xz" \
|
|
&& curl --retry 3 --retry-all-errors --retry-delay 2 \
|
|
--proto '=https' --tlsv1.2 -fsSLO \
|
|
"https://nodejs.org/dist/v${NODE_VERSION}/${node_archive}" \
|
|
&& printf '%s %s\n' "${NODE_LINUX_X64_SHA256}" "${node_archive}" \
|
|
| sha256sum --check --strict \
|
|
&& install -d -m 0755 /usr/local/lib/genarrative-node \
|
|
&& tar -xJf "${node_archive}" \
|
|
--strip-components=1 \
|
|
--directory /usr/local/lib/genarrative-node \
|
|
&& rm -f "${node_archive}" \
|
|
&& ln -sfn /usr/local/lib/genarrative-node/bin/node /usr/local/bin/node \
|
|
&& ln -sfn /usr/local/lib/genarrative-node/bin/npm /usr/local/bin/npm \
|
|
&& ln -sfn /usr/local/lib/genarrative-node/bin/npx /usr/local/bin/npx \
|
|
&& ln -sfn /usr/local/lib/genarrative-node/bin/corepack /usr/local/bin/corepack \
|
|
&& npm install --global "npm@${NPM_VERSION}" --no-audit --no-fund \
|
|
&& test "$(npm --version)" = "${NPM_VERSION}"
|
|
|
|
COPY --from=rust-dependency-cache /usr/local/cargo /usr/local/cargo
|
|
COPY --from=rust-dependency-cache /usr/local/rustup /usr/local/rustup
|
|
|
|
ARG NPM_LOCK_SHA256
|
|
ARG SERVER_RUST_LOCK_SHA256
|
|
ARG DESKTOP_RUST_LOCK_SHA256
|
|
ARG AGC_RUST_LOCK_SHA256
|
|
|
|
COPY package.json package-lock.json /usr/local/share/genarrative-ci/npm/
|
|
COPY apps/admin-web/package.json /usr/local/share/genarrative-ci/npm/apps/admin-web/package.json
|
|
COPY apps/ai-game-creator-shell/package.json /usr/local/share/genarrative-ci/npm/apps/ai-game-creator-shell/package.json
|
|
COPY apps/desktop-shell/package.json /usr/local/share/genarrative-ci/npm/apps/desktop-shell/package.json
|
|
COPY apps/mobile-shell/package.json /usr/local/share/genarrative-ci/npm/apps/mobile-shell/package.json
|
|
COPY apps/preview-deployer-web/package.json /usr/local/share/genarrative-ci/npm/apps/preview-deployer-web/package.json
|
|
COPY packages/image-canvas-core/package.json /usr/local/share/genarrative-ci/npm/packages/image-canvas-core/package.json
|
|
COPY packages/image-canvas-react/package.json /usr/local/share/genarrative-ci/npm/packages/image-canvas-react/package.json
|
|
COPY packages/shared/package.json /usr/local/share/genarrative-ci/npm/packages/shared/package.json
|
|
COPY tools/spine-json-export-validator/package.json /usr/local/share/genarrative-ci/npm/tools/spine-json-export-validator/package.json
|
|
COPY server-rs/Cargo.lock /usr/local/share/genarrative-ci/locks/server-rs.Cargo.lock
|
|
COPY apps/desktop-shell/src-tauri/Cargo.lock /usr/local/share/genarrative-ci/locks/desktop-shell.Cargo.lock
|
|
COPY apps/ai-game-creator-shell/src-tauri/Cargo.lock /usr/local/share/genarrative-ci/locks/ai-game-creator-shell.Cargo.lock
|
|
COPY deploy/container/gitea-ci-checkout.sh /usr/local/bin/genarrative-gitea-checkout
|
|
|
|
RUN test -n "${NPM_LOCK_SHA256}" \
|
|
&& test -n "${SERVER_RUST_LOCK_SHA256}" \
|
|
&& test -n "${DESKTOP_RUST_LOCK_SHA256}" \
|
|
&& test -n "${AGC_RUST_LOCK_SHA256}" \
|
|
&& printf '%s %s\n' \
|
|
"${NPM_LOCK_SHA256}" \
|
|
/usr/local/share/genarrative-ci/npm/package-lock.json \
|
|
| sha256sum --check --strict \
|
|
&& printf '%s %s\n' \
|
|
"${SERVER_RUST_LOCK_SHA256}" \
|
|
/usr/local/share/genarrative-ci/locks/server-rs.Cargo.lock \
|
|
| sha256sum --check --strict \
|
|
&& printf '%s %s\n' \
|
|
"${DESKTOP_RUST_LOCK_SHA256}" \
|
|
/usr/local/share/genarrative-ci/locks/desktop-shell.Cargo.lock \
|
|
| sha256sum --check --strict \
|
|
&& printf '%s %s\n' \
|
|
"${AGC_RUST_LOCK_SHA256}" \
|
|
/usr/local/share/genarrative-ci/locks/ai-game-creator-shell.Cargo.lock \
|
|
| sha256sum --check --strict \
|
|
&& chmod 0755 /usr/local/bin/genarrative-gitea-checkout \
|
|
&& npm ci \
|
|
--ignore-scripts \
|
|
--no-audit \
|
|
--no-fund \
|
|
--prefer-offline \
|
|
--prefix /usr/local/share/genarrative-ci/npm \
|
|
&& rm -rf \
|
|
/usr/local/share/genarrative-ci/npm/node_modules \
|
|
/usr/local/share/genarrative-ci/npm/apps/*/node_modules \
|
|
/usr/local/share/genarrative-ci/npm/packages/*/node_modules \
|
|
/usr/local/share/genarrative-ci/npm/tools/*/node_modules \
|
|
&& npm cache verify
|
|
|
|
RUN install -m 0755 /usr/local/cargo/bin/rustup /usr/local/bin/rustup \
|
|
&& for command_name in cargo cargo-fmt rustc rustdoc rustfmt; do \
|
|
ln -sfn rustup "/usr/local/bin/${command_name}"; \
|
|
done
|
|
|
|
ENV CARGO_HOME=/usr/local/cargo \
|
|
GENARRATIVE_GITEA_CI_AGC_RUST_LOCK_SHA256=${AGC_RUST_LOCK_SHA256} \
|
|
GENARRATIVE_GITEA_CI_DESKTOP_RUST_LOCK_SHA256=${DESKTOP_RUST_LOCK_SHA256} \
|
|
GENARRATIVE_GITEA_CI_NPM_LOCK_SHA256=${NPM_LOCK_SHA256} \
|
|
GENARRATIVE_GITEA_CI_NPM_VERSION=${NPM_VERSION} \
|
|
GENARRATIVE_GITEA_CI_SERVER_RUST_LOCK_SHA256=${SERVER_RUST_LOCK_SHA256} \
|
|
NPM_CONFIG_AUDIT=false \
|
|
NPM_CONFIG_FETCH_RETRIES=10 \
|
|
NPM_CONFIG_FETCH_RETRY_FACTOR=2 \
|
|
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=60000 \
|
|
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=2000 \
|
|
NPM_CONFIG_FUND=false \
|
|
NPM_CONFIG_PREFER_OFFLINE=true \
|
|
RUSTUP_AUTO_INSTALL=0 \
|
|
RUSTUP_HOME=/usr/local/rustup \
|
|
PATH=/usr/local/lib/genarrative-node/bin:/usr/local/bin:/usr/local/cargo/bin:/opt/acttoolcache/node/24.18.0/x64/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
|
|
|
|
ARG IMAGE_REVISION=uncommitted
|
|
LABEL org.opencontainers.image.vendor="GenarrativeAI" \
|
|
org.opencontainers.image.version="2026.08.07.1" \
|
|
org.opencontainers.image.source="https://git.genarrative.world/GenarrativeAI/Genarrative" \
|
|
org.opencontainers.image.revision="${IMAGE_REVISION}" \
|
|
org.opencontainers.image.base.name="docker.gitea.com/runner-images:ubuntu-latest@sha256:58ea92624c7c09582e05594d95488331045053d3a3f34cf09649f2a32313a614" \
|
|
com.genarrative.ci.dockerfile="deploy/container/gitea-ci-job.Dockerfile" \
|
|
com.genarrative.ci.definition-sha256="${IMAGE_REVISION}"
|
|
|
|
RUN node --version \
|
|
&& test "$(npm --version)" = "${NPM_VERSION}" \
|
|
&& rustup show active-toolchain \
|
|
&& rustc --version \
|
|
&& cargo --version \
|
|
&& rustfmt --version \
|
|
&& google-chrome --version \
|
|
&& bwrap --version \
|
|
&& test -x /usr/local/bin/genarrative-gitea-checkout \
|
|
&& bash -n /usr/local/bin/genarrative-gitea-checkout \
|
|
&& test -d /root/.npm/_cacache \
|
|
&& test -d /usr/local/cargo/registry/cache \
|
|
&& rg --version \
|
|
&& ffmpeg -version | head -n 1
|