# CI/CD Workflow with Gitea Actions This diagram shows the complete CI/CD workflow using Gitea Actions with self-hosted runners, including the automated setup process. ## Overview - **Gitea Actions**: GitHub Actions-compatible CI/CD built into Gitea - **Self-hosted runners**: 2 act_runner instances running as systemd services - **Automated setup**: Admin user, runner tokens, and registration fully automated via Ansible - **Test workflow**: Integration tests run on every PR to main branch ## CI/CD Workflow Diagram ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e5e7eb','primaryTextColor':'#111827','primaryBorderColor':'#9ca3af','lineColor':'#111827','secondaryColor':'#d1d5db','tertiaryColor':'#f3f4f6','edgeLabelBackground':'#ffffff','mainBkg':'#f5f5f4','nodeBorder':'#9ca3af','background':'#f5f5f4','clusterBkg':'transparent'},'themeCSS':'.node rect, .node circle, .node ellipse, .node polygon, .node path { filter: none !important; box-shadow: none !important; } .cluster rect { filter: none !important; box-shadow: none !important; } svg { background-color: #f5f5f4 !important; } .cluster-label { background-color: #ffffff !important; padding: 6px 12px !important; border-radius: 4px !important; font-size: 16px !important; font-weight: 700 !important; box-shadow: 0 1px 3px rgba(0,0,0,0.12) !important; border: 1px solid #d1d5db !important; } .edgePath, .edgePath path, .flowchart-link { z-index: 1 !important; }'}}%% flowchart TB Dev([Developer]) subgraph Workflow["CI/CD Workflow"] Push[Git Push / PR Created] Trigger{Gitea Actions
Workflow Trigger} Queue[Job Queued] subgraph Runners["Self-Hosted Runners"] Runner1[act_runner-1
systemd service] Runner2[act_runner-2
systemd service] end Pick{Runner
Available?} Checkout[๐Ÿ“ฅ Checkout Code] Cache[๐Ÿ’พ Setup Docker Cache] Pull[๐Ÿ“ฅ Pre-pull Test Images
postgres:18.4, nginx:1.27-alpine, alpine:3.19/3.20] Test[๐Ÿงช Run Integration Tests
scripts/test-update.sh] TestResult{Tests
Pass?} Success[โœ… Report Success
PR can merge] Failure[โŒ Report Failure
Upload test logs] Artifact[๐Ÿ“ฆ Upload Artifacts
7-day retention] end Dev -->|git push| Push Push --> Trigger Trigger -->|PR to main| Queue Trigger -->|workflow_dispatch| Queue Queue --> Pick Pick -->|Assigns Job| Runner1 Pick -->|Assigns Job| Runner2 Runner1 --> Checkout Runner2 --> Checkout Checkout --> Cache Cache --> Pull Pull --> Test Test --> TestResult TestResult -->|โœ… All Pass| Success TestResult -->|โŒ Any Fail| Failure Failure --> Artifact style Dev fill:#8B5CF6,stroke:#6D28D9,stroke-width:2px,color:#fff style Push fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Trigger fill:#F97316,stroke:#C2410C,stroke-width:2px,color:#111827 style Queue fill:#F59E0B,stroke:#B45309,stroke-width:2px,color:#111827 style Pick fill:#F97316,stroke:#C2410C,stroke-width:2px,color:#111827 style Runner1 fill:#EF4444,stroke:#B91C1C,stroke-width:2px,color:#fff style Runner2 fill:#EF4444,stroke:#B91C1C,stroke-width:2px,color:#fff style Checkout fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Cache fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Pull fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Test fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style TestResult fill:#F97316,stroke:#C2410C,stroke-width:2px,color:#111827 style Success fill:#10B981,stroke:#047857,stroke-width:2px,color:#111827 style Failure fill:#EF4444,stroke:#B91C1C,stroke-width:2px,color:#fff style Artifact fill:#6366F1,stroke:#4338CA,stroke-width:2px,color:#fff ``` ## Automated Setup Flow This diagram shows how the runner infrastructure is automatically provisioned and configured. ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e5e7eb','primaryTextColor':'#111827','primaryBorderColor':'#9ca3af','lineColor':'#111827','secondaryColor':'#d1d5db','tertiaryColor':'#f3f4f6','edgeLabelBackground':'#ffffff','mainBkg':'#f5f5f4','nodeBorder':'#9ca3af','background':'#f5f5f4','clusterBkg':'transparent'},'themeCSS':'.node rect, .node circle, .node ellipse, .node polygon, .node path { filter: none !important; box-shadow: none !important; } .cluster rect { filter: none !important; box-shadow: none !important; } svg { background-color: #f5f5f4 !important; } .cluster-label { background-color: #ffffff !important; padding: 6px 12px !important; border-radius: 4px !important; font-size: 16px !important; font-weight: 700 !important; box-shadow: 0 1px 3px rgba(0,0,0,0.12) !important; border: 1px solid #d1d5db !important; } .edgePath, .edgePath path, .flowchart-link { z-index: 1 !important; }'}}%% flowchart TD Start([Terraform Apply]) Secrets[๐Ÿ” Create AWS Secrets
DB credentials, Admin credentials] EC2[๐Ÿ–ฅ๏ธ Provision EC2 Instance
With IAM role for Secrets Manager] Ansible([Ansible Playbook]) Deploy[๐Ÿ“ฆ Deploy Gitea
docker-compose up] Wait[โณ Wait for Gitea
HTTP 200 response] CreateUser[๐Ÿ‘ค Create Admin User
docker exec gitea gitea admin user create] DisableChange[๐Ÿ”“ Disable Password Change
UPDATE user SET must_change_password=false] GenToken[๐ŸŽŸ๏ธ Generate Runner Token
GET /api/v1/admin/runners/registration-token] UpdateSecret[๐Ÿ’พ Store Token in Secrets Manager
aws secretsmanager update-secret] DownloadRunner[๐Ÿ“ฅ Download act_runner v0.2.10] CreateDirs[๐Ÿ“ Create /etc/act_runner-{1,2}] FetchToken[๐Ÿ” Fetch Runner Token
from Secrets Manager] RegisterRunner[๐Ÿ“ Register Runners
act_runner register --instance http://localhost:3000] CreateService[โš™๏ธ Create systemd services
act_runner-1.service, act_runner-2.service] StartService[โ–ถ๏ธ Enable & Start Services] Complete([โœ… Ready for CI/CD]) Start --> Secrets Secrets --> EC2 EC2 --> Ansible Ansible --> Deploy Deploy --> Wait Wait --> CreateUser CreateUser --> DisableChange DisableChange --> GenToken GenToken --> UpdateSecret UpdateSecret --> DownloadRunner DownloadRunner --> CreateDirs CreateDirs --> FetchToken FetchToken --> RegisterRunner RegisterRunner --> CreateService CreateService --> StartService StartService --> Complete style Start fill:#F59E0B,stroke:#B45309,stroke-width:2px,color:#111827 style Secrets fill:#8B5CF6,stroke:#6D28D9,stroke-width:2px,color:#fff style EC2 fill:#10B981,stroke:#047857,stroke-width:2px,color:#111827 style Ansible fill:#F59E0B,stroke:#B45309,stroke-width:2px,color:#111827 style Deploy fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Wait fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style CreateUser fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style DisableChange fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style GenToken fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style UpdateSecret fill:#8B5CF6,stroke:#6D28D9,stroke-width:2px,color:#fff style DownloadRunner fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style CreateDirs fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style FetchToken fill:#8B5CF6,stroke:#6D28D9,stroke-width:2px,color:#fff style RegisterRunner fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style CreateService fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style StartService fill:#3B82F6,stroke:#1D4ED8,stroke-width:2px,color:#fff style Complete fill:#10B981,stroke:#047857,stroke-width:2px,color:#111827 ``` ## Workflow Configuration The CI/CD workflow is defined in `.gitea/workflows/test.yml`: ```yaml name: Integration Tests on: pull_request: branches: [main] workflow_dispatch: jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: ${{ runner.os }}-buildx- - name: Pre-pull test images run: | docker pull postgres:18.4 docker pull nginx:1.27-alpine docker pull alpine:3.19 docker pull alpine:3.20 - name: Run integration tests run: ./scripts/test-update.sh - name: Upload test logs if: failure() uses: actions/upload-artifact@v4 with: name: test-logs path: /tmp/test-*.log retention-days: 7 ``` ## Test Suite The `scripts/test-update.sh` integration test suite validates: 1. **Static validation** (2 tests): - Script syntax and linting - Required executables available 2. **Docker-based tests** (12 tests): - PostgreSQL backup and restore - Health check functionality - Archive validation (SQL and tar formats) - Update simulation workflow - Container cleanup and resource management All tests must pass for a PR to be mergeable. ## Key Features ### Zero-Configuration CI/CD - Runners automatically registered during initial deployment - No manual token management needed - Runner tokens stored securely in AWS Secrets Manager - Complete automation from infrastructure provision to working CI/CD ### High Availability - 2 concurrent runners for parallel job execution - Automatic job distribution by Gitea - Systemd ensures runners restart on failure ### Security - Runners use local Gitea instance (`http://localhost:3000`) - Admin credentials never exposed (CLI-based user creation) - IAM roles for least-privilege access to AWS resources - Runner tokens rotated on redeployment ### Docker Optimization - Docker layer caching for faster builds - Image pre-pulling reduces test execution time - Shared Docker daemon for all tests ## Deployment Commands ```bash # Full deployment (includes runner setup) make full-deploy # Update only configuration (re-registers runners if needed) make configure # Run tests locally make test ```