littleshop/.gitlab-ci.yml
SysAdmin bbf2764af9 Fix: Align deployment configs with production architecture
Critical fixes to ensure smooth deployments and prevent future outages:

**docker-compose.yml:**
- Fixed image name: littleshop:latest → localhost:5000/littleshop:latest
- Fixed subnet: 172.21.0.0/16 → 172.23.0.0/16 (matches production)
- Fixed environment: Production → Development (matches current production)

**.gitlab-ci.yml:**
- Fixed TeleBot API URL: http://littleshop-admin:8080http://littleshop:5000
- Removed duplicate network flag (was causing issues)
- Added explicit network connection command for littleshop_littleshop-network
- Ensures TeleBot can communicate with LittleShop API on deployment

**CLAUDE.md:**
- Documented October 4, 2025 incident and recovery
- Added comprehensive deployment best practices
- Documented pre-deployment checklist
- Added manual deployment commands for emergencies
- Documented network architecture and container configuration

**Root Cause of Previous Failure:**
TeleBot was trying to connect to non-existent hostname "littleshop-admin"
on wrong network, causing authentication failures and data unavailability.

**Verification:**
All changes tested in production and confirmed working. TeleBot now
successfully authenticates and communicates with LittleShop API.

🤖 Generated with Claude Code
https://claude.com/claude-code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 15:13:56 +01:00

219 lines
7.2 KiB
YAML

