Skip to content

feat: Issues & Wiki Backup (M1.5)#4

Open
paladini wants to merge 5 commits into
mainfrom
feat/issues-wiki-backup
Open

feat: Issues & Wiki Backup (M1.5)#4
paladini wants to merge 5 commits into
mainfrom
feat/issues-wiki-backup

Conversation

@paladini

Copy link
Copy Markdown
Owner

Summary

  • Wiki backup: clones each repo's .wiki.git and pushes to GitLab wiki via git push --mirror. Repos without a wiki are skipped silently. Fully idempotent.
  • Issue migration: copies GitHub Issues (open + closed) to GitLab with labels, milestones, and comments. Idempotency via <!-- github-issue-id: N --> marker embedded in each issue body.
  • Both features are opt-in (backup_wiki: false / backup_issues: false by default in config.yaml). Existing configs without these fields continue to work unchanged.

Changes

File Change
src/models.py Add IssueData, CommentData, LabelData, MilestoneData, IssueMigratorResult, RunSummary
src/config.py Read backup_wiki and backup_issues from config with False defaults
src/github_client.py Add list_issues, list_labels, list_milestones, list_issue_comments, get_wiki_ssh_url
src/gitlab_client.py Add get_project_id, get_wiki_ssh_url, list_issues_markers, create_label, create_milestone, close_milestone, create_issue, close_issue, add_issue_comment, list_labels, list_milestones
src/issue_migrator.py New — IssueMigrator orchestrates label sync → milestone sync → issue migration with comments
src/backup_runner.py Add _backup_wiki(), _migrate_issues(); run() returns RunSummary
backup.py Instantiate IssueMigrator, print extended report (Repos / Wikis / Issues)
config.example.yaml Document backup_wiki and backup_issues with limitations note
README.md Add Wiki & Issue Backup section, update Features list and Roadmap
.specs/features/issues-wiki-backup/ Full spec, design, and task breakdown

Known limitations (documented in README and config)

  • Issue timestamps cannot be preserved (GitLab API requires admin token)
  • Issue authors cannot be preserved (same reason); original author/date recorded in body
  • Pull Requests are not migrated (incompatible semantics with GitLab MRs)

Test plan

  • python backup.py --dry-run with backup_wiki: false / backup_issues: false → output identical to pre-PR behaviour (no new sections)
  • python backup.py --dry-run with backup_wiki: true / backup_issues: true → shows Wiki and Issues dry-run lines per repo
  • python backup.py --filter "test-*" with both enabled → wikis appear in GitLab, issues appear with attribution header and idempotency marker
  • Re-run → Issues shows N already migrated, 0 created; wiki push is a no-op

🤖 Generated with Claude Code

paladini and others added 5 commits June 20, 2026 08:21
Adds full spec, design, and task breakdown for the issues-wiki-backup
feature: wiki git clone/push and GitHub Issues → GitLab migration with
labels, milestones, comments, and idempotency via github-issue-id markers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds IssueData, CommentData, LabelData, MilestoneData, IssueMigratorResult
dataclasses to support Issues & Wiki backup (M1.5).

Adds backup_wiki and backup_issues bool fields to Config (default: false,
read from config.yaml backup section, retrocompatible with existing configs).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GithubClient: add get_wiki_ssh_url, list_labels, list_milestones,
list_issue_comments, list_issues (filters PRs, paginates via PyGithub,
reuses existing rate-limit retry).

GitlabClient: add get_project_id, get_wiki_ssh_url, list_issues_markers,
list_labels, create_label, list_milestones, create_milestone, close_milestone,
create_issue, close_issue, add_issue_comment (all routed through _call for
HTTP 429 retry).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Syncs labels and milestones before migrating issues. Idempotency via
<!-- github-issue-id: N --> marker — existing GitLab issues are scanned
once per repo and skipped. Migrates comments in chronological order.
Individual issue failures are caught and counted without aborting the repo.
dry_run returns counts without creating anything.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BackupRunner.run() now returns RunSummary (repos + wikis + issues).
_backup_wiki() clones/pushes repo.wiki.git; GitOpsError treated as skip
(no wiki). _migrate_issues() delegates to IssueMigrator; skips if GitLab
project not found with a clear warning.

backup.py instantiates IssueMigrator when backup_issues=true, prints
extended report with Repos/Wikis/Issues sections, exits 1 on any errors
including issue migration failures.

config.example.yaml and README updated with backup_wiki/backup_issues
options and documented limitations (timestamps, authors, PRs).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant