Skip to content

Docker Scan & Promote #1296

Docker Scan & Promote

Docker Scan & Promote #1296

Workflow file for this run

name: Docker Scan & Promote
# Runs after Stack Tests completes on main — promotes sha-xxx → latest.
# "latest" is NEVER set during build. Only this workflow can set it,
# and only after all tests pass. If any test fails, latest stays unchanged.
on:
workflow_run:
workflows: ["Stack Tests"]
types: [completed]
workflow_dispatch:
inputs:
sha:
description: 'Full commit SHA to promote (defaults to latest main)'
required: false
env:
REGISTRY: ghcr.io
jobs:
scan:
name: Scan ${{ matrix.image }}
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'main')
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
packages: read
strategy:
fail-fast: false
matrix:
image:
- base
- backend
- frontend
- cert-generator
steps:
- uses: actions/checkout@v6
- name: Compute image ref
id: ref
run: |
PREFIX="${GITHUB_REPOSITORY_OWNER,,}/integr8scode"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
SHA="${{ github.event.inputs.sha || github.sha }}"
else
SHA="${{ github.event.workflow_run.head_sha }}"
fi
TAG="sha-${SHA::7}"
echo "image=${{ env.REGISTRY }}/$PREFIX/${{ matrix.image }}:$TAG" >> $GITHUB_OUTPUT
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.34.1
with:
image-ref: ${{ steps.ref.outputs.image }}
format: 'sarif'
output: 'trivy-${{ matrix.image }}-results.sarif'
ignore-unfixed: true
severity: 'CRITICAL,HIGH'
timeout: '5m0s'
trivyignores: 'backend/.trivyignore'
version: 'v0.68.2'
- name: Upload Trivy scan results
if: always()
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: 'trivy-${{ matrix.image }}-results.sarif'
category: 'trivy-${{ matrix.image }}'
# Promote SHA tag → latest using crane (registry-level manifest copy, no rebuild)
promote:
name: Promote to Latest
needs: [scan]
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'main')
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Install crane
uses: imjasonh/setup-crane@v0.5
- name: Promote images (SHA → latest)
run: |
PREFIX="${GITHUB_REPOSITORY_OWNER,,}/integr8scode"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
SHA="${{ github.event.inputs.sha || github.sha }}"
else
SHA="${{ github.event.workflow_run.head_sha }}"
fi
TAG="sha-${SHA::7}"
echo "Promoting tag: $TAG → latest"
echo ""
crane copy "$REGISTRY/$PREFIX/base:$TAG" "$REGISTRY/$PREFIX/base:latest"
crane copy "$REGISTRY/$PREFIX/backend:$TAG" "$REGISTRY/$PREFIX/backend:latest"
crane copy "$REGISTRY/$PREFIX/frontend:$TAG" "$REGISTRY/$PREFIX/frontend:latest"
crane copy "$REGISTRY/$PREFIX/cert-generator:$TAG" "$REGISTRY/$PREFIX/cert-generator:latest"
summary:
name: Summary
needs: [promote]
runs-on: ubuntu-latest
steps:
- name: Generate summary
run: |
PREFIX="${GITHUB_REPOSITORY_OWNER,,}/integr8scode"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
SHA="${{ github.event.inputs.sha || github.sha }}"
else
SHA="${{ github.event.workflow_run.head_sha }}"
fi
TAG="sha-${SHA::7}"
echo "## Docker Images Promoted to Latest" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then
echo "Images promoted manually from \`$TAG\` to \`latest\` — Stack Tests may not have run." >> $GITHUB_STEP_SUMMARY
else
echo "All Stack Tests passed. Images promoted from \`$TAG\` to \`latest\`." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Image | Pull Command |" >> $GITHUB_STEP_SUMMARY
echo "|-------|--------------|" >> $GITHUB_STEP_SUMMARY
echo "| Base | \`docker pull $REGISTRY/$PREFIX/base:latest\` |" >> $GITHUB_STEP_SUMMARY
echo "| Backend | \`docker pull $REGISTRY/$PREFIX/backend:latest\` |" >> $GITHUB_STEP_SUMMARY
echo "| Frontend | \`docker pull $REGISTRY/$PREFIX/frontend:latest\` |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Security Scans" >> $GITHUB_STEP_SUMMARY
echo "All 4 images scanned with Trivy (CRITICAL + HIGH, unfixed ignored)." >> $GITHUB_STEP_SUMMARY