Skip to content

Commit

Permalink
Merge branch 'master' into update-docker-cuda-readme
Browse files Browse the repository at this point in the history
  • Loading branch information
0x2b3bfa0 authored Sep 6, 2022
2 parents 1c522fe + 341f32e commit 558fc28
Show file tree
Hide file tree
Showing 52 changed files with 2,922 additions and 4,728 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
node_modules/
runner/
.terraform/
.cml/
.DS_Store
Expand Down
173 changes: 123 additions & 50 deletions bin/cml.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,54 @@ const which = require('which');
const winston = require('winston');
const yargs = require('yargs');

const configureLogger = (level) => {
const CML = require('../src/cml').default;
const { jitsuEventPayload, send } = require('../src/analytics');

const setupOpts = (opts) => {
const legacyEnvironmentVariables = {
TB_CREDENTIALS: 'CML_TENSORBOARD_DEV_CREDENTIALS',
DOCKER_MACHINE: 'CML_RUNNER_DOCKER_MACHINE',
RUNNER_IDLE_TIMEOUT: 'CML_RUNNER_IDLE_TIMEOUT',
RUNNER_LABELS: 'CML_RUNNER_LABELS',
RUNNER_SINGLE: 'CML_RUNNER_SINGLE',
RUNNER_REUSE: 'CML_RUNNER_REUSE',
RUNNER_NO_RETRY: 'CML_RUNNER_NO_RETRY',
RUNNER_DRIVER: 'CML_RUNNER_DRIVER',
RUNNER_REPO: 'CML_RUNNER_REPO',
RUNNER_PATH: 'CML_RUNNER_PATH'
};

for (const [oldName, newName] of Object.entries(legacyEnvironmentVariables)) {
if (process.env[oldName]) process.env[newName] = process.env[oldName];
}

const legacyEnvironmentPrefixes = {
CML_CI: 'CML_REPO',
CML_PUBLISH: 'CML_ASSET',
CML_RERUN_WORKFLOW: 'CML_WORKFLOW',
CML_SEND_COMMENT: 'CML_COMMENT',
CML_SEND_GITHUB_CHECK: 'CML_CHECK',
CML_TENSORBOARD_DEV: 'CML_TENSORBOARD'
};

for (const [oldPrefix, newPrefix] of Object.entries(
legacyEnvironmentPrefixes
)) {
for (const key in process.env) {
if (key.startsWith(`${oldPrefix}_`))
process.env[key.replace(oldPrefix, newPrefix)] = process.env[key];
}
}

const { markdownfile } = opts;
opts.markdownFile = markdownfile;
opts.cmlCommand = opts._[0];
opts.cml = new CML(opts);
};

const setupLogger = (opts) => {
const { log: level } = opts;

winston.configure({
format: process.stdout.isTTY
? winston.format.combine(
Expand All @@ -29,62 +76,88 @@ const configureLogger = (level) => {
});
};

const setupTelemetry = async (opts) => {
const { cml, cmlCommand: action } = opts;
opts.telemetryEvent = await jitsuEventPayload({ action, cml });
};

const runPlugin = async ({ $0: executable, command }) => {
try {
if (command === undefined) throw new Error('no command');
const path = which.sync(`${basename(executable)}-${command}`);
const parameters = process.argv.slice(process.argv.indexOf(command) + 1); // HACK
process.exit(await pseudoexec(path, parameters));
} catch (error) {
yargs.showHelp();
winston.debug(error);
}
if (command === undefined) throw new Error('no command');
const { argv } = process.argv;
const path = which.sync(`${basename(executable)}-${command}`);
const parameters = argv.slice(argv.indexOf(command) + 1); // HACK
await pseudoexec(path, parameters);
};

const handleError = (message, error) => {
if (error) {
winston.error(error);
} else {
if (!error) {
yargs.showHelp();
console.error('\n' + message);
}
process.exit(1);
};

const options = {
log: {
type: 'string',
description: 'Maximum log level',
coerce: (value) => configureLogger(value) && value,
choices: ['error', 'warn', 'info', 'debug'],
default: 'info'
process.exit(1);
}
};

const legacyEnvironmentVariables = {
TB_CREDENTIALS: 'CML_TENSORBOARD_DEV_CREDENTIALS',
DOCKER_MACHINE: 'CML_RUNNER_DOCKER_MACHINE',
RUNNER_IDLE_TIMEOUT: 'CML_RUNNER_IDLE_TIMEOUT',
RUNNER_LABELS: 'CML_RUNNER_LABELS',
RUNNER_SINGLE: 'CML_RUNNER_SINGLE',
RUNNER_REUSE: 'CML_RUNNER_REUSE',
RUNNER_NO_RETRY: 'CML_RUNNER_NO_RETRY',
RUNNER_DRIVER: 'CML_RUNNER_DRIVER',
RUNNER_REPO: 'CML_RUNNER_REPO',
RUNNER_PATH: 'CML_RUNNER_PATH'
};

for (const [oldName, newName] of Object.entries(legacyEnvironmentVariables)) {
if (process.env[oldName]) process.env[newName] = process.env[oldName];
}
(async () => {
setupLogger({ log: 'debug' });
try {
await yargs
.env('CML')
.options({
log: {
type: 'string',
description: 'Logging verbosity',
choices: ['error', 'warn', 'info', 'debug'],
default: 'info',
group: 'Global Options:'
},
driver: {
type: 'string',
choices: ['github', 'gitlab', 'bitbucket'],
defaultDescription: 'infer from the environment',
description: 'Git provider where the repository is hosted',
group: 'Global Options:'
},
repo: {
type: 'string',
defaultDescription: 'infer from the environment',
description: 'Repository URL or slug',
group: 'Global Options:'
},
token: {
type: 'string',
defaultDescription: 'infer from the environment',
description: 'Personal access token',
group: 'Global Options:'
}
})
.global('version', false)
.group('help', 'Global Options:')
.fail(handleError)
.middleware(setupOpts)
.middleware(setupLogger)
.middleware(setupTelemetry)
.commandDir('./cml')
.commandDir('./legacy/commands')
.command(
'$0 <command>',
false,
(builder) => builder.strict(false),
runPlugin
)
.recommendCommands()
.demandCommand()
.strict()
.parse();

yargs
.fail(handleError)
.env('CML')
.options(options)
.commandDir('./cml', { exclude: /\.test\.js$/ })
.command('$0 <command>', false, (builder) => builder.strict(false), runPlugin)
.recommendCommands()
.demandCommand()
.strict()
.parse();
const { telemetryEvent } = yargs.parsed.argv;
await send({ event: telemetryEvent });
} catch (err) {
if (yargs.parsed.argv) {
const { telemetryEvent } = yargs.parsed.argv;
const event = { ...telemetryEvent, error: err.message };
await send({ event });
}
winston.error({ err });
process.exit(1);
}
})();
33 changes: 18 additions & 15 deletions bin/cml.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@ describe('command-line interface tests', () => {
"cml.js <command>
Commands:
cml.js ci Fixes specific CI setups
cml.js pr <glob path...> Create a pull request with the
specified files
cml.js publish <asset> Upload an image to build a report
cml.js rerun-workflow Reruns a workflow given the jobId or
workflow Id
cml.js runner Launch and register a self-hosted
runner
cml.js send-comment <markdown file> Comment on a commit
cml.js send-github-check <markdown file> Create a check report
cml.js tensorboard-dev Get a tensorboard link
cml.js check Manage CI checks
cml.js comment Manage comments
cml.js pr <glob path...> Manage pull requests
cml.js runner Manage self-hosted (cloud & on-premise) CI runners
cml.js tensorboard Manage tensorboard.dev connections
cml.js workflow Manage CI workflows
cml.js ci Prepare Git repository for CML operations
Global Options:
--log Logging verbosity
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
--driver Git provider where the repository is hosted
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
environment]
--repo Repository URL or slug[string] [default: infer from the environment]
--token Personal access token [string] [default: infer from the environment]
--help Show help [boolean]
Options:
--help Show help [boolean]
--version Show version number [boolean]
--log Maximum log level
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]"
--version Show version number [boolean]"
`);
});
});
8 changes: 8 additions & 0 deletions bin/cml/asset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
exports.command = 'asset';
exports.description = false;
exports.builder = (yargs) =>
yargs
.commandDir('./asset', { exclude: /\.test\.js$/ })
.recommendCommands()
.demandCommand()
.strict();
73 changes: 73 additions & 0 deletions bin/cml/asset/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const fs = require('fs').promises;
const kebabcaseKeys = require('kebabcase-keys');
const winston = require('winston');

const { CML } = require('../../../src/cml');

exports.command = 'publish <asset>';
exports.description = 'Publish an asset';

exports.handler = async (opts) => {
if (opts.gitlabUploads) {
winston.warn(
'--gitlab-uploads will be deprecated soon, use --native instead'
);
opts.native = true;
}

const { file, repo, native, asset: path } = opts;
const cml = new CML({ ...opts, repo: native ? repo : 'cml' });
const output = await cml.publish({ ...opts, path });

if (!file) console.log(output);
else await fs.writeFile(file, output);
};

exports.builder = (yargs) => yargs.env('CML_ASSET').options(exports.options);

exports.options = kebabcaseKeys({
url: {
type: 'string',
description: 'Self-Hosted URL',
hidden: true
},
md: {
type: 'boolean',
description: 'Output in markdown format [title || name](url)'
},
title: {
type: 'string',
alias: 't',
description: 'Markdown title [title](url) or ![](url title)'
},
native: {
type: 'boolean',
description:
"Uses driver's native capabilities to upload assets instead of CML's storage; not available on GitHub"
},
gitlabUploads: {
type: 'boolean',
hidden: true
},
rmWatermark: {
type: 'boolean',
description: 'Avoid CML watermark.'
},
mimeType: {
type: 'string',
defaultDescription: 'infer from the file contents',
description: 'MIME type'
},
file: {
type: 'string',
alias: 'f',
description:
'Append the output to the given file or create it if does not exist',
hidden: true
},
repo: {
type: 'string',
description:
'Specifies the repo to be used. If not specified is extracted from the CI ENV.'
}
});
34 changes: 16 additions & 18 deletions bin/cml/publish.test.js → bin/cml/asset/publish.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const fs = require('fs');
const { exec } = require('../../src/utils');
const { exec } = require('../../../src/utils');

describe('CML e2e', () => {
test('cml publish --help', async () => {
Expand All @@ -8,27 +8,25 @@ describe('CML e2e', () => {
expect(output).toMatchInlineSnapshot(`
"cml.js publish <asset>
Upload an image to build a report
Global Options:
--log Logging verbosity
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
--driver Git provider where the repository is hosted
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
environment]
--repo Specifies the repo to be used. If not specified is extracted
from the CI ENV. [string] [default: infer from the environment]
--token Personal access token
[string] [default: infer from the environment]
--help Show help [boolean]
Options:
--help Show help [boolean]
--version Show version number [boolean]
--log Maximum log level
[string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
--md Output in markdown format [title || name](url). [boolean]
-t, --title Markdown title [title](url) or ![](url title). [string]
--md Output in markdown format [title || name](url) [boolean]
-t, --title Markdown title [title](url) or ![](url title) [string]
--native Uses driver's native capabilities to upload assets instead
of CML's storage. Not available on GitHub. [boolean]
of CML's storage; not available on GitHub [boolean]
--rm-watermark Avoid CML watermark. [boolean]
--mime-type Specifies the mime-type. If not set guess it from the
content. [string]
--repo Specifies the repo to be used. If not specified is
extracted from the CI ENV. [string]
--token Personal access token to be used. If not specified,
extracted from ENV REPO_TOKEN, GITLAB_TOKEN, GITHUB_TOKEN,
or BITBUCKET_TOKEN. [string]
--driver If not specify it infers it from the ENV.
[string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"]"
--mime-type MIME type [string] [default: infer from the file contents]"
`);
});

Expand Down
8 changes: 8 additions & 0 deletions bin/cml/check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
exports.command = 'check';
exports.description = 'Manage CI checks';
exports.builder = (yargs) =>
yargs
.commandDir('./check', { exclude: /\.test\.js$/ })
.recommendCommands()
.demandCommand()
.strict();
Loading

1 comment on commit 558fc28

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Comment

CML watermark

Please sign in to comment.