Something went wrong. Try again.
Mirror your GitHub repos to GitLab & Tangled — staged Node.js GitHub Actions with parallel jobs, retries, and description sync.
Something went wrong. Try again.
1.8 kB · 57 lines
JavaScript
at master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758// Lists every repo you own (includes forks + archived) and emits the backup matrix.import { appendFileSync } from "node:fs";
const { GH_USER, GH_TOKEN, MAX_BATCHES, GITHUB_OUTPUT } = process.env;if (!GH_USER || !GH_TOKEN) { console.error("Missing GH_USER or GH_TOKEN"); process.exit(1);}
const GH_API = "https://api.github.com";
async function gh(path, query = {}) { const url = new URL(GH_API + path); Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v)); const res = await fetch(url, { headers: { Authorization: `token ${GH_TOKEN}`, "User-Agent": "mirror-discover", Accept: "application/vnd.github+json", }, }); if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); return res.json();}
(async () => { const per_page = 100; let page = 1, repos = []; for (;;) { const list = await gh("/user/repos", { affiliation: "owner", per_page, page, sort: "full_name", direction: "asc", }); if (list.length === 0) break; for (const r of list) { if (r.owner?.login !== GH_USER) continue; repos.push({ name: r.name, description: r.description, homepage: r.homepage }); } if (list.length < per_page) break; page++; }
const batchCount = Math.max(1, Math.min(Number(MAX_BATCHES) || 25, repos.length)); const outputs = { repos: JSON.stringify(repos), batches: JSON.stringify(Array.from({ length: batchCount }, (_, i) => i)), batch_count: String(batchCount), repo_count: String(repos.length), };
const rendered = Object.entries(outputs).map(([k, v]) => `${k}=${v}`).join("\n"); if (GITHUB_OUTPUT) appendFileSync(GITHUB_OUTPUT, `${rendered}\n`); console.log(`${repos.length} repos across ${batchCount} batches`);})().catch(e => { console.error(e); process.exit(1); });