The docker network was the only `archive-*` identifier in either compose file; everything else (user, db, bucket, service account, project name) uses the `archiv-*` spelling. Reviewers' eyes stuttered on it on the prod compose review (round 2 of PR #499 — Markus and Tobi). Renamed in both prod and dev compose for consistency and updated the single doc reference to the dev-project-prefixed network name. Operational note: applying this change to a running stack will recreate the network on the next `docker compose up`; containers restart, named volumes are unaffected. `docker compose config --quiet` passes for both compose files and for the staging profile. Sweep confirms zero `archive-net` references remain in the tree. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
244 lines
8.2 KiB
Markdown
244 lines
8.2 KiB
Markdown
# CI with Gitea Actions
|
|
|
|
This document covers the Gitea Actions CI workflow for Familienarchiv, including the full workflow YAML, differences from GitHub Actions, and self-hosted runner provisioning.
|
|
|
|
---
|
|
|
|
## Self-Hosted Runner Provisioning
|
|
|
|
Gitea Actions requires self-hosted runners. GitHub Actions provides `ubuntu-latest` for free; on Gitea you run the runner yourself.
|
|
|
|
```bash
|
|
# On the VPS — register a Gitea Actions runner
|
|
docker run -d --name gitea-runner --restart unless-stopped -v /var/run/docker.sock:/var/run/docker.sock -v gitea-runner-data:/data -e GITEA_INSTANCE_URL=https://gitea.example.com -e GITEA_RUNNER_REGISTRATION_TOKEN=<token-from-gitea-settings> -e GITEA_RUNNER_NAME=vps-runner-1 -e GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bullseye gitea/act_runner:latest
|
|
```
|
|
|
|
The runner label `ubuntu-latest` maps to the Docker image it uses -- this is how `runs-on: ubuntu-latest` in the workflow YAML continues to work unchanged.
|
|
|
|
---
|
|
|
|
## Gitea vs GitHub Actions Differences
|
|
|
|
### Context Variable Names
|
|
|
|
| GitHub Actions | Gitea Actions |
|
|
|---|---|
|
|
| `github.sha` | `gitea.sha` |
|
|
| `github.actor` | `gitea.actor` |
|
|
| `github.repository` | `gitea.repository` |
|
|
| `github.ref_name` | `gitea.ref_name` |
|
|
| `secrets.GITHUB_TOKEN` | `secrets.GITEA_TOKEN` (must be created manually) |
|
|
|
|
### Token Name Difference
|
|
|
|
```yaml
|
|
# GitHub Actions
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# Gitea Actions — use a Gitea access token stored as a secret
|
|
password: ${{ secrets.GITEA_TOKEN }}
|
|
```
|
|
|
|
### Container Registry
|
|
|
|
```yaml
|
|
# GitHub Actions — GHCR
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
tags: ghcr.io/${{ github.repository }}/app:${{ github.sha }}
|
|
|
|
# Gitea Actions — Gitea Package Registry
|
|
registry: gitea.example.com
|
|
username: ${{ gitea.actor }}
|
|
password: ${{ secrets.GITEA_TOKEN }}
|
|
tags: gitea.example.com/${{ gitea.repository }}/app:${{ gitea.sha }}
|
|
```
|
|
|
|
---
|
|
|
|
## What Works Identically Between GitHub and Gitea Actions
|
|
|
|
- `uses: actions/checkout@v4` -- works unchanged
|
|
- `uses: actions/setup-java@v4` -- works unchanged
|
|
- `uses: actions/setup-node@v4` -- works unchanged
|
|
- `uses: actions/cache@v4` -- works unchanged
|
|
- `uses: docker/build-push-action@v5` -- works unchanged
|
|
- `container:` key for running jobs inside a Docker image -- works unchanged
|
|
- Secrets syntax `${{ secrets.MY_SECRET }}` -- works unchanged
|
|
|
|
---
|
|
|
|
## Full CI Workflow YAML
|
|
|
|
This is the complete `ci.yml` workflow, updated for Gitea with key changes highlighted.
|
|
|
|
```yaml
|
|
# Updated for Gitea — key changes highlighted
|
|
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
pull_request:
|
|
|
|
jobs:
|
|
unit-tests:
|
|
name: Unit & Component Tests
|
|
runs-on: ubuntu-latest # matches runner label registered above
|
|
container:
|
|
image: mcr.microsoft.com/playwright:v1.58.2-noble
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Cache node_modules
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: frontend/node_modules
|
|
key: node-modules-${{ hashFiles('frontend/package-lock.json') }}
|
|
- name: Install dependencies
|
|
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
|
run: npm ci
|
|
working-directory: frontend
|
|
- name: Lint
|
|
run: npm run lint
|
|
working-directory: frontend
|
|
- name: Run unit and component tests
|
|
run: npm test
|
|
working-directory: frontend
|
|
- name: Upload screenshots
|
|
if: always()
|
|
uses: actions/upload-artifact@v4 # ← upgraded from v3
|
|
with:
|
|
name: unit-test-screenshots
|
|
path: frontend/test-results/screenshots/
|
|
|
|
backend-unit-tests:
|
|
name: Backend Unit Tests
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-java@v4
|
|
with:
|
|
java-version: '21'
|
|
distribution: temurin
|
|
- name: Cache Maven repository
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.m2/repository
|
|
key: maven-${{ hashFiles('backend/pom.xml') }}
|
|
restore-keys: maven-
|
|
- name: Run backend tests
|
|
run: |
|
|
chmod +x mvnw
|
|
./mvnw clean test
|
|
working-directory: backend
|
|
- name: Upload test results
|
|
if: always()
|
|
uses: actions/upload-artifact@v4 # ← upgraded from v3
|
|
with:
|
|
name: backend-test-results
|
|
path: backend/target/surefire-reports/
|
|
|
|
e2e-tests:
|
|
name: E2E Tests
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
DOCKER_API_VERSION: "1.43"
|
|
POSTGRES_USER: archive_user
|
|
POSTGRES_PASSWORD: ci_db_password
|
|
POSTGRES_DB: family_archive_db
|
|
MINIO_ROOT_USER: minio_admin
|
|
MINIO_ROOT_PASSWORD: ci_minio_password
|
|
MINIO_DEFAULT_BUCKETS: archive-documents
|
|
PORT_DB: 5433
|
|
PORT_MINIO_API: 9100
|
|
PORT_MINIO_CONSOLE: 9101
|
|
PORT_BACKEND: 8080
|
|
PORT_FRONTEND: 3000
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Cleanup leftover containers
|
|
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml down --volumes --remove-orphans || true
|
|
- name: Start DB and MinIO
|
|
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d db minio create-buckets
|
|
- name: Wait for DB
|
|
run: |
|
|
timeout 30 bash -c \
|
|
'until docker compose -f docker-compose.yml -f docker-compose.ci.yml exec -T db pg_isready -U archive_user; do sleep 2; done'
|
|
- name: Connect job container to compose network
|
|
run: docker network connect familienarchiv_archiv-net $(cat /etc/hostname)
|
|
- uses: actions/setup-java@v4
|
|
with:
|
|
java-version: '21'
|
|
distribution: temurin
|
|
- name: Cache Maven repository
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.m2/repository
|
|
key: maven-${{ hashFiles('backend/pom.xml') }}
|
|
restore-keys: maven-
|
|
- name: Build backend
|
|
run: |
|
|
chmod +x mvnw
|
|
./mvnw clean package -DskipTests
|
|
working-directory: backend
|
|
- name: Start backend
|
|
run: |
|
|
java -jar backend/target/*.jar \
|
|
--spring.profiles.active=e2e \
|
|
--SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/family_archive_db \
|
|
--SPRING_DATASOURCE_USERNAME=archive_user \
|
|
--SPRING_DATASOURCE_PASSWORD=ci_db_password \
|
|
--S3_ENDPOINT=http://minio:9000 \
|
|
--S3_ACCESS_KEY=minio_admin \
|
|
--S3_SECRET_KEY=ci_minio_password \
|
|
--S3_BUCKET_NAME=archive-documents \
|
|
--S3_REGION=us-east-1 \
|
|
--APP_ADMIN_USERNAME=admin \
|
|
--APP_ADMIN_PASSWORD=${{ secrets.E2E_ADMIN_PASSWORD }} \
|
|
&
|
|
timeout 90 bash -c \
|
|
'until curl -sf http://localhost:8080/actuator/health | grep -q "UP"; do sleep 3; done'
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 20
|
|
- name: Cache node_modules
|
|
id: node-modules-cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: frontend/node_modules
|
|
key: node-modules-${{ hashFiles('frontend/package-lock.json') }}
|
|
- name: Install frontend dependencies
|
|
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
|
run: npm ci
|
|
working-directory: frontend
|
|
- name: Cache Playwright browsers
|
|
id: playwright-cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-chromium-${{ hashFiles('frontend/package-lock.json') }}
|
|
- name: Install Playwright Chromium + system deps
|
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
run: npx playwright install chromium --with-deps
|
|
working-directory: frontend
|
|
- name: Install Playwright system deps only
|
|
if: steps.playwright-cache.outputs.cache-hit == 'true'
|
|
run: npx playwright install-deps chromium
|
|
working-directory: frontend
|
|
- name: Run E2E tests
|
|
run: npm run test:e2e
|
|
working-directory: frontend
|
|
env:
|
|
E2E_BASE_URL: http://localhost:3000
|
|
E2E_USERNAME: admin
|
|
E2E_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD }} # ← secret, not hardcoded
|
|
E2E_BACKEND_URL: http://localhost:8080
|
|
- name: Upload E2E results
|
|
if: always()
|
|
uses: actions/upload-artifact@v4 # ← upgraded from v3
|
|
with:
|
|
name: e2e-results
|
|
path: frontend/test-results/e2e/
|
|
```
|