Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6f019d7
feat(cli): check generated service containers
iamgp Jul 22, 2026
6f33dda
fix(cli): report all generated container failures
iamgp Jul 22, 2026
d0bcbde
fix(cli): run container checks through docker
iamgp Jul 22, 2026
a101f1c
fix(cli): invoke hadolint image correctly
iamgp Jul 22, 2026
0ded6a3
fix(containers): harden generated service images
iamgp Jul 22, 2026
b21fe2b
ci: run generated container checks
iamgp Jul 22, 2026
82b9e9a
fix(containers): scan all generated service images
iamgp Jul 23, 2026
494c83e
test(dagster): update runtime install contract
iamgp Jul 23, 2026
864878a
fix(containers): bound scanner failure output
iamgp Jul 24, 2026
156a09c
fix(containers): refresh generated service images
iamgp Jul 24, 2026
227ca22
perf(containers): reuse trivy scan cache
iamgp Jul 24, 2026
4fef812
fix(containers): remove vulnerabilities from owned images
iamgp Jul 24, 2026
d98fd89
fix(containers): harden generated pgweb image
iamgp Jul 24, 2026
d455b3e
fix(containers): pin observatory apk package
iamgp Jul 24, 2026
48b257a
feat(containers): generate hardened image wrappers
iamgp Jul 24, 2026
f1f29b4
fix(containers): build wrappers as root
iamgp Jul 25, 2026
ac2e4d0
fix(containers): make vulnerability waivers explicit
iamgp Jul 26, 2026
c7f4743
fix(containers): harden pinned service images
iamgp Jul 26, 2026
695ddae
fix(containers): harden auth and exporter images
iamgp Jul 26, 2026
8dd23be
fix(registry): sync pinned service images
iamgp Jul 26, 2026
4ced978
fix(cli): preserve container vulnerability evidence
iamgp Jul 26, 2026
0392ed8
fix(clickhouse): pin the stable Alpine image
iamgp Jul 26, 2026
f14a956
fix(containers): set explicit runtime users
iamgp Jul 26, 2026
b958d2d
fix(loki): rebuild stable release with patched grpc
iamgp Jul 26, 2026
349761d
fix(minio): restore the runtime maintenance client
iamgp Jul 26, 2026
4c51ef5
fix(alloy): rebuild current release with patched grpc
iamgp Jul 26, 2026
89df33b
fix(openmetadata): patch current service images
iamgp Jul 26, 2026
44c6b25
fix(trino): rebuild launcher with patched Go
iamgp Jul 26, 2026
011484d
fix(cli): allow large container scans to complete
iamgp Jul 26, 2026
a3eb716
fix(nessie): rebuild stable image with patched libraries
iamgp Jul 26, 2026
30fc77d
fix(grafana): rebuild stable image with patched backends
iamgp Jul 26, 2026
2d64bf1
fix(openmetadata): patch elasticsearch libraries
iamgp Jul 26, 2026
1352a3e
fix(superset): harden the stable runtime image
iamgp Jul 26, 2026
0bec1f3
fix(clickstack): harden the stable all-in-one image
iamgp Jul 26, 2026
59e47be
fix(containers): narrow vulnerability waivers
iamgp Jul 26, 2026
f1a2d25
fix(cli): force disposable service generation
iamgp Jul 26, 2026
1f40aef
fix(cli): attribute companion container files
iamgp Jul 26, 2026
6fbd3c5
fix(alloy): declare the runtime user
iamgp Jul 26, 2026
9cf937e
fix(cli): retain large vulnerability reports
iamgp Jul 26, 2026
56381e9
fix(containers): use generated build contexts
iamgp Jul 26, 2026
7464c0d
fix(cli): build shared container images once
iamgp Jul 26, 2026
dbb1d01
fix(postgrest): minimize the stable runtime image
iamgp Jul 26, 2026
db48b80
fix(alloy): bound transient build storage
iamgp Jul 26, 2026
eec6157
fix(cli): bound generated container disk use
iamgp Jul 26, 2026
68d63ae
fix(cli): prune generated build cache incrementally
iamgp Jul 26, 2026
c7053cc
fix(cli): harden container scan waivers
iamgp Jul 26, 2026
b6ab8e4
fix(ci): harden generated container gate
iamgp Jul 26, 2026
2d5a8dd
fix(ci): hydrate container wheelhouse
iamgp Jul 26, 2026
b407150
fix(cli): restore pulled image tags
iamgp Jul 26, 2026
f9d819a
fix(ci): repair container gate metadata
iamgp Jul 26, 2026
32056b1
fix(qa): wait for WAP rejection evidence
iamgp Jul 26, 2026
1d7cb49
fix(containers): resolve upgrade safety reviews
iamgp Jul 26, 2026
6b4a91c
feat(containers): publish generated service images
iamgp Jul 26, 2026
bfe7ca7
fix(registry): record published service images
iamgp Jul 26, 2026
6ac61bb
fix(containers): target image publication retries
iamgp Jul 26, 2026
9c50858
chore(containers): link published images to repository
iamgp Jul 26, 2026
80f35cc
fix(containers): publish images on native runners
iamgp Jul 26, 2026
b3b2e3d
fix(containers): publish native image digests
iamgp Jul 26, 2026
80d54b5
fix(containers): bypass unreliable image proxies
iamgp Jul 27, 2026
8fe001e
fix(containers): isolate manifest digest artifacts
iamgp Jul 27, 2026
8883706
fix(ci): stabilize remote container scan
iamgp Jul 27, 2026
cccb15e
fix(ci): align pinned Trivy digest
iamgp Jul 27, 2026
eb85f7d
fix(cli): escape scanner output markup
iamgp Jul 27, 2026
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
70 changes: 70 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,72 @@ jobs:
exit 1
fi

generated-container-checks:
name: containers / generated service files
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
with:
version: "0.10.10"

- name: Set up Python
run: uv python install 3.11

- name: Build Phlo and service wheels
run: uv build --all-packages --wheel --out-dir "$RUNNER_TEMP/phlo-container-wheelhouse"

- name: Cache Trivy vulnerability and scan data
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ${{ runner.temp }}/phlo-trivy-cache
key: trivy-${{ runner.os }}-v2-${{ github.run_number }}
restore-keys: |
trivy-${{ runner.os }}-v2-

- name: Install wheels into a clean environment
shell: bash
run: |
set -euo pipefail
env_dir="$RUNNER_TEMP/phlo-container-env"
uv venv "$env_dir" --python 3.11
uv pip install \
--python "$env_dir/bin/python" \
--find-links "$RUNNER_TEMP/phlo-container-wheelhouse" \
phlo \
phlo-alloy \
phlo-api \
phlo-clickhouse \
phlo-clickstack \
phlo-dagster \
phlo-grafana \
phlo-hasura \
phlo-loki \
phlo-minio \
phlo-nessie \
phlo-oauth2-proxy \
phlo-openmetadata \
phlo-observatory \
phlo-pgweb \
phlo-postgres \
phlo-postgrest \
phlo-prometheus \
phlo-rustfs \
phlo-superset \
phlo-traefik \
phlo-trino
echo "$env_dir/bin" >> "$GITHUB_PATH"

- name: Check generated service containers
env:
PHLO_TRIVY_CACHE_DIR: ${{ runner.temp }}/phlo-trivy-cache
run: phlo --no-color plugin check --containers

release-golden-path:
name: python / release golden path
runs-on: ubuntu-latest
Expand Down Expand Up @@ -496,6 +562,7 @@ jobs:
- python-quality
- python-core-tests
- quickstart-smoke
- generated-container-checks
- release-golden-path
- recovery-continuity-drill
- windows-release-contract
Expand All @@ -509,6 +576,7 @@ jobs:
PYTHON_QUALITY: ${{ needs.python-quality.result }}
PYTHON_CORE_TESTS: ${{ needs.python-core-tests.result }}
QUICKSTART_SMOKE: ${{ needs.quickstart-smoke.result }}
GENERATED_CONTAINER_CHECKS: ${{ needs.generated-container-checks.result }}
RELEASE_GOLDEN_PATH: ${{ needs.release-golden-path.result }}
RECOVERY_CONTINUITY_DRILL: ${{ needs.recovery-continuity-drill.result }}
WINDOWS_RELEASE_CONTRACT: ${{ needs.windows-release-contract.result }}
Expand All @@ -526,6 +594,7 @@ jobs:
echo "| python / quality | ${PYTHON_QUALITY} |"
echo "| python / core tests | ${PYTHON_CORE_TESTS} |"
echo "| python / quickstart smoke | ${QUICKSTART_SMOKE} |"
echo "| containers / generated service files | ${GENERATED_CONTAINER_CHECKS} |"
echo "| python / release golden path | ${RELEASE_GOLDEN_PATH} |"
echo "| python / recovery continuity drill | ${RECOVERY_CONTINUITY_DRILL} |"
echo "| windows / release golden path contract | ${WINDOWS_RELEASE_CONTRACT} |"
Expand All @@ -538,6 +607,7 @@ jobs:
"${PYTHON_QUALITY}" \
"${PYTHON_CORE_TESTS}" \
"${QUICKSTART_SMOKE}" \
"${GENERATED_CONTAINER_CHECKS}" \
"${RELEASE_GOLDEN_PATH}" \
"${RECOVERY_CONTINUITY_DRILL}" \
"${WINDOWS_RELEASE_CONTRACT}" \
Expand Down
2 changes: 1 addition & 1 deletion packages/phlo-alloy/src/phlo_alloy/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ category: observability
default: false
profile: observability

