From 2f63b65d0d0ff6c33428790646f55e9fd7bfc1e2 Mon Sep 17 00:00:00 2001 From: S Date: Sun, 1 Mar 2026 08:16:42 -0500 Subject: [PATCH] feat: expand API documentation for repository settings and GitHub Actions management --- contracts/gitea-api.md | 136 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 6 deletions(-) diff --git a/contracts/gitea-api.md b/contracts/gitea-api.md index 02b8141..9b87ed0 100644 --- a/contracts/gitea-api.md +++ b/contracts/gitea-api.md @@ -453,22 +453,146 @@ Auth: `Authorization: token ${GITHUB_TOKEN}` ### PATCH /repos/{owner}/{repo} -**Used in**: Phase 8 (archive repos + update description), Phase 8 teardown (un-archive) +**Used in**: Phase 8 (mark as mirror + update description), Phase 8 teardown (restore settings) **Purpose**: Update repository settings -**Request (archive)**: +**Request (mark as mirror)**: ```json { - "archived": true, - "description": "[MOVED] Now at https://git.domain.com/org/repo — was: original description" + "description": "[MIRROR] Offsite backup — primary at https://git.domain.com/org/repo — was: original description", + "homepage": "https://git.domain.com/org/repo", + "has_wiki": false, + "has_projects": false } ``` -**Request (un-archive)**: +**Request (restore)**: ```json { - "archived": false + "description": "original description", + "homepage": "original homepage", + "has_wiki": true, + "has_projects": true } ``` **Response** (200): Updated repository object + +### PUT /repos/{owner}/{repo}/actions/permissions + +**Used in**: Phase 6 (disable Actions), Phase 6 teardown (re-enable) +**Purpose**: Enable or disable GitHub Actions on a repo + +**Request**: +```json +{ + "enabled": false +} +``` + +**Response** (204): No Content + +### GET /repos/{owner}/{repo}/pages + +**Used in**: Phase 8 (snapshot Pages state for teardown) +**Purpose**: Get GitHub Pages configuration + +**Response** (200): +```json +{ + "cname": "string", + "source": { + "branch": "main", + "path": "/" + } +} +``` + +**404**: Pages not enabled for this repo + +### DELETE /repos/{owner}/{repo}/pages + +**Used in**: Phase 8 (disable Pages on mirror) +**Purpose**: Disable GitHub Pages + +**Response** (204): No Content + +--- + +## Error Responses + +All Gitea and GitHub API endpoints return standard HTTP error codes. The migration +scripts check `http_code >= 400` in `_api_call()` (lib/common.sh) and treat any +4xx/5xx as a failure. + +### Common Error Codes + +| Code | Meaning | Typical Cause | +|------|---------|---------------| +| 400 | Bad Request | Malformed JSON, missing required fields, invalid field values | +| 401 | Unauthorized | Token expired, revoked, or missing | +| 403 | Forbidden | Token lacks required scope (e.g., admin endpoint with non-admin token) | +| 404 | Not Found | Resource doesn't exist — used for idempotency checks (`GET` before `POST`) | +| 409 | Conflict | Resource already exists (e.g., duplicate token name, duplicate org name) | +| 422 | Unprocessable Entity | Validation failed (e.g., password too short, invalid repo name) | +| 500 | Internal Server Error | Server-side failure — retry may work for transient issues | + +### Error Response Body + +Gitea errors return JSON with a `message` field: +```json +{ + "message": "string describing the error", + "url": "https://gitea.docs/api/endpoint" +} +``` + +GitHub errors return JSON with `message` and optionally `errors`: +```json +{ + "message": "Validation Failed", + "errors": [ + { + "resource": "Repository", + "field": "name", + "code": "already_exists" + } + ] +} +``` + +### How Scripts Handle Errors + +- `_api_call()` logs the full response body on any 4xx/5xx and returns exit code 1 +- Callers either `exit 1` (fatal) or continue with `|| true` (non-fatal, e.g., sync triggers) +- Idempotency checks use 404 as a signal to proceed with creation — this is expected, not an error + +--- + +## Pagination + +Gitea list endpoints return paginated results. The migration scripts do NOT +paginate because the data volumes are small (3 repos, ~3 runners, ~3 mirrors). + +### Gitea Pagination Headers + +``` +x-total-count: 42 +link: ; rel="next", ; rel="last" +``` + +### Default Limits + +| Endpoint | Default per-page | Max per-page | +|----------|:----------------:|:------------:| +| GET /admin/runners | 50 | 50 | +| GET /repos/{owner}/{repo}/push_mirrors | 50 | 50 | +| GET /repos/{owner}/{repo}/commits | 50 | 50 | +| GET /repos/{owner}/{repo}/branch_protections | all (no pagination) | — | + +### When Pagination Would Matter + +If any of these grow beyond 50 items, scripts that use these endpoints would +silently miss results. For this migration (3 repos, handful of runners), this +is not a concern. If extending to N repos where N > 50, add `?limit=N` or +implement `Link` header following.