Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 68 additions & 56 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,93 +7,105 @@ on:

env:
REGISTRY: ghcr.io
IMAGE_BASE: ${{ github.repository }}

jobs:
build-and-push:
# --- JOB 1: BACKEND (Dockerized for GHCR) ---
build-backend:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- service: backend
context: ./backend
image: ghcr.io/${{ github.repository }}/backend
- service: frontend
context: ./frontend
image: ghcr.io/${{ github.repository }}/frontend

permissions:
contents: read
packages: write
id-token: write # Required for OIDC and Build Provenance
security-events: write
attestations: write # NEW: Specifically required for official GitHub Attestations

id-token: write
security-events: write
attestations: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
tags: |
type=semver,pattern={{version}}
type=sha,prefix=sha-
type=raw,value=latest,enable=${{ github.event_name == 'release' }}

- name: Build and push Docker image
- name: Build and push Backend Image
id: build-push
uses: docker/build-push-action@v6 # Updated to v6
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
context: ./backend
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# Tags both 'latest' and the specific release version (e.g., v1.0.0)
tags: |
${{ env.REGISTRY }}/${{ github.repository }}/backend:latest
${{ env.REGISTRY }}/${{ github.repository }}/backend:${{ github.event.release.tag_name || github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Run Trivy vulnerability scanner
# Pinned to v0.35.0 specifically for security after March 2026 compromise
uses: aquasecurity/trivy-action@v0.35.0
with:
image-ref: ${{ matrix.image }}@${{ steps.build-push.outputs.digest }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Sign Backend Image
run: |
cosign sign --yes "${{ env.REGISTRY }}/${{ github.repository }}/backend@${{ steps.build-push.outputs.digest }}"

# --- JOB 2: FRONTEND (ZIP Archive for Release Assets) ---
build-frontend:
runs-on: ubuntu-latest
permissions:
contents: write # Required to upload the ZIP to the Release
id-token: write
attestations: write

- name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
sarif_file: 'trivy-results.sarif'
category: ${{ matrix.service }}
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
run: npm ci
working-directory: frontend

- name: Create Placeholder Config
# This ensures the Angular build doesn't fail due to missing environment files
run: |
mkdir -p src/assets
echo '{"production": true}' > src/assets/config.json
working-directory: frontend

- name: Build Angular App
run: npm run build -- --configuration=production
working-directory: frontend

- name: Package Assets
run: |
cd frontend/dist/creative-studio
zip -r ../../../frontend-assets.zip .
cd ../../../
# Generate SHA-256 checksum
sha256sum frontend-assets.zip > frontend-assets.zip.sha256

- name: Install Cosign
uses: sigstore/cosign-installer@v3.5.0

- name: Sign image and Attest SBOM
env:
DIGEST: ${{ steps.build-push.outputs.digest }}
- name: Sign Frontend Blob
# This signs the ZIP file using GitHub's OIDC identity
run: |
cosign sign --yes "${{ matrix.image }}@${{ env.DIGEST }}"
cosign attest --yes --type cyclonedx --predicate <(trivy image --format cyclonedx "${{ matrix.image }}@${{ env.DIGEST }}") "${{ matrix.image }}@${{ env.DIGEST }}"
cosign sign-blob --yes frontend-assets.zip \
--bundle frontend-assets.zip.bundle

- name: Attest Build Provenance
# Official name for the GA version of build provenance
uses: actions/attest-build-provenance@v1
- name: Upload Artifacts to Release
uses: softprops/action-gh-release@v2
with:
subject-name: ${{ matrix.image }}
subject-digest: ${{ steps.build-push.outputs.digest }}
push-to-registry: true
files: |
frontend-assets.zip
frontend-assets.zip.sha256
frontend-assets.zip.bundle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading
Loading