diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..160c582cfb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,47 @@ +# Python artifacts +__pycache__/ +*.py[cod] +*$py.class +*.so +*.egg-info/ +dist/ +build/ +.eggs/ +*.egg + +# Virtual environments +.venv/ +venv/ +env/ +ENV/ + +# Testing +.pytest_cache/ +.coverage +.tox/ +htmlcov/ +junit.xml +coverage.xml + +# Git +.git/ +.github/ +.gitignore + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Documentation +docs/ +site/ +mkdocs.yml + +# Misc +*.md +LICENSE +.DS_Store +.ruff_cache/ +.mypy_cache/ diff --git a/.github/workflows/dockerpublish.yml b/.github/workflows/dockerpublish.yml new file mode 100644 index 0000000000..10be296178 --- /dev/null +++ b/.github/workflows/dockerpublish.yml @@ -0,0 +1,88 @@ +name: Publish Docker Image + +on: + push: + tags: + - "v*" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract version from tag + id: version + run: | + # Remove 'v' prefix from tag (v4.12.1 -> 4.12.1) + VERSION=${GITHUB_REF_NAME#v} + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Version: ${VERSION}" + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + # Full version tag (e.g. 4.12.1) + type=semver,pattern={{version}} + # Version tag with v prefix (e.g. v4.12.1) + type=semver,pattern=v{{version}} + # Major.minor tag (e.g. 4.12) + type=semver,pattern={{major}}.{{minor}} + # Major version tag (e.g. 4) + type=semver,pattern={{major}} + # Always tag as latest + type=raw,value=latest + # SHA tag for debugging (e.g. sha-abc1234) + type=sha,prefix=sha- + labels: | + org.opencontainers.image.title=Commitizen + org.opencontainers.image.description=Python commitizen client tool - release management for teams + org.opencontainers.image.vendor=Commitizen Tools + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + CZ_VERSION=${{ steps.version.outputs.version }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64,linux/arm64 + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v2 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 45e91e428e..e11263bba0 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -68,3 +68,40 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} report_type: test_results + + docker-build-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Check for Dockerfile changes + uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + docker: + - 'Dockerfile' + - '.dockerignore' + - '.github/workflows/dockerpublish.yml' + + - name: Extract version from pyproject.toml + if: steps.filter.outputs.docker == 'true' + id: version + run: | + VERSION=$(grep '^version = ' pyproject.toml | cut -d'"' -f2) + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "Testing with version: ${VERSION}" + + - name: Set up Docker Buildx + if: steps.filter.outputs.docker == 'true' + uses: docker/setup-buildx-action@v3 + + - name: Test Docker build + if: steps.filter.outputs.docker == 'true' + uses: docker/build-push-action@v6 + with: + context: . + push: false + build-args: | + CZ_VERSION=${{ steps.version.outputs.version }} + cache-from: type=gha diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..b047911e75 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM python:3.13-slim AS builder + +WORKDIR /app + +# Installer UV pour une installation rapide des dépendances +RUN pip install --no-cache-dir uv + +# Argument de build pour la version (passé depuis GitHub Actions) +ARG CZ_VERSION +RUN test -n "$CZ_VERSION" || (echo "CZ_VERSION not set" && false) + +# Installer commitizen avec UV +RUN uv pip install --system --no-cache commitizen==${CZ_VERSION} + +# Stage runtime +FROM python:3.13-slim + +LABEL org.opencontainers.image.source="https://github.com/commitizen-tools/commitizen" +LABEL org.opencontainers.image.description="Commitizen is a release management tool designed for teams" +LABEL org.opencontainers.image.licenses="MIT" + +# Installer git (requis pour le fonctionnement de commitizen) +RUN apt-get update && \ + apt-get install -y --no-install-recommends git && \ + rm -rf /var/lib/apt/lists/* + +# Copier les packages Python et binaires depuis le builder +COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages +COPY --from=builder /usr/local/bin/cz /usr/local/bin/cz +COPY --from=builder /usr/local/bin/git-cz /usr/local/bin/git-cz + +# Répertoire de travail +WORKDIR /workspace + +# Point d'entrée sur la commande cz +ENTRYPOINT ["cz"] + +# Commande par défaut : afficher la version +CMD ["version"] diff --git a/docs/README.md b/docs/README.md index 97cd2880d7..8f281dd8fe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -88,6 +88,20 @@ uv tool upgrade commitizen brew install commitizen ``` +#### Docker Installation + +If you prefer using Docker or don't have Python installed: + +```bash +# Pull the latest image +docker pull ghcr.io/commitizen-tools/commitizen:latest + +# Use as a command +docker run -v $(pwd):/workspace ghcr.io/commitizen-tools/commitizen:latest --help +``` + +For detailed Docker usage, see the [Docker tutorial](https://commitizen-tools.github.io/commitizen/tutorials/docker/). + #### Project-Specific Installation You can add Commitizen to your Python project using any of these package managers: @@ -240,6 +254,7 @@ Commitizen provides a comprehensive CLI with various commands. Here's the comple - [Exit Codes Reference](https://commitizen-tools.github.io/commitizen/exit_codes/) - [Configuration Guide](https://commitizen-tools.github.io/commitizen/config/configuration_file/) - [Command Documentation](https://commitizen-tools.github.io/commitizen/commands/init/) +- [Docker Usage Guide](https://commitizen-tools.github.io/commitizen/tutorials/docker/) ### Getting Help diff --git a/docs/tutorials/docker.md b/docs/tutorials/docker.md new file mode 100644 index 0000000000..282cebf5d8 --- /dev/null +++ b/docs/tutorials/docker.md @@ -0,0 +1,48 @@ +# Using Commitizen with Docker + +Commitizen provides official Docker images hosted on GitHub Container Registry (GHCR), making it easy to use Commitizen in containerized environments without needing Python or pip installed on your host machine. + +## Quick Start + +### Pull the Latest Image + +```bash +docker pull ghcr.io/commitizen-tools/commitizen:latest +``` + +### Basic Usage + +```bash +# Check version +docker run ghcr.io/commitizen-tools/commitizen:latest version + +# Get help +docker run ghcr.io/commitizen-tools/commitizen:latest --help + +# Use with a git repository +docker run -v $(pwd):/workspace ghcr.io/commitizen-tools/commitizen:latest check +``` + +## Image Details + +### Base Image + +- **Base**: Python 3.13 slim (Debian) +- **Architecture**: Multi-arch (amd64, arm64) +- **Size**: Optimized with multi-stage build + +### Included Tools + +- Python 3.13 +- Commitizen (from PyPI) +- Git (required for Commitizen operations) + +### Entry Point + +The container entry point is set to `cz`, so you can pass commands directly: + +```bash +# These are equivalent: +docker run ghcr.io/commitizen-tools/commitizen:latest version +docker run --entrypoint cz ghcr.io/commitizen-tools/commitizen:latest version +``` diff --git a/docs/tutorials/gitlab_ci.md b/docs/tutorials/gitlab_ci.md index 0af05c4e7b..dae3ed3454 100644 --- a/docs/tutorials/gitlab_ci.md +++ b/docs/tutorials/gitlab_ci.md @@ -4,6 +4,17 @@ For this example, we have a `python/django` application and `Docker` as a contai _Goal_: Bump a new version every time that a change occurs on the `master` branch. The bump should be executed automatically by the `CI` process. +!!! tip "Using Docker" + Instead of installing Commitizen with pip, you can use the official Docker image: + ```yaml + auto-bump: + stage: auto-bump + image: ghcr.io/commitizen-tools/commitizen:latest + script: + - cz bump --yes + ``` + See the [Docker tutorial](docker.md) for more details. + ### Development Workflow 1. A developer creates a new commit on any branch (except `master`) diff --git a/docs/tutorials/jenkins_pipeline.md b/docs/tutorials/jenkins_pipeline.md index 2b9ad173d3..e97c762278 100644 --- a/docs/tutorials/jenkins_pipeline.md +++ b/docs/tutorials/jenkins_pipeline.md @@ -34,7 +34,7 @@ pipeline { } } -def useCz(String authorName = 'Jenkins CI Server', String authorEmail = 'your-jenkins@email.com', String image = 'registry.hub.docker.com/commitizen/commitizen:latest', Closure body) { +def useCz(String authorName = 'Jenkins CI Server', String authorEmail = 'your-jenkins@email.com', String image = 'ghcr.io/commitizen-tools/commitizen:latest', Closure body) { docker .image(image) .inside("-u 0 -v $WORKSPACE:/workspace -w /workspace -e GIT_AUTHOR_NAME='${authorName}' -e GIT_AUTHOR_EMAIL='${authorEmail}' -entrypoint='/bin/sh'") {