Force remove problematic container and improve Node.js setup
Some checks failed
CI/CD Pipeline (Fast) / production (push) Failing after 4m18s
CI/CD Pipeline (Zero Downtime) / production (push) Failing after 7m51s
CI/CD Pipeline (Simple) / production (push) Failing after 7m53s

- Add specific removal of problematic container afa9a70588844b06e17d5e0527119d589a7a3fde8a17608447cf7d8d448cf261
- Force remove portfolio-app-new container before deployment
- Add container listing for debugging after cleanup
- Upgrade setup-node to v4 for better performance
- Add cache-dependency-path for more efficient caching
- Create fast workflow alternative with manual cache management
This commit is contained in:
2025-09-13 18:44:54 +02:00
parent 65ad26eeae
commit 58dd60ea64
3 changed files with 252 additions and 2 deletions

View File

@@ -0,0 +1,236 @@
name: CI/CD Pipeline (Fast)
on:
push:
branches: [ production ]
env:
NODE_VERSION: '20'
DOCKER_IMAGE: portfolio-app
CONTAINER_NAME: portfolio-app
jobs:
production:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js (Fast)
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
# Disable cache to avoid slow validation
cache: ''
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- 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: Prepare for zero-downtime deployment
run: |
echo "🚀 Preparing zero-downtime deployment..."
# Check if current container is running
if docker ps -q -f name=portfolio-app | grep -q .; then
echo "📊 Current container is running, proceeding with zero-downtime update"
CURRENT_CONTAINER_RUNNING=true
else
echo "📊 No current container running, doing fresh deployment"
CURRENT_CONTAINER_RUNNING=false
fi
# Ensure database and redis are running
echo "🔧 Ensuring database and redis are running..."
docker compose up -d postgres redis
# Wait for services to be ready
sleep 10
- 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
run: |
echo "🚀 Deploying with zero downtime..."
if [ "$CURRENT_CONTAINER_RUNNING" = "true" ]; then
echo "🔄 Performing rolling update..."
# Generate unique container name
TIMESTAMP=$(date +%s)
TEMP_CONTAINER_NAME="portfolio-app-temp-$TIMESTAMP"
echo "🔧 Using temporary container name: $TEMP_CONTAINER_NAME"
# Clean up any existing temporary containers
echo "🧹 Cleaning up any existing temporary containers..."
# Remove specific known problematic containers
docker rm -f portfolio-app-new portfolio-app-temp-* portfolio-app-backup || true
# Find and remove any containers with portfolio-app in the name (except the main one)
EXISTING_CONTAINERS=$(docker ps -a --format "table {{.Names}}" | grep "portfolio-app" | grep -v "^portfolio-app$" || true)
if [ -n "$EXISTING_CONTAINERS" ]; then
echo "🗑️ Removing existing portfolio-app containers:"
echo "$EXISTING_CONTAINERS"
echo "$EXISTING_CONTAINERS" | xargs -r docker rm -f || true
fi
# Also clean up any stopped containers
docker container prune -f || true
# Start new container with unique temporary name (no port mapping needed for health check)
docker run -d \
--name $TEMP_CONTAINER_NAME \
--restart unless-stopped \
--network portfolio_net \
-e NODE_ENV=${{ vars.NODE_ENV }} \
-e LOG_LEVEL=${{ vars.LOG_LEVEL }} \
-e DATABASE_URL=postgresql://portfolio_user:portfolio_pass@postgres:5432/portfolio_db?schema=public \
-e REDIS_URL=redis://redis:6379 \
-e NEXT_PUBLIC_BASE_URL="${{ vars.NEXT_PUBLIC_BASE_URL }}" \
-e NEXT_PUBLIC_UMAMI_URL="${{ vars.NEXT_PUBLIC_UMAMI_URL }}" \
-e NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" \
-e MY_EMAIL="${{ vars.MY_EMAIL }}" \
-e MY_INFO_EMAIL="${{ vars.MY_INFO_EMAIL }}" \
-e MY_PASSWORD="${{ secrets.MY_PASSWORD }}" \
-e MY_INFO_PASSWORD="${{ secrets.MY_INFO_PASSWORD }}" \
-e ADMIN_BASIC_AUTH="${{ secrets.ADMIN_BASIC_AUTH }}" \
${{ env.DOCKER_IMAGE }}:latest
# Wait for new container to be ready
echo "⏳ Waiting for new container to be ready..."
sleep 15
# Health check new container using docker exec
for i in {1..20}; do
if docker exec $TEMP_CONTAINER_NAME curl -f http://localhost:3000/api/health > /dev/null 2>&1; then
echo "✅ New container is healthy!"
break
fi
echo "⏳ Health check attempt $i/20..."
sleep 3
done
# Stop old container
echo "🛑 Stopping old container..."
docker stop portfolio-app || true
# Remove old container
docker rm portfolio-app || true
# Rename new container
docker rename $TEMP_CONTAINER_NAME portfolio-app
# Update port mapping
docker stop portfolio-app
docker rm portfolio-app
# Start with correct port
docker run -d \
--name portfolio-app \
--restart unless-stopped \
--network portfolio_net \
-p 3000:3000 \
-e NODE_ENV=${{ vars.NODE_ENV }} \
-e LOG_LEVEL=${{ vars.LOG_LEVEL }} \
-e DATABASE_URL=postgresql://portfolio_user:portfolio_pass@postgres:5432/portfolio_db?schema=public \
-e REDIS_URL=redis://redis:6379 \
-e NEXT_PUBLIC_BASE_URL="${{ vars.NEXT_PUBLIC_BASE_URL }}" \
-e NEXT_PUBLIC_UMAMI_URL="${{ vars.NEXT_PUBLIC_UMAMI_URL }}" \
-e NEXT_PUBLIC_UMAMI_WEBSITE_ID="${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID }}" \
-e MY_EMAIL="${{ vars.MY_EMAIL }}" \
-e MY_INFO_EMAIL="${{ vars.MY_INFO_EMAIL }}" \
-e MY_PASSWORD="${{ secrets.MY_PASSWORD }}" \
-e MY_INFO_PASSWORD="${{ secrets.MY_INFO_PASSWORD }}" \
-e ADMIN_BASIC_AUTH="${{ secrets.ADMIN_BASIC_AUTH }}" \
${{ env.DOCKER_IMAGE }}:latest
echo "✅ Rolling update completed!"
else
echo "🆕 Fresh deployment..."
docker compose up -d
fi
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: |
sleep 10
timeout 60 bash -c 'until curl -f http://localhost:3000/api/health; do sleep 2; done'
- name: Health check
run: |
curl -f http://localhost:3000/api/health
echo "✅ Deployment successful!"
- name: Cleanup old images
run: |
docker image prune -f
docker system prune -f

