mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 21:55:09 +00:00
212 lines
6.3 KiB
YAML
212 lines
6.3 KiB
YAML
name: Deploy Academy LMS to Hetzner
|
|
|
|
on:
|
|
# Manual trigger
|
|
workflow_dispatch:
|
|
inputs:
|
|
force_rebuild:
|
|
description: 'Force rebuild all images'
|
|
required: false
|
|
default: 'false'
|
|
type: boolean
|
|
environment:
|
|
description: 'Deployment environment'
|
|
required: false
|
|
default: 'test'
|
|
type: choice
|
|
options:
|
|
- production
|
|
- test
|
|
|
|
# Webhook triggers from watched repositories
|
|
repository_dispatch:
|
|
types: [academy-lms-updated, academy-ai-tutor-updated, academy-langchain-updated]
|
|
|
|
# Push to master branch of this repo
|
|
push:
|
|
branches: [ master ]
|
|
paths:
|
|
- 'compose.yaml'
|
|
- 'images/**'
|
|
- '.github/workflows/**'
|
|
- 'nginx/**'
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
HETZNER_HOST: 188.245.211.114
|
|
HETZNER_USER: ignis_academy_lms
|
|
DEPLOY_PATH: /opt/frappe-deployment
|
|
|
|
jobs:
|
|
build-and-deploy:
|
|
runs-on: ubuntu-latest
|
|
# Use environment for secrets management
|
|
environment: ${{ github.event.inputs.environment || 'test' }}
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract metadata for Frappe image
|
|
id: meta-frappe
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/exarlabs/ignis-academy-lms
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=ref,event=pr
|
|
type=sha,prefix={{branch}}-
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
|
|
- name: Build and push Frappe image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
file: ./images/custom/Containerfile
|
|
push: true
|
|
tags: ${{ steps.meta-frappe.outputs.tags }}
|
|
labels: ${{ steps.meta-frappe.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
build-args: |
|
|
LMS_REPO_URL=https://github.com/ExarLabs/academy-lms
|
|
AI_TUTOR_REPO_URL=https://github.com/ExarLabs/academy-ai-tutor-chat
|
|
|
|
- name: Clone and prepare LangChain service
|
|
run: |
|
|
# Clone private repository using PAT (Personal Access Token)
|
|
git clone https://${{ secrets.ACADEMY_DOCKER_PAT }}@github.com/ExarLabs/academy-LangChain.git langchain-temp
|
|
|
|
- name: Extract metadata for LangChain image
|
|
id: meta-langchain
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/exarlabs/academy-langchain
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=ref,event=pr
|
|
type=sha,prefix={{branch}}-
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
|
|
- name: Build and push LangChain image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: ./langchain-temp
|
|
push: true
|
|
tags: ${{ steps.meta-langchain.outputs.tags }}
|
|
labels: ${{ steps.meta-langchain.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
- name: Setup SSH key
|
|
uses: webfactory/ssh-agent@v0.8.0
|
|
with:
|
|
ssh-private-key: ${{ secrets.HETZNER_SSH_KEY }}
|
|
|
|
- name: Add Hetzner server to known hosts
|
|
run: |
|
|
ssh-keyscan -H ${{ env.HETZNER_HOST }} >> ~/.ssh/known_hosts
|
|
|
|
- name: Deploy to Hetzner
|
|
run: |
|
|
# Copy deployment files to server
|
|
scp -r compose.yaml nginx/ scripts/ .env.example ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }}:${{ env.DEPLOY_PATH }}/
|
|
|
|
# Copy environment file if it doesn't exist
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
if [ ! -f .env ]; then
|
|
cp .env.example .env
|
|
echo 'Please update .env file with your configuration'
|
|
fi
|
|
"
|
|
|
|
# Login to private registry
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
echo '${{ secrets.GITHUB_TOKEN }}' | docker login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin
|
|
"
|
|
|
|
- name: Pull latest images
|
|
run: |
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
docker compose pull
|
|
"
|
|
|
|
- name: Stop services
|
|
run: |
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
docker compose down --timeout 30
|
|
"
|
|
|
|
- name: Start services
|
|
run: |
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
docker compose up -d
|
|
"
|
|
|
|
- name: Wait for services to be ready
|
|
run: |
|
|
echo "Waiting for services to start..."
|
|
sleep 30
|
|
|
|
- name: Run migrations
|
|
run: |
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
|
|
# Make sure the script is executable
|
|
chmod +x scripts/*
|
|
|
|
./scripts/migrate-all-sites.sh
|
|
"
|
|
|
|
- name: Check service status
|
|
run: |
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
docker compose ps
|
|
"
|
|
|
|
- name: Health check
|
|
run: |
|
|
# Wait a bit more for services to fully start
|
|
sleep 60
|
|
|
|
# Check if all docker container are up and running
|
|
ssh ${{ env.HETZNER_USER }}@${{ env.HETZNER_HOST }} "
|
|
count=$(docker container ls --format "{{.Status}}" | grep -v "^Up" | wc -l)
|
|
if [ $count -gt 0 ]; then
|
|
echo "❌ $count containers are not running properly"
|
|
cd ${{ env.DEPLOY_PATH }}
|
|
docker compose logs --tail=50
|
|
exit 1
|
|
else
|
|
echo "✅ All containers are running"
|
|
fi
|
|
"
|
|
|
|
- name: Notify deployment status
|
|
if: always()
|
|
run: |
|
|
if [ "${{ job.status }}" == "success" ]; then
|
|
echo "🚀 Deployment to Hetzner completed successfully!"
|
|
echo "🌐 Access your application at: http://${{ env.HETZNER_HOST }}"
|
|
else
|
|
echo "💥 Deployment failed. Check the logs above for details."
|
|
fi
|