Files
hold-slayer/.gitea/workflows/cve-scan-docker-build.yml
Robert Helewka bd078c058e Add Docker image + Gitea CI for Virgo Dev deploy
Containerize Hold Slayer as a single image (one FastAPI process serving
REST/WS/MCP and its built SvelteKit dashboard) for deployment to Virgo Dev
on triton.

- Dockerfile: 3-stage (node builds the dashboard → python wheels → runtime).
  Runs from source via `pip install -e .` so db/database.py resolves
  alembic.ini (via __file__.parent.parent) and migrations run on boot. The
  loose top-level modules (main.py, config.py) also require the source layout.
  pjsua2 is left unbuilt (documented stub media) — fine for a mock-SIP deploy.
- .dockerignore: keep .env and gitignored dashboard build artifacts out of
  the context; the node stage builds a fresh dashboard.
- CI (.gitea/workflows): single-image Trivy scan + build + push to
  git.helu.ca/r/hold-slayer (sha / latest-on-main / semver tags), mirroring
  the Demeter workflow. Requires a PACKAGE_TOKEN Actions secret.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 13:10:54 -04:00

106 lines
3.5 KiB
YAML

name: CVE Scan & Docker Build
on:
push:
branches: [main]
# A pushed version tag (e.g. 0.2.0 or v0.2.0) cuts a release: the build
# below stamps the image with the matching semver tag (e.g. :0.2.0) so the
# deploy can pin an immutable release instead of a moving :latest/:sha.
tags: ['*']
env:
REGISTRY: git.helu.ca
IMAGE_NAME: ${{ gitea.repository }}
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
trivy --version
- name: Install pip-tools and resolve Python dependencies
run: |
python3 -m venv /tmp/scanenv
/tmp/scanenv/bin/pip install --quiet pip-tools
/tmp/scanenv/bin/pip-compile pyproject.toml \
-o /tmp/requirements.txt \
--no-header --quiet --allow-unsafe --strip-extras \
--resolver=backtracking || {
/tmp/scanenv/bin/pip install --quiet . && \
/tmp/scanenv/bin/pip freeze > /tmp/requirements.txt
}
cat /tmp/requirements.txt
- name: Scan Python dependencies for CVEs
continue-on-error: true
run: |
trivy fs --scanners vuln --severity HIGH,CRITICAL --format table /tmp/requirements.txt
- name: Audit dashboard npm dependencies
continue-on-error: true
run: |
cd dashboard
npm ci --ignore-scripts
npm audit --audit-level=high || true
- name: Scan repository for secrets
continue-on-error: true
run: |
trivy fs --scanners secret --severity HIGH,CRITICAL --format table .
build-and-push:
runs-on: ubuntu-latest
needs: security-scan
if: always()
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.PACKAGE_TOKEN }}
# Single image: Hold Slayer is one FastAPI process exposing REST/WS/MCP
# and serving its own built SvelteKit dashboard at "/" — no separate
# web/nginx image. The Dockerfile's node stage builds the dashboard.
- name: Extract metadata for image
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/main' }}
type=semver,pattern={{version}}
- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan image for CVEs
continue-on-error: true
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
IMAGE_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n1)
echo "Scanning image: ${IMAGE_TAG}"
trivy image --severity HIGH,CRITICAL --format table "${IMAGE_TAG}"