All checks were successful
Container CVE Scan (development) / Scan backend/frontend images for CVEs (push) Successful in 2m41s
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 7s
Python Dependency Security / pip-audit (block high/critical) (push) Successful in 50s
This commit integrates pip-audit to enforce vulnerability checks in CI. Dependencies with unresolved HIGH/CRITICAL vulnerabilities will block builds unless explicitly allowlisted. The process is documented, with a strict policy to ensure exceptions are trackable and time-limited.
140 lines
4.9 KiB
YAML
140 lines
4.9 KiB
YAML
name: Docker Publish (Release)
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Version tag to publish (e.g. 0.1.2 or v0.1.2)"
|
|
required: false
|
|
type: string
|
|
|
|
jobs:
|
|
publish:
|
|
name: Build and Push Docker Images
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
attestations: write
|
|
|
|
env:
|
|
# Optional repo variable. If unset, DOCKERHUB_USERNAME is used.
|
|
IMAGE_NAMESPACE: ${{ vars.DOCKERHUB_NAMESPACE }}
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.13"
|
|
|
|
- name: Dependency security gate (pip-audit)
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install pip-audit
|
|
pip-audit -r backend/requirements.txt --format json --aliases --output pip-audit-backend.json || true
|
|
python backend/scripts/pip_audit_gate.py \
|
|
--report pip-audit-backend.json \
|
|
--allowlist ops/security/pip-audit-allowlist.json
|
|
|
|
- name: Resolve version/tag
|
|
id: ver
|
|
shell: bash
|
|
run: |
|
|
RAW_TAG="${{ github.event.release.tag_name }}"
|
|
if [ -z "$RAW_TAG" ]; then
|
|
RAW_TAG="${{ inputs.version }}"
|
|
fi
|
|
if [ -z "$RAW_TAG" ]; then
|
|
RAW_TAG="${GITHUB_REF_NAME}"
|
|
fi
|
|
|
|
CLEAN_TAG="${RAW_TAG#v}"
|
|
echo "raw=$RAW_TAG" >> "$GITHUB_OUTPUT"
|
|
echo "clean=$CLEAN_TAG" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Set image namespace
|
|
id: ns
|
|
shell: bash
|
|
run: |
|
|
NS="${IMAGE_NAMESPACE}"
|
|
if [ -z "$NS" ]; then
|
|
NS="${{ secrets.DOCKERHUB_USERNAME }}"
|
|
fi
|
|
|
|
# Normalize accidental input like spaces or uppercase.
|
|
NS="$(echo "$NS" | tr '[:upper:]' '[:lower:]' | xargs)"
|
|
|
|
# Reject clearly invalid placeholders/config mistakes early.
|
|
if [ -z "$NS" ] || [ "$NS" = "-" ]; then
|
|
echo "Missing Docker Hub namespace. Set repo var DOCKERHUB_NAMESPACE or secret DOCKERHUB_USERNAME."
|
|
exit 1
|
|
fi
|
|
|
|
# Namespace must be a single Docker Hub account/org name, not a path/url.
|
|
if [[ "$NS" == *"/"* ]] || [[ "$NS" == *":"* ]]; then
|
|
echo "Invalid Docker Hub namespace '$NS'. Use only the account/org name (e.g. 'nesterovicit')."
|
|
exit 1
|
|
fi
|
|
|
|
if ! [[ "$NS" =~ ^[a-z0-9]+([._-][a-z0-9]+)*$ ]]; then
|
|
echo "Invalid Docker Hub namespace '$NS'. Allowed: lowercase letters, digits, ., _, -"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using Docker Hub namespace: $NS"
|
|
echo "value=$NS" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Build and push backend image
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: ./backend
|
|
file: ./backend/Dockerfile
|
|
push: true
|
|
provenance: mode=max
|
|
sbom: true
|
|
labels: |
|
|
org.opencontainers.image.title=NexaPG Backend
|
|
org.opencontainers.image.vendor=Nesterovic IT-Services e.U.
|
|
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
|
org.opencontainers.image.version=${{ steps.ver.outputs.clean }}
|
|
tags: |
|
|
${{ steps.ns.outputs.value }}/nexapg-backend:${{ steps.ver.outputs.clean }}
|
|
${{ steps.ns.outputs.value }}/nexapg-backend:latest
|
|
cache-from: type=registry,ref=${{ steps.ns.outputs.value }}/nexapg-backend:buildcache
|
|
cache-to: type=registry,ref=${{ steps.ns.outputs.value }}/nexapg-backend:buildcache,mode=max
|
|
|
|
- name: Build and push frontend image
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: ./frontend
|
|
file: ./frontend/Dockerfile
|
|
push: true
|
|
provenance: mode=max
|
|
sbom: true
|
|
build-args: |
|
|
VITE_API_URL=/api/v1
|
|
labels: |
|
|
org.opencontainers.image.title=NexaPG Frontend
|
|
org.opencontainers.image.vendor=Nesterovic IT-Services e.U.
|
|
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
|
org.opencontainers.image.version=${{ steps.ver.outputs.clean }}
|
|
tags: |
|
|
${{ steps.ns.outputs.value }}/nexapg-frontend:${{ steps.ver.outputs.clean }}
|
|
${{ steps.ns.outputs.value }}/nexapg-frontend:latest
|
|
cache-from: type=registry,ref=${{ steps.ns.outputs.value }}/nexapg-frontend:buildcache
|
|
cache-to: type=registry,ref=${{ steps.ns.outputs.value }}/nexapg-frontend:buildcache,mode=max
|