dotcom-tool-kit 5.0.1-beta.7 → 5.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/run CHANGED
@@ -10,13 +10,17 @@ const argv = require('minimist')(process.argv.slice(2), {
10
10
  })
11
11
 
12
12
  const { rootLogger } = require('@dotcom-tool-kit/logger')
13
+ const { TelemetryProcess } = require('@dotcom-tool-kit/telemetry')
13
14
  const { formatError } = require('../lib/messages')
14
15
 
15
16
  async function main() {
17
+ const metricsProcess = new TelemetryProcess(rootLogger)
18
+ const environment = process.env.CI ? 'ci' : 'local'
19
+ const metrics = metricsProcess.root({ environment })
16
20
  try {
17
21
  if (argv.install) {
18
22
  const installHooks = require('../lib/install').default
19
- await installHooks(rootLogger)
23
+ await installHooks(rootLogger, metrics)
20
24
  } else if (argv.listPlugins) {
21
25
  const { listPlugins } = require('../lib')
22
26
  await listPlugins(rootLogger)
@@ -25,7 +29,7 @@ async function main() {
25
29
  await printConfig(rootLogger)
26
30
  } else if (argv.printMergedOptions) {
27
31
  const { printMergedOptions } = require('../lib')
28
- await printMergedOptions(rootLogger)
32
+ await printMergedOptions(rootLogger, metrics)
29
33
  } else if (argv.help || argv._.length === 0) {
30
34
  const showHelp = require('../lib/help').default
31
35
  await showHelp(rootLogger, argv._)
@@ -39,14 +43,16 @@ async function main() {
39
43
  // the command becomes something like `dotcom-tool-kit test:staged --
40
44
  // index.js`. When this command is executed it runs the configured task
41
45
  // where the file path arguments would then be extracted.
42
- await runCommands(rootLogger, argv._, argv['--'])
46
+ await runCommands(rootLogger, metrics, argv._, argv['--'])
43
47
  } else {
44
- await runCommands(rootLogger, argv._)
48
+ await runCommands(rootLogger, metrics, argv._)
45
49
  }
46
50
  }
47
51
  } catch (error) {
48
52
  rootLogger.error(formatError(error), { skipFormat: true })
49
53
  process.exitCode = error.exitCode || 1
54
+ } finally {
55
+ metricsProcess.disconnect()
50
56
  }
51
57
  }
52
58
 
package/lib/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { Logger } from 'winston';
2
+ import { TelemetryRecorder } from '@dotcom-tool-kit/telemetry';
2
3
  export { runCommands } from './tasks';
3
4
  export { shouldDisableNativeFetch } from './fetch';
4
5
  export declare function listPlugins(logger: Logger): Promise<void>;
5
6
  export declare function printConfig(logger: Logger): Promise<void>;
6
- export declare function printMergedOptions(logger: Logger): Promise<void>;
7
+ export declare function printMergedOptions(logger: Logger, metrics: TelemetryRecorder): Promise<void>;
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAKrC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAElD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/D;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAMrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAElD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/D;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBlG"}
package/lib/index.js CHANGED
@@ -9,6 +9,7 @@ const config_1 = require("./config");
9
9
  const util_1 = tslib_1.__importDefault(require("util"));
10
10
  const messages_1 = require("./messages");
11
11
  const install_1 = require("./install");
12
+ const telemetry_1 = require("./telemetry");
12
13
  var tasks_1 = require("./tasks");
13
14
  Object.defineProperty(exports, "runCommands", { enumerable: true, get: function () { return tasks_1.runCommands; } });
14
15
  var fetch_1 = require("./fetch");
@@ -24,9 +25,10 @@ async function printConfig(logger) {
24
25
  const config = await (0, config_1.loadConfig)(logger, { validate: false, root: process.cwd() });
25
26
  logger.info(util_1.default.inspect(config, { depth: null, colors: true }));
26
27
  }
27
- async function printMergedOptions(logger) {
28
+ async function printMergedOptions(logger, metrics) {
28
29
  const config = await (0, config_1.loadConfig)(logger, { validate: true, root: process.cwd() });
29
- const hookInstallations = (await (0, install_1.loadHookInstallations)(logger, config)).unwrap('invalid hooks');
30
+ (0, telemetry_1.enableTelemetry)(metrics, config.pluginOptions['app root'].options);
31
+ const hookInstallations = (await (0, install_1.loadHookInstallations)(logger, metrics, config)).unwrap('invalid hooks');
30
32
  const mergedOptions = {
31
33
  hooks: hookInstallations.map((h) => h.options),
32
34
  plugins: Object.fromEntries(Object.entries(config.pluginOptions).map(([pluginId, optionsForPlugin]) => [
package/lib/install.d.ts CHANGED
@@ -3,8 +3,9 @@ import type { ValidConfig } from '@dotcom-tool-kit/config';
3
3
  import { Hook } from '@dotcom-tool-kit/base';
4
4
  import { Validated } from '@dotcom-tool-kit/validated';
5
5
  import { HookModule } from './plugin/reduce-installations';
6
+ import { TelemetryRecorder } from '@dotcom-tool-kit/telemetry';
6
7
  export declare const loadHookEntrypoints: (logger: Logger, config: ValidConfig) => Promise<Validated<Record<string, HookModule>>>;
7
- export declare const loadHookInstallations: (logger: Logger, config: ValidConfig) => Promise<Validated<Hook[]>>;
8
- export declare function checkInstall(logger: Logger, config: ValidConfig): Promise<void>;
9
- export default function installHooks(logger: Logger): Promise<ValidConfig>;
8
+ export declare const loadHookInstallations: (logger: Logger, metrics: TelemetryRecorder, config: ValidConfig) => Promise<Validated<Hook[]>>;
9
+ export declare function checkInstall(logger: Logger, metrics: TelemetryRecorder, config: ValidConfig): Promise<void>;
10
+ export default function installHooks(logger: Logger, metrics: TelemetryRecorder): Promise<ValidConfig>;
10
11
  //# sourceMappingURL=install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAGrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAa,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,SAAS,EAAmC,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAE,UAAU,EAAiC,MAAM,+BAA+B,CAAA;AAuBzF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,EACd,QAAQ,WAAW,KAClB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAa/C,CAAA;AAED,eAAO,MAAM,qBAAqB,GAChC,QAAQ,MAAM,EACd,QAAQ,WAAW,KAClB,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAkC3B,CAAA;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBrF;AAED,wBAA8B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAiD/E"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAGrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAa,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,SAAS,EAAmC,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAE,UAAU,EAAiC,MAAM,+BAA+B,CAAA;AAOzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAmB9D,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,EACd,QAAQ,WAAW,KAClB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAa/C,CAAA;AAED,eAAO,MAAM,qBAAqB,GAChC,QAAQ,MAAM,EACd,SAAS,iBAAiB,EAC1B,QAAQ,WAAW,KAClB,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAwC3B,CAAA;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAA8B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwD3G"}
package/lib/install.js CHANGED
@@ -17,6 +17,8 @@ const conflict_1 = require("@dotcom-tool-kit/conflict");
17
17
  const messages_1 = require("./messages");
18
18
  const entry_point_1 = require("./plugin/entry-point");
19
19
  const init_1 = require("./init");
20
+ const systemCode_1 = require("./systemCode");
21
+ const telemetry_1 = require("./telemetry");
20
22
  // implementation of the Array#every method that supports asynchronous predicates
21
23
  async function asyncEvery(arr, pred) {
22
24
  for (const val of arr) {
@@ -39,7 +41,7 @@ const loadHookEntrypoints = async (logger, config) => {
39
41
  return hookResultEntries.map((hookEntries) => Object.fromEntries(hookEntries));
40
42
  };
41
43
  exports.loadHookEntrypoints = loadHookEntrypoints;
42
- const loadHookInstallations = async (logger, config) => {
44
+ const loadHookInstallations = async (logger, metrics, config) => {
43
45
  const hookClassResults = await (0, exports.loadHookEntrypoints)(logger, config);
44
46
  const installationResults = hookClassResults.flatMap((hookClasses) => (0, reduce_installations_1.reducePluginHookInstallations)(logger, config, hookClasses, config.plugins['app root']));
45
47
  const installationsWithoutConflicts = installationResults.flatMap((installations) => {
@@ -54,16 +56,16 @@ const loadHookInstallations = async (logger, config) => {
54
56
  return installationsWithoutConflicts.map((installations) => {
55
57
  return installations.map(({ hookConstructor, forHook, options }) => {
56
58
  const hookPlugin = config.hooks[forHook].plugin;
57
- return new hookConstructor(logger, forHook, options, config.pluginOptions[hookPlugin.id]?.options);
59
+ return new hookConstructor(logger, forHook, options, config.pluginOptions[hookPlugin.id]?.options, metrics);
58
60
  });
59
61
  });
60
62
  };
61
63
  exports.loadHookInstallations = loadHookInstallations;
62
- async function checkInstall(logger, config) {
64
+ async function checkInstall(logger, metrics, config) {
63
65
  if (!(await (0, hash_1.hasConfigChanged)(logger, config))) {
64
66
  return;
65
67
  }
66
- const hooks = (await (0, exports.loadHookInstallations)(logger, config)).unwrap('hooks were found to be invalid when checking install');
68
+ const hooks = (await (0, exports.loadHookInstallations)(logger, metrics, config)).unwrap('hooks were found to be invalid when checking install');
67
69
  const uninstalledHooks = await asyncFilter(hooks, async (hook) => {
68
70
  return !(await hook.isInstalled());
69
71
  });
@@ -74,11 +76,17 @@ async function checkInstall(logger, config) {
74
76
  }
75
77
  await (0, hash_1.updateHashes)(config);
76
78
  }
77
- async function installHooks(logger) {
79
+ async function installHooks(logger, metrics) {
78
80
  const config = await (0, config_1.loadConfig)(logger, { root: process.cwd() });
81
+ (0, telemetry_1.enableTelemetry)(metrics, config.pluginOptions['app root'].options);
79
82
  await (0, init_1.runInit)(logger, config);
83
+ const systemCode = await (0, systemCode_1.guessSystemCode)(config);
84
+ let scoped = metrics;
85
+ if (systemCode) {
86
+ scoped = metrics.scoped({ systemCode });
87
+ }
80
88
  const errors = [];
81
- const hooks = (await (0, exports.loadHookInstallations)(logger, config)).unwrap('hooks were found to be invalid when installing');
89
+ const hooks = (await (0, exports.loadHookInstallations)(logger, scoped, config)).unwrap('hooks were found to be invalid when installing');
82
90
  // group hooks without an installGroup separately so that their check()
83
91
  // method runs independently
84
92
  const groups = (0, groupBy_1.default)(hooks, (hook) => hook.installGroup ?? '__' + hook.id);
@@ -0,0 +1,3 @@
1
+ import type { ValidConfig } from '@dotcom-tool-kit/config';
2
+ export declare function guessSystemCode(config: ValidConfig): Promise<string | undefined>;
3
+ //# sourceMappingURL=systemCode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemCode.d.ts","sourceRoot":"","sources":["../src/systemCode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAM1D,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmBtF"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.guessSystemCode = guessSystemCode;
4
+ const promises_1 = require("node:fs/promises");
5
+ async function guessSystemCode(config) {
6
+ const systemCodeFromRoot = (config.pluginOptions['app root']?.options).systemCode;
7
+ if (systemCodeFromRoot) {
8
+ return systemCodeFromRoot;
9
+ }
10
+ const systemCodeFromDoppler = (config.pluginOptions['@dotcom-tool-kit/doppler']?.options).project;
11
+ if (systemCodeFromDoppler && !systemCodeFromDoppler.startsWith('repo_')) {
12
+ return systemCodeFromDoppler;
13
+ }
14
+ try {
15
+ const packageJson = JSON.parse(await (0, promises_1.readFile)('package.json', 'utf8'));
16
+ if (packageJson.name) {
17
+ return `npm:${packageJson.name}`;
18
+ }
19
+ }
20
+ catch { }
21
+ }
package/lib/tasks.d.ts CHANGED
@@ -4,13 +4,14 @@ import { Validated } from '@dotcom-tool-kit/validated';
4
4
  import type { Logger } from 'winston';
5
5
  import { OptionsForTask } from '@dotcom-tool-kit/plugin';
6
6
  import type { ReadonlyDeep } from 'type-fest';
7
+ import { type TelemetryRecorder } from '@dotcom-tool-kit/telemetry';
7
8
  export type ErrorSummary = {
8
9
  task: string;
9
10
  error: Error;
10
11
  };
11
- export declare function loadTasks(logger: Logger, tasks: OptionsForTask[], config: ReadonlyDeep<ValidConfig>): Promise<Validated<Task[]>>;
12
+ export declare function loadTasks(logger: Logger, tasks: OptionsForTask[], config: ReadonlyDeep<ValidConfig>, metrics?: TelemetryRecorder): Promise<Validated<Task[]>>;
12
13
  export declare function handleTaskErrors(errors: ErrorSummary[], command: string): void;
13
- export declare function runTasks(logger: Logger, config: ValidConfig, tasks: Task[], command: string, files?: string[]): Promise<void>;
14
- export declare function runCommandsFromConfig(logger: Logger, config: ValidConfig, commands: string[], files?: string[]): Promise<void>;
15
- export declare function runCommands(logger: Logger, commands: string[], files?: string[]): Promise<void>;
14
+ export declare function runTasks(logger: Logger, metrics: TelemetryRecorder, config: ValidConfig, tasks: Task[], command: string, files?: string[]): Promise<void>;
15
+ export declare function runCommandsFromConfig(logger: Logger, config: ValidConfig, commands: string[], files?: string[], metrics?: TelemetryRecorder): Promise<void>;
16
+ export declare function runCommands(logger: Logger, metrics: TelemetryRecorder, commands: string[], files?: string[]): Promise<void>;
16
17
  //# sourceMappingURL=tasks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAmB,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAmC,MAAM,4BAA4B,CAAA;AACvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAUrC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,YAAY,CAAC,WAAW,CAAC,GAChC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAiC5B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,QAQvE;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EAAE,iBA8BjB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrG"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAmB,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAmC,MAAM,4BAA4B,CAAA;AACvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAYrC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,4BAA4B,CAAA;AAExF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,YAAY,CAAC,WAAW,CAAC,EAIjC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAmC5B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,QAQvE;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EAAE,iBAiCjB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EAAE,EAIhB,OAAO,GAAE,iBAA6C,GACrD,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,IAAI,CAAC,CAWf"}
package/lib/tasks.js CHANGED
@@ -16,9 +16,16 @@ const logger_1 = require("@dotcom-tool-kit/logger");
16
16
  const fetch_1 = require("./fetch");
17
17
  const init_1 = require("./init");
18
18
  const messages_1 = require("./messages");
19
+ const systemCode_1 = require("./systemCode");
20
+ const telemetry_1 = require("./telemetry");
19
21
  const schemas_1 = require("@dotcom-tool-kit/schemas");
20
22
  const pluralize_1 = tslib_1.__importDefault(require("pluralize"));
21
- async function loadTasks(logger, tasks, config) {
23
+ const telemetry_2 = require("@dotcom-tool-kit/telemetry");
24
+ async function loadTasks(logger, tasks, config,
25
+ // TODO:IM:20251215 make this a required parameter in the next major version.
26
+ // this function is currently used by the parallel plugin and so
27
+ // can't be changed yet.
28
+ metrics) {
22
29
  const taskResults = await Promise.all(tasks.map(async ({ task: taskId, options, plugin }) => {
23
30
  const entryPoint = config.tasks[taskId];
24
31
  const taskResult = await (0, entry_point_1.importEntryPoint)(base_1.Task, entryPoint);
@@ -30,7 +37,8 @@ async function loadTasks(logger, tasks, config) {
30
37
  data: mergedOptions
31
38
  };
32
39
  if (parsedOptions.success) {
33
- const task = new taskModule.baseClass(logger, taskId, config.pluginOptions[entryPoint.plugin.id]?.options ?? {}, parsedOptions.data, plugin);
40
+ const scoped = metrics?.scoped({ plugin: entryPoint.plugin.id });
41
+ const task = new taskModule.baseClass(logger, taskId, config.pluginOptions[entryPoint.plugin.id]?.options ?? {}, parsedOptions.data, plugin, scoped);
34
42
  return (0, validated_1.valid)(task);
35
43
  }
36
44
  else {
@@ -46,15 +54,17 @@ function handleTaskErrors(errors, command) {
46
54
  return error;
47
55
  }), `${(0, pluralize_1.default)('error', errors.length, true)} running tasks for ${logger_1.styles.command(command)}`);
48
56
  }
49
- async function runTasks(logger, config, tasks, command, files) {
57
+ async function runTasks(logger, metrics, config, tasks, command, files) {
50
58
  const errors = [];
51
59
  if (tasks.length === 0) {
52
60
  logger.warn(`no task configured for ${command}: skipping assignment...`);
53
61
  }
54
62
  for (const task of tasks) {
63
+ const scoped = metrics.scoped({ task: task.id });
55
64
  try {
56
65
  logger.info(logger_1.styles.taskHeader(`running ${logger_1.styles.task(task.id)} task`));
57
66
  await task.run({ files, command, cwd: config.root, config });
67
+ scoped.recordEvent('tasks.completed', { success: true });
58
68
  }
59
69
  catch (error) {
60
70
  // if there's an exit code, that's a request from the task to exit early
@@ -67,32 +77,45 @@ async function runTasks(logger, config, tasks, command, files) {
67
77
  task: task.id,
68
78
  error: error
69
79
  });
80
+ scoped.recordEvent('tasks.completed', { success: false });
70
81
  }
71
82
  }
72
83
  if (errors.length > 0) {
73
84
  handleTaskErrors(errors, command);
74
85
  }
75
86
  }
76
- async function runCommandsFromConfig(logger, config, commands, files) {
87
+ async function runCommandsFromConfig(logger, config, commands, files,
88
+ // TODO:IM:20251215 make this a required parameter in the next major version.
89
+ // this function is currently used by the monorepo plugin and so can't be
90
+ // changed yet.
91
+ metrics = new telemetry_2.MockTelemetryClient()) {
77
92
  await (0, init_1.runInit)(logger, config);
78
- await (0, install_1.checkInstall)(logger, config);
93
+ await (0, install_1.checkInstall)(logger, metrics, config);
79
94
  if ((0, fetch_1.shouldDisableNativeFetch)(config.pluginOptions['app root'].options) &&
80
95
  !process.execArgv.includes('--no-experimental-fetch')) {
81
96
  process.execArgv.push('--no-experimental-fetch');
82
97
  }
83
98
  const commandTasks = (0, validated_1.reduceValidated)(await Promise.all(commands.map(async (command) => {
84
99
  const tasks = config.commandTasks[command]?.tasks ?? [];
85
- const validatedTaskInstances = await loadTasks(logger, tasks, config);
100
+ const scoped = metrics.scoped({ command });
101
+ const validatedTaskInstances = await loadTasks(logger, tasks, config, scoped);
86
102
  return validatedTaskInstances.map((taskInstances) => ({ command, tasks: taskInstances }));
87
103
  }))).unwrap('tasks are invalid!');
88
104
  // at this point we no longer need to update the config, so freeze it before
89
105
  // passing it into task run contexts so that plugins can't do crimes
90
106
  Object.freeze(config);
91
107
  for (const { command, tasks } of commandTasks) {
92
- await runTasks(logger, config, tasks, command, files);
108
+ const scoped = metrics.scoped({ command });
109
+ await runTasks(logger, scoped, config, tasks, command, files);
93
110
  }
94
111
  }
95
- async function runCommands(logger, commands, files) {
112
+ async function runCommands(logger, metrics, commands, files) {
96
113
  const config = await (0, config_1.loadConfig)(logger, { root: process.cwd() });
97
- return runCommandsFromConfig(logger, config, commands, files);
114
+ (0, telemetry_1.enableTelemetry)(metrics, config.pluginOptions['app root'].options);
115
+ const systemCode = await (0, systemCode_1.guessSystemCode)(config);
116
+ let scoped = metrics;
117
+ if (systemCode) {
118
+ scoped = metrics.scoped({ systemCode });
119
+ }
120
+ return runCommandsFromConfig(logger, config, commands, files, scoped);
98
121
  }
@@ -0,0 +1,4 @@
1
+ import type { RootOptions } from '@dotcom-tool-kit/plugin/src/root-schema';
2
+ import type { TelemetryProcess, TelemetryRecorder } from '@dotcom-tool-kit/telemetry';
3
+ export declare function enableTelemetry(metrics: TelemetryProcess | TelemetryRecorder, options: RootOptions): void;
4
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAKrF,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,EAAE,OAAO,EAAE,WAAW,QAIlG"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enableTelemetry = enableTelemetry;
4
+ // TODO:IM:20260113 in the future this type signature could be changed to allow
5
+ // enabling telemetry even without a valid config (and the root options derived
6
+ // from it,) so that we can track metrics related to invalid configurations.
7
+ function enableTelemetry(metrics, options) {
8
+ if (options.enableTelemetry) {
9
+ metrics.enable();
10
+ }
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotcom-tool-kit",
3
- "version": "5.0.1-beta.7",
3
+ "version": "5.1.0-beta.1",
4
4
  "description": "modern, maintainable, modular developer tooling for FT.com projects",
5
5
  "author": "FT.com Platforms Team <platforms-team.customer-products@ft.com>",
6
6
  "license": "MIT",
@@ -30,14 +30,15 @@
30
30
  "zod": "^3.24.4"
31
31
  },
32
32
  "dependencies": {
33
- "@dotcom-tool-kit/base": "^2.0.1-beta.1",
34
- "@dotcom-tool-kit/config": "^2.0.0",
35
- "@dotcom-tool-kit/conflict": "^2.0.0",
33
+ "@dotcom-tool-kit/base": "^2.1.0-beta.1",
34
+ "@dotcom-tool-kit/config": "^2.0.1-beta.1",
35
+ "@dotcom-tool-kit/conflict": "^2.0.1-beta.1",
36
36
  "@dotcom-tool-kit/error": "^5.0.0",
37
37
  "@dotcom-tool-kit/logger": "^5.0.0",
38
- "@dotcom-tool-kit/plugin": "^2.0.0",
38
+ "@dotcom-tool-kit/plugin": "^2.1.0-beta.1",
39
39
  "@dotcom-tool-kit/schemas": "^1.9.0",
40
40
  "@dotcom-tool-kit/state": "^5.0.0",
41
+ "@dotcom-tool-kit/telemetry": "^1.0.0",
41
42
  "@dotcom-tool-kit/validated": "^2.0.0",
42
43
  "endent": "^2.1.0",
43
44
  "lodash": "^4.17.21",