Skip to content

Instantly share code, notes, and snippets.

@bencord0
Created January 31, 2019 01:42
Show Gist options
  • Save bencord0/fab3b913ffc35cd61f70121f9f25c0f6 to your computer and use it in GitHub Desktop.
Save bencord0/fab3b913ffc35cd61f70121f9f25c0f6 to your computer and use it in GitHub Desktop.
Write everything in node with async
const fs = require("fs").promises; // nodejs 10.x
const { b64decode, getGithubClient } = require("./utils");
// If API clients need some async setup, create a placeholder for them.
let octokit = undefined;
async function main() {
// Fill in placeholders first
octokit = await getGithubClient();
// Trigger all the things
const stuff = await doStuff();
// Resolve all promises and save the names of the templates
let doneStuff = await Promise.all(stuff);
console.log(`=== Done ${doneStuff.length} stuff ===`);
}
async function doStuff() {
// Array of promises; as each completes, the stuff has been done
let stuff = [];
// For everything that we process, add it to the stuff Array.
// This uses a 3rd party client, notice how it could be initialised
let response = await octokit.repos.getContents({
owner: "bencord0",
repo: "blog",
path: "src"
});
let dirs = response.data.forEach(dentry => {
stuff.push(processDentry(dentry.name));
});
// These promises are still "in-flight" and will need to be `await`ed
return stuff;
}
async function processDentry(name) {
try {
const content = await ...;
} catch (err) {
// Only need to catch errors we want to explicitly handle here
// let everything else propagate to the top-level, including unresolved promises.
...
}
}
// When debugging this script, report errors quickly
// and stop creating further github API requests to protect your API limits.
// This way, we only need a try/catch block for errors we know how
// to handle, then let everything else to propagate to main.
process.on("unhandledRejection", err => {
console.error(err);
console.error(err.stack);
process.exit(1);
});
main().catch(err => {
console.error(err);
process.exit(1);
});
const octokit = require("@octokit/rest");
const JWT = require('jsonwebtoken');
// The github API base64 encodes user content in API responses
// To get the "real" content, we need to decode them.
function b64decode(b64) {
return Buffer.from(b64, "base64").toString();
}
// https://medium.com/happo-io/posting-statuses-as-a-github-app-using-node-js-9f71e9cdbb9e
function generateJwtToken() {
return JWT.sign(
{
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 60,
iss: process.env.GITHUB_APPLICATION_ID,
},
b64decode(process.env.GITHUB_PRIVATE_KEY),
{ algorithm: 'RS256' },
);
}
async function getGithubClient() {
// An unauthenticated client
const client = octokit();
// An authenticated client for a GitHub application,
// does not yet have access to the full API.
client.authenticate({
type: 'app',
token: generateJwtToken(),
});
// Swap the JWT for a (short lived) oauth token specific to an Installed instance of this app.
const { data: { token } } = await client.apps.createInstallationToken({
installation_id: process.env.GITHUB_INSTALLATION_ID,
});
client.authenticate({
type: 'token',
token
});
// A client with full API access (depending on scopes)
return client;
}
module.exports = {
b64decode,
getGithubClient,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment