# CI/CD Configuration This document describes the CI/CD pipeline configuration for FictionArchive using Gitea Actions. ## Workflows Overview | Workflow | File | Trigger | Purpose | |----------|------|---------|---------| | CI | `build.yml` | Push/PR to master | Build and test all projects | | Build Gateway | `build-gateway.yml` | Tag `v*.*.*` or manual | Build subgraphs, compose gateway, push API image | | Release | `release.yml` | Tag `v*.*.*` | Build and push all Docker images | | Claude PR Assistant | `claude_assistant.yml` | Issue/PR comments with @claude | AI-assisted code review and issue handling | ## Pipeline Architecture ``` ┌─────────────────────────────────────────────────────────────────────┐ │ Push to master │ └─────────────────────────────┬───────────────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ build.yml │ │ (CI checks) │ └─────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────┐ │ Push tag v*.*.* │ └─────────────────────────────┬───────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────┐ │ release.yml │ │ build-gateway.yml │ │ (build & push all │ │ (build subgraphs & │ │ backend + frontend) │ │ push API gateway) │ └─────────────────────────┘ └─────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────┐ │ Issue/PR comment containing @claude │ └─────────────────────────────┬───────────────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ claude_assistant.yml │ │ (AI code assistance) │ └─────────────────────────┘ ``` ## Required Configuration ### Repository Secrets Configure these in **Settings → Actions → Secrets**: | Secret | Description | Required By | |--------|-------------|-------------| | `REGISTRY_TOKEN` | Gitea access token with `write:package` scope | `release.yml`, `build-gateway.yml` | | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code OAuth token | `claude_assistant.yml` | | `CLAUDE_GITEA_TOKEN` | Gitea token for Claude assistant | `claude_assistant.yml` | #### Creating Access Tokens 1. Go to **Settings → Applications → Access Tokens** 2. Create a new token with the following scopes: - `write:package` - Push container images - `write:repository` - For Claude assistant to push commits 3. Copy the token and add it as a repository secret ### Repository Variables Configure these in **Settings → Actions → Variables**: | Variable | Description | Example | Required By | |----------|-------------|---------|-------------| | `VITE_GRAPHQL_URI` | GraphQL API endpoint URL | `https://api.fictionarchive.example.com/graphql/` | `release.yml` | | `VITE_OIDC_AUTHORITY` | OIDC provider authority URL | `https://auth.example.com/application/o/fiction-archive/` | `release.yml` | | `VITE_OIDC_CLIENT_ID` | OIDC client identifier | `your-client-id` | `release.yml` | | `VITE_OIDC_REDIRECT_URI` | Post-login redirect URL | `https://fictionarchive.example.com/` | `release.yml` | | `VITE_OIDC_POST_LOGOUT_REDIRECT_URI` | Post-logout redirect URL | `https://fictionarchive.example.com/` | `release.yml` | ## Workflow Details ### CI (`build.yml`) **Trigger:** Push or pull request to `master` **Jobs:** 1. `build-backend` - Builds .NET solution and runs tests 2. `build-frontend` - Builds React application with linting **Requirements:** - .NET 8.0 SDK - Node.js 20 **Steps (Backend):** 1. Checkout repository 2. Setup .NET 8.0 3. Restore dependencies 4. Build solution (Release, with `SkipFusionBuild=true`) 5. Run tests **Steps (Frontend):** 1. Checkout repository 2. Setup Node.js 20 3. Install dependencies (`npm ci`) 4. Run linter (`npm run lint`) 5. Build application (`npm run build`) ### Build Gateway (`build-gateway.yml`) **Trigger:** - Manual dispatch (`workflow_dispatch`) - Push tag matching `v*.*.*` **Jobs:** #### 1. `build-subgraphs` (Matrix Job) Builds GraphQL subgraph packages for each service: | Service | Project | Subgraph Name | |---------|---------|---------------| | novel-service | FictionArchive.Service.NovelService | Novel | | translation-service | FictionArchive.Service.TranslationService | Translation | | scheduler-service | FictionArchive.Service.SchedulerService | Scheduler | | user-service | FictionArchive.Service.UserService | User | **Note:** File Service and Authentication Service are not subgraphs (no GraphQL schema). **Steps:** 1. Checkout repository 2. Setup .NET 8.0 3. Install HotChocolate Fusion CLI 4. Restore and build service project 5. Export GraphQL schema (`schema export`) 6. Pack subgraph into `.fsp` file 7. Upload artifact (retained 30 days) #### 2. `build-gateway` (Depends on `build-subgraphs`) Composes the API gateway from subgraph packages. **Steps:** 1. Checkout repository 2. Setup .NET 8.0 and Fusion CLI 3. Download all subgraph artifacts 4. Configure Docker-internal URLs (`http://{service}-service:8080/graphql`) 5. Compose gateway schema using Fusion CLI 6. Build gateway project 7. Build and push Docker image **Image Tags:** - `//fictionarchive-api:latest` - `//fictionarchive-api:` ### Release (`release.yml`) **Trigger:** Push tag matching `v*.*.*` (e.g., `v1.0.0`) **Jobs:** #### 1. `build-and-push` (Matrix Job) Builds and pushes all backend service images: | Service | Dockerfile | |---------|------------| | novel-service | FictionArchive.Service.NovelService/Dockerfile | | user-service | FictionArchive.Service.UserService/Dockerfile | | translation-service | FictionArchive.Service.TranslationService/Dockerfile | | file-service | FictionArchive.Service.FileService/Dockerfile | | scheduler-service | FictionArchive.Service.SchedulerService/Dockerfile | | authentication-service | FictionArchive.Service.AuthenticationService/Dockerfile | #### 2. `build-frontend` Builds and pushes the frontend image with environment-specific build arguments. **Build Args:** - `VITE_GRAPHQL_URI` - `VITE_OIDC_AUTHORITY` - `VITE_OIDC_CLIENT_ID` - `VITE_OIDC_REDIRECT_URI` - `VITE_OIDC_POST_LOGOUT_REDIRECT_URI` **Image Tags:** - `//fictionarchive-:` - `//fictionarchive-:latest` ### Claude PR Assistant (`claude_assistant.yml`) **Trigger:** Comments or issues containing `@claude`: - Issue comments - Pull request review comments - Pull request reviews - New issues (opened or assigned) **Permissions Required:** - `contents: write` - `pull-requests: write` - `issues: write` - `id-token: write` **Usage:** Mention `@claude` in any issue or PR comment to invoke the AI assistant for: - Code review assistance - Bug analysis - Implementation suggestions - Documentation help ## Container Registry Images are pushed to the Gitea Container Registry at: ``` //fictionarchive-: ``` ### Image Naming Convention | Image | Description | |-------|-------------| | `fictionarchive-api` | API Gateway (GraphQL Federation) | | `fictionarchive-novel-service` | Novel Service | | `fictionarchive-user-service` | User Service | | `fictionarchive-translation-service` | Translation Service | | `fictionarchive-file-service` | File Service | | `fictionarchive-scheduler-service` | Scheduler Service | | `fictionarchive-authentication-service` | Authentication Service | | `fictionarchive-frontend` | Web Frontend | ### Pulling Images ```bash # Login to registry docker login -u -p # Pull an image docker pull //fictionarchive-api:latest ``` ## Creating a Release 1. Ensure all changes are committed and pushed to `master` 2. Create and push a version tag: ```bash git tag v1.0.0 git push origin v1.0.0 ``` 3. The release workflow will automatically build and push all images 4. Monitor progress in **Actions** tab ## Troubleshooting ### Build Failures **"REGISTRY_TOKEN secret not found"** - Ensure the `REGISTRY_TOKEN` secret is configured in repository settings - Verify the token has `write:package` scope **"No subgraph artifacts found"** - The gateway build requires subgraph artifacts from the `build-subgraphs` job - If subgraph builds failed, check the matrix job logs for errors **"Schema export failed"** - Ensure the service project has a valid `subgraph-config.json` - Check that the service starts correctly for schema export ### Frontend Build Failures **"VITE_* variables are empty"** - Ensure all required variables are configured in repository settings - Variables use `vars.*` context, not `secrets.*` ### Docker Push Failures **"unauthorized: authentication required"** - Verify `REGISTRY_TOKEN` has correct permissions - Check that the token hasn't expired ### Claude Assistant Failures **"Claude assistant not responding"** - Verify `CLAUDE_CODE_OAUTH_TOKEN` is configured - Verify `CLAUDE_GITEA_TOKEN` is configured and has write permissions - Check that the comment contains `@claude` mention ## Local Testing To test workflows locally before pushing: ```bash # Install act (GitHub Actions local runner) # Note: act has partial Gitea Actions compatibility # Run CI workflow act push -W .gitea/workflows/build.yml # Run with specific event act push --eventpath .gitea/test-event.json ```