Files
holocron/docs/notes/onedev-migration-plan.md
Defame1297 a3453c5d6f docs(adr): supersede ADR-0007, plan OneDev migration
This repo's own hosting, issue tracking, and pull requests move from Gitea
to OneDev (ADR-0029), keeping the Gitea repo as a read-only archive rather
than deleting it. plugins/gitea is unaffected — it continues to ship as a
marketplace product regardless of what this repo hosts itself on.

Records the full execution plan (prerequisites, mirror/issue/PR/release
phases, verification checklist) and updates CONTEXT.md's Issue entry and
AGENTS.md's source-of-truth line to name OneDev instead of Gitea.

ADR: 0029
Refs: ADR-0007
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GGCPJBXPLJP5FprL4C8nu3
2026-09-22 19:24:48 +00:00

7.8 KiB

Gitea → OneDev migration plan

Executes ADR-0029 (supersedes ADR-0007). Scope: this repo's own self-hosting only — git history, issues, milestones, wiki (already mirrored), and this repo's own tooling config. plugins/gitea/ ships unchanged as a marketplace product. Historical PR objects and Gitea's exact issue/PR numbering are explicitly not migrated (see ADR-0029's "Considered and rejected").

Source: Defame1297/holocron on git.dev.rkdr.net. Target: Holocron (project id 1, currently empty) on onedev.dev.rkdr.net.

Prerequisites

  • tod installed and configured — ~/.config/tod/config already has server-url and access-token; ~/.bashrc sources ~/.config/tod/env automatically (set -a; . env; set +a), but non-interactive shells (scripts, CI, this tool) must source it explicitly per invocation.
  • OneDev project Holocron exists (tod project get Holocron), codeManagement / issueManagement enabled, currently no defaultBranch (empty repo).
  • Gotcha to build scripts around: tod issue/tod pr subcommands resolve their target project from the working directory's git remote, not from --project (verified — --project is accepted by the flag parser but ignored; commands fail outside a repo with a OneDev remote). Every migration script step below must run from inside a local clone with a remote pointing at onedev.dev.rkdr.net/Holocron.
  • Create the 7 OneDev Iterations (milestone equivalent) manually via the OneDev web UI — tod has no iteration-create command. Names, verbatim, to match Gitea milestones for clean --iteration references on migrated issues: Governance: enforcement, Kyberforge basics, Legacy / Triage, Road to homelab - prep, Skills & Agents, The great refactoring, Tooling.
  • Freeze Gitea: stop merging PRs there once Phase 1 starts. Solo-maintainer repo, so this is just "don't push to git.dev.rkdr.net after the mirror point."

