CI/CD Deployment Guide
ScannerSky uses an automated continuous integration and continuous deployment (CI/CD) pipeline built on GitHub Actions and Docker Compose. Every push to the main branch triggers an automated deployment over SSH to the production server.
1. Architecture Overview
The CI/CD workflow ensures zero-downtime rolling updates, automated database schema migrations, static file collection, security checks, and live health verification.
graph LR
Dev["Developer Push (main)"] --> GA["GitHub Actions Runner"]
GA -->|"SSH (appleboy/ssh-action)"| Server["Production Ubuntu Server"]
Server --> GitPull["git pull --ff-only"]
GitPull --> Build["docker compose build django"]
Build --> Up["docker compose up -d --remove-orphans"]
Up --> Migrate["python manage.py migrate"]
Migrate --> Collect["python manage.py collectstatic"]
Collect --> Check["python manage.py check --deploy"]
Check --> Health["curl http://127.0.0.1/ (Healthcheck)"]
2. GitHub Actions Workflow
The deployment workflow is defined in .github/workflows/deploy.yml.
Workflow Triggers & Concurrency
- Push Triggers: Automatically runs whenever commits are pushed to the
mainbranch. - Manual Dispatch: Can be triggered manually from the GitHub Actions tab via
workflow_dispatch. - Concurrency Locking: Uses the
scannersky-production-deployconcurrency group withcancel-in-progress: falseto ensure deployments queue safely and never collide.
name: Deploy to Ubuntu
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: scannersky-production-deploy
cancel-in-progress: false
3. Required GitHub Secrets
Configure the following deployment secrets in your GitHub repository (Settings > Secrets and variables > Actions):
| Secret Name | Description | Example / Notes |
|---|---|---|
DEPLOY_HOST | Production server IP address or domain | 192.0.2.1 or scannersky.example.edu |
DEPLOY_USER | SSH user with sudo/docker privileges | ubuntu or deploy |
DEPLOY_SSH_KEY | Private SSH key (ED25519 or RSA) | -----BEGIN OPENSSH PRIVATE KEY-----... |
DEPLOY_PORT | SSH port on target server | 22 |
4. Production Deployment Execution Steps
When triggered, the pipeline executes the following automated shell script on the production host:
- Safety Snapshot: Records the current commit SHA (
PREV_COMMIT) for easy rollback if needed. - Repository Sync: Performs
git fetchandgit pull --ff-onlyto pull the latest codebase as the service user (scannersky). - Container Build: Builds the Django container image (
docker compose build django) to refresh dependencies and application code. - Stack Launch: Starts all containerized services (
web,db,nginx,minio) in detached mode with--remove-orphans. - Database Migrations: Runs Django migrations automatically inside the container:
docker compose exec -T django python manage.py migrate --noinput
- Static File Collection: Compiles and hashes static assets:
docker compose exec -T django python manage.py collectstatic --noinput
- Production Security Check: Verifies security settings:
docker compose exec -T django python manage.py check --deploy
- Healthcheck Probe: Queries the local endpoint (
http://127.0.0.1/) to confirm the web server is actively responding.
5. Rollback Strategy
If a deployment fails the healthcheck or introduces an unexpected bug, roll back to the previous commit:
# SSH into production server
ssh deploy@scannersky.example.edu
# Switch to app directory
cd /srv/scannersky-django
# Checkout previous stable commit
sudo -u scannersky git checkout <PREV_COMMIT_SHA>
# Rebuild and restart containers
sudo -u scannersky docker compose up -d --build
# Run migrations if necessary
sudo -u scannersky docker compose exec -T django python manage.py migrate --noinput
6. Troubleshooting & Diagnostics
:::tip IT Operations Quick Commands
# View live container logs
docker compose logs -f --tail=100 django
# Check Nginx reverse proxy logs
docker compose logs -f nginx
# Inspect database connectivity
docker compose exec django python manage.py health_check
:::