Add auto deploy workflow #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Deploy | |
on: | |
push: | |
branches: [ master ] | |
workflow_dispatch: | |
env: | |
DOCKER_REGISTRY: ghcr.io | |
IMAGE_NAME: ${{ github.repository }} | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
submodules: recursive | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Initialize submodules | |
run: | | |
git submodule update --init --recursive | |
- name: Setup .NET | |
uses: actions/setup-dotnet@v4 | |
env: | |
DOTNET_NOLOGO: true | |
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
DOTNET_CLI_TELEMETRY_OPTOUT: true | |
with: | |
dotnet-version: 9.* | |
- name: Setup Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Install Aspire CLI | |
run: dotnet tool install --global Aspire.Cli | |
- name: Publish with Aspire | |
run: | | |
aspire publish -o ./publish/aspire | |
- name: Create deployment package | |
run: | | |
mkdir -p ./deploy | |
# Copy Aspire generated files | |
cp ./publish/aspire/docker-compose.yaml ./deploy/ | |
cp ./publish/aspire/*.env ./deploy/ 2>/dev/null || true | |
# Create environment-specific docker-compose override for Docker-based cloudflared | |
cat > ./deploy/docker-compose.override.yaml << 'EOF' | |
services: | |
safeturned-api: | |
image: safeturned-api:latest | |
environment: | |
ASPNETCORE_ENVIRONMENT: Production | |
ASPNETCORE_URLS: http://0.0.0.0:80 | |
ports: | |
- "8080:80" # Expose on port 8080 for Cloudflare Tunnel | |
restart: unless-stopped | |
healthcheck: | |
test: ["CMD", "curl", "-f", "http://localhost:80/health"] | |
interval: 30s | |
timeout: 10s | |
retries: 3 | |
start_period: 40s | |
networks: | |
- aspire | |
# Optional: Add cloudflared service if not already running separately | |
cloudflared: | |
image: cloudflare/cloudflared:latest | |
command: tunnel run | |
environment: | |
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN} | |
restart: unless-stopped | |
depends_on: | |
- safeturned-api | |
networks: | |
- aspire | |
networks: | |
aspire: | |
external: true | |
EOF | |
# Create deployment script | |
cat > ./deploy/deploy.sh << 'EOF' | |
#!/bin/bash | |
set -e | |
echo "Starting deployment..." | |
# Stop existing containers | |
docker-compose down || true | |
# Pull latest images for other services | |
docker-compose pull | |
# Start with new configuration | |
docker-compose up -d --build | |
# Wait for services to be healthy | |
echo "Waiting for services to be healthy..." | |
timeout 300 bash -c 'until docker-compose ps | grep -q "healthy"; do sleep 5; done' || echo "Warning: Some services may not be healthy" | |
echo "Deployment completed successfully!" | |
echo "API is available on port 8080 for Cloudflare Tunnel" | |
EOF | |
chmod +x ./deploy/deploy.sh | |
echo "Deployment package created in ./deploy/" | |
- name: Copy files to server | |
uses: appleboy/scp-action@v1 | |
with: | |
host: ${{ secrets.SERVER_HOST }} | |
port: ${{ secrets.SSH_PORT || 22 }} | |
username: ${{ secrets.SERVER_USER }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
source: "./deploy/*" | |
target: "/opt/safeturned" | |
strip_components: 1 | |
- name: Copy Aspire build artifacts | |
run: | | |
# Aspire creates the container image, we just need to copy the compose files | |
echo "Aspire build artifacts are ready in ./publish/aspire/" | |
echo "Deployment package created in ./deploy/" | |
- name: Deploy to server | |
uses: appleboy/ssh-action@v1 | |
with: | |
host: ${{ secrets.SERVER_HOST }} | |
port: ${{ secrets.SSH_PORT || 22 }} | |
username: ${{ secrets.SERVER_USER }} | |
key: ${{ secrets.SSH_PRIVATE_KEY }} | |
script: | | |
cd /opt/safeturned | |
./deploy.sh | |
- name: Create Release | |
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' | |
uses: actions/create-release@v1 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
with: | |
tag_name: v${{ github.run_number }} | |
release_name: Release v${{ github.run_number }} | |
body: | | |
## Changes | |
- Built from commit: ${{ github.sha }} | |
- Deployed to server: ${{ secrets.SERVER_HOST }} | |
## Deployment Status | |
Application has been deployed to your server and is running with docker-compose. | |
## Cloudflare Tunnel Configuration | |
Your API is now available on port 8080 and ready for Cloudflare Tunnel configuration. | |
### Cloudflare Tunnel Setup: | |
1. Install cloudflared on your server | |
2. Create a tunnel in Cloudflare dashboard | |
3. Configure the tunnel to point to `localhost:8080` | |
4. Set up your custom domain in Cloudflare | |
draft: false | |
prerelease: false |