diff --git a/.forgejo/workflows/ci.yaml b/.gitea/workflows/ci.yaml similarity index 100% rename from .forgejo/workflows/ci.yaml rename to .gitea/workflows/ci.yaml diff --git a/.forgejo/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml similarity index 98% rename from .forgejo/workflows/deploy.yaml rename to .gitea/workflows/deploy.yaml index 4101823..3f45e80 100644 --- a/.forgejo/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -100,4 +100,4 @@ jobs: run: | test -n "$DEPLOY_HOST" || (echo "DEPLOY_HOST must be set" && exit 1) test -n "$DEPLOY_SSH_PRIVATE_KEY" || (echo "DEPLOY_SSH_PRIVATE_KEY must be set" && exit 1) - bash scripts/deploy-forgejo.sh \ No newline at end of file + bash scripts/deploy-actions.sh \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 2086aad..b7882ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,32 +89,109 @@ validation_checklist: - screenshot artifact captured when useful - relevant logs checked -forgejo_ci: +gitea_ci: + repo: + base_url: "http://tea.uncloud.vpn" + api_base_url: "http://tea.uncloud.vpn/api/v1" + owner: "bu5hm4nn" + name: "vault-dash" + full_name: "bu5hm4nn/vault-dash" + ssh_remote: "ssh://git@tea.uncloud.vpn:2223/bu5hm4nn/vault-dash.git" + auth: + preferred_method: "tea login" + notes: + - "`tea` is already logged in for this repo and should be preferred for API access" + - "`tea api` works against this Gitea 1.25.5 instance even when higher-level `tea actions` commands are unavailable" + - A raw token may exist separately, but automation should not assume one unless the user says so + shell_setup: | + export GITEA_URL="${GITEA_URL:-http://tea.uncloud.vpn}" + export GITEA_API="${GITEA_API:-$GITEA_URL/api/v1}" + export GITEA_REPO="bu5hm4nn/vault-dash" + tea login list >/dev/null + command -v jq >/dev/null + triage: + preferred_method: "use `tea api` for run/job/log discovery; use the Gitea web UI as fallback" + tested_on: "2026-04-07" + tested_behavior: + - "`tea actions runs list` refuses to run because the server is older than 1.26.0" + - "`tea api` works and authenticates via the stored tea login" + - Gitea 1.25.5 exposes Actions run, job, log, workflow, artifact, and runner endpoints in swagger + - The new server supports `/repos/{owner}/{repo}/actions/runs/{run}/jobs` and `/repos/{owner}/{repo}/actions/jobs/{job_id}/logs` + response_shape_note: + - Gitea Actions list endpoints return object wrappers such as `.workflow_runs` or `.jobs` + - In jq, prefer `(.workflow_runs // .)` for runs and `(.jobs // .)` for jobs + default_scope: + - Prefer latest run for `git rev-parse HEAD` + - If there is no run for HEAD yet, inspect the latest failed run on the current branch + - If CI failed, Build and Deploy will not run because deploy is triggered after CI success + query_recipes: + list_recent_runs_current_branch: | + branch="$(git branch --show-current)" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/runs?branch=$branch&limit=20" | jq '(.workflow_runs // .) | map({id, workflow_id, status, event, head_branch, head_sha, created_at, html_url})' + latest_run_for_head_sha: | + branch="$(git branch --show-current)" + sha="$(git rev-parse HEAD)" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/runs?branch=$branch&limit=50" | jq -r --arg sha "$sha" '((.workflow_runs // .) | map(select((.head_sha // .commit_sha) == $sha)) | sort_by(.created_at // .run_started_at // .id) | reverse | .[0])' + latest_failed_run_current_branch: | + branch="$(git branch --show-current)" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/runs?branch=$branch&status=failure&limit=20" | jq -r '((.workflow_runs // .) | sort_by(.created_at // .run_started_at // .id) | reverse | .[0])' + list_jobs_for_run: | + run_id="" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/runs/$run_id/jobs" | jq '(.jobs // .) | map({id, name, status, conclusion, started_at, completed_at})' + first_failed_job_for_run: | + run_id="" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/runs/$run_id/jobs" | jq -r '((.jobs // .) | map(select((.conclusion // .status) == "failure" or .status == "failure")) | sort_by(.started_at // .id) | .[0])' + download_job_log: | + job_id="" + tea api -l tea.uncloud.vpn "/repos/bu5hm4nn/vault-dash/actions/jobs/$job_id/logs" viewing_job_logs: web_ui: - url: "http://git.uncloud.vpn:3000/bu5hm4nn/vault-dash/actions" + url: "http://tea.uncloud.vpn/bu5hm4nn/vault-dash/actions" steps: - - Navigate to Actions tab in Forgejo UI (VPN access required) - - Click on the workflow run to see job status - - Expand failing job (lint/test/type-check/build/deploy) - - Click on failed step to see detailed logs - runner_logs: - ssh: "ssh root@5.75.141.4" - command: "docker logs forgejo-runner --tail 100" - job_workspace: "/opt/forgejo-runner/data/" + - Navigate to Actions tab in the Gitea UI + - Open the run from its `html_url` returned by `tea api` + - Expand the failing job (lint/test/type-check/build/deploy) + - Click the failed step to inspect detailed logs + api: + preferred_cli: "tea api" + notes: + - High-level `tea actions` commands may be version-gated by the CLI + - "`tea api` is the stable fallback for this Gitea instance" + workflows: + CI: + file: ".gitea/workflows/ci.yaml" + jobs: [lint, type-check, test] + triggers: [push main, pull_request main] + Build_and_Deploy: + file: ".gitea/workflows/deploy.yaml" + jobs: [build, deploy] + triggers: + - workflow_run after CI succeeds on main + - manual workflow_dispatch common_failures: missing_dependency: symptom: "ModuleNotFoundError: No module named 'X'" - fix: "Add package to requirements.txt AND .forgejo/workflows/deploy.yaml (test + type-check jobs)" + fix: + - Add runtime deps to requirements.txt + - Add dev/test tooling deps to requirements-dev.txt + - CI installs requirements-dev.txt, so keep CI-critical deps there + playwright_version_drift: + symptom: "Playwright browser/package mismatch or local vs CI behavior differs" + fix: + - Keep Python Playwright pinned in requirements-dev.txt + - Keep the pin aligned with `.gitea/workflows/ci.yaml` Playwright container image tag + tea_version_gate: + symptom: "`tea actions ...` says the server is older than 1.26.0" + fix: "Use `tea api` directly against the Actions endpoints instead of high-level tea subcommands" type_error: symptom: "error: Incompatible types..." - fix: "Run `mypy app --ignore-missing-imports` locally to reproduce" + fix: "Run `mypy app/core app/models app/strategies app/services app/domain --show-error-codes --show-traceback` locally to reproduce" test_failure: symptom: "FAILED test_name" - fix: "Run failing test locally with pytest -xvs" + fix: "Run failing test locally with `pytest -xvs `" pre_merge_checklist: - run `pytest tests/ -v --tb=short` locally and ensure all new/changed tests pass - run `/review` to get implementation review and QA validation - - verify CI passes on Forgejo (lint, test, type-check, build, deploy) + - verify CI passes on Gitea (lint, test, type-check, build, deploy) - address all review comments before merging to main diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index d982869..9973d0f 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -1,13 +1,13 @@ # Deployment Guide -This project uses Forgejo Actions for CI/CD, building a Docker image and deploying to a VPN-reachable VPS over SSH. +This project uses Gitea Actions for CI/CD, building a Docker image and deploying to a VPN-reachable VPS over SSH. ## Overview Deployment workflow: -1. **CI** (`.forgejo/workflows/ci.yaml`): Lint, test, type-check on every push -2. **Deploy** (`.forgejo/workflows/deploy.yaml`): Build, scan, and deploy on main branch +1. **CI** (`.gitea/workflows/ci.yaml`): lint, test, type-check on every push +2. **Build and Deploy** (`.gitea/workflows/deploy.yaml`): build and deploy on `main` after CI succeeds, or manually via workflow dispatch --- @@ -20,14 +20,15 @@ Deployment workflow: - SSH access via VPN - Python 3.11+ (for healthcheck script) -### Forgejo Instance Setup +### Gitea Instance Setup -1. Enable Actions in Forgejo admin settings -2. Register a runner (or use Forgejo's built-in runner) +1. Enable Actions in Gitea admin settings +2. Enable Actions for the repository +3. Register an Actions runner ### Runner Setup -Forgejo supports both built-in runners and self-hosted Docker runners. For Docker-in-Docker builds, ensure the runner has: +Gitea Actions uses `act_runner`. For Docker-based builds, ensure the runner host has: - Docker installed and accessible - `docker` and `docker compose` commands available @@ -35,34 +36,40 @@ Forgejo supports both built-in runners and self-hosted Docker runners. For Docke Example runner registration: ```bash -# On your Forgejo server -forgejo actions generate-runner-token > token.txt -forgejo-runner register --instance-addr http://localhost:3000 --token $(cat token.txt) -forgejo-runner daemon +# On the runner host +./act_runner register --no-interactive --instance http://tea.uncloud.vpn --token +./act_runner daemon ``` +Repository, organization, and instance runner tokens can be created from the Gitea web UI under Actions runner settings. + --- ## 2. Required Secrets -Configure in **Settings → Secrets and variables → Actions**: +Configure in **Settings → Secrets and variables → Actions**. + +### Secrets | Secret | Description | |--------|-------------| | `DEPLOY_SSH_PRIVATE_KEY` | SSH key for VPS access | -| `DEPLOY_HOST` | VPS IP/hostname (VPN-reachable) | -| `DEPLOY_USER` | Deploy user (default: `deploy`) | -| `DEPLOY_PORT` | SSH port (default: 22) | -| `DEPLOY_PATH` | Deploy path (default: `/opt/vault-dash`) | -| `NICEGUI_STORAGE_SECRET` | Session secret | | `REGISTRY_PASSWORD` | Container registry token (if needed) | +| `DOCKERHUB_TOKEN` | Docker Hub token | +| `TURNSTILE_SECRET_KEY` | Turnstile secret key | +| `DATABENTO_API_KEY` | Databento API key | -### Optional Variables +### Variables | Variable | Description | |----------|-------------| +| `DEPLOY_HOST` | VPS IP/hostname (VPN-reachable) | +| `DEPLOY_USER` | Deploy user (default: `deploy`) | +| `DEPLOY_PORT` | SSH port (default: `22`) | +| `DEPLOY_PATH` | Deploy path (default: `/opt/vault-dash`) | | `REGISTRY` | Container registry URL | -| `EXTERNAL_HEALTHCHECK_URL` | Public health check URL | +| `DOCKERHUB_USERNAME` | Docker Hub username | +| `TURNSTILE_SITE_KEY` | Turnstile site key | --- @@ -127,7 +134,7 @@ export DEPLOY_SSH_PRIVATE_KEY="$(cat ~/.ssh/deploy_key)" export APP_IMAGE="registry.example.com/vault-dash:latest" # Run deploy script -bash scripts/deploy.sh +bash scripts/deploy-actions.sh ``` --- @@ -150,22 +157,12 @@ vault.uncloud.vpn { --- -## 7. Future: OAuth Integration - -When ready to expose publicly: - -1. Set up OAuth provider (Authentik, Keycloak, etc.) -2. Configure `CORS_ORIGINS` for public URL -3. Add OAuth middleware to FastAPI -4. Enable HTTPS via Let's Encrypt - ---- - -## 8. Troubleshooting +## 7. Troubleshooting ### Runner can't build Docker images Ensure runner has Docker access: + ```bash docker run --rm hello-world ``` @@ -192,4 +189,4 @@ cd /opt/vault-dash PREVIOUS=$(cat .last_successful_image) sed -i "s|^APP_IMAGE=.*|APP_IMAGE=$PREVIOUS|" .env docker compose -f docker-compose.deploy.yml up -d -``` \ No newline at end of file +``` diff --git a/scripts/deploy-forgejo.sh b/scripts/deploy-actions.sh similarity index 96% rename from scripts/deploy-forgejo.sh rename to scripts/deploy-actions.sh index 3c947d7..3341d49 100755 --- a/scripts/deploy-forgejo.sh +++ b/scripts/deploy-actions.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash set -Eeuo pipefail -# Deploy script for Forgejo Actions -# Uses Forgejo environment variables instead of GitLab CI variables +# Deploy script for Gitea Actions +# Uses Git hosting Actions environment variables instead of GitLab CI variables : "${DEPLOY_USER:?DEPLOY_USER is required}" : "${DEPLOY_HOST:?DEPLOY_HOST is required}"