image: grafana/alloy:v1.4.2
image: grafana/alloy:v1.18.0

compose:
restart: unless-stopped
Expand Down
23 changes: 19 additions & 4 deletions packages/phlo-api/src/phlo_api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.11-slim AS phlo-build-context
FROM python:3.11-alpine AS phlo-build-context

WORKDIR /opt/phlo-build-context

Expand All @@ -8,15 +8,21 @@ RUN set -eux; \
install -m 0755 "$entrypoint" /opt/phlo-build-context/phlo-api-entrypoint.sh; \
mkdir -p /opt/phlo-build-context/wheelhouse

FROM python:3.11-slim
FROM python:3.11-alpine

WORKDIR /app

ARG PHLO_VERSION=
ARG PHLO_API_VERSION=
ARG PHLO_WHEELHOUSE=

RUN pip install --no-cache-dir uv
RUN apk upgrade --no-cache \
&& apk add --no-cache ca-certificates \
&& apk add --no-cache --virtual .build-deps gcc musl-dev \
&& pip install --no-cache-dir \
"setuptools==83.0.0" \
"wheel==0.47.0" \
"uv==0.8.13"

COPY --from=phlo-build-context /opt/phlo-build-context/wheelhouse /opt/phlo-wheelhouse

Expand All @@ -34,10 +40,19 @@ RUN set -eux; \
uv pip install --system --prerelease explicit "$PHLO_REQUIREMENT" "$PHLO_API_REQUIREMENT"; \
else \
uv pip install --system phlo "$PHLO_API_REQUIREMENT"; \
fi
fi && apk del .build-deps

# Do not retain uv's downloaded archives in the runtime image; they are not needed to run Phlo.
RUN rm -rf /root/.cache/uv

COPY --from=phlo-build-context /opt/phlo-build-context/phlo-api-entrypoint.sh /usr/local/bin/phlo-api-entrypoint.sh

RUN addgroup -S phlo \
&& adduser -S -G phlo -h /app -H phlo \
&& chown -R phlo:phlo /app

USER phlo

EXPOSE 4000

ENTRYPOINT ["/usr/local/bin/phlo-api-entrypoint.sh"]
Expand Down
31 changes: 21 additions & 10 deletions packages/phlo-dagster/src/phlo_dagster/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM python:3.12-slim AS phlo-build-context
FROM python:3.12-alpine AS phlo-build-context

WORKDIR /opt/phlo-build-context

COPY . .
RUN mkdir -p /opt/phlo-build-context/wheelhouse

FROM python:3.12-slim
FROM python:3.12-alpine

WORKDIR /opt/dagster

Expand All @@ -14,11 +14,12 @@ ARG PHLO_DBT_VERSION=""
ARG PHLO_WHEELHOUSE=""