stages:
- build
- deploy
variables:
DOCKER_HOST: unix:///var/run/docker.sock
build:littleshop:
stage: build
image: docker:24
script:
- echo "Building LittleShop Docker image"
- docker build -t localhost:5000/littleshop:latest .
- |
if [ -n "$CI_COMMIT_TAG" ]; then
echo "Tagging as version $CI_COMMIT_TAG"
docker tag localhost:5000/littleshop:latest localhost:5000/littleshop:$CI_COMMIT_TAG
fi
- echo "LittleShop build complete"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG'
tags:
- docker
build:telebot:
stage: build
image: docker:24
script:
- echo "Building TeleBot Docker image"
- docker build -t localhost:5000/telebot:latest -f Dockerfile.telebot .
- |
if [ -n "$CI_COMMIT_TAG" ]; then
echo "Tagging as version $CI_COMMIT_TAG"
docker tag localhost:5000/telebot:latest localhost:5000/telebot:$CI_COMMIT_TAG
fi
- echo "TeleBot build complete"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG'
tags:
- docker
deploy:vps:
stage: deploy
image: docker:24
before_script:
- apk add --no-cache openssh-client bash curl
- echo "$VPS_SSH_KEY_B64" | base64 -d > /tmp/deploy_key
- chmod 600 /tmp/deploy_key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -p "$VPS_PORT" "$VPS_HOST" >> ~/.ssh/known_hosts
script:
- export VERSION="${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
- echo "Deploying version $VERSION to VPS"
- echo "Building images from source..."
- docker build --no-cache -t littleshop:$VERSION .
- docker build --no-cache -t telebot:$VERSION -f Dockerfile.telebot .
- echo "Copying images to VPS via SSH..."
- docker save littleshop:$VERSION | ssh -i /tmp/deploy_key -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" "docker load"
- docker save telebot:$VERSION | ssh -i /tmp/deploy_key -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" "docker load"
- echo "Deploying on VPS..."
- |
ssh -i /tmp/deploy_key -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" bash -s << EOF
set -e
export VERSION="$VERSION"
# Tag the images
docker tag littleshop:\$VERSION localhost:5000/littleshop:\$VERSION
docker tag littleshop:\$VERSION localhost:5000/littleshop:latest
docker tag telebot:\$VERSION localhost:5000/telebot:\$VERSION
docker tag telebot:\$VERSION localhost:5000/telebot:latest
# Push to local registry
echo "Pushing images to local Docker registry..."
docker push localhost:5000/littleshop:\$VERSION
docker push localhost:5000/littleshop:latest
docker push localhost:5000/telebot:\$VERSION
docker push localhost:5000/telebot:latest
# Navigate to deployment directory
cd /opt/littleshop
# Force stop all littleshop containers (including orphans)
echo "Stopping all littleshop containers..."
docker stop \$(docker ps -q --filter "name=littleshop") 2>/dev/null || true
docker rm \$(docker ps -aq --filter "name=littleshop") 2>/dev/null || true
# Stop TeleBot container
echo "Stopping TeleBot container..."
docker stop telebot-service 2>/dev/null || true
docker rm telebot-service 2>/dev/null || true
# Stop services with compose (removes networks)
echo "Stopping compose services..."
docker-compose down --remove-orphans || true
# Prune unused Docker networks to avoid conflicts
echo "Cleaning up Docker networks..."
docker network prune -f || true
# Apply database migrations if they exist
echo "Checking for database migrations..."
if [ -d "LittleShop/Migrations" ] && [ -n "\$(ls -A LittleShop/Migrations/*.sql 2>/dev/null)" ]; then
echo "Found migration files, applying to database..."
for migration in LittleShop/Migrations/*.sql; do
migration_name=\$(basename "\$migration")
echo "Applying migration: \$migration_name"
docker run --rm -v littleshop_littleshop_data:/data -v \$(pwd)/LittleShop/Migrations:/migrations alpine:latest sh -c "
apk add --no-cache sqlite > /dev/null 2>&1
echo 'Creating backup before migration...'
cp /data/littleshop-production.db /data/littleshop-production.db.backup-\\\$(date +%Y%m%d-%H%M%S) 2>/dev/null || true
echo 'Applying migration: \$migration_name'
sqlite3 /data/littleshop-production.db < /migrations/\$migration_name
echo 'Migration applied successfully'
"
done
else
echo "No migration files found, skipping..."
fi
# Start services with new images
echo "Starting services with new images..."
docker-compose up -d
# Start TeleBot with new image
echo "Starting TeleBot with new image..."
docker run -d \
--name telebot-service \
--restart unless-stopped \
--network silverpay_silverpay-network \
-e ASPNETCORE_URLS=http://+:5010 \
-e LittleShop__ApiUrl=http://littleshop:5000 \
-e LittleShop__UseTor=false \
-e Privacy__EnableTor=true \
-e Privacy__TorSocksHost=tor-gateway \
-e Privacy__TorSocksPort=9050 \
localhost:5000/telebot:latest
# Connect TeleBot to LittleShop network for API access
docker network connect littleshop_littleshop-network telebot-service
# Wait for startup
echo "Waiting for services to start..."
sleep 30
# Health check
echo "Running health checks..."
for i in 1 2 3 4 5 6; do
if curl -f -s http://localhost:5100/api/catalog/products > /dev/null 2>&1; then
echo "✅ Deployment successful - health check passed"
exit 0
fi
echo "Health check attempt \$i/6 failed, waiting..."
sleep 10
done
echo "❌ Health check failed after deployment"
docker logs littleshop-admin --tail 50
docker logs telebot-service --tail 30
exit 1
EOF
environment:
name: production
url: http://hq.lan
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
- if: '$CI_COMMIT_TAG'
when: manual
tags:
- docker
rollback:vps:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client bash
- echo "$VPS_SSH_KEY_B64" | base64 -d > /tmp/deploy_key
- chmod 600 /tmp/deploy_key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -p "$VPS_PORT" "$VPS_HOST" >> ~/.ssh/known_hosts
script:
- echo "Rolling back to previous version"
- |
ssh -i /tmp/deploy_key -p "$VPS_PORT" "$VPS_USER@$VPS_HOST" bash -s << EOF
set -e
cd /opt/littleshop
# Pull previous image
docker tag localhost:5000/littleshop:previous localhost:5000/littleshop:latest
# Restart services
echo "Restarting with previous version..."
docker-compose down
docker-compose up -d
# Health check
sleep 30
if curl -f -s http://localhost:5100/api/catalog/products > /dev/null 2>&1; then
echo "✅ Rollback complete"
exit 0
else
echo "❌ Rollback health check failed"
docker logs littleshop-admin --tail 50
exit 1
fi
EOF
environment:
name: production
rules:
- if: '$CI_COMMIT_TAG'
when: manual
tags:
- docker