## Summary - Add complete CI/CD pipeline with Gitea Actions for automated testing, building, and deployment - Implement backup and restore system with full database and file backup to ZIP - Add deployment automation with webhook receiver and systemd service - Enhance recipe editing UI with improved ingredient parsing and cooking mode features - Add comprehensive documentation for CI/CD, deployment, and backup features ## CI/CD Pipeline - New workflow in .gitea/workflows/ci-cd.yml with test, build, and deploy stages - Automated Docker image building and pushing to registry - Webhook-triggered deployments to production servers ## Backup & Restore - New backup service with ZIP creation including database dump and uploads - REST API endpoints for create, list, download, restore, and delete operations - Configurable backup path via BACKUP_PATH environment variable ## Deployment - Automated deployment scripts (deploy.sh, manual-deploy.sh) - Webhook receiver with systemd service for deployment triggers - Environment configuration template (.env.deploy.example) ## Documentation - docs/CI-CD-SETUP.md - Complete CI/CD pipeline setup guide - docs/DEPLOYMENT-QUICK-START.md - Quick deployment reference - docs/BACKUP.md - Backup and restore documentation - docs/REMOTE_DATABASE.md - Remote database configuration guide - scripts/README.md - Deployment scripts documentation ## Web Improvements - Enhanced ingredient parser with better unit and quantity detection - Improved recipe editing interface with unified edit experience - Better cooking mode functionality - Updated dependencies in package.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
CI/CD Setup Guide for Basil
This document describes the complete CI/CD pipeline for the Basil recipe manager, including Gitea Actions workflows, Docker image building, and automated deployments.
Table of Contents
- Overview
- Prerequisites
- Gitea Actions Workflow
- Docker Registry Setup
- Deployment Methods
- Configuration
- Troubleshooting
Overview
The CI/CD pipeline consists of three main stages:
- Testing: Runs unit tests (Vitest) and E2E tests (Playwright)
- Build & Push: Builds Docker images and pushes to registry (on main branch only)
- Deploy: Pulls new images and restarts containers on the production server
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│ Git Push │────▶│ Gitea Actions│────▶│ Docker Registry│
│ (main) │ │ - Test │ │ - API image │
└─────────────┘ │ - Build │ │ - Web image │
│ - Push │ └────────────────┘
└──────────────┘ │
│ │
▼ ▼
┌──────────────┐ ┌────────────────┐
│ Webhook │────▶│ Production │
│ Trigger │ │ Server │
└──────────────┘ └────────────────┘
Prerequisites
For CI/CD (Gitea)
- Gitea instance with Actions enabled
- Docker Hub account (or other registry)
- Node.js 20+ for testing
For Deployment Server
- Docker and Docker Compose installed
- Bash shell
webhookpackage (for automatic deployments)- Network access to pull from Docker registry
Gitea Actions Workflow
The workflow is defined in .gitea/workflows/ci-cd.yml and runs on:
- Push to
mainordevelopbranches - Pull requests targeting
mainordevelop
Jobs
1. Test Job
Runs all tests with a PostgreSQL service container:
- Unit Tests: API, Web, and Shared packages using Vitest
- E2E Tests: Full application tests using Playwright
- Database: Temporary PostgreSQL instance for testing
Test Commands:
# Run all tests locally
npm test
# Run E2E tests
npm run test:e2e
# Run with coverage
npm run test:coverage
2. Lint Job
Runs ESLint on all packages to ensure code quality:
npm run lint
3. Build and Push Job
Only runs on push to main branch:
- Builds Docker images for API and Web
- Tags with multiple tags (latest, SHA, semver)
- Pushes to Docker registry
- Triggers deployment webhook
Image Names:
- API:
{registry}/{username}/basil-api:{tag} - Web:
{registry}/{username}/basil-web:{tag}
Docker Registry Setup
1. Create Docker Hub Account
If using Docker Hub:
- Sign up at https://hub.docker.com
- Create an access token in Account Settings → Security
2. Configure Gitea Secrets
Add the following secrets to your Gitea repository:
Settings → Secrets → Actions
| Secret Name | Description | Example |
|---|---|---|
DOCKER_USERNAME |
Docker Hub username | myusername |
DOCKER_PASSWORD |
Docker Hub access token | dckr_pat_xxxxx... |
DEPLOY_WEBHOOK_URL |
Webhook endpoint URL | http://server.com:9000/hooks/basil-deploy |
3. Alternative Registries
To use a different registry (e.g., GitHub Container Registry, GitLab):
-
Update
DOCKER_REGISTRYin.gitea/workflows/ci-cd.yml:env: DOCKER_REGISTRY: ghcr.io # or registry.gitlab.com -
Update login credentials accordingly
Deployment Methods
Method 1: Automatic Webhook Deployment (Recommended)
Uses a webhook server to automatically deploy when images are pushed.
Setup Steps
-
Copy environment template:
cp .env.deploy.example .env.deploy -
Edit
.env.deploy:DOCKER_USERNAME=your-docker-username DOCKER_REGISTRY=docker.io IMAGE_TAG=latest WEBHOOK_PORT=9000 WEBHOOK_SECRET=your-random-secret-here -
Install webhook package:
# Ubuntu/Debian sudo apt-get install webhook # RHEL/CentOS sudo yum install webhook -
Install systemd service:
# Copy service file sudo cp scripts/basil-webhook.service /etc/systemd/system/ # Edit service file with your settings sudo nano /etc/systemd/system/basil-webhook.service # Enable and start service sudo systemctl enable basil-webhook sudo systemctl start basil-webhook # Check status sudo systemctl status basil-webhook -
Configure firewall (if needed):
sudo ufw allow 9000/tcp -
Add webhook URL to Gitea secrets:
DEPLOY_WEBHOOK_URL=http://your-server.com:9000/hooks/basil-deployAdd this header when calling the webhook:
X-Webhook-Secret: your-random-secret-here
Manual Webhook Trigger
Test webhook manually:
curl -X POST http://localhost:9000/hooks/basil-deploy \
-H "Content-Type: application/json" \
-H "X-Webhook-Secret: your-secret" \
-d '{"branch": "main", "commit": "abc123"}'
Method 2: Manual Deployment
For manual deployments without webhooks:
# Interactive deployment
./scripts/manual-deploy.sh
# Or with environment variables
DOCKER_USERNAME=myuser \
DOCKER_REGISTRY=docker.io \
IMAGE_TAG=latest \
./scripts/deploy.sh
The deployment script will:
- Check Docker is running
- Create a pre-deployment backup
- Pull latest images from registry
- Update docker-compose configuration
- Restart containers
- Perform health checks
- Clean up old images
Method 3: Cron-based Deployment
Set up a cron job for scheduled deployments:
# Edit crontab
crontab -e
# Add line to deploy every night at 2 AM
0 2 * * * cd /srv/docker-compose/basil && DOCKER_USERNAME=myuser ./scripts/deploy.sh >> /var/log/basil-deploy.log 2>&1
Configuration
Environment Variables
For Deployment Scripts:
| Variable | Required | Default | Description |
|---|---|---|---|
DOCKER_USERNAME |
Yes | - | Docker registry username |
DOCKER_REGISTRY |
No | docker.io |
Docker registry URL |
IMAGE_TAG |
No | latest |
Image tag to pull |
WEBHOOK_PORT |
No | 9000 |
Port for webhook server |
WEBHOOK_SECRET |
No | changeme |
Secret for webhook authentication |
For Application:
See packages/api/.env.example for application configuration.
Docker Compose Override
The deployment script automatically creates docker-compose.override.yml to use registry images instead of building from source:
services:
api:
image: docker.io/username/basil-api:latest
web:
image: docker.io/username/basil-web:latest
This file is in .gitignore and is regenerated on each deployment.
Monitoring and Logs
View Deployment Logs
# Deployment log
tail -f deploy.log
# Webhook log
tail -f webhook.log
# Container logs
docker-compose logs -f api
docker-compose logs -f web
Check Deployment Status
# Check running containers
docker-compose ps
# Check API health
curl http://localhost:3001/health
# View recent deployments
grep "Deployment completed" deploy.log
Systemd Service Logs
# View webhook service logs
sudo journalctl -u basil-webhook -f
# View recent errors
sudo journalctl -u basil-webhook --since "1 hour ago" -p err
Backup and Rollback
Automatic Backups
The deployment script automatically creates a backup before deploying:
backups/pre-deploy-YYYYMMDD-HHMMSS.zip
Manual Backup
# Via API
curl -X POST http://localhost:3001/api/backup \
-o backup-$(date +%Y%m%d).zip
# Via Docker
docker exec basil-api npm run backup
Rollback to Previous Version
# Pull specific tag
DOCKER_USERNAME=myuser IMAGE_TAG=main-abc123 ./scripts/deploy.sh
# Or restore from backup
curl -X POST http://localhost:3001/api/backup/restore \
-F "file=@backups/pre-deploy-20250101-020000.zip"
Troubleshooting
Tests Failing in CI
Check test logs in Gitea:
- Go to Actions tab in repository
- Click on failed workflow run
- Expand failed job to see detailed logs
Common issues:
- Database connection: Ensure PostgreSQL service is healthy
- Missing dependencies: Check
npm installstep - Environment variables: Verify test environment configuration
Images Not Pushing
Check Docker credentials:
# Test Docker login
docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
# Verify secrets in Gitea
# Settings → Secrets → Actions
Check registry permissions:
- Ensure token has write permissions
- Verify repository exists on Docker Hub
Webhook Not Triggering
Check webhook service:
# Service status
sudo systemctl status basil-webhook
# Check if port is listening
sudo netstat -tlnp | grep 9000
# Test webhook endpoint
curl -I http://localhost:9000/hooks/basil-deploy
Check firewall:
# Ubuntu/Debian
sudo ufw status
# RHEL/CentOS
sudo firewall-cmd --list-all
Verify secret header:
# Wrong secret returns 403
curl -X POST http://localhost:9000/hooks/basil-deploy
# Should return 403 Forbidden
# Correct secret triggers deployment
curl -X POST http://localhost:9000/hooks/basil-deploy \
-H "X-Webhook-Secret: your-secret"
# Should return "Deployment triggered successfully"
Deployment Fails
Check Docker:
# Docker running?
docker info
# Disk space?
df -h
# View deployment log
tail -100 deploy.log
Check images:
# Can we pull images?
docker pull $DOCKER_REGISTRY/$DOCKER_USERNAME/basil-api:latest
# Check image tags
docker images | grep basil
Health check failures:
# Check API logs
docker-compose logs api
# Check database connection
docker-compose exec api npx prisma studio
# Test API manually
curl http://localhost:3001/health
Container Won't Start
Check logs:
docker-compose logs api
docker-compose logs web
Common issues:
- Database migrations: Check Prisma migration logs
- Environment variables: Verify
.envfiles - Port conflicts: Check if ports 3001/5173 are available
- Volume permissions: Check uploads/backups directory permissions
Rollback Failed
Manual rollback:
# Stop containers
docker-compose down
# Remove override file
rm docker-compose.override.yml
# Restore from backup
unzip backups/pre-deploy-YYYYMMDD-HHMMSS.zip -d restore-temp/
# Manually restore database and files
# (See backup documentation)
# Start containers
docker-compose up -d
Security Considerations
- Webhook Secret: Use a strong, random secret (32+ characters)
- Firewall: Restrict webhook port to known IPs if possible
- HTTPS: Use HTTPS for webhook endpoint in production
- Secrets: Never commit secrets to git
- Backups: Store backups securely with encryption
- Docker Registry: Use private registries for sensitive applications
Best Practices
- Test Locally: Always test changes locally before pushing
- Review PRs: Use pull requests for code review
- Monitor Logs: Regularly check deployment and application logs
- Backup First: Always backup before major deployments
- Tag Releases: Use semantic versioning for releases
- Health Checks: Monitor application health after deployment
- Rollback Plan: Know how to rollback quickly if needed