Skip to content

test(picklescan): cover operator setitem protocol dispatch #3780

test(picklescan): cover operator setitem protocol dispatch

test(picklescan): cover operator setitem protocol dispatch #3780

name: Docker Image CI
on:
pull_request:
paths:
- "Dockerfile*"
- ".dockerignore"
- "modelaudit/**"
- "packages/modelaudit-picklescan/**"
- "pyproject.toml"
- "uv.lock"
- ".github/workflows/docker-image-test.yml"
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
# Detect what changed to optimize Docker builds
changes:
name: Detect Docker Changes
runs-on: ubuntu-latest
outputs:
docker: ${{ steps.filter.outputs.docker }}
full-image: ${{ steps.filter.outputs.full-image }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v4
id: filter
with:
filters: |
docker:
- 'Dockerfile*'
- '.dockerignore'
- 'modelaudit/**'
- 'packages/modelaudit-picklescan/**'
- 'pyproject.toml'
- 'uv.lock'
- '.github/workflows/docker-image-test.yml'
full-image:
- 'Dockerfile.full'
- 'packages/modelaudit-picklescan/**'
- '.github/workflows/docker-image-test.yml'
build-test-lightweight:
name: Build and Test Lightweight Docker Image
needs: changes
# Only run if Docker-related files changed
if: needs.changes.outputs.docker == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30 # Increased for reliability
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
- name: Build lightweight image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: .
file: Dockerfile
tags: modelaudit:lightweight
load: true
cache-from: type=gha,scope=lightweight
cache-to: type=gha,mode=max,scope=lightweight
build-args: |
BUILDKIT_INLINE_CACHE=1
- name: Test lightweight container help command
run: |
docker run --rm modelaudit:lightweight --help
- name: Test lightweight container scan help
run: |
docker run --rm modelaudit:lightweight scan --help
- name: Test lightweight container version
run: |
# Test that the package is properly installed
docker run --rm modelaudit:lightweight --version
- name: Test lightweight container with invalid command
run: |
# This should fail gracefully
docker run --rm modelaudit:lightweight invalid-command && exit 1 || echo "Command properly rejected invalid input"
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0
with:
# Pin an explicit released Trivy binary to avoid setup failures when
# auto-resolved tags exist without matching release assets.
version: v0.69.2
image-ref: modelaudit:lightweight
format: table
exit-code: "1"
severity: CRITICAL,HIGH
ignore-unfixed: true
- name: Test lightweight container with actual scan
run: |
# Create a test model file using Docker to ensure Python is available
docker run --rm -v $(pwd):/data python:3.11-slim@sha256:543d6cace00ffc96bc95d332493bb28a4332c6dd614aab5fcbd649ae8a7953d9 sh -c "python -c \"import pickle; pickle.dump({'test': 'data'}, open('/data/test.pkl', 'wb'))\""
# Now scan the created file
docker run --rm -v $(pwd):/data modelaudit:lightweight /data/test.pkl
build-test-full:
name: Build and Test Full Docker Image
needs: [changes, build-test-lightweight]
runs-on: ubuntu-latest
timeout-minutes: 90 # Increased for large ML dependency builds
# Only run if Dockerfile.full specifically changed
if: needs.changes.outputs.full-image == 'true'
steps:
- uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
- name: Build full image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7
with:
context: .
file: Dockerfile.full
tags: modelaudit:full
load: true
cache-from: type=gha,scope=full
cache-to: type=gha,mode=max,scope=full
build-args: |
BUILDKIT_INLINE_CACHE=1
timeout-minutes: 60 # Increased timeout for ML dependency build
- name: Test full container help command
run: |
docker run --rm modelaudit:full --help
- name: Test full container scan help
run: |
docker run --rm modelaudit:full scan --help
- name: Test full container version
run: |
# Test that the package is properly installed
docker run --rm modelaudit:full --version
- name: Test full container runs as non-root
run: |
docker run --rm modelaudit:full python -c "import os; uid = os.getuid(); print(f'Container UID: {uid}'); assert uid == 10001"
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # 0.35.0
with:
# Keep full-image scan on the same pinned released Trivy version.
version: v0.69.2
image-ref: modelaudit:full
format: table
exit-code: "1"
severity: CRITICAL,HIGH
ignore-unfixed: true
- name: Verify ML dependencies in full image
run: |
# Test that ML dependencies are available
docker run --rm modelaudit:full python -c "import tensorflow, torch, onnx; print('All ML dependencies available')" || echo "Warning: Some ML dependencies missing"
- name: Test full container with ML model scan
run: |
# Create the fixture with a root Python image because the full image intentionally runs as UID 10001.
docker run --rm -v $(pwd):/data python:3.11-slim@sha256:543d6cace00ffc96bc95d332493bb28a4332c6dd614aab5fcbd649ae8a7953d9 sh -c "python -c \"import pickle; pickle.dump({'test': 'data', 'numbers': [1, 2, 3]}, open('/data/test_numpy.pkl', 'wb')); print('Created test model')\""
# Scan the bind-mounted model as the non-root full image.
docker run --rm -v $(pwd):/data modelaudit:full /data/test_numpy.pkl
docker-ci-success:
name: Docker CI Success
needs: [build-test-lightweight]
# Don't require full image test to pass since it's conditional
if: always()
runs-on: ubuntu-latest
steps:
- name: Check if required jobs succeeded
run: |
LIGHTWEIGHT_RESULT="${{ needs.build-test-lightweight.result }}"
echo "Lightweight Docker build result: $LIGHTWEIGHT_RESULT"
# Success or skipped are both acceptable
# (skipped means the path filters determined the job wasn't needed)
if [[ "$LIGHTWEIGHT_RESULT" == "success" || "$LIGHTWEIGHT_RESULT" == "skipped" ]]; then
echo "Docker CI checks passed (or were skipped due to path filters)!"
exit 0
else
echo "Docker CI checks failed!"
exit 1
fi