Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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