Skip to content

CD Pipeline - UnHackable #9

CD Pipeline - UnHackable

CD Pipeline - UnHackable #9

Workflow file for this run

name: CD Pipeline - UnHackable
on:
# Triggered after CI completes successfully
workflow_run:
workflows: ["CI Pipeline - UnHackable"]
types:
- completed
branches: [main, master]
# Manual trigger
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
env:
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/unhackable
jobs:
# ============================================
# Stage 1: Deploy to Staging (Kubernetes)
# WHY: Validates deployment in non-production environment,
# allows testing before production release
# ============================================
deploy-staging:
name: 🚀 Deploy to Staging
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
environment: staging
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
# For demo: Show what would be deployed
- name: Show deployment configuration
run: |
echo "📦 Deploying image: ${{ env.IMAGE_NAME }}:latest"
echo ""
echo "=== Deployment Manifest ==="
sed "s|IMAGE_PLACEHOLDER|${{ env.IMAGE_NAME }}:latest|g" k8s/deployment.yaml
echo ""
echo "=== Service Manifest ==="
cat k8s/service.yaml
# NOTE: In production, you would configure KUBE_CONFIG secret and run:
# - name: Configure kubeconfig
# run: |
# mkdir -p $HOME/.kube
# echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
#
# - name: Deploy to Kubernetes
# run: |
# sed -i "s|IMAGE_PLACEHOLDER|${{ env.IMAGE_NAME }}:latest|g" k8s/deployment.yaml
# kubectl apply -f k8s/deployment.yaml -n staging
# kubectl apply -f k8s/service.yaml -n staging
# kubectl rollout status deployment/unhackable -n staging
- name: Deployment ready
run: |
echo "✅ Staging deployment manifests validated!"
echo "📝 To deploy to a real cluster, configure KUBE_CONFIG secret"
# ============================================
# Stage 2: DAST - Dynamic Application Security Testing
# WHY: Tests running application for vulnerabilities,
# identifies runtime security issues
# ============================================
dast:
name: 🔐 DAST - Security Scan
runs-on: ubuntu-latest
needs: deploy-staging
steps:
- name: Checkout code
uses: actions/checkout@v4
# Run container locally for DAST scan
- name: Start application for DAST
run: |
docker pull ${{ env.IMAGE_NAME }}:latest || echo "Using local build"
docker run -d --name dast-target -p 3000:3000 \
-e DATABASE_URI="${{ secrets.DATABASE_URI }}" \
-e NEXT_PUBLIC_RPC_URL="${{ secrets.NEXT_PUBLIC_RPC_URL }}" \
-e GOOGLE_CLIENT_ID="${{ secrets.GOOGLE_CLIENT_ID }}" \
-e GOOGLE_CLIENT_SECRET="${{ secrets.GOOGLE_CLIENT_SECRET }}" \
-e AUTH_SECRET="${{ secrets.AUTH_SECRET }}" \
-e NEXTAUTH_URL="http://localhost:3000" \
${{ env.IMAGE_NAME }}:latest || \
echo "⚠️ Could not pull image, skipping DAST"
sleep 15
# OWASP ZAP Baseline Scan (lightweight scan)
- name: OWASP ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.12.0
if: success()
continue-on-error: true
with:
target: 'http://localhost:3000'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a -j'
- name: Upload DAST Report
uses: actions/upload-artifact@v4
if: always()
with:
name: dast-report
path: report_html.html
retention-days: 7
- name: Cleanup
if: always()
run: docker rm -f dast-target || true
# ============================================
# Stage 3: Deploy to Production
# WHY: Final deployment after security validation,
# requires manual approval for safety
# ============================================
deploy-production:
name: 🚀 Deploy to Production
runs-on: ubuntu-latest
needs: dast
environment: production # Requires manual approval in GitHub
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Production deployment info
run: |
echo "🚀 Production Deployment"
echo "========================"
echo ""
echo "Image: ${{ env.IMAGE_NAME }}:latest"
echo "Commit: ${{ github.sha }}"
echo ""
echo "In a real setup, this would:"
echo "1. Connect to production Kubernetes cluster"
echo "2. Apply deployment manifests"
echo "3. Perform rolling update"
echo "4. Verify deployment health"
echo ""
echo "✅ Production deployment pipeline validated!"