Created
January 31, 2019 01:42
-
-
Save bencord0/fab3b913ffc35cd61f70121f9f25c0f6 to your computer and use it in GitHub Desktop.
Write everything in node with async
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 characters
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); | |
}); |
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 characters
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