2026-03-23 11:46:45 +08:00
|
|
|
# ============================================
|
2026-04-24 18:02:21 +08:00
|
|
|
# SnapOtter - Test Dockerfile
|
2026-03-23 11:46:45 +08:00
|
|
|
# Runs the full test suite (unit + integration)
|
|
|
|
|
# ============================================
|
|
|
|
|
|
2026-06-05 17:05:01 +08:00
|
|
|
# ============================================
|
|
|
|
|
# Stage 1: Build libheif from source
|
|
|
|
|
# ============================================
|
2026-07-20 17:54:39 +08:00
|
|
|
FROM node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37 AS libheif-builder
|
2026-06-05 17:05:01 +08:00
|
|
|
|
|
|
|
|
ARG LIBHEIF_VERSION=1.21.2
|
|
|
|
|
|
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
|
|
cmake pkg-config gcc g++ make curl ca-certificates \
|
|
|
|
|
libde265-dev libx265-dev libjpeg-dev libpng-dev \
|
|
|
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
|
|
2026-07-27 15:37:30 +08:00
|
|
|
RUN curl --fail --location --silent --show-error --retry 3 \
|
|
|
|
|
--proto '=https' --tlsv1.2 \
|
|
|
|
|
--output /tmp/libheif.tar.gz \
|
|
|
|
|
"https://github.com/strukturag/libheif/releases/download/v${LIBHEIF_VERSION}/libheif-${LIBHEIF_VERSION}.tar.gz" \
|
|
|
|
|
&& printf '%s %s\n' \
|
|
|
|
|
"75f530b7154bc93e7ecf846edfc0416bf5f490612de8c45983c36385aa742b42" \
|
|
|
|
|
/tmp/libheif.tar.gz | sha256sum --check --strict - \
|
|
|
|
|
&& tar -xzf /tmp/libheif.tar.gz \
|
2026-06-05 17:05:01 +08:00
|
|
|
&& cmake -B build -S "libheif-${LIBHEIF_VERSION}" \
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=/opt/libheif \
|
|
|
|
|
-DWITH_EXAMPLES=ON \
|
|
|
|
|
-DWITH_GDK_PIXBUF=OFF \
|
|
|
|
|
-DWITH_AOM_DECODER=OFF \
|
|
|
|
|
-DWITH_AOM_ENCODER=OFF \
|
|
|
|
|
-DWITH_DAV1D=OFF \
|
|
|
|
|
&& cmake --build build -j$(nproc) \
|
|
|
|
|
&& cmake --install build
|
|
|
|
|
|
|
|
|
|
# ============================================
|
|
|
|
|
# Stage 2: Test runner
|
|
|
|
|
# ============================================
|
2026-07-20 17:54:39 +08:00
|
|
|
FROM node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37
|
2026-03-23 11:46:45 +08:00
|
|
|
|
|
|
|
|
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
|
|
|
|
|
|
2026-04-20 20:53:54 +08:00
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
2026-06-05 17:05:01 +08:00
|
|
|
libde265-0 \
|
2026-04-20 20:53:54 +08:00
|
|
|
libimage-exiftool-perl \
|
2026-04-21 09:59:57 +08:00
|
|
|
imagemagick \
|
|
|
|
|
libraw-dev \
|
2026-06-16 15:16:40 +08:00
|
|
|
libjxl-tools \
|
|
|
|
|
ghostscript \
|
2026-06-24 21:59:02 +08:00
|
|
|
qpdf \
|
2026-07-24 03:54:50 +08:00
|
|
|
tesseract-ocr \
|
|
|
|
|
tesseract-ocr-eng tesseract-ocr-deu tesseract-ocr-fra \
|
|
|
|
|
tesseract-ocr-spa tesseract-ocr-chi-sim tesseract-ocr-jpn \
|
2026-07-15 03:34:24 +08:00
|
|
|
&& if apt-cache show libmagickcore-6.q16-7-extra >/dev/null 2>&1; then \
|
|
|
|
|
apt-get install -y --no-install-recommends libmagickcore-6.q16-7-extra; \
|
|
|
|
|
elif apt-cache show libmagickcore-6.q16-6-extra >/dev/null 2>&1; then \
|
|
|
|
|
apt-get install -y --no-install-recommends libmagickcore-6.q16-6-extra; \
|
|
|
|
|
else \
|
|
|
|
|
echo "No supported ImageMagick EXR coder package found" >&2; exit 1; \
|
|
|
|
|
fi \
|
|
|
|
|
&& convert -list format | grep -Eq '^[[:space:]]*EXR([*[:space:]]|$)' \
|
2026-06-05 17:05:01 +08:00
|
|
|
&& if apt-cache show libx265-199 >/dev/null 2>&1; then \
|
|
|
|
|
apt-get install -y --no-install-recommends libx265-199; \
|
|
|
|
|
elif apt-cache show libx265-209 >/dev/null 2>&1; then \
|
|
|
|
|
apt-get install -y --no-install-recommends libx265-209; \
|
2026-04-20 20:53:54 +08:00
|
|
|
fi \
|
|
|
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
|
|
2026-06-05 17:05:01 +08:00
|
|
|
COPY --from=libheif-builder /opt/libheif/bin/ /usr/local/bin/
|
|
|
|
|
COPY --from=libheif-builder /opt/libheif/lib/ /usr/local/lib/
|
2026-06-16 15:16:40 +08:00
|
|
|
# The base image ships an older system libheif (~1.15) that shadows our built
|
|
|
|
|
# 1.21 without this, so heif-dec fails with an undefined-symbol error.
|
|
|
|
|
ENV LD_LIBRARY_PATH=/usr/local/lib
|
2026-06-05 17:05:01 +08:00
|
|
|
RUN ldconfig
|
|
|
|
|
|
2026-06-16 16:35:27 +08:00
|
|
|
# Allow ImageMagick's Ghostscript delegate to read EPS. Decoding an EPS goes
|
|
|
|
|
# through the PostScript (PS) coder, so the default Debian policy.xml blocking
|
|
|
|
|
# PS/PS2/PS3 must be opened too, not just EPS -- otherwise `convert` refuses with
|
|
|
|
|
# a policy error before Ghostscript ever runs.
|
2026-06-16 15:16:40 +08:00
|
|
|
RUN POLICY_FILE=$(find /etc/ImageMagick* -name policy.xml 2>/dev/null | head -1) && \
|
|
|
|
|
if [ -n "$POLICY_FILE" ]; then \
|
2026-06-16 16:35:27 +08:00
|
|
|
for CODER in EPS PS PS2 PS3; do \
|
|
|
|
|
sed -i "s/<policy domain=\"coder\" rights=\"none\" pattern=\"${CODER}\"/<policy domain=\"coder\" rights=\"read|write\" pattern=\"${CODER}\"/" "$POLICY_FILE"; \
|
|
|
|
|
done; \
|
2026-06-16 15:16:40 +08:00
|
|
|
fi
|
|
|
|
|
|
2026-03-23 11:46:45 +08:00
|
|
|
WORKDIR /app
|
|
|
|
|
|
|
|
|
|
# Copy workspace config first (for layer caching)
|
|
|
|
|
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json turbo.json tsconfig.base.json vitest.config.ts ./
|
2026-06-24 20:08:40 +08:00
|
|
|
# patchedDependencies (gray-matter) needs the patch files present at install
|
|
|
|
|
# time, otherwise pnpm exits with ENOENT (exit 254). The prod Dockerfile copies
|
|
|
|
|
# these too; the test image was missing them.
|
|
|
|
|
COPY patches/ ./patches/
|
2026-03-23 11:46:45 +08:00
|
|
|
|
|
|
|
|
# Copy all package.json files
|
|
|
|
|
COPY apps/web/package.json apps/web/tsconfig.json apps/web/vite.config.ts ./apps/web/
|
|
|
|
|
COPY apps/api/package.json apps/api/tsconfig.json ./apps/api/
|
|
|
|
|
COPY packages/shared/package.json packages/shared/tsconfig.json ./packages/shared/
|
|
|
|
|
COPY packages/image-engine/package.json packages/image-engine/tsconfig.json ./packages/image-engine/
|
|
|
|
|
COPY packages/ai/package.json packages/ai/tsconfig.json ./packages/ai/
|
2026-06-16 16:35:27 +08:00
|
|
|
# enterprise ships @aws-sdk/client-s3, which tests/integration/s3-storage.test.ts
|
|
|
|
|
# imports at module load; without it that suite fails to collect.
|
|
|
|
|
COPY packages/enterprise/package.json packages/enterprise/tsconfig.json ./packages/enterprise/
|
2026-03-23 11:46:45 +08:00
|
|
|
|
2026-06-24 18:23:23 +08:00
|
|
|
# Install ALL dependencies (including devDependencies for testing).
|
2026-03-23 11:46:45 +08:00
|
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
|
|
|
|
|
|
# Copy source code
|
|
|
|
|
COPY . .
|
|
|
|
|
|
2026-07-27 15:37:30 +08:00
|
|
|
# Non-sensitive test defaults. Authentication credentials belong to the test
|
|
|
|
|
# runner or Compose environment rather than the reusable image metadata.
|
2026-03-23 11:46:45 +08:00
|
|
|
ENV NODE_ENV=test \
|
|
|
|
|
WORKSPACE_PATH=/tmp/test-workspace \
|
|
|
|
|
MAX_MEGAPIXELS=100 \
|
|
|
|
|
MAX_UPLOAD_SIZE_MB=100 \
|
|
|
|
|
MAX_BATCH_SIZE=200 \
|
|
|
|
|
CONCURRENT_JOBS=3 \
|
|
|
|
|
RATE_LIMIT_PER_MIN=1000 \
|
|
|
|
|
FILE_MAX_AGE_HOURS=1 \
|
|
|
|
|
CLEANUP_INTERVAL_MINUTES=60
|
|
|
|
|
|
|
|
|
|
# Run unit + integration tests with coverage
|
|
|
|
|
CMD ["pnpm", "test:all"]
|