# Install system dependencies and uv
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
&& rm -rf /var/lib/apt/lists/* \
&& pip install uv
RUN apk upgrade --no-cache \
&& apk add --no-cache bash ca-certificates curl git \
&& apk add --no-cache --virtual .build-deps gcc musl-dev \
&& pip install --no-cache-dir "uv==0.8.13"

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Copy only the artifact directory from the context stage; normal generated builds receive an
# empty directory and retain the existing PyPI installation path.
Expand All @@ -38,15 +39,25 @@ RUN \
else \
uv pip install --system --no-deps --prerelease explicit "phlo==$PHLO_VERSION"; \
PHLO_PRERELEASE_REQUIREMENTS="$(python -c 'import importlib.metadata as md, re; print(" ".join(req.split(";")[0].strip() for req in (md.metadata("phlo").get_all("Requires-Dist") or []) if "extra == '\''defaults'\''" in req and re.search(r"(a|b|rc|dev)[0-9]+", req)))')"; \
uv pip install --system --prerelease explicit "phlo[defaults]==$PHLO_VERSION" "$PHLO_DBT_REQUIREMENT" $PHLO_PRERELEASE_REQUIREMENTS dagster-webserver dagster-postgres "psycopg[binary]"; \
base_requirements=("phlo[defaults]==$PHLO_VERSION" "$PHLO_DBT_REQUIREMENT" dagster-webserver dagster-postgres "psycopg[binary]"); \
if [ -n "$PHLO_PRERELEASE_REQUIREMENTS" ]; then read -r -a prerelease_requirements <<< "$PHLO_PRERELEASE_REQUIREMENTS"; base_requirements+=("${prerelease_requirements[@]}"); fi; \
uv pip install --system --prerelease explicit "${base_requirements[@]}"; \
fi; \
else \
uv pip install --system "phlo[defaults]" "$PHLO_DBT_REQUIREMENT" dagster-webserver dagster-postgres "psycopg[binary]"; \
fi
fi && apk del .build-deps

# Do not retain uv's downloaded archives in the runtime image; they are not needed to run Phlo.
RUN rm -rf /root/.cache/uv

# Keep entrypoint outside /opt/dagster so dev volume mounts never hide it.
COPY dagster/entrypoint.sh /usr/local/bin/phlo-dagster-entrypoint.sh
RUN chmod +x /usr/local/bin/phlo-dagster-entrypoint.sh
RUN chmod +x /usr/local/bin/phlo-dagster-entrypoint.sh \
&& addgroup -S phlo \
&& adduser -S -G phlo -h /opt/dagster -H phlo \
&& chown -R phlo:phlo /opt/dagster

USER phlo

# Copy workspace configuration
COPY dagster/workspace.yaml /opt/dagster/workspace.yaml
Expand Down
6 changes: 3 additions & 3 deletions packages/phlo-dagster/tests/test_runtime_image_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
def test_dagster_runtime_image_installs_prerelease_phlo_with_postgres_driver() -> None:
dockerfile = resources.files("phlo_dagster").joinpath("Dockerfile").read_text()

assert dockerfile.startswith("FROM python:3.12-slim")
assert dockerfile.startswith("FROM python:3.12-alpine")
assert (
'uv pip install --system --no-deps --prerelease explicit "phlo==$PHLO_VERSION"'
in dockerfile
)
assert "PHLO_PRERELEASE_REQUIREMENTS" in dockerfile
assert (
'uv pip install --system --prerelease explicit "phlo[defaults]==$PHLO_VERSION"'
in dockerfile
'base_requirements=("phlo[defaults]==$PHLO_VERSION" "$PHLO_DBT_REQUIREMENT"' in dockerfile
)
assert 'uv pip install --system --prerelease explicit "${base_requirements[@]}"' in dockerfile
assert 'dagster-postgres "psycopg[binary]"' in dockerfile


Expand Down
2 changes: 1 addition & 1 deletion packages/phlo-grafana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Part of the `observability` profile.
| Variable | Default | Description |
| ------------------------ | -------- | ------------------- |
| `GRAFANA_PORT` | `3003` | Grafana web UI port |
| `GRAFANA_VERSION` | `11.3.1` | Grafana version |
| `GRAFANA_VERSION` | `13.1.1` | Grafana version |
| `GRAFANA_ADMIN_USER` | `admin` | Admin username |
| `GRAFANA_ADMIN_PASSWORD` | `admin` | Admin password |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
},
"textMode": "auto"
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -127,7 +127,7 @@
},
"textMode": "auto"
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -187,7 +187,7 @@
},
"textMode": "auto"
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -247,7 +247,7 @@
},
"textMode": "auto"
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -369,7 +369,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -456,7 +456,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"sizing": "auto",
"valueMode": "color"
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -235,7 +235,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -371,7 +371,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -467,7 +467,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -567,7 +567,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down Expand Up @@ -664,7 +664,7 @@
"sort": "none"
}
},
"pluginVersion": "11.3.1",
"pluginVersion": "13.1.1",
"targets": [
{
"datasource": {
Expand Down
4 changes: 2 additions & 2 deletions packages/phlo-grafana/src/phlo_grafana/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ category: observability
default: false
profile: observability

image: grafana/grafana:${GRAFANA_VERSION:-11.3.1}
image: grafana/grafana:${GRAFANA_VERSION:-13.1.1}

depends_on:
- prometheus
Expand Down Expand Up @@ -43,7 +43,7 @@ compose:

env_vars:
GRAFANA_VERSION:
default: "11.3.1"
default: "13.1.1"
description: Grafana version
GRAFANA_PORT:
default: 3003
Expand Down
2 changes: 1 addition & 1 deletion packages/phlo-hasura/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Part of the `api` profile.
| Variable | Default | Description |
| --------------------- | -------------------------- | ----------------------- |
| `HASURA_PORT` | `8082` | Hasura console/API port |
| `HASURA_VERSION` | `v2.46.0` | Hasura version |
| `HASURA_VERSION` | `v2.49.5` | Hasura version |
| `HASURA_ADMIN_SECRET` | `phlo-hasura-admin-secret` | Admin secret |

## Auto-Configuration
Expand Down
Loading
Loading