Created
September 3, 2024 15:47
-
-
Save qoomon/1138485cddf23aea7a23ec14a5d1ee3e to your computer and use it in GitHub Desktop.
Revisions
-
qoomon renamed this gist
Sep 3, 2024 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
qoomon renamed this gist
Sep 3, 2024 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
qoomon created this gist
Sep 3, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,86 @@ import {Octokit} from 'octokit'; import * as process from 'node:process' import YAML from 'yaml'; const metaDataPath = '.github/metadata.yaml'; const input = { token: process.env.GITHUB_TOKEN ?? _throw(new Error('environment variable GITHUB_TOKEN is required')), owner: process.env.GITHUB_OWNER ?? _throw(new Error('environment variable GITHUB_OWNER is required')), } const githubClient = new Octokit({auth: input.token}); const summary = { repositories: 0, metaData: 0, errors: 0, missing: 0 } await forEachOrgRepository(githubClient, async ({owner, repo}, index) => { console.log(`repo ${index.toString().padStart(4)}: ${owner}/${repo}`); const metaData = await getRepositoryMetaData(githubClient, {owner, repo}) .then((metaData) => { if (metaData) summary.metaData++; else summary.missing++; return metaData; }) .catch((error) => { summary.errors++; console.error("ERROR", error); return null; }) .then((metaData) => { summary.repositories++; return metaData; }); if (metaData) { console.log(JSON.stringify({ repository: `${owner}/${repo}`, metaData, }, null, 2)); } }) console.log('summary:', JSON.stringify(summary, null, 2)); // --- functions ------------------------------------------------------------------------------------------------------- export function _throw(error: unknown): never { throw error } async function forEachOrgRepository( octokit: Octokit, callback: ({owner, repo}: { owner: string, repo: string }, index: number) => Promise<void>): Promise<void> { let index = 0; const iterator = octokit.paginate.iterator(octokit.rest.repos.listForOrg, { org: input.owner, per_page: 100 }); for await (const {data: repos} of iterator) { await Promise.all(repos.map(async (repo) => callback({owner: repo.owner.login, repo: repo.name}, index++))); } } async function getRepositoryFileContent(octokit: Octokit, {owner, repo, path}: { owner: string, repo: string, path: string, }): Promise<string | null> { return octokit.rest.repos.getContent({owner, repo, path}) .then((res) => { if ('type' in res.data && res.data.type === 'file') { return Buffer.from(res.data.content, 'base64').toString(); } throw new Error('Unexpected file content'); }) .catch((error) => { if (error.status === 404) return null; throw error; }); } async function getRepositoryMetaData(octokit: Octokit, {owner, repo}: { owner: string, repo: string }) { return getRepositoryFileContent(octokit, {owner, repo, path: metaDataPath}) .then((content) => YAML.parse(content ?? '')) }