|
require('dotenv').config(); |
|
require('node:http'); |
|
const moment = require('moment'); |
|
|
|
const githubBase = process.env.GITHUB_BASE; |
|
const githubOrg = process.env.GITHUB_ORG; |
|
const repos = `${githubBase}/orgs/${githubOrg}/repos`; |
|
let projects = []; |
|
|
|
const ghInit = { headers: { 'Authorization': `Bearer ${process.env.GITHUB_AUTH_TOKEN}` } }; |
|
|
|
let P = []; |
|
|
|
|
|
P.push(Promise.all([...P]).then(async () => { |
|
let resp = await fetch(repos, ghInit); |
|
let nextPage, nextHref; |
|
let [pageLink, rateUse, rateRemain, rateLimit, rateReset] = [ |
|
resp.headers.get('link'), |
|
resp.headers.get('x-ratelimit-used'), |
|
resp.headers.get('x-ratelimit-remaining'), |
|
resp.headers.get('x-ratelimit-limit'), |
|
resp.headers.get('x-ratelimit-reset') |
|
]; |
|
console.debug(`GitHub API Rate Limit Usage: ${rateUse}/${rateLimit} Used (${rateRemain} Remain) - Resets ${moment.unix(rateReset).fromNow()}`); |
|
if (rateRemain < 50) { |
|
console.warn('Critical Rate Limit Reached -- Stopping Operation'); |
|
return; |
|
} |
|
let links = pageLink ? pageLink.split(',').map(link => { |
|
let [href, rel] = link.split(";").map(_ => _.trim()); |
|
return { href, rel } |
|
}) : []; |
|
[nextPage] = links.filter(_ => _.rel === 'rel="next"').map(_ => _.href.match(/page=(\d+)/)[1]); |
|
[nextHref] = links.filter(_ => _.rel === 'rel="next"').map(_ => _.href.match(/<(.*)>/)[1]); |
|
let json, new_proj; |
|
do { |
|
json = await resp.json(); |
|
new_proj = json.filter(_filter1).map(_map1); |
|
projects.push(...new_proj); |
|
// Fetch next page |
|
if (!nextHref) |
|
break; |
|
resp = await fetch(nextHref, ghInit); |
|
[pageLink] = [ |
|
resp.headers.get('link') |
|
]; |
|
links = pageLink ? pageLink.split(',').map(link => { |
|
let [href, rel] = link.split(";").map(_ => _.trim()) |
|
return { href, rel } |
|
}) : []; |
|
[nextPage] = links.filter(_ => _.rel === 'rel="next"').map(_ => _.href.match(/page=(\d+)/)[1]); |
|
[nextHref] = links.filter(_ => _.rel === 'rel="next"').map(_ => _.href.match(/<(.*)>/)[1]); |
|
} while (nextHref); |
|
})); |
|
|
|
P.push(Promise.all([...P]).then(async () => { |
|
const orgName = process.env.GITEA_ORG; |
|
const isOrg = await fetch(_gitea(`/orgs/${orgName}`)); |
|
let newOrg; |
|
if (!isOrg.ok) { |
|
newOrg = await fetch(_post('/orgs', { username: orgName, visibility: 'public', repo_admin_change_team_access: true })); |
|
} |
|
})); |
|
|
|
P.push(Promise.all([...P]).then(async () => { |
|
const orgName = process.env.GITEA_ORG; |
|
for (const p of projects) { |
|
const repoName = p.name; |
|
const cloneUrl = p.clone_url; |
|
const isPrivate = !!p.private; |
|
const isRepo = await fetch(_gitea(`/repos/${orgName}/${repoName}`)); |
|
let newRepo; |
|
if (isRepo.ok) { |
|
console.log(`Repo [${repoName}] found!`); |
|
} else { |
|
console.log(`Repo [${repoName}] not found...`); |
|
const postReq = _post('/repos/migrate', { |
|
clone_addr: cloneUrl, |
|
service: 'github', |
|
auth_token: process.env.GITHUB_AUTH_TOKEN, |
|
lfs: true, |
|
mirror: true, |
|
private: isPrivate, |
|
repo_owner: orgName, |
|
repo_name: repoName |
|
}); |
|
newRepo = await Promise.resolve(fetch(postReq).catch(()=>{})); |
|
console.log(`${repoName}: ${newRepo.status} ${newRepo.statusText}`); |
|
} |
|
} |
|
})); |
|
|
|
function _filter1(_) { |
|
const isPublic = _.visibility === 'public'; |
|
const nameMatch = _.name.match(process.env.NAME_FILTER ?? '') != null; |
|
return isPublic && nameMatch; |
|
} |
|
function _map1(_) { return ({ name: _.name, clone_url: _.clone_url, private: _.private }) } |
|
function _gitea(path) { return `${process.env.GITEA_BASE}/api/v1${path}?token=${process.env.GITEA_API_KEY}` } |
|
function _headers(h) { |
|
let headers = new Headers(); |
|
headers.append('accept', 'application/vnd.github+json'); |
|
headers.append('user-agent', |
|
`node-fetch/1.0 (Node.js ${process.version}; ${process.release.name}; ${process.platform}; ${process.arch})` + |
|
` node/${process.versions.node} v8/${process.versions.v8}` + |
|
` openssl/${process.versions.openssl}`) |
|
Object.entries(h).forEach(hh => headers.append(...hh)); |
|
return headers; |
|
} |
|
function _post(path, body) { |
|
return new Request(_gitea(path), |
|
{ |
|
method: 'POST', |
|
headers: _headers({ |
|
'Content-Type': 'application/json' |
|
}), |
|
body: JSON.stringify(body) |
|
} |
|
); |
|
} |
|
|
|
Promise.all([...P]).then(() => { |
|
console.log("All done!"); |
|
}); |