ai-wpa/.github/workflows/deploy.yml

158 lines
5.7 KiB
YAML

name: Deploy SiliconPin
on:
push:
branches: [ main ] # Change this to match your main branch name if different
workflow_dispatch: # Allows manual workflow runs
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Cache Yarn dependencies
uses: actions/cache@v4
with:
path: |
~/.cache/yarn
node_modules
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Create .env file
run: |
echo "Creating .env file with secrets..."
echo "MONGODB_URI=${{ secrets.MONGODB_URI }}" > .env
echo "REDIS_URL=${{ secrets.REDIS_URL }}" >> .env
echo "SESSION_SECRET=${{ secrets.SESSION_SECRET }}" >> .env
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
echo "JWT_REFRESH_SECRET=${{ secrets.JWT_REFRESH_SECRET }}" >> .env
echo "GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}" >> .env
echo "GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}" >> .env
echo "GOOGLE_REDIRECT_URI=${{ secrets.GOOGLE_REDIRECT_URI }}" >> .env
echo "NEXT_PUBLIC_APP_URL=${{ secrets.NEXT_PUBLIC_APP_URL }}" >> .env
echo "NODE_ENV=production" >> .env
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: siliconpin:latest
cache-from: type=gha
cache-to: type=gha,mode=max
outputs: type=docker,dest=/tmp/siliconpin-image.tar
build-args: |
SKIP_ENV_VALIDATION=true
- name: Load Docker image
run: docker load -i /tmp/siliconpin-image.tar
- name: Set up SSH
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
known_hosts: 'just-a-placeholder'
- name: Add remote host to known hosts
run: |
mkdir -p ~/.ssh
echo "Adding ${{ secrets.SSH_HOST }} to known hosts..."
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts
- name: Compress Docker image
run: |
echo "Compressing Docker image..."
gzip /tmp/siliconpin-image.tar
mv /tmp/siliconpin-image.tar.gz siliconpin-image.tar.gz
- name: Transfer Docker image to server
run: |
echo "Transferring Docker image to server..."
scp -o StrictHostKeyChecking=no siliconpin-image.tar.gz ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/root/services/siliconpin-image.tar.gz
scp -o StrictHostKeyChecking=no docker-compose.yml ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/root/services/siliconpin/docker-compose.yml
- name: Deploy to production
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
# Force using bash instead of fish
bash -c '
# Navigate to the services directory
cd /root/services/
# Create siliconpin directory if it doesn not exist
mkdir -p siliconpin
cd siliconpin
# Stop the current container
docker compose down || true
# Load the new Docker image
echo "Loading Docker image..."
docker load < /root/services/siliconpin-image.tar.gz
# Remove the transferred image file
rm -f /root/services/siliconpin-image.tar.gz
# Start the container using the new image
echo "Starting container..."
docker compose up -d
# Wait for container to be fully running
echo "Waiting for container to be ready..."
attempt=1
max_attempts=30
until [ $attempt -gt $max_attempts ] || docker container inspect siliconpin --format="{{.State.Running}}" 2>/dev/null | grep -q "true"; do
echo "Attempt $attempt/$max_attempts: Container not ready yet, waiting..."
sleep 2
attempt=$((attempt+1))
done
if [ $attempt -gt $max_attempts ]; then
echo "Container failed to start properly within time limit!"
docker compose logs
exit 1
fi
# Further verification of application health
echo "Verifying application health..."
timeout=120
start_time=$(date +%s)
end_time=$((start_time + timeout))
while [ $(date +%s) -lt $end_time ]; do
if curl -s http://localhost:4023/ > /dev/null; then
echo "Application is responding!"
break
fi
echo "Waiting for application to respond..."
sleep 10
done
if ! curl -s http://localhost:4023/ > /dev/null; then
echo "Application failed to respond within timeout!"
docker compose logs
exit 1
fi
# Clean up is already done above
# Verify deployment
echo "Deployment successful! Container is running and application is responding."
docker ps | grep siliconpin
'
EOF