#!/bin/sh set -eu require_value() { key="$1" value="$2" if [ -z "$value" ]; then echo "Missing required workflow configuration: $key" >&2 exit 1 fi } require_value "DEPLOY_TARGET" "${DEPLOY_TARGET:-}" require_value "CALENDAR_URL" "${CALENDAR_URL:-}" require_value "PRIMARY_DOMAIN" "${PRIMARY_DOMAIN:-}" require_value "TRAEFIK_CERTRESOLVER" "${TRAEFIK_CERTRESOLVER:-}" require_value "REGISTRY" "${REGISTRY:-}" require_value "APP_IMAGE_REPOSITORY" "${APP_IMAGE_REPOSITORY:-}" require_value "REGISTRY_USERNAME" "${REGISTRY_USERNAME:-}" require_value "REGISTRY_TOKEN" "${REGISTRY_TOKEN:-}" APP_URL="${APP_URL:-https://$PRIMARY_DOMAIN}" CORS_ORIGIN="${CORS_ORIGIN:-$APP_URL}" case "$DEPLOY_TARGET" in dev) default_stack_name="website-starter-dev" default_traefik_network="traefik-external" ;; master|production) default_stack_name="website-starter-prod" default_traefik_network="traefik" ;; *) echo "Unsupported deployment target: $DEPLOY_TARGET" >&2 exit 1 ;; esac COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-$default_stack_name}" TRAEFIK_STACK_NAME="${TRAEFIK_STACK_NAME:-$COMPOSE_PROJECT_NAME}" TRAEFIK_NETWORK_NAME="${TRAEFIK_NETWORK_NAME:-$default_traefik_network}" TRIVY_IMAGE="${TRIVY_IMAGE:-aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969}" BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" DOCKER_BUILDKIT="${DOCKER_BUILDKIT:-1}" revision="$(git rev-parse --short=12 HEAD)" build_timestamp="$(date -u +%Y%m%dT%H%M%SZ)" APP_IMAGE_TAG="scheduled-$DEPLOY_TARGET-$revision-$build_timestamp" APP_IMAGE_NAME="$APP_IMAGE_REPOSITORY:$APP_IMAGE_TAG" export CALENDAR_URL export PRIMARY_DOMAIN export APP_URL export CORS_ORIGIN export COMPOSE_PROJECT_NAME export TRAEFIK_STACK_NAME export TRAEFIK_CERTRESOLVER export TRAEFIK_NETWORK_NAME export APP_IMAGE_NAME export TRIVY_IMAGE export DOCKER_BUILDKIT export DEPLOY_MODE=app echo "Scheduled rebuild target: $DEPLOY_TARGET" echo "Git revision: $revision" echo "App image: $APP_IMAGE_NAME" docker build --pull \ --build-arg BUILD_DATE="$BUILD_DATE" \ --build-arg VCS_REF="$revision" \ --build-arg APP_URL="$APP_URL" \ --build-arg APP_NAME="${APP_NAME:-Example Website}" \ --build-arg COMPANY_NAME="${COMPANY_NAME:-Example Company}" \ --build-arg CONTACT_EMAIL="${CONTACT_EMAIL:-info@example.com}" \ --build-arg CONTACT_PHONE="${CONTACT_PHONE:-+49 000 000000}" \ --build-arg CONTACT_ADDRESS="${CONTACT_ADDRESS:-Example Street 1, 12345 Example City}" \ -f Dockerfile \ -t "$APP_IMAGE_NAME" \ . echo "Reporting app runtime image vulnerabilities..." sh scripts/trivy-scan.sh vuln-image "$APP_IMAGE_NAME" echo "Blocking app critical runtime vulnerabilities..." TRIVY_SEVERITY=CRITICAL TRIVY_EXIT_CODE=1 sh scripts/trivy-scan.sh vuln-image "$APP_IMAGE_NAME" docker_config="$(mktemp -d)" cleanup_registry_credentials() { DOCKER_CONFIG="$docker_config" docker logout "$REGISTRY" >/dev/null 2>&1 || true rm -rf "$docker_config" } trap cleanup_registry_credentials EXIT trap 'exit 1' HUP INT TERM export DOCKER_CONFIG="$docker_config" echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin docker push "$APP_IMAGE_NAME" docker logout "$REGISTRY" >/dev/null rm -rf "$docker_config" trap - EXIT HUP INT TERM unset DOCKER_CONFIG REGISTRY_USERNAME REGISTRY_TOKEN sh scripts/deploy-and-verify.sh