From 116dac89b3ce1847d61252ae238b583ea223d8b2 Mon Sep 17 00:00:00 2001 From: denshooter Date: Sat, 13 Sep 2025 23:20:51 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Fix=20Gitea=20Actions=20for=20ze?= =?UTF-8?q?ro-downtime=20deployment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create new ci-cd-zero-downtime-fixed.yml workflow - Disable old workflows that try to access port 3000 directly - New workflow uses docker-compose.zero-downtime.yml - Health checks now use nginx on port 80 instead of direct port 3000 - Fixes the 'Connection refused' errors in Gitea Actions โœ… Actions now properly work with zero-downtime nginx setup --- .../workflows/ci-cd-zero-downtime-fixed.yml | 164 ++++++++++++++++++ ...e.yml => ci-cd-zero-downtime.yml.disabled} | 0 .../{ci-cd.yml => ci-cd.yml.disabled} | 0 scripts/deploy.sh | 18 +- scripts/monitor.sh | 2 +- 5 files changed, 174 insertions(+), 10 deletions(-) create mode 100644 .gitea/workflows/ci-cd-zero-downtime-fixed.yml rename .gitea/workflows/{ci-cd-zero-downtime.yml => ci-cd-zero-downtime.yml.disabled} (100%) rename .gitea/workflows/{ci-cd.yml => ci-cd.yml.disabled} (100%) diff --git a/.gitea/workflows/ci-cd-zero-downtime-fixed.yml b/.gitea/workflows/ci-cd-zero-downtime-fixed.yml new file mode 100644 index 0000000..d540a4f --- /dev/null +++ b/.gitea/workflows/ci-cd-zero-downtime-fixed.yml @@ -0,0 +1,164 @@ +name: CI/CD Pipeline (Zero Downtime - Fixed) + +on: + push: + branches: [ production ] + +env: + NODE_VERSION: '20' + DOCKER_IMAGE: portfolio-app + +jobs: + production: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run linting + run: npm run lint + + - name: Run tests + run: npm run test + + - name: Build application + run: npm run build + + - name: Run security scan + run: | + echo "๐Ÿ” Running npm audit..." + npm audit --audit-level=high || echo "โš ๏ธ Some vulnerabilities found, but continuing..." + + - name: Build Docker image + run: | + docker build -t ${{ env.DOCKER_IMAGE }}:latest . + docker tag ${{ env.DOCKER_IMAGE }}:latest ${{ env.DOCKER_IMAGE }}:$(date +%Y%m%d-%H%M%S) + + - name: Verify secrets and variables before deployment + run: | + echo "๐Ÿ” Verifying secrets and variables..." + + # Check Variables + if [ -z "${{ vars.NEXT_PUBLIC_BASE_URL }}" ]; then + echo "โŒ NEXT_PUBLIC_BASE_URL variable is missing!" + exit 1 + fi + if [ -z "${{ vars.MY_EMAIL }}" ]; then + echo "โŒ MY_EMAIL variable is missing!" + exit 1 + fi + if [ -z "${{ vars.MY_INFO_EMAIL }}" ]; then + echo "โŒ MY_INFO_EMAIL variable is missing!" + exit 1 + fi + + # Check Secrets + if [ -z "${{ secrets.MY_PASSWORD }}" ]; then + echo "โŒ MY_PASSWORD secret is missing!" + exit 1 + fi + if [ -z "${{ secrets.MY_INFO_PASSWORD }}" ]; then + echo "โŒ MY_INFO_PASSWORD secret is missing!" + exit 1 + fi + if [ -z "${{ secrets.ADMIN_BASIC_AUTH }}" ]; then + echo "โŒ ADMIN_BASIC_AUTH secret is missing!" + exit 1 + fi + + echo "โœ… All required secrets and variables are present" + + - name: Deploy with zero downtime using docker-compose + run: | + echo "๐Ÿš€ Deploying with zero downtime using docker-compose..." + + # Export environment variables for docker compose + export NODE_ENV="${{ vars.NODE_ENV }}" + export LOG_LEVEL="${{ vars.LOG_LEVEL }}" + export NEXT_PUBLIC_BASE_URL="${{ vars.NEXT_PUBLIC_BASE_URL }}" + export NEXT_PUBLIC_UMAMI_URL="${{ vars.NEXT_PUBLIC_UMAMI_URL }}" + export NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" + export MY_EMAIL="${{ vars.MY_EMAIL }}" + export MY_INFO_EMAIL="${{ vars.MY_INFO_EMAIL }}" + export MY_PASSWORD="${{ secrets.MY_PASSWORD }}" + export MY_INFO_PASSWORD="${{ secrets.MY_INFO_PASSWORD }}" + export ADMIN_BASIC_AUTH="${{ secrets.ADMIN_BASIC_AUTH }}" + + # Stop old containers + echo "๐Ÿ›‘ Stopping old containers..." + docker compose -f docker-compose.zero-downtime.yml down || true + + # Start new containers + echo "๐Ÿš€ Starting new containers..." + docker compose -f docker-compose.zero-downtime.yml up -d + + echo "โœ… Zero downtime deployment completed!" + env: + NODE_ENV: ${{ vars.NODE_ENV }} + LOG_LEVEL: ${{ vars.LOG_LEVEL }} + NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL }} + NEXT_PUBLIC_UMAMI_URL: ${{ vars.NEXT_PUBLIC_UMAMI_URL }} + NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID }} + MY_EMAIL: ${{ vars.MY_EMAIL }} + MY_INFO_EMAIL: ${{ vars.MY_INFO_EMAIL }} + MY_PASSWORD: ${{ secrets.MY_PASSWORD }} + MY_INFO_PASSWORD: ${{ secrets.MY_INFO_PASSWORD }} + ADMIN_BASIC_AUTH: ${{ secrets.ADMIN_BASIC_AUTH }} + + - name: Wait for container to be ready + run: | + echo "โณ Waiting for containers to be ready..." + sleep 15 + + # Wait for nginx to be healthy + for i in {1..30}; do + if curl -f http://localhost/health > /dev/null 2>&1; then + echo "โœ… Nginx is healthy!" + break + fi + echo "โณ Waiting for nginx... ($i/30)" + sleep 2 + done + + - name: Health check + run: | + echo "๐Ÿ” Running health checks..." + + # Check nginx health + if curl -f http://localhost/health; then + echo "โœ… Nginx health check passed!" + else + echo "โŒ Nginx health check failed!" + exit 1 + fi + + # Check application health through nginx + if curl -f http://localhost/api/health; then + echo "โœ… Application health check passed!" + else + echo "โŒ Application health check failed!" + exit 1 + fi + + echo "โœ… All health checks passed! Deployment successful!" + + - name: Show container status + run: | + echo "๐Ÿ“Š Container status:" + docker compose -f docker-compose.zero-downtime.yml ps + + - name: Cleanup old images + run: | + echo "๐Ÿงน Cleaning up old images..." + docker image prune -f + docker system prune -f + echo "โœ… Cleanup completed" \ No newline at end of file diff --git a/.gitea/workflows/ci-cd-zero-downtime.yml b/.gitea/workflows/ci-cd-zero-downtime.yml.disabled similarity index 100% rename from .gitea/workflows/ci-cd-zero-downtime.yml rename to .gitea/workflows/ci-cd-zero-downtime.yml.disabled diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml.disabled similarity index 100% rename from .gitea/workflows/ci-cd.yml rename to .gitea/workflows/ci-cd.yml.disabled diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 1a0e56b..0e3221e 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -10,7 +10,7 @@ ENVIRONMENT=${1:-production} REGISTRY="ghcr.io" IMAGE_NAME="dennis-konkol/my_portfolio" CONTAINER_NAME="portfolio-app" -COMPOSE_FILE="docker-compose.prod.yml" +COMPOSE_FILE="docker-compose.zero-downtime.yml" # Colors for output RED='\033[0;31m' @@ -79,10 +79,10 @@ echo "$GITHUB_TOKEN" | docker login $REGISTRY -u $GITHUB_ACTOR --password-stdin warning "Failed to login to registry. Make sure GITHUB_TOKEN and GITHUB_ACTOR are set." } -# Pull latest image -log "Pulling latest image..." -docker pull $FULL_IMAGE_NAME || { - error "Failed to pull image $FULL_IMAGE_NAME" +# Build latest image locally +log "Building latest image locally..." +docker build -t portfolio-app:latest . || { + error "Failed to build image locally" exit 1 } @@ -112,7 +112,7 @@ HEALTH_CHECK_INTERVAL=2 ELAPSED=0 while [ $ELAPSED -lt $HEALTH_CHECK_TIMEOUT ]; do - if curl -f http://localhost:3000/api/health > /dev/null 2>&1; then + if curl -f http://localhost/api/health > /dev/null 2>&1; then success "Application is healthy!" break fi @@ -131,7 +131,7 @@ fi # Verify deployment log "Verifying deployment..." -if curl -f http://localhost:3000/api/health > /dev/null 2>&1; then +if curl -f http://localhost/api/health > /dev/null 2>&1; then success "Deployment successful!" # Show container status @@ -156,5 +156,5 @@ docker system prune -f --volumes || { } success "Deployment completed successfully!" -log "Application is available at: http://localhost:3000" -log "Health check endpoint: http://localhost:3000/api/health" +log "Application is available at: http://localhost/" +log "Health check endpoint: http://localhost/api/health" diff --git a/scripts/monitor.sh b/scripts/monitor.sh index 215af68..4c15c31 100755 --- a/scripts/monitor.sh +++ b/scripts/monitor.sh @@ -37,7 +37,7 @@ warning() { check_health() { log "Checking application health..." - if curl -f http://localhost:3000/api/health > /dev/null 2>&1; then + if curl -f http://localhost/api/health > /dev/null 2>&1; then success "Application is healthy" return 0 else