Skip to content

Delivery + curation arc (epic #1413) #1277

Delivery + curation arc (epic #1413)

Delivery + curation arc (epic #1413) #1277

Workflow file for this run

name: Snyk Security Scan
on:
push:
branches: [ "main", "release/2.4", "release/2.5", "release/2.6" ]
paths:
- '**.py'
- 'pyproject.toml'
- 'docker/pipeline/Dockerfile'
- '.dockerignore'
- '.github/workflows/snyk.yml'
pull_request:
branches: [ "main", "release/2.4", "release/2.5", "release/2.6" ]
paths:
- '**.py'
- 'pyproject.toml'
- 'docker/pipeline/Dockerfile'
- '.dockerignore'
- '.github/workflows/snyk.yml'
schedule:
# Run weekly on Mondays at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch:
permissions:
contents: read
security-events: write
packages: read # pull the GHCR registry build cache that docker-build-full maintains (#915)
# Cancel in-progress scan when a newer push to the same ref arrives.
# Snyk runs are 3-18 min; old run's findings are superseded the moment a
# new commit lands.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Scan Python dependencies
snyk-dependencies:
name: Snyk - Dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /home/linuxbrew/.linuxbrew
docker image prune -af || true
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
df -h
- name: Set up Python 3.11
uses: actions/setup-python@v7
with:
python-version: "3.11.8"
cache: "pip"
cache-dependency-path: pyproject.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Retry: spaCy model wheels are direct GitHub release URLs; transient 502s happen.
for n in 1 2 3 4 5; do
if pip install -e ".[dev,ml,llm,search]"; then
pip cache purge || true
exit 0
fi
echo "pip install failed (attempt $n/5), retry in 45s..."
sleep 45
done
exit 1
# Associate scans with the GitHub repo so public OSS repos are not billed as private CLI tests.
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/python@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --file=pyproject.toml --package-manager=pip --severity-threshold=high --sarif-file-output=snyk.sarif --remote-repo-url=${{ github.server_url }}/${{ github.repository }}
- name: Upload Snyk results to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v4
if: always() && hashFiles('snyk.sarif') != ''
with:
sarif_file: snyk.sarif
wait-for-processing: true
continue-on-error: true
# Scan Docker image (aligned with docker.yml: fast LLM-only on PRs; on main, same ML+preload
# args as docker-build-full `ml` matrix so the scanned image matches prod bake)
snyk-docker:
name: Snyk - Docker
runs-on: ubuntu-latest
# ML+preload bake can run ~17 min; do not cancel mid-build when another push lands.
timeout-minutes: 45
if: github.event_name != 'schedule'
concurrency:
group: snyk-docker-${{ github.ref }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v7
# Match docker.yml (#703): hosted toolchains are unused for pure docker builds.
- name: Free disk space
run: |
echo "before:"
df -h /
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /home/linuxbrew/.linuxbrew \
/opt/hostedtoolcache /usr/share/swift /usr/local/share/boost \
/usr/local/lib/node_modules /usr/local/.ghcup /usr/lib/google-cloud-sdk \
/usr/local/share/powershell /usr/local/share/chromium /opt/microsoft /opt/az || true
sudo swapoff -a || true
sudo rm -f /swapfile /mnt/swapfile || true
sudo apt-get clean || true
sudo rm -rf /var/lib/apt/lists/* || true
docker image prune -af || true
echo "after:"
df -h /
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
with:
driver-opts: |
image=moby/buildkit:latest
- name: Log in to GHCR (registry build cache, read-only)
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Snyk reuses the GHCR build cache that docker-build-full maintains — cache-from
# only (no cache-to), so it no longer exports a duplicate of the ~5 GB model layer (#915).
- name: Build Docker image (PR — LLM-only, fast)
if: github.event_name == 'pull_request'
uses: docker/build-push-action@v7
with:
context: .
file: docker/pipeline/Dockerfile
build-args: |
INSTALL_EXTRAS=
push: false
load: true
tags: podcast-scraper:snyk-scan
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/podcast-scraper-buildcache:llm-only
# Push / workflow_dispatch: same ML args as docker-build-full `ml`, reusing its GHCR
# build cache READ-ONLY (no cache-to) — the duplicate ~5 GB model-layer export is gone.
- name: Build Docker image (main — ML + preload)
if: github.event_name != 'pull_request'
uses: docker/build-push-action@v7
with:
context: .
file: docker/pipeline/Dockerfile
build-args: |
INSTALL_EXTRAS=ml
PRELOAD_ML_MODELS=true
push: false
load: true
tags: podcast-scraper:snyk-scan
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/podcast-scraper-buildcache:ml
- name: Verify Docker image exists
run: |
docker images | grep podcast-scraper || echo "Image not found"
docker inspect podcast-scraper:snyk-scan || echo "Image inspection failed"
- name: Run Snyk to check Docker image for vulnerabilities
uses: snyk/actions/docker@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
image: podcast-scraper:snyk-scan
args: --severity-threshold=high --sarif-file-output=snyk-docker.sarif
- name: Upload Snyk Docker results to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v4
if: |
always()
&& hashFiles('snyk-docker.sarif') != ''
&& (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
with:
sarif_file: snyk-docker.sarif
wait-for-processing: true
continue-on-error: true
# Monitor dependencies (for PRs and scheduled runs)
snyk-monitor:
name: Snyk - Monitor
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'schedule'
steps:
- uses: actions/checkout@v7
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /home/linuxbrew/.linuxbrew
docker image prune -af || true
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
df -h
- name: Set up Python 3.11
uses: actions/setup-python@v7
with:
python-version: "3.11.8"
cache: "pip"
cache-dependency-path: pyproject.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Retry: spaCy model wheels are direct GitHub release URLs; transient 502s happen.
for n in 1 2 3 4 5; do
if pip install -e ".[dev,ml,llm,search]"; then
pip cache purge || true
exit 0
fi
echo "pip install failed (attempt $n/5), retry in 45s..."
sleep 45
done
exit 1
- name: Run Snyk to monitor project
uses: snyk/actions/python@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: monitor
args: --file=pyproject.toml --package-manager=pip --remote-repo-url=${{ github.server_url }}/${{ github.repository }}