c537073c21
ci / dockerfile (push) Has been cancelled
ci / types (push) Has been cancelled
ci / lint (push) Has been cancelled
ci / security (push) Has been cancelled
ci / chart (push) Has been cancelled
ci / image (api) (push) Has been cancelled
ci / image (reconciler) (push) Has been cancelled
ci / image (worker) (push) Has been cancelled
ci / integration (push) Has been cancelled
ci / unit (push) Has been cancelled
ci / bump (push) Has been cancelled
Python 3.12 -> 3.14, postgres 16 -> 18, uv 0.5.11 -> 0.11.29, trivy 0.58.1 -> 0.72.0, gitleaks 8.21.2 -> 8.30.1, yq 4.44.6 -> 4.53.3, and every action re-pinned to the SHA of its latest tag (checkout v7, setup-uv v8, buildx v4, login v4, hadolint v3.3.0). helm stays 3.21.3: already current for 3.x, and helm 4 is a breaking change, not a CVE fix. trivy mattered most. A vulnerability scanner fourteen minor versions behind is the one stale pin that hides all the others. ruff target-version is deliberately py313 while the runtime is 3.14. It controls the syntax the formatter may emit, and at py314 it rewrites 'except (A, B):' into PEP 758's unparenthesized form — which reads exactly like Python 2's 'except E, name:' and is a hard SyntaxError below 3.14. No semantic gain, real readability cost, in a repo meant to be read. Verified on 3.14: ruff, ruff format, mypy --strict, 166 tests, helm lint, bandit, pip-audit. The digest guard still rejects placeholder digests. Risk carried knowingly: the bumped actions run on node24. If act_runner only provides node20, every job fails at action startup and this commit is the revert.
63 lines
3.1 KiB
Docker
63 lines
3.1 KiB
Docker
# syntax=docker/dockerfile:1.10
|
|
#
|
|
# svcforge api. Build from the REPO ROOT:
|
|
# docker buildx build -f services/api/Dockerfile -t svcforge/api:dev .
|
|
# `COPY ../..` is illegal, so the context must be the root. There is no other option.
|
|
#
|
|
# Two syncs, not one: deps change rarely and our own code changes every commit, so the
|
|
# expensive layer (third-party wheels) must land before the cheap one (our source).
|
|
|
|
FROM python:3.14-slim@sha256:cea0e6040540fb2b965b6e7fb5ffa00871e632eef63719f0ea54bca189ce14a6 AS builder
|
|
|
|
COPY --from=ghcr.io/astral-sh/uv:0.11.29@sha256:eb2843a1e56fd9e30c7276ce1a52cba86e64c7b385f5e3279a0e08e02dd058fc /uv /usr/local/bin/uv
|
|
|
|
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy UV_PYTHON_DOWNLOADS=never
|
|
WORKDIR /app
|
|
|
|
# --- layer 1: third-party dependencies only -------------------------------------------
|
|
# --no-install-project skips the root; --no-install-package skips our path dependency.
|
|
# Without the latter, uv would try to build svcforge-core here, where its source is not
|
|
# yet in the context, and the build would fail.
|
|
COPY pyproject.toml uv.lock ./
|
|
COPY libs/svcforge_core/pyproject.toml libs/svcforge_core/
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-dev --no-editable \
|
|
--no-install-project --no-install-package svcforge-core
|
|
|
|
# --- layer 2: our code ----------------------------------------------------------------
|
|
COPY libs/ libs/
|
|
COPY services/api/ services/api/
|
|
COPY catalog.yaml ./
|
|
# The migrate Job runs from THIS image (migrate-job.yaml pins the api digest), so the SQL
|
|
# has to be in it. svcforge_core.migrate's fallback resolves MIGRATIONS_DIR relative to
|
|
# its own __file__, which lands under site-packages here — a directory that does not and
|
|
# should not contain SQL — so main() returned 1 and the pre-install/pre-upgrade hook
|
|
# failed every sync. SVCFORGE_MIGRATIONS_DIR below points it at this copy instead.
|
|
COPY migrations/ migrations/
|
|
# --no-editable is what turns svcforge-core into a real wheel in site-packages.
|
|
# pyproject.toml declares it `editable = true` for local dev; an editable install in an
|
|
# image points at /app/libs, which is a source tree that need not survive the final stage.
|
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
uv sync --frozen --no-dev --no-editable && \
|
|
/app/.venv/bin/python -c 'import svcforge_core, sys; \
|
|
p = svcforge_core.__file__; \
|
|
sys.exit(0) if "site-packages" in p else sys.exit("not a wheel install: " + p)'
|
|
|
|
# --- runtime --------------------------------------------------------------------------
|
|
FROM python:3.14-slim@sha256:cea0e6040540fb2b965b6e7fb5ffa00871e632eef63719f0ea54bca189ce14a6
|
|
|
|
ARG BUILD_SHA=unknown
|
|
LABEL org.opencontainers.image.title="svcforge-api" \
|
|
org.opencontainers.image.source="https://gitea.oci-oci.duckdns.org/gitea_admin/svcforge" \
|
|
org.opencontainers.image.revision="${BUILD_SHA}"
|
|
|
|
RUN useradd -u 10001 -m -s /usr/sbin/nologin svcforge
|
|
WORKDIR /app
|
|
COPY --from=builder --chown=10001:10001 /app /app
|
|
ENV PATH="/app/.venv/bin:$PATH" \
|
|
PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
SVCFORGE_MIGRATIONS_DIR=/app/migrations
|
|
USER 10001
|
|
ENTRYPOINT ["python", "-m", "services.api"]
|