Merge pull request #13 from maxh33/feat/tests #96
This file contains 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 to Production | |
on: | |
push: | |
branches: | |
- main | |
pull_request: | |
branches: | |
- main | |
- feat/tests # Include for testing deployment in PRs | |
env: | |
REGISTRY: ghcr.io | |
IMAGE_NAME: ${{ github.repository }} | |
jobs: | |
test: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v3 | |
- uses: actions/setup-node@v3 | |
with: | |
node-version: '18' | |
cache: 'npm' | |
- name: Install dependencies | |
run: npm ci | |
- name: Run tests | |
run: | | |
npm run test:unit | |
npm run test:integration | |
env: | |
MONGODB_URI: mongodb://localhost:27017/test | |
RABBITMQ_URL: amqp://guest:guest@localhost:5672 | |
build-and-deploy: | |
needs: test # Only deploy if tests pass | |
if: github.ref == 'refs/heads/main' # Only deploy on main branch | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v3 | |
- name: Setup Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: '18' | |
cache: 'npm' | |
- name: Install dependencies | |
run: npm ci | |
- name: Build TypeScript | |
run: npm run build | |
- name: Verify MongoDB Connection | |
run: npm run verify:mongodb | |
env: | |
MONGODB_URI: ${{ secrets.MONGODB_URI }} | |
NODE_ENV: production | |
- name: Set RabbitMQ Credentials | |
run: | | |
# Use localhost for GitHub Actions since we're running verification locally | |
echo "RABBITMQ_PASSWORD=${{ secrets.RABBITMQ_PASSWORD }}" >> $GITHUB_ENV | |
echo "RABBITMQ_URL=amqp://pulse_flow_user:${{ secrets.RABBITMQ_PASSWORD }}@localhost:5672" >> $GITHUB_ENV | |
- name: Verify RabbitMQ Connection | |
run: npm run verify:rabbitmq | |
env: | |
RABBITMQ_URL: ${{ secrets.RABBITMQ_URL }} | |
NODE_ENV: production | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Log in to GitHub Container Registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Create environment file | |
run: | | |
cat > .env << 'EOL' | |
PORT=3000 | |
NODE_ENV=production | |
MONGODB_URI=${{ secrets.MONGODB_URI }} | |
GRAFANA_PUSH_URL=${{ secrets.GRAFANA_PUSH_URL }} | |
GRAFANA_PROMETHEUS_URL=${{ secrets.GRAFANA_PROMETHEUS_URL }} | |
GRAFANA_USERNAME=${{ secrets.GRAFANA_USERNAME }} | |
GRAFANA_API_KEY=${{ secrets.GRAFANA_API_KEY }} | |
RABBITMQ_URL=${{ secrets.RABBITMQ_URL }} | |
METRICS_PUSH_INTERVAL=60000 | |
EOL | |
- name: Build and push Docker image | |
uses: docker/build-push-action@v4 | |
with: | |
context: . | |
file: ./Dockerfile.prod | |
push: true | |
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
- name: Install Docker Compose | |
run: | | |
sudo curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r .tag_name)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose | |
sudo chmod +x /usr/local/bin/docker-compose | |
- name: Setup and Deploy | |
run: | | |
# Clean up existing deployment first | |
bash scripts/cleanup.sh | |
# Initialize network with proper labels | |
bash scripts/init-network.sh | |
# Deploy with proper project name | |
COMPOSE_PROJECT_NAME=pulse-flow docker-compose -f docker-compose.prod.yml up -d | |
env: | |
MONGODB_URI: ${{ secrets.MONGODB_URI }} | |
GRAFANA_PUSH_URL: ${{ secrets.GRAFANA_PUSH_URL }} | |
GRAFANA_PROMETHEUS_URL: ${{ secrets.GRAFANA_PROMETHEUS_URL }} | |
GRAFANA_USERNAME: ${{ secrets.GRAFANA_USERNAME }} | |
GRAFANA_API_KEY: ${{ secrets.GRAFANA_API_KEY }} | |
RABBITMQ_URL: ${{ secrets.RABBITMQ_URL }} | |
GITHUB_REPOSITORY: ${{ github.repository }} | |
- name: Wait for app to start | |
run: sleep 30 # Give containers time to fully start | |
- name: Verify Deployment | |
run: | | |
# Check if container is running and get its status | |
CONTAINER_STATUS=$(docker inspect --format='{{.State.Status}}' pulse-flow-app 2>/dev/null || echo "not_found") | |
if [ "$CONTAINER_STATUS" != "running" ]; then | |
echo "Container pulse-flow-app is not running (status: $CONTAINER_STATUS)" | |
echo "Container logs:" | |
docker logs pulse-flow-app || true | |
echo "All running containers:" | |
docker ps | |
exit 1 | |
fi | |
# Check container logs | |
echo "Container logs:" | |
docker logs pulse-flow-app | |
# Try direct health check | |
for i in {1..5}; do | |
if curl -f http://localhost:3000/healthz; then | |
echo "Health check passed!" | |
exit 0 | |
fi | |
echo "Attempt $i failed, waiting..." | |
sleep 10 | |
done | |
echo "Health check failed after 5 attempts" | |
exit 1 | |
- name: Cleanup on Failure | |
if: failure() | |
run: | | |
docker-compose -f docker-compose.prod.yml down --volumes --remove-orphans || true | |
docker network rm pulse-flow_app_network || true |