Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions REPOSITORIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
32 changes: 31 additions & 1 deletion scripts/detect-drift.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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');
Expand All @@ -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})`);
Expand Down Expand Up @@ -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}`);
Expand Down
4 changes: 3 additions & 1 deletion scripts/parse-repositories.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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();
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions scripts/parse-repositories.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
13 changes: 13 additions & 0 deletions scripts/sync-repositories.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down