Skip to content

Commit 2c3e847

Browse files
authored
feat: log & confirm plugins (#13)
1 parent d1c3868 commit 2c3e847

File tree

6 files changed

+1119
-34
lines changed

6 files changed

+1119
-34
lines changed

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@ Positionals:
1616
all repositories the user has access to [default: []]
1717
1818
Options:
19-
--help Show help [boolean]
20-
--version Show version number [boolean]
21-
--octoherd-token Requires the "public_repo" scope for public repositories,
22-
"repo" scope for private repositories. [string] [required]
23-
--octoherd-cache Cache responses for debugging [boolean] [default: false]
24-
--octoherd-debug Show debug logs [boolean] [default: false]
19+
--help Show help [boolean]
20+
--version Show version number [boolean]
21+
--octoherd-token Requires the "public_repo" scope for public
22+
repositories, "repo" scope for private
23+
repositories. [string] [required]
24+
--octoherd-cache Cache responses for debugging. Creates a ./cache
25+
folder if flag is set. Override by passing custom
26+
path [string]
27+
--octoherd-debug Show debug logs [boolean] [default: false]
28+
--octoherd-bypass-confirms Bypass prompts to confirm mutating requests
29+
[boolean] [default: false]
2530
```
2631

2732
The `script` must export a `script` function which takes three parameters:

bin/octoherd.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#!/usr/bin/env node
22

33
import yargs from "yargs";
4+
import { VERSION as OctokitVersion } from "@octoherd/octokit";
5+
import chalk from "chalk";
46

57
import { octoherd } from "../index.js";
8+
import { VERSION } from "../version.js";
69

710
const argv = yargs
811
.usage("Usage: $0 [options] [script] [repos...]")
@@ -28,19 +31,35 @@ const argv = yargs
2831
type: "string",
2932
})
3033
.option("octoherd-cache", {
31-
description: "Cache responses for debugging",
32-
type: "boolean",
33-
default: false,
34+
description:
35+
"Cache responses for debugging. Creates a ./cache folder if flag is set. Override by passing custom path",
36+
type: "string",
3437
})
3538
.option("octoherd-debug", {
3639
description: "Show debug logs",
3740
type: "boolean",
3841
default: false,
3942
})
43+
.option("octoherd-bypass-confirms", {
44+
description: "Bypass prompts to confirm mutating requests",
45+
type: "boolean",
46+
default: false,
47+
})
4048
.epilog("copyright 2020").argv;
4149

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

52+
console.log(
53+
`\n${chalk.bold("Running @octoherd/cli v%s")} ${chalk.gray(
54+
"(@octoherd/octokit v%s, Node.js: %s, %s %s)"
55+
)}\n`,
56+
VERSION,
57+
OctokitVersion,
58+
process.version,
59+
process.platform,
60+
process.arch
61+
);
62+
4463
octoherd({ ...options, octoherdScript: script, octoherdRepos: repos }).catch(
4564
(error) => {
4665
console.error(error);

index.js

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import chalk from "chalk";
66
import tempy from "tempy";
77

88
import { cache as octokitCachePlugin } from "./lib/octokit-plugin-cache.js";
9+
import { requestLog } from "./lib/octokit-plugin-request-log.js";
10+
import { requestConfirm } from "./lib/octokit-plugin-request-confirm.js";
911
import { resolveRepositories } from "./lib/resolve-repositories.js";
1012
import { VERSION } from "./version.js";
1113

@@ -37,23 +39,36 @@ export async function octoherd(
3739
octoherdDebug,
3840
octoherdScript,
3941
octoherdRepos,
42+
octoherdBypassConfirms,
4043
...userOptions
4144
} = options;
45+
4246
const tmpLogFile = tempy.file({ extension: "ndjson.log" });
4347

44-
const CliOctokit = octoherdCache
45-
? Octokit.plugin(octokitCachePlugin)
46-
: Octokit;
48+
const plugins = [requestLog, requestConfirm];
49+
if (typeof octoherdCache === "string") plugins.push(octokitCachePlugin);
50+
const CliOctokit = Octokit.plugin(...plugins);
51+
4752
const octokit = new CliOctokit({
4853
auth: octoherdToken,
4954
userAgent: ["octoherd-cli", VERSION].join("/"),
5055
octoherd: {
5156
debug: octoherdDebug,
57+
cache: octoherdCache,
58+
bypassConfirms: octoherdBypassConfirms,
5259
onLogMessage(level, message, additionalData) {
60+
// ignore the `octoherd` property in meta data
61+
const { octoherd, ...meta } = additionalData;
62+
let additionalDataString = JSON.stringify(meta);
63+
64+
if (additionalDataString.length > 300) {
65+
additionalDataString = additionalDataString.slice(0, 295) + " … }";
66+
}
67+
5368
console.log(
5469
levelColor[level](" " + level.toUpperCase() + " "),
55-
Object.keys(additionalData).length
56-
? `${message} ${chalk.gray(JSON.stringify(additionalData))}`
70+
Object.keys(meta).length
71+
? `${message} ${chalk.gray(additionalDataString)}`
5772
: message
5873
);
5974
},
@@ -78,7 +93,7 @@ export async function octoherd(
7893
throw new Error(`[octoherd] no "script" exported at ${path}`);
7994
}
8095

81-
if (octoherdCache.length === 0) {
96+
if (octoherdRepos.length === 0) {
8297
throw new Error("[octoherd] No repositories provided");
8398
}
8499

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

94109
for (const repository of repositories) {
95110
octokit.log.info(
111+
{ octoherd: true },
96112
"Running %s on %s...",
97113
octoherdScript,
98114
repository.full_name
99115
);
100-
await userScript(octokit, repository, userOptions);
101-
}
102116

103-
console.log("");
104-
console.log(levelColor.info(" DONE "), `Log file written to ${tmpLogFile}`);
117+
try {
118+
await userScript(octokit, repository, userOptions);
119+
} catch (error) {
120+
if (!error.cancel) throw error;
121+
octokit.log.debug(error.message);
122+
}
123+
}
105124
} catch (error) {
106125
octokit.log.error(error);
107-
console.log("");
126+
process.exitCode = 1;
127+
}
128+
129+
console.log("");
130+
console.log(chalk.gray("-".repeat(80)));
131+
console.log("");
132+
console.log(`Log file written to ${tmpLogFile}`);
133+
134+
if ("octoherdCache" in options) {
108135
console.log(
109-
levelColor.error(" DONE "),
110-
`Log file written to ${tmpLogFile}`
136+
"Request cache written to %s",
137+
options.octoherdCache || "./cache"
111138
);
112-
process.exit(1);
113139
}
114140
}

lib/octokit-plugin-cache.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { URL } from "url";
2-
import { dirname } from "path";
2+
import { dirname, join } from "path";
33

44
import mkdirp from "mkdirp";
55
import jsonfile from "jsonfile";
66

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

1515
const { pathname, searchParams } = new URL(url);
1616
const page = searchParams.get("page");
17-
const cachePath = `./cache${pathname}${page ? `-page-${page}` : ""}.json`;
17+
const basePath = cache || "./cache";
18+
const cachePath = join(
19+
basePath,
20+
`${pathname}${page ? `-page-${page}` : ""}.json`
21+
);
1822

1923
try {
2024
return jsonfile.readFileSync(cachePath);

0 commit comments

Comments
 (0)