Skip to content

Commit

Permalink
feat: log & confirm plugins (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
gr2m authored Feb 26, 2021
1 parent d1c3868 commit 2c3e847
Show file tree
Hide file tree
Showing 6 changed files with 1,119 additions and 34 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ Positionals:
all repositories the user has access to [default: []]
Options:
--help Show help [boolean]
--version Show version number [boolean]
--octoherd-token Requires the "public_repo" scope for public repositories,
"repo" scope for private repositories. [string] [required]
--octoherd-cache Cache responses for debugging [boolean] [default: false]
--octoherd-debug Show debug logs [boolean] [default: false]
--help Show help [boolean]
--version Show version number [boolean]
--octoherd-token Requires the "public_repo" scope for public
repositories, "repo" scope for private
repositories. [string] [required]
--octoherd-cache Cache responses for debugging. Creates a ./cache
folder if flag is set. Override by passing custom
path [string]
--octoherd-debug Show debug logs [boolean] [default: false]
--octoherd-bypass-confirms Bypass prompts to confirm mutating requests
[boolean] [default: false]
```

The `script` must export a `script` function which takes three parameters:
Expand Down
25 changes: 22 additions & 3 deletions bin/octoherd.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#!/usr/bin/env node

import yargs from "yargs";
import { VERSION as OctokitVersion } from "@octoherd/octokit";
import chalk from "chalk";

import { octoherd } from "../index.js";
import { VERSION } from "../version.js";

const argv = yargs
.usage("Usage: $0 [options] [script] [repos...]")
Expand All @@ -28,19 +31,35 @@ const argv = yargs
type: "string",
})
.option("octoherd-cache", {
description: "Cache responses for debugging",
type: "boolean",
default: false,
description:
"Cache responses for debugging. Creates a ./cache folder if flag is set. Override by passing custom path",
type: "string",
})
.option("octoherd-debug", {
description: "Show debug logs",
type: "boolean",
default: false,
})
.option("octoherd-bypass-confirms", {
description: "Bypass prompts to confirm mutating requests",
type: "boolean",
default: false,
})
.epilog("copyright 2020").argv;

const { _, $0, script, repos, ...options } = argv;

console.log(
`\n${chalk.bold("Running @octoherd/cli v%s")} ${chalk.gray(
"(@octoherd/octokit v%s, Node.js: %s, %s %s)"
)}\n`,
VERSION,
OctokitVersion,
process.version,
process.platform,
process.arch
);

octoherd({ ...options, octoherdScript: script, octoherdRepos: repos }).catch(
(error) => {
console.error(error);
Expand Down
54 changes: 40 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import chalk from "chalk";
import tempy from "tempy";

import { cache as octokitCachePlugin } from "./lib/octokit-plugin-cache.js";
import { requestLog } from "./lib/octokit-plugin-request-log.js";
import { requestConfirm } from "./lib/octokit-plugin-request-confirm.js";
import { resolveRepositories } from "./lib/resolve-repositories.js";
import { VERSION } from "./version.js";

Expand Down Expand Up @@ -37,23 +39,36 @@ export async function octoherd(
octoherdDebug,
octoherdScript,
octoherdRepos,
octoherdBypassConfirms,
...userOptions
} = options;

const tmpLogFile = tempy.file({ extension: "ndjson.log" });

const CliOctokit = octoherdCache
? Octokit.plugin(octokitCachePlugin)
: Octokit;
const plugins = [requestLog, requestConfirm];
if (typeof octoherdCache === "string") plugins.push(octokitCachePlugin);
const CliOctokit = Octokit.plugin(...plugins);

const octokit = new CliOctokit({
auth: octoherdToken,
userAgent: ["octoherd-cli", VERSION].join("/"),
octoherd: {
debug: octoherdDebug,
cache: octoherdCache,
bypassConfirms: octoherdBypassConfirms,
onLogMessage(level, message, additionalData) {
// ignore the `octoherd` property in meta data
const { octoherd, ...meta } = additionalData;
let additionalDataString = JSON.stringify(meta);

if (additionalDataString.length > 300) {
additionalDataString = additionalDataString.slice(0, 295) + " … }";
}

console.log(
levelColor[level](" " + level.toUpperCase() + " "),
Object.keys(additionalData).length
? `${message} ${chalk.gray(JSON.stringify(additionalData))}`
Object.keys(meta).length
? `${message} ${chalk.gray(additionalDataString)}`
: message
);
},
Expand All @@ -78,7 +93,7 @@ export async function octoherd(
throw new Error(`[octoherd] no "script" exported at ${path}`);
}

if (octoherdCache.length === 0) {
if (octoherdRepos.length === 0) {
throw new Error("[octoherd] No repositories provided");
}

Expand All @@ -93,22 +108,33 @@ export async function octoherd(

for (const repository of repositories) {
octokit.log.info(
{ octoherd: true },
"Running %s on %s...",
octoherdScript,
repository.full_name
);
await userScript(octokit, repository, userOptions);
}

console.log("");
console.log(levelColor.info(" DONE "), `Log file written to ${tmpLogFile}`);
try {
await userScript(octokit, repository, userOptions);
} catch (error) {
if (!error.cancel) throw error;
octokit.log.debug(error.message);
}
}
} catch (error) {
octokit.log.error(error);
console.log("");
process.exitCode = 1;
}

console.log("");
console.log(chalk.gray("-".repeat(80)));
console.log("");
console.log(`Log file written to ${tmpLogFile}`);

if ("octoherdCache" in options) {
console.log(
levelColor.error(" DONE "),
`Log file written to ${tmpLogFile}`
"Request cache written to %s",
options.octoherdCache || "./cache"
);
process.exit(1);
}
}
10 changes: 7 additions & 3 deletions lib/octokit-plugin-cache.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { URL } from "url";
import { dirname } from "path";
import { dirname, join } from "path";

import mkdirp from "mkdirp";
import jsonfile from "jsonfile";

export function cache(octokit) {
export function cache(octokit, { octoherd: { cache } }) {
octokit.hook.wrap("request", async (request, options) => {
if (options.method !== "GET") {
return request(options);
Expand All @@ -14,7 +14,11 @@ export function cache(octokit) {

const { pathname, searchParams } = new URL(url);
const page = searchParams.get("page");
const cachePath = `./cache${pathname}${page ? `-page-${page}` : ""}.json`;
const basePath = cache || "./cache";
const cachePath = join(
basePath,
`${pathname}${page ? `-page-${page}` : ""}.json`
);

try {
return jsonfile.readFileSync(cachePath);
Expand Down
Loading

0 comments on commit 2c3e847

Please sign in to comment.