View File

@@ -21,10 +21,11 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
cache: 'npm' cache: 'npm'
cache-dependency-path: 'package-lock.json'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
@@ -52,6 +53,11 @@ jobs:
run: | run: |
echo "🚀 Preparing zero-downtime deployment..." echo "🚀 Preparing zero-downtime deployment..."
# FORCE REMOVE the problematic container
echo "🧹 FORCE removing problematic container portfolio-app-new..."
docker rm -f portfolio-app-new || true
docker rm -f afa9a70588844b06e17d5e0527119d589a7a3fde8a17608447cf7d8d448cf261 || true
# Check if current container is running # Check if current container is running
if docker ps -q -f name=portfolio-app | grep -q .; then if docker ps -q -f name=portfolio-app | grep -q .; then
echo "📊 Current container is running, proceeding with zero-downtime update" echo "📊 Current container is running, proceeding with zero-downtime update"
@@ -120,6 +126,9 @@ jobs:
# Remove specific known problematic containers # Remove specific known problematic containers
docker rm -f portfolio-app-new portfolio-app-temp-* portfolio-app-backup || true docker rm -f portfolio-app-new portfolio-app-temp-* portfolio-app-backup || true
# FORCE remove the specific problematic container by ID
docker rm -f afa9a70588844b06e17d5e0527119d589a7a3fde8a17608447cf7d8d448cf261 || true
# Find and remove any containers with portfolio-app in the name (except the main one) # Find and remove any containers with portfolio-app in the name (except the main one)
EXISTING_CONTAINERS=$(docker ps -a --format "table {{.Names}}" | grep "portfolio-app" | grep -v "^portfolio-app$" || true) EXISTING_CONTAINERS=$(docker ps -a --format "table {{.Names}}" | grep "portfolio-app" | grep -v "^portfolio-app$" || true)
if [ -n "$EXISTING_CONTAINERS" ]; then if [ -n "$EXISTING_CONTAINERS" ]; then
@@ -131,6 +140,10 @@ jobs:
# Also clean up any stopped containers # Also clean up any stopped containers
docker container prune -f || true docker container prune -f || true
# Double-check: list all containers to see what's left
echo "📋 Current containers after cleanup:"
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep portfolio || echo "No portfolio containers found"
# Start new container with unique temporary name (no port mapping needed for health check) # Start new container with unique temporary name (no port mapping needed for health check)
docker run -d \ docker run -d \
--name $TEMP_CONTAINER_NAME \ --name $TEMP_CONTAINER_NAME \

View File

@@ -17,10 +17,11 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
cache: 'npm' cache: 'npm'
cache-dependency-path: 'package-lock.json'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci