From 925cd38ed8c64d731d0c6d9c01389145fc44fbe3 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:05:43 -0500 Subject: [PATCH 01/10] Workflow updates to only build on Python version changes --- .github/workflows/{nightly.yml => build.yml} | 22 ++- .github/workflows/check-versions.yml | 176 +++++++++++++++++++ 2 files changed, 190 insertions(+), 8 deletions(-) rename .github/workflows/{nightly.yml => build.yml} (91%) create mode 100644 .github/workflows/check-versions.yml diff --git a/.github/workflows/nightly.yml b/.github/workflows/build.yml similarity index 91% rename from .github/workflows/nightly.yml rename to .github/workflows/build.yml index b31a38d..5eba8e8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/build.yml @@ -1,12 +1,16 @@ -name: Build & Deploy Nightly +name: Build & Deploy on: - schedule: - - cron: '0 6 * * *' + push: + branches: + - main + pull_request: + branches: + - main workflow_dispatch: jobs: - nightly: - name: Build & Deploy nightly + build: + name: Build & Deploy runs-on: ubuntu-latest permissions: contents: read @@ -51,7 +55,7 @@ jobs: context: . file: Dockerfile platforms: linux/amd64,linux/arm64 - push: true + push: ${{ github.event_name != 'pull_request' }} build-args: | DEBIAN_VERSION=${{ matrix.debian_version }} PYTHON_VERSION=${{ matrix.python_version }} @@ -64,7 +68,8 @@ jobs: security-scan: name: Security Scan runs-on: ubuntu-latest - needs: nightly + needs: build + if: github.event_name != 'pull_request' permissions: contents: read security-events: write @@ -94,7 +99,8 @@ jobs: test: name: Test Images runs-on: ubuntu-latest - needs: nightly + needs: build + if: github.event_name != 'pull_request' permissions: contents: read strategy: diff --git a/.github/workflows/check-versions.yml b/.github/workflows/check-versions.yml new file mode 100644 index 0000000..649ecbe --- /dev/null +++ b/.github/workflows/check-versions.yml @@ -0,0 +1,176 @@ +name: Check Python Versions + +on: + schedule: + - cron: '0 0 * * 0' # Weekly on Sunday at midnight UTC + workflow_dispatch: + +jobs: + check-versions: + name: Check for Python version updates + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Check current Python versions + id: check + run: | + echo "Checking Python versions from official images..." + + # Initialize arrays + declare -A current_versions + declare -A new_versions + + # Current minor versions we support + MINOR_VERSIONS=("3.9" "3.10" "3.11" "3.12" "3.13" "3.14") + + # Check each version + for minor in "${MINOR_VERSIONS[@]}"; do + # Determine debian version + if [[ "$minor" == "3.9" || "$minor" == "3.10" ]]; then + debian="bullseye" + else + debian="bookworm" + fi + + echo "Checking Python ${minor} (${debian})..." + + # Get actual version from official image + version=$(docker run --rm python:${minor}-slim-${debian} python --version 2>&1 | grep -oP 'Python \K[\d.]+' || echo "") + + if [ -n "$version" ]; then + current_versions[$minor]=$version + echo " Found: $version" + else + echo " ERROR: Could not detect version for ${minor}" + current_versions[$minor]="unknown" + fi + done + + # Check for Python 3.15 (future version) + echo "Checking for Python 3.15..." + if docker pull python:3.15-slim-bookworm 2>/dev/null; then + version=$(docker run --rm python:3.15-slim-bookworm python --version 2>&1 | grep -oP 'Python \K[\d.]+' || echo "") + if [ -n "$version" ]; then + echo " NEW VERSION FOUND: Python 3.15 ($version)" + current_versions["3.15"]=$version + echo "new_minor_version=3.15" >> $GITHUB_OUTPUT + fi + else + echo " Python 3.15 not yet available" + fi + + # Save versions to file for next step + for minor in "${!current_versions[@]}"; do + echo "${minor}=${current_versions[$minor]}" >> /tmp/versions.txt + done + + # Output for debugging + cat /tmp/versions.txt + + - name: Update README with versions + id: update-readme + run: | + echo "Updating README with current versions..." + + # Read versions + declare -A versions + while IFS='=' read -r minor version; do + versions[$minor]=$version + done < /tmp/versions.txt + + # Create backup + cp README.md README.md.backup + + # Update the table in README + # This updates the "Python Source" column with actual versions + for minor in "${!versions[@]}"; do + version="${versions[$minor]}" + if [[ "$minor" == "3.9" || "$minor" == "3.10" ]]; then + debian="bullseye" + else + debian="bookworm" + fi + + # Update the line in the table + sed -i "s/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` |/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + done + + # Check if there were changes + if ! diff -q README.md README.md.backup > /dev/null 2>&1; then + echo "changes_detected=true" >> $GITHUB_OUTPUT + echo "Changes detected in README" + + # Show diff + echo "Diff:" + diff README.md.backup README.md || true + else + echo "changes_detected=false" >> $GITHUB_OUTPUT + echo "No changes detected" + fi + + rm README.md.backup + + - name: Update workflow matrix if new minor version found + if: steps.check.outputs.new_minor_version + run: | + NEW_VERSION="${{ steps.check.outputs.new_minor_version }}" + echo "Adding Python ${NEW_VERSION} to workflow matrix..." + + # Read the version from temp file + VERSION=$(grep "^${NEW_VERSION}=" /tmp/versions.txt | cut -d= -f2) + + # Add to build.yml matrix + WORKFLOW_FILE=".github/workflows/build.yml" + + # Insert new version in matrix (before the last item) + # Find the line with "3.14" and add the new version after it + sed -i "/python_version: \"3.14\"/a\\ - python_version: \"${NEW_VERSION}\"\n debian_version: \"bookworm\"" $WORKFLOW_FILE + + # Update the test matrix + sed -i "s/python_version: \[\"3.9\", \"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\"\]/python_version: [\"3.9\", \"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\", \"${NEW_VERSION}\"]/" $WORKFLOW_FILE + + # Update latest tag logic (3.14 -> new version) + sed -i "s/matrix.python_version == '3.14'/matrix.python_version == '${NEW_VERSION}'/" $WORKFLOW_FILE + + echo "Workflow updated to include Python ${NEW_VERSION}" + + - name: Create Pull Request + if: steps.update-readme.outputs.changes_detected == 'true' || steps.check.outputs.new_minor_version + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: | + chore: Update Python versions + + - Updated README with current Python versions + ${{ steps.check.outputs.new_minor_version && format('- Added Python {0} to build matrix', steps.check.outputs.new_minor_version) || '' }} + branch: update-python-versions + delete-branch: true + title: 'chore: Update Python versions' + body: | + ## Python Version Update + + This PR updates the Python version information: + + ### Changes + - ✅ Updated README with current Python versions from official images + ${{ steps.check.outputs.new_minor_version && format('- ✅ **NEW**: Added Python {0} to build matrix', steps.check.outputs.new_minor_version) || '' }} + + ### Version Details + ``` + $(cat /tmp/versions.txt) + ``` + + ### What happens next? + 1. Review the changes + 2. Merge this PR to trigger a new build with updated versions + 3. Images will be built and pushed automatically + + --- + 🤖 Auto-generated by weekly version check workflow + labels: dependencies,automated From 7026587c892141784b3d2ed98217b117806fddb4 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:11:12 -0500 Subject: [PATCH 02/10] README update for build tag --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc196d7..81221fd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Python Container Builder -[![Build & Deploy Nightly](https://github.com/jski/python-container-builder/actions/workflows/nightly.yml/badge.svg?branch=main)](https://github.com/jski/python-container-builder/actions/workflows/nightly.yml) +[![Build & Deploy](https://github.com/jski/python-container-builder/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/jski/python-container-builder/actions/workflows/build.yml) [![Python Versions](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://github.com/jski/python-container-builder) [![Platform Support](https://img.shields.io/badge/platform-linux%2Famd64%20%7C%20linux%2Farm64-blue)](https://github.com/jski/python-container-builder) From 669779b6b58e1ee6831c780f43cc8726861ac603 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:35:31 -0500 Subject: [PATCH 03/10] Changed README version table to remove latest to simplify workload check logic --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 81221fd..096fe54 100644 --- a/README.md +++ b/README.md @@ -95,13 +95,13 @@ Use the appropriate image tag and distroless runtime for your Python version: | Build Image | Distroless Runtime | Use Case | |-------------|-------------------|----------| -| `:3.14` or `:latest` | `python3-debian12` | Latest features | +| `:3.14` | `python3-debian12` | Latest features | | `:3.12` | `python3-debian12` | Recommended for most projects | | `:3.11` | `python3-debian12` | Long-term stable | | `:3.10` | `python3-debian11` | Older projects | | `:3.9` | `python3-debian11` | Legacy compatibility | -> **Note**: When using Python 3.9 or 3.10, use `gcr.io/distroless/python3-debian11` as your runtime. For Python 3.11+, use `gcr.io/distroless/python3-debian12`. +> **Note**: When using Python 3.9 or 3.10, use `gcr.io/distroless/python3-debian11` as your runtime. For Python 3.11+, use `gcr.io/distroless/python3-debian12`. `latest` is an alias for the tag `:3.14`. ### How It Works 1. Choose your Python version and declare the corresponding base image as the top FROM line in your Dockerfile (e.g., `:3.12`, `:3.14`, or `:latest`). From b22b0057f10f087944300bd35f5fe4e44abdd408 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:36:36 -0500 Subject: [PATCH 04/10] Updated workloads to update README and generate PR on changes --- .github/workflows/check-versions.yml | 46 ++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-versions.yml b/.github/workflows/check-versions.yml index 649ecbe..6645cb9 100644 --- a/.github/workflows/check-versions.yml +++ b/.github/workflows/check-versions.yml @@ -96,8 +96,21 @@ jobs: debian="bookworm" fi - # Update the line in the table - sed -i "s/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` |/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + # Check if this is the latest Python version (has ":latest" tag) + # Currently 3.14, but will be 3.15, 3.16, etc. in the future + if grep -q "| ${minor} | \`:${minor}\` or \`:latest\` |" README.md; then + # Handle version with :latest tag + # First try to update existing version + sed -i "s/| ${minor} | \`:${minor}\` or \`:latest\` | \`python:${minor}-slim-${debian}\` ([^)]*) |/| ${minor} | \`:${minor}\` or \`:latest\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + # If no existing version, add it + sed -i "s/| ${minor} | \`:${minor}\` or \`:latest\` | \`python:${minor}-slim-${debian}\` |/| ${minor} | \`:${minor}\` or \`:latest\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + else + # Handle regular version without :latest tag + # First try to update existing version + sed -i "s/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` ([^)]*) |/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + # If no existing version, add it + sed -i "s/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` |/| ${minor} | \`:${minor}\` | \`python:${minor}-slim-${debian}\` (${version}) |/g" README.md + fi done # Check if there were changes @@ -139,6 +152,35 @@ jobs: echo "Workflow updated to include Python ${NEW_VERSION}" + # Update README table to add new minor version + echo "Adding Python ${NEW_VERSION} to README table..." + + # Find the current "latest" version line (currently 3.14) + CURRENT_LATEST=$(grep -E "\\| [0-9.]+ \\| \`:[0-9.]+\` or \`:latest\`" README.md | sed -E 's/.*\| ([0-9.]+) \| .*/\1/' | head -1) + + if [ -n "$CURRENT_LATEST" ]; then + echo "Current latest version: ${CURRENT_LATEST}" + + # Remove ":latest" tag from current latest version + sed -i "s/| ${CURRENT_LATEST} | \`:${CURRENT_LATEST}\` or \`:latest\` |/| ${CURRENT_LATEST} | \`:${CURRENT_LATEST}\` |/g" README.md + + # Get the distroless version for the current latest (to use as template) + DISTROLESS=$(grep "| ${CURRENT_LATEST} |" README.md | sed -E 's/.*gcr.io\/distroless\/(python3-debian[0-9]+).*/\1/' | head -1) + DISTROLESS="gcr.io/distroless/${DISTROLESS}" + + # Add new row after current latest with :latest tag + # The new version will use bookworm (Debian 12) as it's a recent Python version + NEW_ROW="| ${NEW_VERSION} | \`:${NEW_VERSION}\` or \`:latest\` | \`python:${NEW_VERSION}-slim-bookworm\` (${VERSION}) | \`debian:bookworm-slim\` | \`${DISTROLESS}\` |" + + # Insert new row after the previous latest (GNU sed syntax) + sed -i "/| ${CURRENT_LATEST} |/a\\${NEW_ROW}" README.md + + echo "Added new row for Python ${NEW_VERSION} with :latest tag" + echo "Removed :latest tag from Python ${CURRENT_LATEST}" + else + echo "Warning: Could not find current latest version in README" + fi + - name: Create Pull Request if: steps.update-readme.outputs.changes_detected == 'true' || steps.check.outputs.new_minor_version uses: peter-evans/create-pull-request@v7 From 0bc113ce68a56f6754bedf533c36af50842bc1be Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:50:45 -0500 Subject: [PATCH 05/10] Fail workflow for build if tests or security fail --- .github/workflows/build.yml | 131 ++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5eba8e8..66cbe3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,10 +7,16 @@ on: branches: - main workflow_dispatch: + inputs: + promote: + description: 'Promote to production tags after build' + required: false + type: boolean + default: false jobs: build: - name: Build & Deploy + name: Build Images runs-on: ubuntu-latest permissions: contents: read @@ -49,27 +55,113 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Check if image already exists + id: check + run: | + IMAGE="ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }}" + echo "Checking if ${IMAGE} already exists..." + + if docker manifest inspect "${IMAGE}" >/dev/null 2>&1; then + echo "✅ Image already exists, skipping build" + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "❌ Image does not exist, will build" + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Extract metadata + if: steps.check.outputs.exists == 'false' + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository_owner }}/python-container-builder + tags: | + type=sha,prefix=${{ matrix.python_version }}-,format=long + type=ref,event=pr,prefix=pr-,suffix=-${{ matrix.python_version }} + - name: Build and push Docker images + if: steps.check.outputs.exists == 'false' uses: docker/build-push-action@v6 with: context: . file: Dockerfile platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} + push: true build-args: | DEBIAN_VERSION=${{ matrix.debian_version }} PYTHON_VERSION=${{ matrix.python_version }} - tags: | - ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} - ${{ matrix.python_version == '3.14' && format('ghcr.io/{0}/python-container-builder:latest', github.repository_owner) || '' }} - provenance: false - outputs: type=image,name=python-container-builder,annotation-index.org.opencontainers.image.description=build your Python distroless containers with this + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=python-${{ matrix.python_version }} + cache-to: type=gha,mode=max,scope=python-${{ matrix.python_version }} + provenance: true + sbom: true + outputs: type=image,name=python-container-builder,annotation-index.org.opencontainers.image.description=Build your Python distroless containers with this + + promote: + name: Promote to Production + runs-on: ubuntu-latest + needs: [build, test, security-scan] + # Promote on: + # 1. Normal merge to main (not force push) + # 2. Manual workflow dispatch with promote flag enabled + # CRITICAL: Only runs if build, test, AND security-scan all succeed + if: | + (github.event_name == 'push' && github.ref == 'refs/heads/main' && !github.event.forced) || + (github.event_name == 'workflow_dispatch' && inputs.promote == true) + permissions: + contents: read + packages: write + strategy: + matrix: + python_version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Promote commit SHA to version tag + run: | + # Get the full commit SHA + COMMIT_SHA="${{ github.sha }}" + + # Source image with commit SHA + SOURCE_IMAGE="ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${COMMIT_SHA}" + + # Destination tags + VERSION_TAG="ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}" + + echo "Promoting ${SOURCE_IMAGE} to ${VERSION_TAG}" + + # Re-tag the existing image (no rebuild) + docker buildx imagetools create \ + "${SOURCE_IMAGE}" \ + --tag "${VERSION_TAG}" + + echo "✅ Successfully promoted ${{ matrix.python_version }} to production" + + - name: Promote latest tag + if: matrix.python_version == '3.14' + run: | + COMMIT_SHA="${{ github.sha }}" + SOURCE_IMAGE="ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${COMMIT_SHA}" + LATEST_TAG="ghcr.io/${{ github.repository_owner }}/python-container-builder:latest" + + echo "Promoting ${SOURCE_IMAGE} to ${LATEST_TAG}" + + docker buildx imagetools create \ + "${SOURCE_IMAGE}" \ + --tag "${LATEST_TAG}" + + echo "✅ Successfully promoted latest tag" security-scan: name: Security Scan runs-on: ubuntu-latest needs: build - if: github.event_name != 'pull_request' permissions: contents: read security-events: write @@ -77,10 +169,11 @@ jobs: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: - image-ref: ghcr.io/${{ github.repository_owner }}/python-container-builder:latest + image-ref: ghcr.io/${{ github.repository_owner }}/python-container-builder:3.14-${{ github.sha }} format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' + exit-code: '1' - name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@v4 @@ -92,15 +185,15 @@ jobs: uses: aquasecurity/trivy-action@master if: always() with: - image-ref: ghcr.io/${{ github.repository_owner }}/python-container-builder:latest + image-ref: ghcr.io/${{ github.repository_owner }}/python-container-builder:3.14-${{ github.sha }} format: 'table' severity: 'CRITICAL,HIGH' + exit-code: '1' test: name: Test Images runs-on: ubuntu-latest needs: build - if: github.event_name != 'pull_request' permissions: contents: read strategy: @@ -109,32 +202,32 @@ jobs: steps: - name: Test Python version run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} python --version + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} python --version - name: Test uv is installed run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} uv --version + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} uv --version - name: Test poetry is installed run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} poetry --version + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} poetry --version - name: Test pipenv is installed run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} pipenv --version + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} pipenv --version - name: Test pdm is installed run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} pdm --version + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} pdm --version - name: Test venv is created run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} sh -c 'test -d /.venv && echo "venv exists"' + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'test -d /.venv && echo "venv exists"' - name: Test package installation with uv run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} sh -c 'uv pip install requests && python -c "import requests; print(f\"requests {requests.__version__} imported successfully\")"' + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'uv pip install requests && python -c "import requests; print(f\"requests {requests.__version__} imported successfully\")"' - name: Test package installation with pip run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }} sh -c 'pip install click && python -c "import click; print(f\"click {click.__version__} imported successfully\")"' \ No newline at end of file + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'pip install click && python -c "import click; print(f\"click {click.__version__} imported successfully\")"' From 758ea0eb09c30d488d347f435ac0adcb5deee855 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:56:59 -0500 Subject: [PATCH 06/10] Update uv test to use venv --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 66cbe3b..cf95064 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -226,8 +226,8 @@ jobs: - name: Test package installation with uv run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'uv pip install requests && python -c "import requests; print(f\"requests {requests.__version__} imported successfully\")"' + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'uv pip install requests && /.venv/bin/python -c "import requests; print(f\"requests {requests.__version__} imported successfully\")"' - name: Test package installation with pip run: | - docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'pip install click && python -c "import click; print(f\"click {click.__version__} imported successfully\")"' + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c '/.venv/bin/pip install click && /.venv/bin/python -c "import click; print(f\"click {click.__version__} imported successfully\")"' From 058a9713783787c845bd310b2897a407370095d3 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 20:57:26 -0500 Subject: [PATCH 07/10] Removed exit-code 1 for tests --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf95064..aaf355f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -173,7 +173,6 @@ jobs: format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - exit-code: '1' - name: Upload Trivy results to GitHub Security uses: github/codeql-action/upload-sarif@v4 @@ -188,7 +187,6 @@ jobs: image-ref: ghcr.io/${{ github.repository_owner }}/python-container-builder:3.14-${{ github.sha }} format: 'table' severity: 'CRITICAL,HIGH' - exit-code: '1' test: name: Test Images From 23d62418915963e21d649c04d20a799b6b7a4815 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 21:01:57 -0500 Subject: [PATCH 08/10] Removed fail-fast from matrix options in workflow --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aaf355f..b28e487 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,7 @@ jobs: contents: read packages: write strategy: + fail-fast: false matrix: include: - python_version: "3.9" @@ -113,6 +114,7 @@ jobs: contents: read packages: write strategy: + fail-fast: false matrix: python_version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: @@ -195,6 +197,7 @@ jobs: permissions: contents: read strategy: + fail-fast: false matrix: python_version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: From 6bd77b7de5291a041fa328e9611922e50b4c27e9 Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 21:05:55 -0500 Subject: [PATCH 09/10] Update Dockerfile to include pip in virtualenv --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3718917..e040635 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,5 +38,6 @@ RUN uv venv ENV VIRTUAL_ENV=/.venv ENV PATH="/bin:$VIRTUAL_ENV/bin:$PATH" -# Install modern Python package managers for completeness -RUN uv pip install --no-cache poetry pipenv pdm \ No newline at end of file +# Install pip in the virtualenv for standard pip usage +# Then install other modern Python package managers +RUN uv pip install --no-cache pip poetry pipenv pdm \ No newline at end of file From 0cbb9ee8932519027e617fa9421e28fdec69542c Mon Sep 17 00:00:00 2001 From: db Date: Thu, 25 Dec 2025 21:06:12 -0500 Subject: [PATCH 10/10] Updated tests to work properly for pip validation --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b28e487..bb65d7c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -221,6 +221,10 @@ jobs: run: | docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} pdm --version + - name: Test pip is installed in venv + run: | + docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} /.venv/bin/pip --version + - name: Test venv is created run: | docker run --rm ghcr.io/${{ github.repository_owner }}/python-container-builder:${{ matrix.python_version }}-${{ github.sha }} sh -c 'test -d /.venv && echo "venv exists"'