Phase 1 — Mirror git history (lossless, zero risk)

  1. git remote add onedev https://onedev.dev.rkdr.net/Holocron in the local clone.
  2. git push onedev refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* (explicit branch+tag push, not --mirror — avoids touching any Gitea-internal refs that aren't real branches).
  3. Verify: tod project get Holocron shows defaultBranch populated; HEAD of main on OneDev matches Gitea main HEAD (d654dca... as of this plan).
  4. This alone carries every commit, author, message, and merge losslessly — nothing else in this plan is required for code-level fidelity.

Phase 2 — Issues (~95 total: 81 closed + 14 open across 7 milestones, per Gitea milestone counts)

Field mapping (OneDev's out-of-the-box Type/Priority fields, no new labels created):

Gitea label OneDev field
Kind/Bug Type: Bug
Kind/Feature Type: New Feature
Kind/Enhancement Type: Improvement
Kind/Documentation, Kind/Testing Type: Task
Kind/Security Type: Bug
Priority/Critical Priority: Critical
Priority/High Priority: Major
Priority/Medium Priority: Normal
Priority/Low Priority: Minor
Reviewed/*, Status/*, Compat/Breaking no field/state equivalent — fold into a one-line note in the migrated body

State mapping: Gitea open → OneDev Open (default, no action); Gitea closed → tod issue change-state <ref> Closed. OneDev's out-of-the-box workflow only has Open/In Progress/Closed — no disposition states, confirmed by probing the live server.

Per issue: 5. tod issue create "<title>" --field Type=<mapped> --field Priority=<mapped> --iteration "<milestone>" --description "<body>\n\n---\nMigrated from git.dev.rkdr.net/Defame1297/holocron/issues/<N>.[\nGitea disposition: <label>.]" 6. Replay comments via tod issue add-comment (low effort, worth doing for continuity). 7. tod issue change-state <new-ref> Closed for originally-closed issues. 8. Spot-check a sample (e.g. 5 issues across different milestones) against the Gitea source.

Numbers will not match Gitea's (accepted — ADR-0029). Author/submitter on migrated issues will be the migration token's own OneDev account, not the original Gitea author — no CLI-exposed way to override this (the onBehalfOf field exists in OneDev's issue schema but isn't exposed through tod; using it would mean raw, unverified REST calls, not worth it for this scope).

Phase 3 — Pull requests

  • Currently-open PRs only (check at execution time: list_pull_requests state=open): migrate for real via tod pr create, since the source branch still exists. Add description, reviewers.
  • Closed/merged historical PRs (~140 of them): explicitly skipped. Per ADR-0029, their content survives losslessly in the Phase 1 git mirror; the archived Gitea instance remains the record for anyone who wants the original review thread.

Phase 4 — Releases

Git tags (v1.0.0, v2.0.0, v2.0.1) carry over automatically in Phase 1. OneDev has no confirmed first-class "Release" object with a rendered markdown body the way Gitea does — this needs a quick check against the live server before deciding further (not yet verified in this session). Fallback if none exists: leave the 3 release-note bodies in the archived Gitea (read-only) and optionally fold them into a CHANGELOG.md in the repo for local discoverability. Flag this to the user before executing Phase 4 — not fully resolved.

Phase 5 — Wiki

Nothing to do. docs/wiki/HUMANS.md and docs/wiki/Home.md already mirror the two Gitea wiki pages in-repo (confirmed identical), and OneDev has no separate wiki feature to migrate into (confirmed: no wiki flag on the project object, no wiki REST resource). They travel with Phase 1 automatically.

Phase 6 — Repo self-reference updates (code changes)

  1. Repoint the six first-party apm.yml plugin dependencies (git, gitea, kyberforge, lint, core, bin) from git@git.dev.rkdr.net:Defame1297/holocron.git to the OneDev remote.
  2. Update AGENTS.md's routing table (currently: "Issues, PRs, labels, milestones → gitea-issues, gitea-prs, gitea-labels-milestones...") to route this repo's own issue/PR operations to the OneDev/tod skills instead (using-tod as the catch-all, plus work-on-issue, work-on-pull-request, submit-issue-work, submit-pull-request-work). This needs a deliberate mapping pass, not a mechanical find-replace — the tod skillset is workflow-shaped, not CRUD-shaped like the gitea skills it replaces.
  3. Update local origin remote to point at OneDev; rename the old one (e.g. git remote rename origin gitea-archive) rather than deleting it.
  4. Run apm install against the repointed remote and verify it resolves cleanly.
  5. Sweep README.md and any other doc prose that names Gitea as this repo's own host (separate from plugins/gitea/'s own product documentation, which is unaffected).

Phase 7 — Freeze and archive Gitea

  1. Set the Gitea repository to read-only/archived via the Gitea web UI (no MCP tool exposes this — manual step).

Verification checklist

  • tod project get Holocron → defaultBranch: main, HEAD SHA matches Gitea's main.
  • Issue count on OneDev matches Gitea's ~95 (open + closed).
  • apm install succeeds from a fresh clone against the new remote.
  • Pre-commit hooks (pre-commit run --all-files) pass in a fresh OneDev clone.
  • Gitea repo is read-only; a test push to it fails as expected.

Explicitly out of scope (deferred, per earlier decisions)

  • .onedev-buildspec.yml / CI setup — no Gitea Actions exist today to migrate; separate follow-up task via the edit-build-spec skill.
  • Sunsetting plugins/gitea/ as a marketplace product — agreed as a later phase, not part of this migration.