4b788fa73a
Project CI / AI game creator shell Rust shard 3/4 (push) Failing after 7m25s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 7m39s
Project CI / AI game creator shell Rust shard 2/4 (push) Failing after 7m48s
Project CI / AI game creator shell Rust crates (push) Successful in 1m11s
Project CI / AI game creator shell Rust shard 1/4 (push) Failing after 9m55s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m29s
Project CI / Repository checks (push) Successful in 4m9s
Project CI / Backend tests (push) Successful in 6m18s
Project CI / Frontend tests (push) Successful in 6m17s
Project CI / Native shell tests (push) Successful in 9m22s
Project CI / AI game creator shell web tests (push) Successful in 5m21s
修复 CI job 镜像无法构建的问题,并换用 Rust 1.98.1 工具链镜像,跑通 PR 门禁。 Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/438 Co-authored-by: kdletters <kdletters@qq.com> Co-committed-by: kdletters <kdletters@qq.com>
268 lines
13 KiB
Docker
268 lines
13 KiB
Docker
ARG RUST_IMAGE=rust:1.98-bookworm@sha256:93ce27a88655056a51dbdd8f5f2d7ddc071c7b0070fb288a37b5a285fc83971e
|
||
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
|
||
COPY plugins/agc-cocos-editor/native/cocos-editor-bridge /tmp/genarrative-cargo-cache/plugins/agc-cocos-editor/native/cocos-editor-bridge
|
||
COPY plugins/agc-unity-editor/native/unity-editor-bridge /tmp/genarrative-cargo-cache/plugins/agc-unity-editor/native/unity-editor-bridge
|
||
COPY plugins/agc-godot-editor/native/godot-editor-bridge /tmp/genarrative-cargo-cache/plugins/agc-godot-editor/native/godot-editor-bridge
|
||
|
||
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=153.0.8010.52-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.09.20.2"
|
||
|
||
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/npx /usr/local/bin/npx \
|
||
&& ln -sfn /usr/local/lib/genarrative-node/bin/corepack /usr/local/bin/corepack
|
||
|
||
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
|
||
|
||
# npm registry 偶发 ECONNRESET,镜像预热也需要整命令级有界重试;
|
||
# 失败重试复用同一 npm cache,不会重复下载已完成的包。
|
||
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_with_retry() { \
|
||
for attempt in 1 2 3 4 5; do \
|
||
if npm ci \
|
||
--ignore-scripts \
|
||
--no-audit \
|
||
--no-fund \
|
||
--prefer-offline \
|
||
--prefix /usr/local/share/genarrative-ci/npm; then \
|
||
return 0; \
|
||
fi; \
|
||
if [ "${attempt}" -eq 5 ]; then \
|
||
return 1; \
|
||
fi; \
|
||
sleep "$((attempt * 5))"; \
|
||
done; \
|
||
} \
|
||
&& npm_ci_with_retry \
|
||
&& 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
|
||
|
||
# 依赖预热会在 workspace 内解析出 Node 发行包自带的 npm(例如 10.9.8),
|
||
# 并通过 PATH 里的 node_modules/.bin 影子化固定版本,因此全局固定版本在预热之后安装。
|
||
# 基础 runner 镜像把 /opt/acttoolcache/node/24.18.0/x64/bin 放在 PATH 最前,会影子化固定 Node / npm;
|
||
# 而 command.exec 只信任 /usr/local/bin 等系统目录,Node 必须在那里可见。
|
||
# 因此固定工具链写成绝对路径 wrapper,并用同一组链接覆盖 base 镜像残留的 toolcache bin,
|
||
# 避免 shell 是否登录改变解析结果,同时保证 command.exec 能找到受信任 node。
|
||
RUN npm install --global --prefix /usr/local/lib/genarrative-node \
|
||
--no-audit --no-fund "npm@${NPM_VERSION}" \
|
||
&& test "$(/usr/local/lib/genarrative-node/bin/node /usr/local/lib/genarrative-node/lib/node_modules/npm/bin/npm-cli.js --version)" = "${NPM_VERSION}" \
|
||
&& ln -sfn /usr/local/lib/genarrative-node/bin/node /usr/local/bin/node \
|
||
&& rm -f /usr/local/bin/npm \
|
||
&& printf '%s\n' '#!/bin/sh' \
|
||
'exec /usr/local/lib/genarrative-node/bin/node /usr/local/lib/genarrative-node/lib/node_modules/npm/bin/npm-cli.js "$@"' \
|
||
> /usr/local/bin/npm \
|
||
&& chmod 0755 /usr/local/bin/npm \
|
||
&& rm -rf /opt/acttoolcache/node/24.18.0/x64/bin \
|
||
&& mkdir -p /opt/acttoolcache/node/24.18.0/x64/bin \
|
||
&& ln -sfn /usr/local/lib/genarrative-node/bin/node /opt/acttoolcache/node/24.18.0/x64/bin/node \
|
||
&& ln -sfn /usr/local/bin/npm /opt/acttoolcache/node/24.18.0/x64/bin/npm \
|
||
&& ln -sfn /usr/local/lib/genarrative-node/bin/npx /opt/acttoolcache/node/24.18.0/x64/bin/npx \
|
||
&& test "$(readlink -f "$(command -v node)")" = "/usr/local/lib/genarrative-node/bin/node" \
|
||
&& test "$(node --version)" = "v${NODE_VERSION}" \
|
||
&& test "$(npm --version)" = "${NPM_VERSION}"
|
||
|
||
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.09.20.2" \
|
||
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
|