Skip to content

Deploy Cube Cloud Services #32

Deploy Cube Cloud Services

Deploy Cube Cloud Services #32

Workflow file for this run

# Copyright (c) Ultraviolet
# SPDX-License-Identifier: Apache-2.0
name: Deploy Cube Cloud Services
on:
push:
branches:
- main
paths:
- "docker/compose.yaml"
- "docker/supermq-compose.yaml"
- "docker/cube-compose.yaml"
- "docker/.env"
- "docker/config.json"
- "docker/fluent-bit.conf"
- "docker/parsers.conf"
- "docker/opensearch-index-template.json"
- "docker/traefik/traefik.toml"
- "docker/traefik/dynamic.toml"
- ".github/workflows/deploy-cloud.yaml"
workflow_dispatch:
inputs:
environment:
description: "Deployment environment"
required: true
default: "dev"
type: choice
options:
- dev
- staging
- production
concurrency:
group: deploy-cloud-${{ github.ref }}
cancel-in-progress: false
env:
REGISTRY: ghcr.io
DEPLOY_DIR: cube-cloud
jobs:
deploy-cloud:
runs-on: ubuntu-latest
environment: ${{ inputs.environment || 'dev' }}
permissions:
contents: read
packages: read
steps:
- name: Deploy Cube Cloud Services
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.CUBE_SERVER_IP }}
port: 49200
username: ${{ secrets.CUBE_SERVER_USERNAME }}
key: ${{ secrets.CUBE_SERVER_KEY }}
script_stop: true
command_timeout: 200m
script: |
set -euo pipefail
echo "=== Cube Cloud Deployment Started ==="
echo "Logging into GitHub Container Registry"
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
echo "Changing directory to project"
cd ${{ env.DEPLOY_DIR }}
echo "Pulling latest code from repository"
git stash
git pull
echo "Creating required directories and setting up SSL"
mkdir -p docker/traefik/ssl/certs
# Initialize acme.json if it doesn't exist
if test -f docker/traefik/ssl/certs/acme.json; then
chmod 600 docker/traefik/ssl/certs/acme.json
echo " ✓ acme.json already exists"
else
printf '{}' > docker/traefik/ssl/certs/acme.json
chmod 600 docker/traefik/ssl/certs/acme.json
echo " ✓ Created acme.json"
fi
echo "Updating environment variables and configuration with secrets"
# Replace placeholder with actual public URL from secrets
sed -i "s|__SMQ_EMAIL_HOST__|${{ secrets.SMQ_EMAIL_HOST }}|g" docker/.env
sed -i "s|__SMQ_EMAIL_PORT__|${{ secrets.SMQ_EMAIL_PORT }}|g" docker/.env
sed -i "s|__SMQ_EMAIL_USERNAME__|${{ secrets.SMQ_EMAIL_USERNAME }}|g" docker/.env
sed -i "s|__SMQ_EMAIL_PASSWORD__|${{ secrets.SMQ_EMAIL_PASSWORD }}|g" docker/.env
sed -i "s|__SMQ_EMAIL_FROM_ADDRESS__|${{ secrets.SMQ_EMAIL_FROM_ADDRESS }}|g" docker/.env
sed -i "s|admin@example.com|${{ secrets.CUBE_ADMIN_EMAIL }}|g" docker/.env
sed -i "s|"m2N2Lfno"|"${{ secrets.CUBE_ADMIN_PASSWORD }}"|g" docker/.env
sed -i "s|__CUBE_PUBLIC_URL__|${{ secrets.CUBE_PUBLIC_URL }}|g" docker/.env
sed -i "s|__CUBE_INTERNAL_AGENT_URL__|${{ secrets.CUBE_INTERNAL_AGENT_URL }}|g" docker/.env
# Replace Google OAuth placeholders
sed -i "s|__SMQ_GOOGLE_CLIENT_ID__|${{ secrets.SMQ_GOOGLE_CLIENT_ID }}|g" docker/.env
sed -i "s|__SMQ_GOOGLE_CLIENT_SECRET__|${{ secrets.SMQ_GOOGLE_CLIENT_SECRET }}|g" docker/.env
sed -i "s|__SMQ_GOOGLE_STATE__|${{ secrets.SMQ_GOOGLE_STATE }}|g" docker/.env
# Replace Traefik configuration placeholders
sed -i "s|__TRAEFIK_HTTP_PORT__|${{ secrets.TRAEFIK_HTTP_PORT }}|g" docker/.env
sed -i "s|__TRAEFIK_HTTPS_PORT__|${{ secrets.TRAEFIK_HTTPS_PORT }}|g" docker/.env
sed -i "s|__TRAEFIK_DASHBOARD_PORT__|${{ secrets.TRAEFIK_DASHBOARD_PORT }}|g" docker/.env
sed -i "s|__TUNNEL_TOKEN__|${{ secrets.TUNNEL_TOKEN }}|g" docker/.env
sed -i "s|__CUBE_AGENT_CERTS_TOKEN__|${{ secrets.CUBE_AGENT_CERTS_TOKEN }}|g" docker/.env
sed -i "s|__CUBE_INTERNAL_AGENT_URL__|${{ secrets.CUBE_INTERNAL_AGENT_URL }}|g" docker/config.json
# Replace placeholder with actual domain from secrets
sed -i "s|__CUBE_DOMAIN__|${{ secrets.CUBE_DOMAIN }}|g" docker/traefik/dynamic.toml
echo "Pulling latest Docker images"
docker compose -f docker/compose.yaml --profile cloud pull 2>&1
echo "Stopping existing services"
docker compose -f docker/compose.yaml --profile cloud down 2>&1
echo "Starting cloud services"
docker compose -f docker/compose.yaml --profile cloud up -d 2>&1
echo "Waiting for services to start (30 seconds)..."
sleep 30
echo "Checking service status..."
docker compose -f docker/compose.yaml --profile cloud ps 2>&1
echo "=== Verifying Critical Services ==="
SERVICES="traefik opensearch nats spicedb auth users domains ui cube-proxy guardrails fluent-bit"
ALL_RUNNING=true
for SERVICE in $SERVICES; do
if docker ps --format '{{.Names}}' | grep -q "$SERVICE"; then
echo "✓ Service $SERVICE is running"
else
echo "✗ Service $SERVICE is not running"
ALL_RUNNING=false
fi
done
if [ "$ALL_RUNNING" = false ]; then
echo "Deployment verification failed!"
make logs-cloud 2>&1 | tail -100
exit 1
fi
echo "✓ All cloud services deployed successfully!"
echo ""
echo "=== Service URLs (All through Traefik Gateway) ==="
echo " - Cube UI: ${{ secrets.CUBE_PUBLIC_URL }}/"
echo " - Cube Proxy API: ${{ secrets.CUBE_PUBLIC_URL }}/proxy"
echo " - Traefik Dashboard: http://${{ secrets.CUBE_SERVER_IP }}:49212"
echo ""
echo "Note: HTTP automatically redirects to HTTPS"
- name: System Cleanup
if: always()
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.CUBE_SERVER_IP }}
port: 49200
username: ${{ secrets.CUBE_SERVER_USERNAME }}
key: ${{ secrets.CUBE_SERVER_KEY }}
script_stop: false
command_timeout: 10m
script: |
echo "Running system cleanup..."
docker system prune -a -f
echo "✓ Cleanup completed"