|
| 1 | +#!/usr/bin/env node |
| 2 | +// examples/advanced/check-org-repos.js |
| 3 | + |
| 4 | +/** |
| 5 | + * Example: Check Organization Repositories |
| 6 | + * |
| 7 | + * This script demonstrates how to evaluate all repositories |
| 8 | + * in a GitHub organization for contributor readiness. |
| 9 | + */ |
| 10 | + |
| 11 | +const { exec } = require('child_process'); |
| 12 | +const util = require('util'); |
| 13 | +const fs = require('fs').promises; |
| 14 | +const path = require('path'); |
| 15 | + |
| 16 | +const execPromise = util.promisify(exec); |
| 17 | + |
| 18 | +class OrganizationEvaluator { |
| 19 | + constructor(githubToken) { |
| 20 | + this.githubToken = githubToken; |
| 21 | + this.results = []; |
| 22 | + } |
| 23 | + |
| 24 | + async getOrganizationRepos(orgName) { |
| 25 | + try { |
| 26 | + console.log(`🔍 Fetching repositories for organization: ${orgName}`); |
| 27 | + |
| 28 | + // Use GitHub API to get organization repositories |
| 29 | + const command = `curl -H "Authorization: token ${this.githubToken}" "https://api.github.com/orgs/${orgName}/repos?per_page=100"`; |
| 30 | + const { stdout } = await execPromise(command); |
| 31 | + |
| 32 | + const repos = JSON.parse(stdout); |
| 33 | + return repos.map(repo => `${repo.owner.login}/${repo.name}`); |
| 34 | + } catch (error) { |
| 35 | + console.error(`❌ Error fetching organization repos:`, error.message); |
| 36 | + return []; |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + async evaluateRepository(owner, repo) { |
| 41 | + try { |
| 42 | + console.log(`📊 Evaluating ${owner}/${repo}...`); |
| 43 | + |
| 44 | + const command = this.githubToken |
| 45 | + ? `node ../../dist/index.js evaluate ${owner}/${repo} --token ${this.githubToken}` |
| 46 | + : `node ../../dist/index.js evaluate ${owner}/${repo}`; |
| 47 | + |
| 48 | + const { stdout } = await execPromise(command); |
| 49 | + |
| 50 | + // Parse the output to extract score information |
| 51 | + const scoreMatch = stdout.match(/Score: (\d+)%/); |
| 52 | + const ratingMatch = stdout.match(/Rating: (\w+)/); |
| 53 | + |
| 54 | + const result = { |
| 55 | + repository: `${owner}/${repo}`, |
| 56 | + score: scoreMatch ? parseInt(scoreMatch[1]) : 0, |
| 57 | + rating: ratingMatch ? ratingMatch[1] : 'Unknown', |
| 58 | + timestamp: new Date().toISOString() |
| 59 | + }; |
| 60 | + |
| 61 | + this.results.push(result); |
| 62 | + console.log(` Score: ${result.score}% (${result.rating})`); |
| 63 | + |
| 64 | + return result; |
| 65 | + } catch (error) { |
| 66 | + console.error(`❌ Error evaluating ${owner}/${repo}:`, error.message); |
| 67 | + return null; |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + async evaluateOrganization(orgName) { |
| 72 | + console.log(`🏢 Evaluating Organization: ${orgName}\n`); |
| 73 | + |
| 74 | + const repositories = await this.getOrganizationRepos(orgName); |
| 75 | + |
| 76 | + if (repositories.length === 0) { |
| 77 | + console.log('No repositories found for this organization'); |
| 78 | + return; |
| 79 | + } |
| 80 | + |
| 81 | + console.log(`Found ${repositories.length} repositories to evaluate\n`); |
| 82 | + |
| 83 | + for (const repo of repositories) { |
| 84 | + const [owner, name] = repo.split('/'); |
| 85 | + await this.evaluateRepository(owner, name); |
| 86 | + |
| 87 | + // Respect rate limits |
| 88 | + await new Promise(resolve => setTimeout(resolve, 1000)); |
| 89 | + } |
| 90 | + |
| 91 | + this.generateOrganizationReport(orgName); |
| 92 | + await this.exportOrganizationResults(orgName); |
| 93 | + } |
| 94 | + |
| 95 | + generateOrganizationReport(orgName) { |
| 96 | + if (this.results.length === 0) return; |
| 97 | + |
| 98 | + console.log(`\n📊 Organization Report: ${orgName}`); |
| 99 | + console.log('='.repeat(60)); |
| 100 | + |
| 101 | + const avgScore = this.results.reduce((sum, r) => sum + r.score, 0) / this.results.length; |
| 102 | + const ratingCounts = this.results.reduce((counts, r) => { |
| 103 | + counts[r.rating] = (counts[r.rating] || 0) + 1; |
| 104 | + return counts; |
| 105 | + }, {}); |
| 106 | + |
| 107 | + // Sort by score |
| 108 | + const sortedResults = this.results.sort((a, b) => b.score - a.score); |
| 109 | + |
| 110 | + console.log(`Total Repositories: ${this.results.length}`); |
| 111 | + console.log(`Average Score: ${avgScore.toFixed(1)}%`); |
| 112 | + console.log(`Rating Distribution:`, ratingCounts); |
| 113 | + |
| 114 | + console.log('\nTop Performing Repositories:'); |
| 115 | + sortedResults.slice(0, 5).forEach((result, index) => { |
| 116 | + console.log(` ${index + 1}. ${result.repository} - ${result.score}% (${result.rating})`); |
| 117 | + }); |
| 118 | + |
| 119 | + console.log('\nRepositories Needing Attention:'); |
| 120 | + sortedResults.slice(-5).reverse().forEach((result, index) => { |
| 121 | + console.log(` ${index + 1}. ${result.repository} - ${result.score}% (${result.rating})`); |
| 122 | + }); |
| 123 | + } |
| 124 | + |
| 125 | + async exportOrganizationResults(orgName) { |
| 126 | + const outputPath = path.join(__dirname, '..', 'data', `${orgName}-evaluation.json`); |
| 127 | + await fs.writeFile(outputPath, JSON.stringify(this.results, null, 2)); |
| 128 | + console.log(`\n📄 Organization results exported to ${outputPath}`); |
| 129 | + } |
| 130 | +} |
| 131 | + |
| 132 | +// Example usage |
| 133 | +async function main() { |
| 134 | + const orgName = process.argv[2]; |
| 135 | + const token = process.env.GITHUB_TOKEN; |
| 136 | + |
| 137 | + if (!orgName) { |
| 138 | + console.error('Please provide organization name: node check-org-repos.js <org-name>'); |
| 139 | + process.exit(1); |
| 140 | + } |
| 141 | + |
| 142 | + if (!token) { |
| 143 | + console.error('Please set GITHUB_TOKEN environment variable'); |
| 144 | + process.exit(1); |
| 145 | + } |
| 146 | + |
| 147 | + const evaluator = new OrganizationEvaluator(token); |
| 148 | + await evaluator.evaluateOrganization(orgName); |
| 149 | +} |
| 150 | + |
| 151 | +if (require.main === module) { |
| 152 | + main().catch(console.error); |
| 153 | +} |
| 154 | + |
| 155 | +module.exports = { OrganizationEvaluator }; |
0 commit comments