Skip to content

feat: GitHub App-based repository migration (supersedes #9) #23

@TooAngel

Description

@TooAngel

Summary

Issue #9 proposed a migration workflow where repository owners grant admin permission to worlddrivenbot, enabling automated transfers. This approach doesn't work for personal repositories.

Problem Discovery

During testing with TooAngel/worlddriven-migration-test, we discovered a fundamental GitHub limitation:

Personal Repository Permission Levels

According to GitHub documentation:

A repository owned by a personal account has two permission levels: the repository owner and collaborators.

Collaborators can only receive write access - there is no way to grant admin access to a collaborator on a personal repository. The GitHub UI doesn't even show an option to change permission levels for collaborators on personal repos.

Why This Breaks the Original Plan

  • Transfer API (POST /repos/{owner}/{repo}/transfer) requires admin permission
  • Personal repos can only grant write to collaborators
  • Therefore: worlddrivenbot can never transfer a personal repository

This affects the majority of potential migrations, since most repositories that would join worlddriven are personal repos.

New Solution: GitHub App with Administration Permission

GitHub Apps can request Administration permission, which grants the ability to transfer repositories where the app is installed.

How It Works

  1. Create a new GitHub App: worlddriven-migrate
  2. App requests only: administration: write and metadata: read
  3. User installs the app on their repository (one click)
  4. App installation grants admin-equivalent access
  5. App can then transfer the repository via API

Why a Separate App?

The main worlddriven app should stay minimal to encourage adoption. Users might hesitate to install an app with Administration permission for regular PR voting. A separate migration app:

  • Has minimal permissions (only what's needed for transfer)
  • Is clearly labeled as one-time use
  • Keeps the main app trustworthy

Proposed Migration Flow

┌─────────────────────────────────────────────────────────────────┐
│  1. User creates PR adding repo to REPOSITORIES.md             │
│     with Origin: owner/repo field                              │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│  2. Community votes on PR (worlddriven voting system)          │
│     Drift detection fails (expected - repo not in org yet)     │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│  3. PR reaches approval threshold                              │
│     Bot comments: "Please install worlddriven-migrate app"     │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│  4. User installs worlddriven-migrate on their repo            │
│     (grants Administration permission via app installation)    │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│  5. App webhook triggers, verifies approved PR exists          │
│     Transfers repo to worlddriven org via API                  │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│  6. App comments on PR, triggers CI re-run                     │
│     Drift detection passes, PR auto-merges                     │
└─────────────────────────────────────────────────────────────────┘

Implementation Tasks

1. Create GitHub App (manual, one-time)

  • Create worlddriven-migrate app in worlddriven org
  • Set permissions: administration: write, metadata: read
  • Subscribe to event: installation_repositories
  • Set webhook URL: https://www.worlddriven.org/api/webhooks/migrate
  • Store credentials securely

2. Backend Implementation (worlddriven-core)

  • Add webhook endpoint /api/webhooks/migrate
  • Implement findApprovedMigrationPR(repoFullName) - find PR in documentation repo
  • Implement transferRepository(repoFullName, installationId) - call transfer API
  • Implement triggerPRChecks(prNumber) - re-run CI after transfer
  • Add environment variables for migrate app credentials

3. Documentation Updates

  • Update REPOSITORIES.md with new migration instructions
  • Create or update MIGRATION.md guide
  • Document the two-app architecture

Technical Details

GitHub App Transfer API

With Administration permission, the app can call:

POST /repos/{owner}/{repo}/transfer
Authorization: Bearer <installation-token>

{
  "new_owner": "worlddriven"
}

Reference: Permissions required for GitHub Apps confirms POST /repos/{owner}/{repo}/transfer requires administration: write.

Webhook Payload

When app is installed on a repo, GitHub sends installation_repositories event:

{
  "action": "added",
  "installation": { "id": 12345 },
  "repositories_added": [
    { "full_name": "owner/repo" }
  ]
}

Open Questions

  1. What defines "approved"? - Voting threshold reached? Has approving reviews? Time-based?
  2. Should we verify PR author = repo owner? - Prevent adding someone else's repo
  3. Auto-uninstall after transfer? - Clean up or leave to user?
  4. Fallback for org-owned repos? - They CAN grant admin to collaborators, support both paths?

References

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions