--- name: gitea-transfer description: Guide for transferring repositories from GitHub to self-hosted Gitea, including remotes, branches, PR migration, Gitea Actions porting, runner images, and cutover verification. --- # Gitea Transfer Use when moving a repository from GitHub to self-hosted Gitea, converting a Gitea mirror into the canonical source, migrating active branches/PRs, or porting GitHub Actions to Gitea Actions. ## Principles - Treat Gitea as canonical only after verifying the repo is no longer a mirror and the default branch exists there. - Keep GitHub as a recovery/reference remote unless the user explicitly asks to remove it. - Prefer `tea` or the Gitea API for Gitea operations; do not use `gh` for Gitea work. - Never paste, log, commit, or store registration tokens, API tokens, deploy keys, or package credentials. - Do not merge PRs, force-push, or rewrite shared branches unless the user explicitly approves. - Verify each cutover step with `git`, `tea`, or API output before moving on. ## Preflight ```bash git status --short --branch git remote -v git branch --show-current tea login list tea repo ls tea api repos/{owner}/{repo} ``` If Gitea sits behind a reverse proxy, ensure dot directories such as `.gitea` and `.github` are not blocked by generic hidden-file rules. ## Mirror To Source If the Gitea repo was imported as a mirror, convert it to a normal source repo in the UI or API, then verify `mirror` is `false`: ```bash tea api repos/{owner}/{repo} ``` Enable repository features as needed, using fields supported by the installed Gitea version: ```bash tea api --method PATCH repos/{owner}/{repo} \ --field has_pull_requests=true \ --field has_actions=true ``` ## Remote Cutover Keep GitHub as fallback and make Gitea `origin`: ```bash git remote rename origin github git remote add origin ssh://git@git.example.com:30009/{owner}/{repo}.git git remote -v git fetch github --prune git push origin {default-branch}:{default-branch} tea api repos/{owner}/{repo}/branches/{default-branch} ``` If `origin` already exists, adjust non-destructively with `git remote set-url origin ...` and add `github` only if absent. ## Branches And PRs - Push only active work branches, not every stale remote branch by default. - For each open GitHub PR, recreate enough context in Gitea: title, body, base, head, draft/WIP state, and original GitHub PR link. - Verify each recreated PR is open, points at the expected branches, and has the expected conflict state. ```bash git branch -r git push origin github/{branch-name}:refs/heads/{branch-name} tea pr create --repo {owner}/{repo} --base {base} --head {head} --title "{title}" --description "{body}" tea pr {index} --repo {owner}/{repo} ``` ## Actions Porting Gitea Actions workflows live in `.gitea/workflows/`. Port incrementally: tests first, then build/deploy. Keep syntax close to GitHub Actions where Gitea supports it, validate YAML, and use small commits so failures isolate one change. Common changes: - Replace GitHub-only secrets with neutral Gitea secrets such as `REGISTRY_USERNAME`, `REGISTRY_TOKEN`, `REVIEW_BOT_TOKEN`, and `OPENCODE_GO_TOKEN`. - Avoid secret names beginning with `GITEA_` or `GITHUB_`. - Remove GitHub Packages auth unless it is still intentionally used. - Use service hostnames such as `postgres`, not `127.0.0.1`, for service containers. - Add explicit service readiness checks. - Do not rely on `permissions:` for security-sensitive sandboxing; some Gitea versions ignore it. See [runner images](references/runner-images.md), [OpenCode PR review](references/opencode-review.md), and [deploy porting](references/deploy-porting.md) for deeper CI guidance. ## Package Registry Cutover Identify GitHub-specific package auth before enabling Gitea CI: npm/Bun scopes, Composer auth, workflow-written `.npmrc`, private package tarballs in lockfiles, and deploy/package secrets. Choose deliberately: remove dependency, mirror package to Gitea Packages, or keep GitHub Packages temporarily with explicit Gitea secrets. Do not leave workflows requiring missing secrets. ## Verification Checklist - Gitea repo is not a mirror. - `origin` points to Gitea; `github` remote exists if retained. - Default branch and active PR branches are pushed. - Open PRs are recreated. - Pull requests and Actions are enabled. - Test workflow passes on PR and default branch. - Deploy workflow succeeds or skips cleanly with a clear missing-secrets message. - Runner is online with generic labels and job containers pull expected images. - Optional `/review` workflow posts or updates the aggregate review comment. - Local default branch is synchronized with Gitea. ```bash git pull --rebase origin {default-branch} git push origin {default-branch} git rev-list --left-right --count origin/{default-branch}...{default-branch} git status --short --branch ``` Expected commit comparison after sync: `0 0`. See [failure modes](references/failure-modes.md) when cutover or CI fails.