Skip to content

Commit 45b127a

Browse files
authored
feat: octoherd run, use --octoherd-* flags for script and repos (#24)
BREAKING CHANGE: `octoherd` can no longer be run without a command. Use `octoherd run` instead BREAKING CHANGE: the script and repos arguments are now flags. Instead of ``` octoherd --octoherd-token $TOKEN script.js octoherd/octoherd ``` do ``` octoherd run --octoherd-token $TOKEN --octoherd-script script.js --octoherd-repos octoherd/octoherd ``` or use the shortcut aliases ``` octoherd run -T $TOKEN -S script.js -R octoherd/octoherd ```
1 parent 9fdeb96 commit 45b127a

File tree

7 files changed

+8648
-154
lines changed

7 files changed

+8648
-154
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
## Usage
66

77
```
8-
$ octoherd.js [script] [repos...]
8+
Usage: octoherd run [options] [script] [repos...]
99
1010
Positionals:
1111
script Path to *.js script. Must be an ES Module.
1212
repos One or multiple arrays in the form of 'repo-owner/repo-name'.
1313
'repo-owner/*' will find all repositories for one owner. '*' will find
14-
all repositories the user has access to [default: []]
14+
all repositories the user has access to [array] [default: []]
1515
1616
Options:
1717
--help Show help [boolean]
@@ -25,6 +25,9 @@ Options:
2525
--octoherd-debug Show debug logs [boolean] [default: false]
2626
--octoherd-bypass-confirms Bypass prompts to confirm mutating requests
2727
[boolean] [default: false]
28+
29+
Examples:
30+
octoherd run --octoherd-token $TOKEN path/to/script.js octoherd/cli
2831
```
2932

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

bin/cli-options.js

Lines changed: 0 additions & 23 deletions
This file was deleted.

bin/commands/run.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { resolve } from "path";
2+
3+
import chalk from "chalk";
4+
import { VERSION as OctokitVersion } from "@octoherd/octokit";
5+
6+
import { VERSION } from "../../version.js";
7+
8+
const VERSIONS = `
9+
@octoherd/cli: v${VERSION}
10+
@octoherd/octokit: v${OctokitVersion}
11+
Node.js: ${process.version}, ${process.platform} ${process.arch}`.trim();
12+
13+
/** @type { {[key: string]: import("yargs").Options} } */
14+
const options = {
15+
"octoherd-token": {
16+
description:
17+
'Requires the "public_repo" scope for public repositories, "repo" scope for private repositories.',
18+
demandOption: true,
19+
type: "string",
20+
alias: "T",
21+
},
22+
"octoherd-script": {
23+
description: "Path to *.js script. Must be an ES Module.",
24+
demandOption: true,
25+
type: "string",
26+
alias: "S",
27+
},
28+
"octoherd-repos": {
29+
description:
30+
"One or multiple repositories in the form of 'repo-owner/repo-name'. 'repo-owner/*' will find all repositories for one owner. '*' will find all repositories the user has access to",
31+
type: "string",
32+
array: true,
33+
demandOption: true,
34+
alias: "R",
35+
},
36+
"octoherd-cache": {
37+
description:
38+
"Cache responses for debugging. Creates a ./cache folder if flag is set. Override by passing custom path",
39+
type: "string",
40+
},
41+
"octoherd-debug": {
42+
description: "Show debug logs",
43+
type: "boolean",
44+
default: false,
45+
},
46+
"octoherd-bypass-confirms": {
47+
description: "Bypass prompts to confirm mutating requests",
48+
type: "boolean",
49+
default: false,
50+
},
51+
};
52+
53+
/** @type import('yargs').CommandModule */
54+
const runCommand = {
55+
command: "run",
56+
describe: "",
57+
builder: (yargs) =>
58+
yargs
59+
.usage("Usage: $0 run [options]")
60+
.example("$0 run -T $TOKEN -S path/to/script.js -R octoherd/cli", "")
61+
.options(options)
62+
.version(VERSIONS)
63+
.coerce("octoherd-script", async (script) => {
64+
if (!script) return;
65+
66+
if (typeof script === "function") return script;
67+
68+
let scriptModule;
69+
const path = resolve(process.cwd(), script);
70+
71+
try {
72+
scriptModule = await import(path);
73+
} catch (error) {
74+
throw new Error(
75+
`[octoherd] ${path} does not exist or is not an ES Module`
76+
);
77+
}
78+
79+
if (!scriptModule.script) {
80+
throw new Error(`[octoherd] no "script" exported at ${path}`);
81+
}
82+
83+
return scriptModule.script;
84+
}),
85+
handler: () => {
86+
console.log(
87+
`\n${chalk.bold("Running @octoherd/cli v%s")} ${chalk.gray(
88+
"(@octoherd/octokit v%s, Node.js: %s, %s %s)"
89+
)}\n`,
90+
VERSION,
91+
OctokitVersion,
92+
process.version,
93+
process.platform,
94+
process.arch
95+
);
96+
},
97+
};
98+
99+
export default runCommand;

bin/octoherd.js

Lines changed: 14 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,67 +2,27 @@
22

33
import yargs from "yargs";
44
import { hideBin } from "yargs/helpers";
5-
import { resolve } from "path";
6-
import { VERSION as OctokitVersion } from "@octoherd/octokit";
5+
76
import chalk from "chalk";
87

98
import { octoherd } from "../index.js";
109
import { VERSION } from "../version.js";
11-
import { cliOptions } from "./cli-options.js";
12-
13-
const argv = yargs(hideBin(process.argv))
14-
.usage("Usage: $0 [options] [script] [repos...]")
15-
.example(
16-
"$0 --token 0123456789012345678901234567890123456789 octokit/rest.js"
17-
)
18-
.command("$0 [script] [repos...]", "", (yargs) => {
19-
yargs.positional("script", {
20-
demandOption: true,
21-
describe: "Path to *.js script. Must be an ES Module.",
22-
});
23-
yargs.positional("repos", {
24-
demandOption: true,
25-
describe:
26-
"One or multiple arrays in the form of 'repo-owner/repo-name'. 'repo-owner/*' will find all repositories for one owner. '*' will find all repositories the user has access to",
27-
default: [],
28-
});
29-
})
30-
.options(cliOptions)
31-
.version(VERSION)
32-
.epilog(`copyright 2020-${new Date().getFullYear()}`).argv;
33-
34-
const { _, $0, script, repos, ...options } = argv;
35-
36-
console.log(
37-
`\n${chalk.bold("Running @octoherd/cli v%s")} ${chalk.gray(
38-
"(@octoherd/octokit v%s, Node.js: %s, %s %s)"
39-
)}`,
40-
VERSION,
41-
OctokitVersion,
42-
process.version,
43-
process.platform,
44-
process.arch
45-
);
10+
import runCommand from "./commands/run.js";
4611

47-
let octoherdScript;
48-
const path = resolve(process.cwd(), script);
12+
const EPILOG = chalk.gray(`Questions? Ideas? Feedback?
13+
https://github.com/octoherd/octoherd/discussions
14+
15+
Copyright 2020-${new Date().getFullYear()} Octoherd Contributors`);
4916

50-
console.log("Loading script at %s\n", script);
17+
const argv = await yargs(hideBin(process.argv))
18+
.command(runCommand)
19+
.demandCommand()
20+
.version(VERSION)
21+
.epilog(EPILOG).argv;
5122

5223
try {
53-
octoherdScript = (await import(path)).script;
24+
await octoherd(argv);
5425
} catch (error) {
55-
console.error(error.stack);
56-
throw new Error(`[octoherd] ${script} script could not be found`);
57-
}
58-
59-
if (!octoherdScript) {
60-
throw new Error(`[octoherd] no "script" exported at ${path}`);
26+
console.error(error);
27+
process.exit(1);
6128
}
62-
63-
octoherd({ ...options, octoherdScript, octoherdRepos: repos }).catch(
64-
(error) => {
65-
console.error(error);
66-
process.exit(1);
67-
}
68-
);

bin/run.js

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
import yargs from "yargs";
22
import { hideBin } from "yargs/helpers";
33

4-
import { VERSION as OctokitVersion } from "@octoherd/octokit";
5-
import chalk from "chalk";
6-
74
import { octoherd } from "../index.js";
8-
import { VERSION } from "../version.js";
9-
import { cliOptions } from "./cli-options.js";
5+
import runCommand from "./commands/run.js";
106

117
/**
128
* Function is used by Octoherd Script modules to provide a dedicated CLI binary
@@ -17,41 +13,15 @@ import { cliOptions } from "./cli-options.js";
1713
*
1814
* @param {function} script Octoherd Script function
1915
*/
20-
export function run(script) {
21-
const argv = yargs(hideBin(process.argv))
22-
.usage("Usage: $0 [options] [repos...]")
23-
.example(
24-
"$0 --token 0123456789012345678901234567890123456789 octokit/rest.js"
25-
)
26-
.command("$0 [repos...]", "", (yargs) => {
27-
yargs.positional("repos", {
28-
demandOption: true,
29-
describe:
30-
"One or multiple arrays in the form of 'repo-owner/repo-name'. 'repo-owner/*' will find all repositories for one owner. '*' will find all repositories the user has access to",
31-
default: [],
32-
});
33-
})
34-
.options(cliOptions)
35-
.version(VERSION)
36-
.epilog(`copyright 2020-${new Date().getFullYear()}`).argv;
37-
38-
const { _, $0, repos, ...options } = argv;
39-
40-
console.log(
41-
`\n${chalk.bold("Running @octoherd/cli v%s")} ${chalk.gray(
42-
"(@octoherd/octokit v%s, Node.js: %s, %s %s)"
43-
)}\n`,
44-
VERSION,
45-
OctokitVersion,
46-
process.version,
47-
process.platform,
48-
process.arch
49-
);
16+
export async function run(script) {
17+
const argv = await yargs(["run", ...hideBin(process.argv)])
18+
.command(runCommand)
19+
.default("octoherd-script", () => script).argv;
5020

51-
octoherd({ ...options, octoherdScript: script, octoherdRepos: repos }).catch(
52-
(error) => {
53-
console.error(error);
54-
process.exit(1);
55-
}
56-
);
21+
try {
22+
await octoherd(argv);
23+
} catch (error) {
24+
console.error(error);
25+
process.exit(1);
26+
}
5727
}

0 commit comments

Comments
 (0)