diff --git a/bin/cml.js b/bin/cml.js index 56e28ea85..9f41d3f65 100755 --- a/bin/cml.js +++ b/bin/cml.js @@ -8,8 +8,7 @@ const winston = require('winston'); const yargs = require('yargs'); const CML = require('../src/cml').default; -const { jitsuEventPayload } = require('../src/analytics'); -let OPTS; +const { jitsuEventPayload, send } = require('../src/analytics'); const setupOpts = (opts) => { const legacyEnvironmentVariables = { @@ -33,8 +32,6 @@ const setupOpts = (opts) => { opts.markdownFile = markdownfile; opts.cmlCommand = opts._[0]; opts.cml = new CML(opts); - - OPTS = opts; }; const setupLogger = (opts) => { @@ -68,48 +65,55 @@ const setupTelemetry = async (opts) => { const runPlugin = async ({ $0: executable, command }) => { if (command === undefined) throw new Error('no command'); + const { argv } = process.argv; const path = which.sync(`${basename(executable)}-${command}`); - const parameters = process.argv.slice(process.argv.indexOf(command) + 1); // HACK + const parameters = argv.slice(argv.indexOf(command) + 1); // HACK await pseudoexec(path, parameters); }; -const handleError = async (message, error, yargs) => { - if (error) { - const { telemetryEvent, cml } = OPTS; - const event = { ...telemetryEvent, error: error.message }; - await cml.telemetrySend({ event }); - return; +const handleError = (message, error) => { + if (!error) { + yargs.showHelp(); + console.error('\n' + message); + process.exit(1); } - - yargs.showHelp(); - console.error('\n' + message); }; -process.on('uncaughtException', async (err) => { - await handleError('', err, yargs); -}); - -process.on('unhandledRejection', async (reason) => { - await handleError('', new Error(reason), yargs); -}); - -yargs - .env('CML') - .options({ - log: { - type: 'string', - description: 'Maximum log level', - choices: ['error', 'warn', 'info', 'debug'], - default: 'info' - } - }) - .fail(handleError) - .middleware(setupOpts) - .middleware(setupLogger) - .middleware(setupTelemetry) - .commandDir('./cml', { exclude: /\.test\.js$/ }) - .command('$0 ', false, (builder) => builder.strict(false), runPlugin) - .recommendCommands() - .demandCommand() - .strict() - .parse(); +(async () => { + try { + await yargs + .env('CML') + .options({ + log: { + type: 'string', + description: 'Maximum log level', + choices: ['error', 'warn', 'info', 'debug'], + default: 'info' + } + }) + .fail(handleError) + .middleware(setupOpts) + .middleware(setupLogger) + .middleware(setupTelemetry) + .commandDir('./cml', { exclude: /\.test\.js$/ }) + .command( + '$0 ', + false, + (builder) => builder.strict(false), + runPlugin + ) + .recommendCommands() + .demandCommand() + .strict() + .parse(); + + const { telemetryEvent } = yargs.parsed.argv; + await send({ event: telemetryEvent }); + } catch (err) { + const { telemetryEvent } = yargs.parsed.argv; + const event = { ...telemetryEvent, error: err.message }; + await send({ event }); + winston.error({ err }); + process.exit(1); + } +})(); diff --git a/bin/cml/pr.js b/bin/cml/pr.js index 3c9a3122d..c051d32a8 100755 --- a/bin/cml/pr.js +++ b/bin/cml/pr.js @@ -11,10 +11,9 @@ exports.command = 'pr '; exports.description = 'Create a pull request with the specified files'; exports.handler = async (opts) => { - const { cml, telemetryEvent: event, globpath: globs } = opts; + const { cml, globpath: globs } = opts; const link = await cml.prCreate({ ...opts, globs }); console.log(link); - await cml.telemetrySend({ event }); }; exports.builder = (yargs) => diff --git a/bin/cml/publish.js b/bin/cml/publish.js index ecb0780dc..148bed459 100644 --- a/bin/cml/publish.js +++ b/bin/cml/publish.js @@ -15,14 +15,12 @@ exports.handler = async (opts) => { opts.native = true; } - const { file, repo, native, asset: path, telemetryEvent: event } = opts; + 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); - - await cml.telemetrySend({ event }); }; exports.builder = (yargs) => diff --git a/bin/cml/rerun-workflow.js b/bin/cml/rerun-workflow.js index d1e6fbf8c..eaa19207d 100644 --- a/bin/cml/rerun-workflow.js +++ b/bin/cml/rerun-workflow.js @@ -6,9 +6,8 @@ exports.description = 'Reruns a workflow given the jobId or workflow Id'; const { repoOptions } = require('../../src/cml'); exports.handler = async (opts) => { - const { cml, telemetryEvent: event } = opts; + const { cml } = opts; await cml.pipelineRerun(opts); - await cml.telemetrySend({ event }); }; exports.builder = (yargs) => diff --git a/bin/cml/runner.js b/bin/cml/runner.js index cafb54540..6c7420767 100755 --- a/bin/cml/runner.js +++ b/bin/cml/runner.js @@ -420,10 +420,8 @@ exports.description = 'Launch and register a self-hosted runner'; exports.handler = async (opts) => { ({ cml } = opts); - const { telemetryEvent: event } = opts; try { await run(opts); - await cml.telemetrySend({ event }); } catch (error) { await shutdown({ ...opts, error }); } diff --git a/bin/cml/send-comment.js b/bin/cml/send-comment.js index f8f4b0094..af11e0027 100644 --- a/bin/cml/send-comment.js +++ b/bin/cml/send-comment.js @@ -6,9 +6,8 @@ exports.command = 'send-comment '; exports.description = 'Comment on a commit'; exports.handler = async (opts) => { - const { cml, telemetryEvent: event } = opts; - console.log(await opts.cml.commentCreate(opts)); - await cml.telemetrySend({ event }); + const { cml } = opts; + console.log(await cml.commentCreate(opts)); }; exports.builder = (yargs) => diff --git a/bin/cml/send-github-check.js b/bin/cml/send-github-check.js index 1d943b206..a2f4bc8b7 100755 --- a/bin/cml/send-github-check.js +++ b/bin/cml/send-github-check.js @@ -7,10 +7,9 @@ exports.command = 'send-github-check '; exports.description = 'Create a check report'; exports.handler = async (opts) => { - const { cml, telemetryEvent: event, markdownfile } = opts; + const { cml, markdownfile } = opts; const report = await fs.readFile(markdownfile, 'utf-8'); - await opts.cml.checkCreate({ ...opts, report }); - await cml.telemetrySend({ event }); + await cml.checkCreate({ ...opts, report }); }; exports.builder = (yargs) => diff --git a/bin/cml/tensorboard-dev.js b/bin/cml/tensorboard-dev.js index 4f4a3264f..0cdb2d9a2 100644 --- a/bin/cml/tensorboard-dev.js +++ b/bin/cml/tensorboard-dev.js @@ -92,9 +92,6 @@ exports.handler = async (opts) => { const url = await launchAndWaitLink({ ...opts, extraParams }); if (!file) console.log(url); else await fs.appendFile(file, url); - - const { cml, telemetryEvent: event } = opts; - await cml.telemetrySend({ event }); }; exports.builder = (yargs) => diff --git a/package-lock.json b/package-lock.json index 141da5d68..d982b7563 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,6 @@ "strip-url-auth": "^1.0.1", "tar": "^6.1.11", "tempy": "^0.6.0", - "timeout-signal": "^1.1.0", "timestring": "^6.0.0", "unist-util-visit": "^2.0.3", "uuid": "^8.3.2", @@ -1401,17 +1400,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/acorn": { "version": "8.8.0", "license": "MIT", @@ -3055,14 +3043,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/execa": { "version": "5.1.1", "license": "MIT", @@ -5697,14 +5677,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/os.js": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os.js/-/os.js-0.2.1.tgz", - "integrity": "sha512-PxCFo501IZfL8O8Bq3zLV+Q7ie82lI/budZBmTuVqyPgQC+auMNh0wcqFJsznZmi4JIKF3zSzJp4oqzfxx/4dA==", - "bin": { - "os.js": "bin/cli.js" - } - }, "node_modules/p-limit": { "version": "1.3.0", "dev": true, @@ -6905,17 +6877,6 @@ "dev": true, "license": "MIT" }, - "node_modules/timeout-signal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/timeout-signal/-/timeout-signal-1.1.0.tgz", - "integrity": "sha512-fuWY4tM1njcHCiOB7XkTmP0EOxzBkPbuQwPN+ZCzM6G0Tj4fMVgEffG/OPgiNUX48o+FhQEa2Oh4qjEDBCy5WQ==", - "dependencies": { - "abort-controller": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/timestring": { "version": "6.0.0", "license": "MIT", @@ -8597,14 +8558,6 @@ "version": "2.0.6", "dev": true }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "acorn": { "version": "8.8.0" }, @@ -9623,11 +9576,6 @@ "esutils": { "version": "2.0.3" }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "execa": { "version": "5.1.1", "requires": { @@ -11301,10 +11249,6 @@ "windows-release": "^5.0.1" } }, - "os.js": { - "version": "https://registry.npmjs.org/os.js/-/os.js-0.2.1.tgz", - "integrity": "sha512-PxCFo501IZfL8O8Bq3zLV+Q7ie82lI/budZBmTuVqyPgQC+auMNh0wcqFJsznZmi4JIKF3zSzJp4oqzfxx/4dA==" - }, "p-limit": { "version": "1.3.0", "dev": true, @@ -12029,14 +11973,6 @@ "version": "2.3.8", "dev": true }, - "timeout-signal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/timeout-signal/-/timeout-signal-1.1.0.tgz", - "integrity": "sha512-fuWY4tM1njcHCiOB7XkTmP0EOxzBkPbuQwPN+ZCzM6G0Tj4fMVgEffG/OPgiNUX48o+FhQEa2Oh4qjEDBCy5WQ==", - "requires": { - "abort-controller": "^3.0.0" - } - }, "timestring": { "version": "6.0.0" }, diff --git a/package.json b/package.json index f0d3426c8..993752f68 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,6 @@ "strip-url-auth": "^1.0.1", "tar": "^6.1.11", "tempy": "^0.6.0", - "timeout-signal": "^1.1.0", "timestring": "^6.0.0", "unist-util-visit": "^2.0.3", "uuid": "^8.3.2", diff --git a/src/analytics.js b/src/analytics.js index a84585b65..b0399a955 100644 --- a/src/analytics.js +++ b/src/analytics.js @@ -3,7 +3,6 @@ const path = require('path'); const fs = require('fs').promises; const fetch = require('node-fetch'); -const timeoutSignal = require('timeout-signal'); const ProxyAgent = require('proxy-agent'); const { promisify } = require('util'); const { scrypt } = require('crypto'); @@ -187,8 +186,10 @@ const send = async ({ if (ITERATIVE_DO_NOT_TRACK) return; if (!event.user_id || event.user_id === ID_DO_NOT_TRACK) return; + const controller = new AbortController(); + const id = setTimeout(() => controller.abort(), 5 * 1000); await fetch(endpoint, { - signal: timeoutSignal(5 * 1000), + signal: controller.signal, method: 'POST', headers: { 'X-Auth-Token': token, @@ -197,6 +198,7 @@ const send = async ({ body: JSON.stringify(event), agent: new ProxyAgent() }); + clearInterval(id); } catch (err) { winston.debug(`Send analytics failed: ${err.message}`); } diff --git a/src/cml.js b/src/cml.js index 3af6203cf..ba07d4a78 100755 --- a/src/cml.js +++ b/src/cml.js @@ -20,7 +20,6 @@ const { preventcacheUri, waitForever } = require('./utils'); -const analytics = require('../src/analytics'); const { GITHUB_REPOSITORY, CI_PROJECT_URL, BITBUCKET_REPO_UUID } = process.env; @@ -572,10 +571,6 @@ Automated commits for ${this.repo}/commit/${sha} created by CML. return await this.getDriver().pipelineJobs(opts); } - async telemetrySend({ event }) { - await analytics.send({ event }); - } - logError(e) { winston.error(e.message); }