name: Build & Deploy Mintel.me on: push: branches: - main tags: - 'v*' workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ (github.ref_type == 'tag' && !contains(github.ref_name, '-')) && 'prod' || (github.ref_type == 'tag' && 'staging' || 'testing') }} cancel-in-progress: true jobs: prepare: name: ๐Ÿ” Prepare Environment runs-on: docker outputs: target: ${{ steps.determine.outputs.target }} image_tag: ${{ steps.determine.outputs.image_tag }} env_file: ${{ steps.determine.outputs.env_file }} traefik_host: ${{ steps.determine.outputs.traefik_host }} next_public_base_url: ${{ steps.determine.outputs.next_public_base_url }} directus_url: ${{ steps.determine.outputs.directus_url }} directus_host: ${{ steps.determine.outputs.directus_host }} project_name: ${{ steps.determine.outputs.project_name }} is_prod: ${{ steps.determine.outputs.is_prod }} gotify_title: ${{ steps.determine.outputs.gotify_title }} container: image: catthehacker/ubuntu:act-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: ๐Ÿ” Determine Environment id: determine shell: bash run: | TAG="${{ github.ref_name }}" SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-9) if [[ "${{ github.ref_type }}" == "branch" && "$TAG" == "main" ]]; then TARGET="testing" IMAGE_TAG="main-${SHORT_SHA}" ENV_FILE=".env.testing" TRAEFIK_HOST="testing.mintel.me" NEXT_PUBLIC_BASE_URL="https://testing.mintel.me" DIRECTUS_URL="https://cms.testing.mintel.me" DIRECTUS_HOST="cms.testing.mintel.me" PROJECT_NAME="mintel-me-testing" IS_PROD="false" GOTIFY_TITLE="๐Ÿงช Testing-Deploy" elif [[ "${{ github.ref_type }}" == "tag" ]]; then if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then TARGET="production" IMAGE_TAG="$TAG" ENV_FILE=".env.prod" TRAEFIK_HOST="mintel.me, www.mintel.me" NEXT_PUBLIC_BASE_URL="https://mintel.me" DIRECTUS_URL="https://cms.mintel.me" DIRECTUS_HOST="cms.mintel.me" PROJECT_NAME="mintel-me-prod" IS_PROD="true" GOTIFY_TITLE="๐Ÿš€ Production-Release" else TARGET="staging" IMAGE_TAG="$TAG" ENV_FILE=".env.staging" TRAEFIK_HOST="staging.mintel.me" NEXT_PUBLIC_BASE_URL="https://staging.mintel.me" DIRECTUS_URL="https://cms.staging.mintel.me" DIRECTUS_HOST="cms.staging.mintel.me" PROJECT_NAME="mintel-me-staging" IS_PROD="false" GOTIFY_TITLE="๐Ÿงช Staging-Deploy" fi else echo "Skipping deploy for unknown ref type" exit 1 fi echo "target=$TARGET" >> $GITHUB_OUTPUT echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT echo "env_file=$ENV_FILE" >> $GITHUB_OUTPUT echo "traefik_host=$TRAEFIK_HOST" >> $GITHUB_OUTPUT echo "next_public_base_url=$NEXT_PUBLIC_BASE_URL" >> $GITHUB_OUTPUT echo "directus_url=$DIRECTUS_URL" >> $GITHUB_OUTPUT echo "directus_host=$DIRECTUS_HOST" >> $GITHUB_OUTPUT echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT echo "is_prod=$IS_PROD" >> $GITHUB_OUTPUT echo "gotify_title=$GOTIFY_TITLE" >> $GITHUB_OUTPUT build: name: ๐Ÿ—๏ธ Build & Push needs: prepare runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: ๐Ÿณ Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: ๐Ÿ” Registry Login run: | echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin - name: ๐Ÿ—๏ธ Build & Push env: IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }} TARGET: ${{ needs.prepare.outputs.target }} NEXT_PUBLIC_BASE_URL: ${{ needs.prepare.outputs.next_public_base_url }} DIRECTUS_URL: ${{ needs.prepare.outputs.directus_url }} run: | docker buildx build \ --pull \ --platform linux/arm64 \ --build-arg NEXT_PUBLIC_BASE_URL="$NEXT_PUBLIC_BASE_URL" \ --build-arg NEXT_PUBLIC_TARGET="$TARGET" \ --build-arg DIRECTUS_URL="$DIRECTUS_URL" \ --secret id=NPM_TOKEN,env=NPM_TOKEN \ -t registry.infra.mintel.me/mintel/mintel.me:$IMAGE_TAG \ --push . env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} deploy: name: ๐Ÿš€ Deploy needs: [prepare, build] runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: ๐Ÿš€ Deploy via SSH env: TARGET: ${{ needs.prepare.outputs.target }} IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }} ENV_FILE: ${{ needs.prepare.outputs.env_file }} PROJECT_NAME: ${{ needs.prepare.outputs.project_name }} AUTH_MIDDLEWARE: ${{ needs.prepare.outputs.is_prod == 'true' && 'compress' || format('{0}-auth,compress', needs.prepare.outputs.project_name) }} run: | mkdir -p ~/.ssh echo "${{ secrets.ALPHA_SSH_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H alpha.mintel.me >> ~/.ssh/known_hosts 2>/dev/null # Create .env on the fly cat > .env.tmp << EOF # Generated by CI NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_base_url }} NEXT_PUBLIC_TARGET=$TARGET DIRECTUS_URL=${{ needs.prepare.outputs.directus_url }} DIRECTUS_HOST=${{ needs.prepare.outputs.directus_host }} TRAEFIK_HOST=${{ needs.prepare.outputs.traefik_host }} IMAGE_TAG=$IMAGE_TAG PROJECT_NAME=$PROJECT_NAME AUTH_MIDDLEWARE=$AUTH_MIDDLEWARE # Secrets DIRECTUS_KEY=${{ secrets.DIRECTUS_KEY }} DIRECTUS_SECRET=${{ secrets.DIRECTUS_SECRET }} DIRECTUS_DB_NAME=${{ secrets.DIRECTUS_DB_NAME || 'directus' }} DIRECTUS_DB_USER=${{ secrets.DIRECTUS_DB_USER || 'directus' }} DIRECTUS_DB_PASSWORD=${{ secrets.DIRECTUS_DB_PASSWORD }} EOF scp .env.tmp root@alpha.mintel.me:/home/deploy/sites/mintel.me/$ENV_FILE scp docker-compose.yml root@alpha.mintel.me:/home/deploy/sites/mintel.me/docker-compose.yml scp -r varnish root@alpha.mintel.me:/home/deploy/sites/mintel.me/ ssh root@alpha.mintel.me IMAGE_TAG="$IMAGE_TAG" ENV_FILE="$ENV_FILE" PROJECT_NAME="$PROJECT_NAME" bash << 'EOF' cd /home/deploy/sites/mintel.me echo "${{ secrets.REGISTRY_PASS }}" | docker login registry.infra.mintel.me -u "${{ secrets.REGISTRY_USER }}" --password-stdin docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" pull docker compose -p "$PROJECT_NAME" --env-file "$ENV_FILE" up -d --remove-orphans docker system prune -f --filter "until=24h" EOF notifications: name: ๐Ÿ”” Notifications needs: [prepare, deploy] if: always() runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: ๐Ÿ”” Gotify run: | STATUS="${{ needs.deploy.result == 'success' && 'โœ…' || 'โŒ' }}" curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \ -F "title=$STATUS ${{ needs.prepare.outputs.gotify_title }}" \ -F "message=Deploy to **${{ needs.prepare.outputs.target }}** ${{ needs.deploy.result }}.\nVersion: ${{ needs.prepare.outputs.image_tag }}" \ -F "priority=5" || true