Update Deploy.yml #58
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: safeturned/api | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
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/ | |
- name: Login to GHCR | |
run: | | |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin | |
- name: Find and tag Docker image | |
run: | | |
# Look for the built image with various possible names | |
BUILT_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -E "(safeturned-api|safeturned-api)" | head -n 1) | |
if [ -z "$BUILT_IMAGE" ]; then | |
# Try to find any image with safeturned in the name | |
BUILT_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep safeturned | head -n 1) | |
fi | |
if [ -z "$BUILT_IMAGE" ]; then | |
# List all images for debugging | |
echo "Available Docker images:" | |
docker images | |
echo "❌ No built image found" | |
exit 1 | |
fi | |
echo "Found built image: $BUILT_IMAGE" | |
# Tag for GHCR | |
docker tag "$BUILT_IMAGE" "ghcr.io/safeturned/api:latest" | |
docker tag "$BUILT_IMAGE" "ghcr.io/safeturned/api:v${{ github.run_number }}" | |
echo "✅ Image tagged successfully" | |
- name: Push Docker image | |
run: | | |
# Push both latest and versioned tags | |
docker push "ghcr.io/safeturned/api:latest" | |
docker push "ghcr.io/safeturned/api:v${{ github.run_number }}" | |
echo "✅ Images pushed successfully" | |
- name: Create deployment package | |
run: | | |
mkdir -p ./deploy | |
cp ./publish/aspire/docker-compose.yaml ./deploy/ | |
cp ./publish/aspire/.env ./deploy/ 2>/dev/null || true | |
cat > ./deploy/docker-compose.override.yaml << 'EOF' | |
services: | |
safeturned-api: | |
image: ghcr.io/safeturned/api:latest | |
ports: | |
- "8081:8081" # Map host port to container port | |
nginx: | |
image: nginx:alpine | |
ports: | |
- "8082:80" | |
volumes: | |
- ./nginx.conf:/etc/nginx/nginx.conf:ro | |
depends_on: | |
- safeturned-api | |
restart: unless-stopped | |
EOF | |
cat > ./deploy/nginx.conf << 'EOF' | |
events { | |
worker_connections 1024; | |
} | |
http { | |
upstream safeturned_api { | |
server safeturned-api:8081; | |
} | |
server { | |
listen 80; | |
server_name _; | |
location / { | |
proxy_pass http://safeturned_api; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Proto $scheme; | |
} | |
} | |
} | |
EOF | |
cat > ./deploy/deploy.sh << 'EOF' | |
#!/bin/bash | |
set -e | |
echo "Starting deployment..." | |
docker compose down || true | |
echo "Pulling latest image from registry..." | |
docker pull ghcr.io/safeturned/api:latest || echo "Image pull failed, will build locally" | |
docker compose up -d | |
echo "Waiting for services to be healthy..." | |
timeout 300 bash -c 'until docker compose ps | grep -q "healthy"; do sleep 20; echo "Still waiting for healthy services..."; docker compose ps; done' || echo "Warning: Some services may not be healthy" | |
echo "Deployment completed successfully!" | |
echo "API is available on port 8081 for Cloudflare Tunnel" | |
EOF | |
echo "Deployment package created in ./deploy/" | |
echo "=== Debug: Listing deploy directory contents ===" | |
ls -la ./deploy/ | |
echo "=== Debug: Checking if deploy.sh exists and is executable ===" | |
ls -la ./deploy/deploy.sh || echo "deploy.sh not found" | |
echo "=== Debug: File contents of deploy.sh (first 10 lines) ===" | |
head -10 ./deploy/deploy.sh || echo "Cannot read deploy.sh" | |
chmod +x ./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/deploy.sh,./deploy/docker-compose.yaml,./deploy/docker-compose.override.yaml,./deploy/nginx.conf" | |
target: "/opt/safeturned" | |
- 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: | | |
echo "=== Starting deployment ===" | |
# Go to the deploy directory where files are copied | |
cd /opt/safeturned/deploy | |
# Run deployment | |
./deploy.sh | |
- name: Verify deployment | |
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 "=== Verifying deployment ===" | |
cd /opt/safeturned | |
echo "=== Container Status ===" | |
docker compose ps | |
echo "=== Port Check ===" | |
netstat -tlnp | grep 8081 || echo "Port 8081 not listening" | |
echo "=== Test API from host ===" | |
curl -f -s http://localhost:8081/health && echo "✅ API is responding" || echo "❌ API not responding" | |
echo "=== Deployment verification completed ===" | |
#- 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 }} | |
# | |
# draft: false | |
# prerelease: false |