diff --git a/REPOSITORIES.md b/REPOSITORIES.md index 30b82cc..3f50109 100644 --- a/REPOSITORIES.md +++ b/REPOSITORIES.md @@ -34,6 +34,7 @@ Each repository is defined using markdown headers and properties: - **Repository Name**: Markdown heading level 2 (`##`) - **Description** (required): Brief description of the repository's purpose - **Topics** (optional): Comma-separated list of repository topics for discoverability +- **Origin** (optional, not yet implemented): Source repository for migration (e.g., `owner/repo-name`) ## Example @@ -47,6 +48,25 @@ Each repository is defined using markdown headers and properties: - Topics: documentation, organization-management, governance ``` +## Repository Migration (Coming Soon) + +🚧 **Feature in development** - Repository transfer automation is not yet implemented. + +The `Origin` field will enable migrating repositories from "powered by worlddriven" to "worlddriven project": + +- **Powered by worlddriven**: Repository stays under owner's control, uses worlddriven for PR automation +- **Worlddriven project**: Repository lives in worlddriven org with full democratic governance + +**Planned workflow** (not yet functional): +1. Origin repository owner grants admin permissions to worlddriven org +2. Add repository to REPOSITORIES.md with `Origin: owner/repo-name` +3. Drift detection verifies permissions +4. On merge, repository automatically transfers to worlddriven org +5. Standard democratic configurations applied + +**Current status**: Parser supports Origin field, transfer logic pending implementation. +Track progress in the GitHub issue for repository migration feature. + --- ## Current Repositories diff --git a/scripts/detect-drift.js b/scripts/detect-drift.js index 0adafb1..bb64089 100755 --- a/scripts/detect-drift.js +++ b/scripts/detect-drift.js @@ -29,6 +29,7 @@ function detectDrift(desiredRepos, actualRepos) { extra: [], // In GitHub but not in REPOSITORIES.md descriptionDiff: [], // Description mismatch topicsDiff: [], // Topics mismatch + pendingTransfer: [], // Repositories with origin field (not yet implemented) }; // Create lookup maps @@ -39,6 +40,12 @@ function detectDrift(desiredRepos, actualRepos) { for (const desired of desiredRepos) { const actual = actualMap.get(desired.name); + // Check for origin field (repository transfer - not yet implemented) + if (desired.origin) { + drift.pendingTransfer.push(desired); + continue; // Skip other checks for transfer repos + } + if (!actual) { drift.missing.push(desired); } else { @@ -86,7 +93,8 @@ function formatDriftReport(drift, desiredCount, actualCount) { const hasDrift = drift.missing.length > 0 || drift.extra.length > 0 || drift.descriptionDiff.length > 0 || - drift.topicsDiff.length > 0; + drift.topicsDiff.length > 0 || + drift.pendingTransfer.length > 0; if (!hasDrift) { lines.push('āœ… **No drift detected** - REPOSITORIES.md matches GitHub organization state'); @@ -96,6 +104,21 @@ function formatDriftReport(drift, desiredCount, actualCount) { lines.push('āš ļø **Drift detected** - Differences found between REPOSITORIES.md and GitHub'); lines.push(''); + // Pending transfers (not yet implemented) + if (drift.pendingTransfer.length > 0) { + lines.push(`## 🚧 Repository Transfer Pending (${drift.pendingTransfer.length})`); + lines.push(''); + lines.push('āš ļø **FEATURE NOT YET IMPLEMENTED** - These repositories have an `Origin` field for migration:'); + lines.push(''); + for (const repo of drift.pendingTransfer) { + lines.push(`- **${repo.name}** ← \`${repo.origin}\``); + lines.push(` - Description: ${repo.description}`); + lines.push(` - **Action required**: Repository transfer automation is not yet implemented`); + lines.push(` - See issue for implementation progress and manual transfer instructions`); + } + lines.push(''); + } + // Missing repositories if (drift.missing.length > 0) { lines.push(`## šŸ“ Missing in GitHub (${drift.missing.length})`); @@ -173,11 +196,18 @@ async function main() { console.log(report); // Exit with error code if drift detected (useful for CI) + // Note: pendingTransfer is informational, not an error const hasDrift = drift.missing.length > 0 || drift.extra.length > 0 || drift.descriptionDiff.length > 0 || drift.topicsDiff.length > 0; + // Warn about pending transfers + if (drift.pendingTransfer.length > 0) { + console.error('\nāš ļø Warning: Repository transfer feature is not yet implemented'); + console.error(' PRs with Origin field cannot be merged until implementation is complete'); + } + process.exit(hasDrift ? 1 : 0); } catch (error) { console.error(`āŒ Error: ${error.message}`); diff --git a/scripts/parse-repositories.js b/scripts/parse-repositories.js index cf1f242..e3450d3 100755 --- a/scripts/parse-repositories.js +++ b/scripts/parse-repositories.js @@ -15,7 +15,7 @@ const __dirname = dirname(__filename); /** * Parse markdown content and extract repository definitions * @param {string} content - Markdown content - * @returns {Array<{name: string, description: string, topics?: string[]}>} + * @returns {Array<{name: string, description: string, topics?: string[], origin?: string}>} */ function parseRepositories(content) { const repositories = []; @@ -67,6 +67,8 @@ function parseRepositories(content) { currentRepo.description = value.trim(); } else if (keyLower === 'topics') { currentRepo.topics = value.split(',').map(t => t.trim()).filter(Boolean); + } else if (keyLower === 'origin') { + currentRepo.origin = value.trim(); } } } diff --git a/scripts/parse-repositories.test.js b/scripts/parse-repositories.test.js index c366d60..095e57c 100644 --- a/scripts/parse-repositories.test.js +++ b/scripts/parse-repositories.test.js @@ -185,6 +185,41 @@ Here's an example: assert.strictEqual(result[0].topics, undefined); }); + test('should parse repository with origin field for migration', () => { + const content = ` +## core +- Description: Democratic governance system for GitHub pull requests +- Topics: democracy, open-source, governance +- Origin: TooAngel/worlddriven +`; + const result = parseRepositories(content); + assert.deepStrictEqual(result, [ + { + name: 'core', + description: 'Democratic governance system for GitHub pull requests', + topics: ['democracy', 'open-source', 'governance'], + origin: 'TooAngel/worlddriven' + } + ]); + }); + + test('should parse multiple repositories with and without origin', () => { + const content = ` +## documentation +- Description: Core documentation repository +- Topics: documentation, worlddriven + +## core +- Description: Democratic governance system +- Topics: governance +- Origin: TooAngel/worlddriven +`; + const result = parseRepositories(content); + assert.strictEqual(result.length, 2); + assert.strictEqual(result[0].origin, undefined); + assert.strictEqual(result[1].origin, 'TooAngel/worlddriven'); + }); + test('should match actual REPOSITORIES.md structure', () => { const content = `# Worlddriven Organization Repositories diff --git a/scripts/sync-repositories.js b/scripts/sync-repositories.js index c61e32f..c8b5a87 100755 --- a/scripts/sync-repositories.js +++ b/scripts/sync-repositories.js @@ -663,6 +663,19 @@ async function main() { console.error('šŸ” Detecting drift...'); const drift = detectDrift(desiredRepos, actualRepos); + // Check for pending transfers (not yet implemented) + if (drift.pendingTransfer && drift.pendingTransfer.length > 0) { + console.error(''); + console.error('🚧 WARNING: Repository transfer feature not yet implemented'); + console.error(` Found ${drift.pendingTransfer.length} repository(ies) with Origin field:`); + for (const repo of drift.pendingTransfer) { + console.error(` - ${repo.name} ← ${repo.origin}`); + } + console.error(' These repositories will be SKIPPED until transfer feature is implemented'); + console.error(' See GitHub issue for implementation progress'); + console.error(''); + } + // Generate sync plan console.error('šŸ“‹ Generating sync plan...'); const plan = generateSyncPlan(drift, desiredRepos);