Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ jobs:
# Same platform flag as native-app/scripts/build-and-push.ps1;
# --provenance only matters for the registry push, not a local scan.
run: docker build --platform linux/amd64 -t "${{ matrix.image }}:scan" "${{ matrix.context }}"
- name: Check runtime imports
if: matrix.image != 'mendix-base'
env:
IMAGE: ${{ matrix.image }}
run: |
imports="import ssl, ctypes, bz2, lzma, sqlite3, uuid, dbm, readline; import snowflake.connector"
if [ "$IMAGE" = "mendix-deploy-controller" ]; then
imports="$imports; import fastapi, uvicorn, pydantic, yaml, psycopg"
else
imports="$imports; import streamlit, httpx"
fi
docker run --rm --entrypoint /usr/local/bin/python "$IMAGE:scan" -c "$imports"
- name: Trivy scan (full report, SARIF)
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ concurrency:

jobs:
pytest:
name: pytest (${{ matrix.service }})
name: pytest (${{ matrix.service }}, Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service: [Controller, Admin UI]
python-version: ['3.12', '3.14']
include:
- service: Controller
slug: controller
Expand All @@ -56,8 +58,8 @@ jobs:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
# Matches the python:3.12-slim base of both service images.
python-version: '3.12'
# Cover both runtimes while the service images move to Python 3.14.
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: |
${{ matrix.requirements }}
Expand All @@ -77,5 +79,5 @@ jobs:
if: always()
uses: actions/upload-artifact@v7
with:
name: coverage-${{ matrix.slug }}
name: coverage-${{ matrix.slug }}-${{ matrix.python-version }}
path: coverage-${{ matrix.slug }}.xml
10 changes: 5 additions & 5 deletions Controller/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Bases pinned to immutable digests for reproducible, scannable builds (NAAAPS).
# Refresh: docker pull python:3.12-slim && docker inspect --format '{{index .RepoDigests 0}}' python:3.12-slim
# Refresh: docker pull python:3.14-slim && docker inspect --format '{{index .RepoDigests 0}}' python:3.14-slim
# Refresh: docker pull gcr.io/distroless/cc-debian13:nonroot && docker inspect --format '{{index .RepoDigests 0}}' gcr.io/distroless/cc-debian13:nonroot
# Local-only debug variant: swap the final FROM to gcr.io/distroless/cc-debian13:debug-nonroot
# (adds a BusyBox shell). Never push the debug variant.

# --- builder ---------------------------------------------------------------
FROM python:3.12-slim@sha256:423ed6ab25b1921a477529254bfeeabf5855151dc2c3141699a1bfc852199fbf AS builder
FROM python:3.14-slim@sha256:b877e50bd90de10af8d82c57a022fc2e0dc731c5320d762a27986facfc3355c1 AS builder
WORKDIR /app
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
Expand Down Expand Up @@ -35,15 +35,15 @@ RUN mkdir -p /opt/runtime-libs \

# --- runtime ---------------------------------------------------------------
# distroless/cc-debian13 = glibc + libssl + libstdc++, no shell, no package
# manager. Same Debian 13 (trixie) userland as the python:3.12-slim builder
# manager. Same Debian 13 (trixie) userland as the python:3.14-slim builder
# (glibc 2.41), so native wheels (cryptography, pydantic-core, uvloop,
# httptools) are ABI-compatible. cc-debian12 does NOT work here: its glibc
# 2.36 predates the GLIBC_2.38 symbols libpython3.12.so needs.
# 2.36 predates the GLIBC_2.38 symbols libpython3.14.so needs.
# NOTE: no RUN is possible in this stage (no shell). Anything needing mkdir/
# chown at build time goes in the builder stage above.
FROM gcr.io/distroless/cc-debian13:nonroot@sha256:54df941ed0d06a1bd95ef5e0ce391fd8d9f94b64782dc9a60062727849ee3f97
# /usr/local carries the interpreter, stdlib C extensions (lib-dynload),
# libpython3.12.so, and all pip-installed packages in one consistent copy.
# libpython3.14.so, and all pip-installed packages in one consistent copy.
COPY --from=builder --chown=65532:65532 /usr/local /usr/local
# Stdlib-required shared libs absent from distroless cc (see builder stage).
COPY --from=builder /opt/runtime-libs/ /usr/lib/x86_64-linux-gnu/
Expand Down