Skip to content

Update Deploy.yml

Update Deploy.yml #11

Workflow file for this run

name: Deploy

Check failure on line 1 in .github/workflows/Deploy.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/Deploy.yml

Invalid workflow file

(Line: 10, Col: 15): Unexpected symbol: '|'. Located at position 19 within expression: github.repository | lower
on:
push:
branches: [ master ]
workflow_dispatch:
env:
DOCKER_REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository | lower }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code with submodules
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.GITHUB_TOKEN }}
- name: Force initialize submodule
run: |
echo "=== Force initializing FileChecker submodule ==="
git submodule add --force https://github.com/Safeturned/FileChecker.git FileChecker || true
git submodule update --init --recursive
echo "=== Checking submodule status ==="
git submodule status
echo "=== FileChecker directory contents ==="
ls -la FileChecker/
echo "=== FileChecker/src directory contents ==="
ls -la FileChecker/src/
- 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: Debug Aspire output
run: |
echo "=== Aspire publish output ==="
ls -la ./publish/aspire/
echo "=== Docker compose content ==="
cat ./publish/aspire/docker-compose.yaml
- name: Tag and push Docker image
run: |
# Find the latest built image for safeturned-api from aspire publish
BUILT_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep safeturned-api | head -n 1)
if [ -n "$BUILT_IMAGE" ]; then
echo "Found built image: $BUILT_IMAGE"
# Login to registry
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ env.DOCKER_REGISTRY }} -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
# Tag with registry path
docker tag "$BUILT_IMAGE" "${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
# Push to registry
docker push "${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
echo "✅ Image pushed successfully"
else
echo "❌ No built image found, skipping push"
exit 1
fi
- 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
# No tar files from Aspire - it builds locally but doesn't export
# Create override to use registry image and expose port
cat > ./deploy/docker-compose.override.yaml << 'EOF'
services:
safeturned-api:
image: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
ports:
- "8080:${SAFETURNED_API_PORT:-80}" # Expose for Cloudflare Tunnel
EOF
# Create deployment script
cat > ./deploy/deploy.sh << 'EOF'
#!/bin/bash
set -e
echo "Starting deployment..."
# Set default environment variables
export DATABASE_PASSWORD=${DATABASE_PASSWORD:-"safeturned_password"}
export SAFETURNED_API_PORT=${SAFETURNED_API_PORT:-"8080"}
export CLOUDFLARE_TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN:-""}
echo "Environment variables set:"
echo "DATABASE_PASSWORD: $DATABASE_PASSWORD"
echo "SAFETURNED_API_PORT: $SAFETURNED_API_PORT"
echo "CLOUDFLARE_TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN:0:10}..."
# Stop existing containers
docker compose down || true
# Pull the latest image from registry
echo "Pulling latest image from registry..."
docker pull ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest || echo "Image pull failed, will build locally"
# Start with Aspire's docker-compose
docker compose up -d
# 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: Debug deployment files
run: |
echo "=== Debugging deployment files ==="
echo "Current directory: $(pwd)"
echo "Deploy directory contents:"
ls -la ./deploy/
echo "Deploy.sh contents:"
cat ./deploy/deploy.sh
- name: Copy files to server
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "./deploy/"
target: "/opt/safeturned"
strip_components: 0
- name: Debug server files
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
echo "=== Debugging server files ==="
echo "Current directory: $(pwd)"
echo "Opt directory contents:"
ls -la /opt/
echo "Safeturned directory contents:"
ls -la /opt/safeturned/ || echo "Directory does not exist"
- 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 }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /opt/safeturned/deploy
./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