Skip to content

Instantly share code, notes, and snippets.

@smeijer
Created February 6, 2024 17:43
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smeijer/2d29f29f5663103a74879d60f7a59b06 to your computer and use it in GitHub Desktop.
Save smeijer/2d29f29f5663103a74879d60f7a59b06 to your computer and use it in GitHub Desktop.
sync github repositories
#! /usr/bin/env node
import fs from 'fs';
import { promisify } from 'util';
import path from 'path';
import { spawn } from 'child_process';
const fsExists = promisify(fs.exists);
if (!process.env.GITHUB_TOKEN) throw new Error("process.env.GITHUB_TOKEN is required");
if (!process.env.GITHUB_USER) throw new Error("process.env.GITHUB_USER is required");
async function* fetchRepositoriesForUser(user) {
let page = 1;
let perPage = 50;
while (true) {
const url = `https://api.github.com/users/${user}/repos?per_page=${perPage}&page=${page}`;
const response = await fetch(url, {
headers: {
'Authorization': `token ${process.env.GITHUB_TOKEN}`
}
});
if (!response.ok) {
throw new Error(`GitHub API responded with a status of ${response.status}`);
}
const result = await response.json();
for (const repo of result) {
yield repo;
}
if (result.length < perPage) return;
page++;
}
};
function git(command, cwd) {
return new Promise((resolve, reject) => {
const gitProcess = spawn('git', command, { cwd, stdio: 'inherit' });
gitProcess.on('close', (code) => {
if (code === 0) {
resolve(code);
} else {
reject(new Error(`git command exited with code ${code}`));
}
});
});
}
async function syncRepository(repo) {
const targetDirectory = path.join(process.cwd(), repo.full_name);
const exists = await fsExists(targetDirectory);
if (!exists) {
await git(['clone', repo.ssh_url, targetDirectory], process.cwd());
} else {
await git(['pull'], targetDirectory);
}
};
for await (const repo of fetchRepositoriesForUser(process.env.GITHUB_USER)) {
console.log(`Sync ${repo.full_name}`)
await syncRepository(repo);
}
@smeijer
Copy link
Author

smeijer commented Feb 6, 2024

GitHub shouldn't be the only place where we keep our repositories. This script will download all your github repos, and keep the in sync. Run with node after setting the GITHUB_TOKEN and GITHUB_USER environment variables. Ideally, you'd add it to a cronjob.

@miguelbemartin
Copy link

How do you install the dependencies for an script like this one?

@smeijer
Copy link
Author

smeijer commented Mar 26, 2024

Only node native modules are used, so it doesn't require an install.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment