Files
soroush.asadi 6f39e47aaa
CI/CD / CI · dotnet build (push) Successful in 25s
CI/CD / Deploy · drsousan (push) Successful in 12s
ci: backup DB before every deploy, fix deploy conflict error
- Add "Backup database" step that copies drsousan.db out of the
  running container to /opt/drsousan-backups/ before any container
  changes, keeping the last 10 backups
- Replace --force-recreate (broken on this Docker version) with
  explicit docker stop + docker rm before docker compose up

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-02 08:22:34 +03:30

140 lines
5.1 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: drsousan-cicd-${{ github.ref }}
cancel-in-progress: true
# ─────────────────────────────────────────────────────────────────────────────
# HOW THIS WORKS
# ─────────────────────────────────────────────────────────────────────────────
# Runner labels:
# ubuntu-latest → container runner ← CI dotnet build runs here
# self-hosted → host runner ← docker build/push/deploy runs here
#
# Local Nexus:
# Docker registry → mirror.soroushasadi.com (group: pull | host: push)
# NuGet → 171.22.25.73:8081/repository/nuget-group/
#
# Required Gitea secrets:
# ENV_FILE → contents of .env
# ─────────────────────────────────────────────────────────────────────────────
jobs:
# ── CI: compile-check (runs on every push / PR) ──────────────────────────────
ci:
name: "CI · dotnet build"
runs-on: ubuntu-latest
container:
image: mirror.soroushasadi.com/dotnet/sdk:10.0
options: --add-host=gitea:host-gateway
steps:
- name: Checkout
env:
TOKEN: ${{ github.token }}
REF: ${{ github.ref }}
run: |
git init
git remote add origin "${{ github.server_url }}/${{ github.repository }}.git"
git config http.extraheader "Authorization: Bearer ${TOKEN}"
git fetch --depth=1 origin "${REF}"
git checkout FETCH_HEAD
- name: Restore
working-directory: DrSousan.Api
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
run: dotnet restore DrSousan.Api.csproj
- name: Build
working-directory: DrSousan.Api
run: dotnet build DrSousan.Api.csproj --no-restore -c Release
# ── CD: build image → deploy locally (push to main only) ───────────────────
deploy:
name: "Deploy · drsousan"
runs-on: self-hosted
env:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
REGISTRY: mirror.soroushasadi.com
IMAGE: mirror.soroushasadi.com/drsousan/api
needs: [ci]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
timeout-minutes: 20
steps:
- name: Checkout
env:
TOKEN: ${{ github.token }}
REF: ${{ github.ref }}
run: |
git init
git remote add origin "${{ github.server_url }}/${{ github.repository }}.git"
git config http.extraheader "Authorization: Bearer ${TOKEN}"
git fetch --depth=1 origin "${REF}"
git checkout FETCH_HEAD
- name: Write .env
run: printf '%s' "$ENV_FILE" > .env
env:
ENV_FILE: ${{ secrets.ENV_FILE }}
- name: Build image
run: docker compose build api
env:
DOCKER_BUILDKIT: 1
- name: Backup database
run: |
BACKUP_DIR="/opt/drsousan-backups"
mkdir -p "$BACKUP_DIR"
STAMP=$(date +%Y%m%d-%H%M%S)
# Copy DB out of volume before any container changes
if docker ps -q --filter name=drsousan_api | grep -q .; then
docker cp drsousan_api:/data/drsousan.db "$BACKUP_DIR/drsousan-$STAMP.db" && \
echo "✅ DB backed up → $BACKUP_DIR/drsousan-$STAMP.db" || \
echo "⚠️ DB backup failed (non-fatal)"
else
echo "️ Container not running — skipping backup"
fi
# Keep last 10 backups only
ls -t "$BACKUP_DIR"/*.db 2>/dev/null | tail -n +11 | xargs -r rm
- name: Deploy
run: |
docker stop drsousan_api 2>/dev/null || true
docker rm drsousan_api 2>/dev/null || true
docker compose up -d --no-deps api
- name: Wait for healthy
run: |
for i in $(seq 1 24); do
STATUS=$(docker inspect --format='{{.State.Health.Status}}' drsousan_api 2>/dev/null || echo "missing")
echo " [$i/24] $STATUS"
[ "$STATUS" = "healthy" ] && echo "✅ drsousan_api healthy" && exit 0
sleep 5
done
echo "❌ timed out"
docker compose logs --tail=60 api
exit 1
- name: Show containers
if: always()
run: docker compose ps
- name: Prune old drsousan images
if: success()
# Only remove untagged (dangling) drsousan images — never touches other projects
run: |
docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' \
| grep '^mirror\.soroushasadi\.com/drsousan/' \
| grep '<none>' \
| awk '{print $2}' \
| xargs -r docker rmi || true