diff --git a/.github/actions/smoke-docker-image/action.yml b/.github/actions/smoke-docker-image/action.yml new file mode 100644 index 000000000..843b11260 --- /dev/null +++ b/.github/actions/smoke-docker-image/action.yml @@ -0,0 +1,34 @@ +name: Smoke test Docker image +description: Generate a small model with a datamodel-code-generator Docker image. + +inputs: + image: + description: Docker image tag to smoke test. + required: true + +runs: + using: composite + steps: + - name: Generate and validate model + shell: bash + env: + SMOKE_IMAGE: ${{ inputs.image }} + SMOKE_WORKSPACE: ${{ github.workspace }} + run: | + set -euo pipefail + + output="$( + docker run --rm \ + --volume "$SMOKE_WORKSPACE/tests/data/jsonschema:/data:ro" \ + "$SMOKE_IMAGE" \ + --input /data/simple_string.json \ + --input-file-type jsonschema \ + --disable-timestamp + )" + + printf '%s\n' "$output" | grep -Fqx "class Model(BaseModel):" + printf '%s\n' "$output" | grep -Fqx " s: str" + if printf '%s\n' "$output" | grep -Fq "timestamp:"; then + echo "generated output contains a timestamp" >&2 + exit 1 + fi diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 5c173ef3e..8207252bb 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -22,3 +22,11 @@ updates: github-actions: patterns: - "*" +- package-ecosystem: docker + directory: "/" + schedule: + interval: weekly + day: thursday + time: "10:45" + timezone: Asia/Tokyo + open-pull-requests-limit: 5 diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 000000000..4f77376ba --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,58 @@ +name: Docker + +on: + push: + branches: [main] + paths: + - Dockerfile + - .github/actions/smoke-docker-image/action.yml + - .github/workflows/docker.yaml + - .github/workflows/publish.yaml + pull_request: + branches: [main] + paths: + - Dockerfile + - .github/actions/smoke-docker-image/action.yml + - .github/workflows/docker.yaml + - .github/workflows/publish.yaml + workflow_dispatch: + +concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + smoke: + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 1 + persist-credentials: false + - name: Resolve latest release version + id: release + run: | + set -euo pipefail + version="$( + curl -fsSL https://pypi.org/pypi/datamodel-code-generator/json \ + | python3 -c 'import json, sys; print(json.load(sys.stdin)["info"]["version"])' + )" + echo "version=$version" >> "$GITHUB_OUTPUT" + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + - name: Build Docker image + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 + with: + context: . + load: true + tags: datamodel-code-generator:smoke + build-args: | + VERSION=${{ steps.release.outputs.version }} + - name: Smoke test Docker image + uses: ./.github/actions/smoke-docker-image + with: + image: datamodel-code-generator:smoke diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index c0fb7fb13..c3a449d3d 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -20,6 +20,8 @@ jobs: persist-credentials: false - name: Install the latest version of uv uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + enable-cache: false - name: Build package run: uv build --python 3.13 --python-preference only-managed --sdist --wheel . --out-dir dist - name: Store the distribution packages @@ -77,6 +79,18 @@ jobs: uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + - name: Build Docker image for smoke test + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 + with: + context: . + load: true + tags: datamodel-code-generator:smoke + build-args: | + VERSION=${{ github.ref_name }} + - name: Smoke test Docker image + uses: ./.github/actions/smoke-docker-image + with: + image: datamodel-code-generator:smoke - name: Build and push uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: diff --git a/Dockerfile b/Dockerfile index 80f7ff7ab..76ae93250 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,27 @@ -FROM python:3.12.0-alpine3.17 as builder +FROM python:3.14.2-slim-bookworm AS builder + +ARG VERSION + +ENV VIRTUAL_ENV=/opt/datamodel-code-generator +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" LABEL maintainer="Koudai Aono " -RUN apk add --no-cache gcc musl-dev +RUN test -n "${VERSION}" \ + || { echo "The VERSION build arg is required." >&2; exit 1; } \ + && python -m venv "${VIRTUAL_ENV}" \ + && pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir "datamodel-code-generator[http]==${VERSION}" -ARG VERSION +FROM python:3.14.2-slim-bookworm + +LABEL maintainer="Koudai Aono " + +ENV VIRTUAL_ENV=/opt/datamodel-code-generator +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" -RUN pip install "datamodel-code-generator[http]==$VERSION" +RUN useradd --create-home --shell /usr/sbin/nologin appuser +COPY --from=builder --chown=appuser:appuser /opt/datamodel-code-generator /opt/datamodel-code-generator +USER appuser ENTRYPOINT ["datamodel-codegen"]