feat(merchant): extract merchant portal as first-class frontend with auth, Tailwind fixes, and Gitea CI
Some checks failed
CI / ruff (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / architecture (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / audit (push) Has been cancelled
CI / docs (push) Has been cancelled

- Extract login/dashboard from billing module into core (matching admin pattern)
- Add merchant auth API with path-isolated cookies (path=/merchants)
- Add merchant base layout with sidebar/header partials and Alpine.js init
- Add frontend detection and login redirect for MERCHANT type
- Wire merchant token in shared api-client.js (get/clear)
- Migrate billing templates to merchant base with dark mode support
- Fix Tailwind: rename shop→storefront in sources and config
- DRY Makefile tailwind targets with TAILWIND_FRONTENDS loop
- Rebuild all Tailwind outputs (production minified)
- Add Gitea Actions CI workflow (ruff, pytest, architecture, docs)
- Add Gitea deployment documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 20:25:29 +01:00
parent ecb5309879
commit 0437af67ec
31 changed files with 1925 additions and 780 deletions

302
docs/deployment/gitea.md Normal file
View File

@@ -0,0 +1,302 @@
# Gitea CI/CD Deployment Guide
This document describes how to **self-host Gitea** on an external server and migrate CI/CD from GitLab to **Gitea Actions** (GitHub Actions-compatible).
---
## Why Gitea?
- Lightweight, self-hosted Git forge (single binary or Docker image)
- Built-in CI/CD via **Gitea Actions** (GitHub Actions-compatible YAML)
- Built-in migration tool imports repos, issues, and PRs from GitLab
- Low resource usage compared to GitLab
---
## 1. Server Prerequisites
```bash
# Ubuntu/Debian
sudo apt update && sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USER # log out/in after this
```
---
## 2. Gitea Server Setup (Docker Compose)
Create a directory on your server:
```bash
mkdir -p ~/gitea && cd ~/gitea
```
Create `docker-compose.yml`:
```yaml
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: always
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=gitea-db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=<CHANGE_ME>
- GITEA__server__ROOT_URL=https://git.yourdomain.com/
- GITEA__server__SSH_DOMAIN=git.yourdomain.com
- GITEA__server__DOMAIN=git.yourdomain.com
- GITEA__actions__ENABLED=true
volumes:
- gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000" # Web UI
- "2222:22" # SSH (Git over SSH)
depends_on:
gitea-db:
condition: service_healthy
gitea-db:
image: postgres:15
container_name: gitea-db
restart: always
environment:
POSTGRES_DB: gitea
POSTGRES_USER: gitea
POSTGRES_PASSWORD: <CHANGE_ME>
volumes:
- gitea-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gitea"]
interval: 10s
timeout: 5s
retries: 5
# Gitea Actions runner — executes CI workflows
gitea-runner:
image: gitea/act_runner:latest
container_name: gitea-runner
restart: always
environment:
GITEA_INSTANCE_URL: http://gitea:3000
GITEA_RUNNER_REGISTRATION_TOKEN: <RUNNER_TOKEN>
GITEA_RUNNER_NAME: default-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- gitea-runner-data:/data
depends_on:
- gitea
volumes:
gitea-data:
gitea-db-data:
gitea-runner-data:
```
!!! warning "Replace placeholders"
Replace `<CHANGE_ME>` with a strong database password and `<RUNNER_TOKEN>` with the token from step 4.
Start Gitea and the database first:
```bash
docker compose up -d gitea gitea-db
```
Visit `http://your-server-ip:3000` and complete the initial setup wizard.
---
## 3. Reverse Proxy with HTTPS (Nginx + Let's Encrypt)
```bash
sudo apt install -y nginx certbot python3-certbot-nginx
```
Create `/etc/nginx/sites-available/gitea`:
```nginx
server {
server_name git.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100M;
}
}
```
Enable and get a certificate:
```bash
sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
sudo certbot --nginx -d git.yourdomain.com
sudo systemctl reload nginx
```
---
## 4. Enable Actions & Register the Runner
1. Go to **Site Administration > Runners** in the Gitea web UI.
2. Click **Create new Runner** and copy the registration token.
3. Paste the token into `docker-compose.yml` as `GITEA_RUNNER_REGISTRATION_TOKEN`.
4. Start the runner:
```bash
docker compose up -d gitea-runner
```
Verify the runner appears as **Online** in the admin panel.
---
## 5. Migrate Your Repository
### Option A: Git push (code only)
```bash
# On your local machine
cd /path/to/letzshop-product-import
git remote add gitea ssh://git@git.yourdomain.com:2222/your-username/letzshop-product-import.git
git push gitea --all
git push gitea --tags
```
### Option B: Gitea built-in migration (code + issues + PRs)
1. In Gitea, click **+** > **New Migration**.
2. Select **GitLab** as the source.
3. Enter your GitLab URL and a Personal Access Token.
4. Gitea will import the repository, issues, labels, milestones, and merge requests.
---
## 6. CI/CD — GitLab vs Gitea Actions
The workflow file lives in `.gitea/workflows/ci.yml` (already created in this repository).
| GitLab CI (`.gitlab-ci.yml`) | Gitea Actions (`.gitea/workflows/ci.yml`) |
|------------------------------|-------------------------------------------|
| `stages:` + `stage:` per job | Jobs run in parallel; use `needs:` for ordering |
| `services:` (top-level on job) | `services:` nested under each job with `options:` |
| `allow_failure: true` | `continue-on-error: true` |
| `rules: - if:` | `on:` triggers + `if:` conditionals per job |
| `artifacts: paths:` | `actions/upload-artifact@v4` |
| `cache: paths:` | `actions/cache@v4` |
| `coverage: '/regex/'` | Use coverage action or parse in step |
| CI/CD Variables (UI) | Repository **Settings > Secrets** |
---
## 7. CI/CD Secrets
Configure these in your Gitea repository under **Settings > Actions > Secrets**:
| Secret | Description | Used by |
|--------|-------------|---------|
| `SSH_PRIVATE_KEY` | Private key for deployment server | Deploy job (if added) |
| `SERVER_HOST` | Production server IP/hostname | Deploy job |
| `SERVER_USER` | SSH user on production server | Deploy job |
| `SERVER_PATH` | App directory on server | Deploy job |
---
## 8. Pipeline Overview
The CI pipeline (`.gitea/workflows/ci.yml`) runs:
```
push/PR to master
├── ruff (lint)
├── pytest (tests + PostgreSQL service)
├── architecture (architecture validation)
├── dependency-scanning (pip-audit, non-blocking)
├── audit (custom audit, non-blocking)
└── docs (mkdocs build, master-only, after lint+test pass)
```
All jobs run in parallel except `docs`, which waits for `ruff`, `pytest`, and `architecture` to pass.
---
## 9. Adding a Deploy Job (Optional)
To add automated deployment via SSH (similar to the GitLab deploy stage), add this job to `.gitea/workflows/ci.yml`:
```yaml
deploy:
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
needs: [ruff, pytest, architecture]
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd ${{ secrets.SERVER_PATH }}
git pull origin master
source .venv/bin/activate
uv sync --frozen
python -m alembic upgrade head
sudo systemctl restart wizamart
```
---
## 10. Firewall Configuration
```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
```
---
## 11. Maintenance
```bash
# View Gitea logs
docker compose -f ~/gitea/docker-compose.yml logs -f gitea
# View runner logs
docker compose -f ~/gitea/docker-compose.yml logs -f gitea-runner
# Update Gitea
cd ~/gitea
docker compose pull
docker compose up -d
# Backup Gitea data
docker run --rm -v gitea-data:/data -v $(pwd):/backup alpine \
tar czf /backup/gitea-backup-$(date +%Y%m%d).tar.gz /data
```
---
## 12. Removing GitLab (After Migration)
Once you have verified everything works on Gitea:
1. Update your local git remote:
```bash
git remote set-url origin ssh://git@git.yourdomain.com:2222/your-username/letzshop-product-import.git
```
2. The `.gitlab-ci.yml` file can be removed from the repository.
3. Archive or delete the GitLab project.