Skip to content

Commit a7d3312

Browse files
authored
feat: add webhook handler for worlddriven-migrate app (#329)
Implement the backend support for a separate GitHub App that handles repository transfers to the worlddriven organization. Changes: - Add /api/webhooks/migrate endpoint for the migrate app - Add migrationHandler.js with transfer logic: - findApprovedMigrationPR: checks for approved PRs in documentation repo - transferRepository: calls GitHub transfer API - triggerPRChecks: re-runs CI after successful transfer - Add getInstallationAccessToken to githubApp.js for multi-app support - Update .env-example with migrate app credentials The migrate app uses a separate minimal permission set (administration only) to enable transfers without requiring elevated permissions on the main worlddriven app. Flow: 1. User installs worlddriven-migrate app on their repo 2. Webhook triggers, checks for approved migration PR 3. If approved, transfers repo to worlddriven org 4. Comments on PR and triggers CI re-run Relates to worlddriven/documentation#23
1 parent a36e795 commit a7d3312

4 files changed

Lines changed: 522 additions & 2 deletions

File tree

.env-example

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
export GITHUB_CLIENT_ID=
22
export GITHUB_CLIENT_SECRET=
3-
export SESSION_SECRET=
3+
export SESSION_SECRET=
4+
5+
# Main worlddriven GitHub App
6+
export GITHUB_APP_ID=
7+
export GITHUB_APP_PRIVATE_KEY=
8+
9+
# Worlddriven Migrate GitHub App (for repository transfers)
10+
export MIGRATE_APP_ID=
11+
export MIGRATE_APP_PRIVATE_KEY=
12+
13+
# Token for worlddrivenbot user (used for documentation repo operations)
14+
export WORLDDRIVEN_GITHUB_TOKEN=

src/helpers/githubApp.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,33 @@ export async function getInstallationOctokit(installationId) {
2222
});
2323
}
2424

25+
/**
26+
* Get installation access token for a specific GitHub App
27+
* Used for apps other than the main worlddriven app (e.g., migrate app)
28+
* @param {number} installationId - Installation ID
29+
* @param {string} appId - GitHub App ID
30+
* @param {string} privateKey - GitHub App private key
31+
* @returns {string} Installation access token
32+
*/
33+
export async function getInstallationAccessToken(
34+
installationId,
35+
appId,
36+
privateKey
37+
) {
38+
if (!appId || !privateKey) {
39+
throw new Error('App ID and private key are required');
40+
}
41+
42+
const auth = createAppAuth({
43+
appId,
44+
privateKey,
45+
installationId: parseInt(installationId),
46+
});
47+
48+
const { token } = await auth({ type: 'installation' });
49+
return token;
50+
}
51+
2552
// GitHub App API functions
2653
export async function getPullRequestsApp(installationId, owner, repo) {
2754
const octokit = await getInstallationOctokit(installationId);

0 commit comments

Comments
 (0)