Skip to content

Commit 341f32e

Browse files
0x2b3bfa0casperdcldacbd
authored
Introduce subcommands in a backwards-compatible way (#1073)
Co-authored-by: Casper da Costa-Luis <casper.dcl@physics.org> Co-authored-by: Daniel Barnes <dabarnes2b@gmail.com>
1 parent 4ade9a5 commit 341f32e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1462
-1398
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
node_modules/
2-
runner/
32
.terraform/
43
.cml/
54
.DS_Store

bin/cml.js

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ const setupOpts = (opts) => {
2828
if (process.env[oldName]) process.env[newName] = process.env[oldName];
2929
}
3030

31+
const legacyEnvironmentPrefixes = {
32+
CML_CI: 'CML_REPO',
33+
CML_PUBLISH: 'CML_ASSET',
34+
CML_RERUN_WORKFLOW: 'CML_WORKFLOW',
35+
CML_SEND_COMMENT: 'CML_COMMENT',
36+
CML_SEND_GITHUB_CHECK: 'CML_CHECK',
37+
CML_TENSORBOARD_DEV: 'CML_TENSORBOARD'
38+
};
39+
40+
for (const [oldPrefix, newPrefix] of Object.entries(
41+
legacyEnvironmentPrefixes
42+
)) {
43+
for (const key in process.env) {
44+
if (key.startsWith(`${oldPrefix}_`))
45+
process.env[key.replace(oldPrefix, newPrefix)] = process.env[key];
46+
}
47+
}
48+
3149
const { markdownfile } = opts;
3250
opts.markdownFile = markdownfile;
3351
opts.cmlCommand = opts._[0];
@@ -80,22 +98,46 @@ const handleError = (message, error) => {
8098
};
8199

82100
(async () => {
101+
setupLogger({ log: 'debug' });
83102
try {
84103
await yargs
85104
.env('CML')
86105
.options({
87106
log: {
88107
type: 'string',
89-
description: 'Maximum log level',
108+
description: 'Logging verbosity',
90109
choices: ['error', 'warn', 'info', 'debug'],
91-
default: 'info'
110+
default: 'info',
111+
group: 'Global Options:'
112+
},
113+
driver: {
114+
type: 'string',
115+
choices: ['github', 'gitlab', 'bitbucket'],
116+
defaultDescription: 'infer from the environment',
117+
description: 'Git provider where the repository is hosted',
118+
group: 'Global Options:'
119+
},
120+
repo: {
121+
type: 'string',
122+
defaultDescription: 'infer from the environment',
123+
description: 'Repository URL or slug',
124+
group: 'Global Options:'
125+
},
126+
token: {
127+
type: 'string',
128+
defaultDescription: 'infer from the environment',
129+
description: 'Personal access token',
130+
group: 'Global Options:'
92131
}
93132
})
133+
.global('version', false)
134+
.group('help', 'Global Options:')
94135
.fail(handleError)
95136
.middleware(setupOpts)
96137
.middleware(setupLogger)
97138
.middleware(setupTelemetry)
98-
.commandDir('./cml', { exclude: /\.test\.js$/ })
139+
.commandDir('./cml')
140+
.commandDir('./legacy/commands')
99141
.command(
100142
'$0 <command>',
101143
false,
@@ -110,9 +152,11 @@ const handleError = (message, error) => {
110152
const { telemetryEvent } = yargs.parsed.argv;
111153
await send({ event: telemetryEvent });
112154
} catch (err) {
113-
const { telemetryEvent } = yargs.parsed.argv;
114-
const event = { ...telemetryEvent, error: err.message };
115-
await send({ event });
155+
if (yargs.parsed.argv) {
156+
const { telemetryEvent } = yargs.parsed.argv;
157+
const event = { ...telemetryEvent, error: err.message };
158+
await send({ event });
159+
}
116160
winston.error({ err });
117161
process.exit(1);
118162
}

bin/cml.test.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,26 @@ describe('command-line interface tests', () => {
88
"cml.js <command>
99
1010
Commands:
11-
cml.js ci Fixes specific CI setups
12-
cml.js pr <glob path...> Create a pull request with the
13-
specified files
14-
cml.js publish <asset> Upload an image to build a report
15-
cml.js rerun-workflow Reruns a workflow given the jobId or
16-
workflow Id
17-
cml.js runner Launch and register a self-hosted
18-
runner
19-
cml.js send-comment <markdown file> Comment on a commit
20-
cml.js send-github-check <markdown file> Create a check report
21-
cml.js tensorboard-dev Get a tensorboard link
11+
cml.js check Manage CI checks
12+
cml.js comment Manage comments
13+
cml.js pr <glob path...> Manage pull requests
14+
cml.js runner Manage self-hosted (cloud & on-premise) CI runners
15+
cml.js tensorboard Manage tensorboard.dev connections
16+
cml.js workflow Manage CI workflows
17+
cml.js ci Prepare Git repository for CML operations
18+
19+
Global Options:
20+
--log Logging verbosity
21+
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
22+
--driver Git provider where the repository is hosted
23+
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
24+
environment]
25+
--repo Repository URL or slug[string] [default: infer from the environment]
26+
--token Personal access token [string] [default: infer from the environment]
27+
--help Show help [boolean]
2228
2329
Options:
24-
--help Show help [boolean]
25-
--version Show version number [boolean]
26-
--log Maximum log level
27-
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]"
30+
--version Show version number [boolean]"
2831
`);
2932
});
3033
});

bin/cml/asset.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
exports.command = 'asset';
2+
exports.description = false;
3+
exports.builder = (yargs) =>
4+
yargs
5+
.commandDir('./asset', { exclude: /\.test\.js$/ })
6+
.recommendCommands()
7+
.demandCommand()
8+
.strict();

bin/cml/asset/publish.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const fs = require('fs').promises;
2+
const kebabcaseKeys = require('kebabcase-keys');
3+
const winston = require('winston');
4+
5+
const { CML } = require('../../../src/cml');
6+
7+
exports.command = 'publish <asset>';
8+
exports.description = 'Publish an asset';
9+
10+
exports.handler = async (opts) => {
11+
if (opts.gitlabUploads) {
12+
winston.warn(
13+
'--gitlab-uploads will be deprecated soon, use --native instead'
14+
);
15+
opts.native = true;
16+
}
17+
18+
const { file, repo, native, asset: path } = opts;
19+
const cml = new CML({ ...opts, repo: native ? repo : 'cml' });
20+
const output = await cml.publish({ ...opts, path });
21+
22+
if (!file) console.log(output);
23+
else await fs.writeFile(file, output);
24+
};
25+
26+
exports.builder = (yargs) => yargs.env('CML_ASSET').options(exports.options);
27+
28+
exports.options = kebabcaseKeys({
29+
url: {
30+
type: 'string',
31+
description: 'Self-Hosted URL',
32+
hidden: true
33+
},
34+
md: {
35+
type: 'boolean',
36+
description: 'Output in markdown format [title || name](url)'
37+
},
38+
title: {
39+
type: 'string',
40+
alias: 't',
41+
description: 'Markdown title [title](url) or ![](url title)'
42+
},
43+
native: {
44+
type: 'boolean',
45+
description:
46+
"Uses driver's native capabilities to upload assets instead of CML's storage; not available on GitHub"
47+
},
48+
gitlabUploads: {
49+
type: 'boolean',
50+
hidden: true
51+
},
52+
rmWatermark: {
53+
type: 'boolean',
54+
description: 'Avoid CML watermark.'
55+
},
56+
mimeType: {
57+
type: 'string',
58+
defaultDescription: 'infer from the file contents',
59+
description: 'MIME type'
60+
},
61+
file: {
62+
type: 'string',
63+
alias: 'f',
64+
description:
65+
'Append the output to the given file or create it if does not exist',
66+
hidden: true
67+
},
68+
repo: {
69+
type: 'string',
70+
description:
71+
'Specifies the repo to be used. If not specified is extracted from the CI ENV.'
72+
}
73+
});

bin/cml/publish.test.js renamed to bin/cml/asset/publish.test.js

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const fs = require('fs');
2-
const { exec } = require('../../src/utils');
2+
const { exec } = require('../../../src/utils');
33

44
describe('CML e2e', () => {
55
test('cml publish --help', async () => {
@@ -8,26 +8,25 @@ describe('CML e2e', () => {
88
expect(output).toMatchInlineSnapshot(`
99
"cml.js publish <asset>
1010
11-
Upload an image to build a report
11+
Global Options:
12+
--log Logging verbosity
13+
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
14+
--driver Git provider where the repository is hosted
15+
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
16+
environment]
17+
--repo Specifies the repo to be used. If not specified is extracted
18+
from the CI ENV. [string] [default: infer from the environment]
19+
--token Personal access token
20+
[string] [default: infer from the environment]
21+
--help Show help [boolean]
1222
1323
Options:
14-
--help Show help [boolean]
15-
--version Show version number [boolean]
16-
--log Maximum log level
17-
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
18-
--repo Specifies the repo to be used. If not specified is
19-
extracted from the CI ENV. [string]
20-
--token Personal access token to be used. If not specified is
21-
extracted from ENV REPO_TOKEN. [string]
22-
--driver If not specify it infers it from the ENV.
23-
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"]
24-
--md Output in markdown format [title || name](url). [boolean]
25-
-t, --title Markdown title [title](url) or ![](url title). [string]
24+
--md Output in markdown format [title || name](url) [boolean]
25+
-t, --title Markdown title [title](url) or ![](url title) [string]
2626
--native Uses driver's native capabilities to upload assets instead
27-
of CML's storage. Not available on GitHub. [boolean]
27+
of CML's storage; not available on GitHub [boolean]
2828
--rm-watermark Avoid CML watermark. [boolean]
29-
--mime-type Specifies the mime-type. If not set guess it from the
30-
content. [string]"
29+
--mime-type MIME type [string] [default: infer from the file contents]"
3130
`);
3231
});
3332

bin/cml/check.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
exports.command = 'check';
2+
exports.description = 'Manage CI checks';
3+
exports.builder = (yargs) =>
4+
yargs
5+
.commandDir('./check', { exclude: /\.test\.js$/ })
6+
.recommendCommands()
7+
.demandCommand()
8+
.strict();

bin/cml/check/create.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const fs = require('fs').promises;
2+
const kebabcaseKeys = require('kebabcase-keys');
3+
4+
exports.command = 'create <markdown file>';
5+
exports.description = 'Create a check report';
6+
7+
exports.handler = async (opts) => {
8+
const { cml, markdownfile } = opts;
9+
const report = await fs.readFile(markdownfile, 'utf-8');
10+
await cml.checkCreate({ ...opts, report });
11+
};
12+
13+
exports.builder = (yargs) => yargs.env('CML_CHECK').options(exports.options);
14+
15+
exports.options = kebabcaseKeys({
16+
token: {
17+
type: 'string',
18+
description:
19+
"GITHUB_TOKEN or Github App token. Personal access token won't work"
20+
},
21+
commitSha: {
22+
type: 'string',
23+
alias: 'head-sha',
24+
defaultDescription: 'HEAD',
25+
description: 'Commit SHA linked to this comment'
26+
},
27+
conclusion: {
28+
type: 'string',
29+
choices: [
30+
'success',
31+
'failure',
32+
'neutral',
33+
'cancelled',
34+
'skipped',
35+
'timed_out'
36+
],
37+
default: 'success',
38+
description: 'Conclusion status of the check'
39+
},
40+
status: {
41+
type: 'string',
42+
choices: ['queued', 'in_progress', 'completed'],
43+
default: 'completed',
44+
description: 'Status of the check'
45+
},
46+
title: {
47+
type: 'string',
48+
default: 'CML Report',
49+
description: 'Title of the check'
50+
}
51+
});

bin/cml/send-github-check.test.js renamed to bin/cml/check/create.test.js

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { exec } = require('../../src/utils');
1+
const { exec } = require('../../../src/utils');
22
const fs = require('fs').promises;
33

44
describe('CML e2e', () => {
@@ -36,29 +36,27 @@ describe('CML e2e', () => {
3636
expect(output).toMatchInlineSnapshot(`
3737
"cml.js send-github-check <markdown file>
3838
39-
Create a check report
39+
Global Options:
40+
--log Logging verbosity
41+
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
42+
--driver Git provider where the repository is hosted
43+
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
44+
environment]
45+
--repo Repository URL or slug[string] [default: infer from the environment]
46+
--token GITHUB_TOKEN or Github App token. Personal access token won't work
47+
[string] [default: infer from the environment]
48+
--help Show help [boolean]
4049
4150
Options:
42-
--help Show help [boolean]
43-
--version Show version number [boolean]
44-
--log Maximum log level
45-
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
46-
--repo Specifies the repo to be used. If not specified is
47-
extracted from the CI ENV. [string]
48-
--token GITHUB_TOKEN or Github App token. Personal access
49-
token won't work [string]
50-
--driver If not specify it infers it from the ENV.
51-
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"]
52-
--commit-sha, --head-sha Commit SHA linked to this comment. Defaults to HEAD.
53-
[string]
54-
--conclusion Sets the conclusion status of the check.
51+
--commit-sha, --head-sha Commit SHA linked to this comment
52+
[string] [default: HEAD]
53+
--conclusion Conclusion status of the check
5554
[string] [choices: \\"success\\", \\"failure\\", \\"neutral\\", \\"cancelled\\", \\"skipped\\",
5655
\\"timed_out\\"] [default: \\"success\\"]
57-
--status Sets the status of the check.
56+
--status Status of the check
5857
[string] [choices: \\"queued\\", \\"in_progress\\", \\"completed\\"] [default:
5958
\\"completed\\"]
60-
--title Sets title of the check.
61-
[string] [default: \\"CML Report\\"]"
59+
--title Title of the check [string] [default: \\"CML Report\\"]"
6260
`);
6361
});
6462
});

0 commit comments

Comments
 (0)