@alwaysmeticulous/cli 2.278.0 → 2.280.0

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.
@@ -1,17 +1,42 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="eddc9a2a-df30-52e9-9a53-256bfdbd3541")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9277f775-c52a-556c-99d0-389c4257c25c")}catch(e){}}();
3
3
 
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.imageFilesCommand = void 0;
6
6
  const promises_1 = require("fs/promises");
7
- const os_1 = require("os");
8
7
  const path_1 = require("path");
9
8
  const client_1 = require("@alwaysmeticulous/client");
10
9
  const common_1 = require("@alwaysmeticulous/common");
11
10
  const downloading_helpers_1 = require("@alwaysmeticulous/downloading-helpers");
12
11
  const sentry_utils_1 = require("../../command-utils/sentry.utils");
13
- const downloadImageToTmpDir = async (tmpDir, label, url) => {
14
- const filePath = (0, path_1.join)(tmpDir, `${label}.png`);
12
+ const AGENT_IMAGES_SUBDIR = "agent-images";
13
+ const MAX_AGE_MS = 24 * 60 * 60 * 1000;
14
+ const getAgentImagesDir = () => (0, path_1.join)((0, common_1.getMeticulousLocalDataDir)(), AGENT_IMAGES_SUBDIR);
15
+ const cleanupOldImages = async (dir) => {
16
+ const logger = (0, common_1.initLogger)();
17
+ let entries;
18
+ try {
19
+ entries = await (0, promises_1.readdir)(dir);
20
+ }
21
+ catch {
22
+ return;
23
+ }
24
+ const cutoff = Date.now() - MAX_AGE_MS;
25
+ await Promise.all(entries.map(async (entry) => {
26
+ const entryPath = (0, path_1.join)(dir, entry);
27
+ try {
28
+ const stats = await (0, promises_1.stat)(entryPath);
29
+ if (stats.isFile() && stats.mtimeMs < cutoff) {
30
+ await (0, promises_1.unlink)(entryPath);
31
+ }
32
+ }
33
+ catch (error) {
34
+ logger.debug(`Failed to inspect/remove ${entryPath}: ${error}`);
35
+ }
36
+ }));
37
+ };
38
+ const downloadImage = async (dir, fileName, url) => {
39
+ const filePath = (0, path_1.join)(dir, fileName);
15
40
  await (0, downloading_helpers_1.downloadFile)(url, filePath);
16
41
  return filePath;
17
42
  };
@@ -19,8 +44,9 @@ const handler = async ({ apiToken, replayDiffId, screenshotName, }) => {
19
44
  (0, common_1.initLogger)();
20
45
  const client = (0, client_1.createClient)({ apiToken });
21
46
  const urls = await (0, client_1.getScreenshotUrls)(client, replayDiffId, screenshotName);
22
- const tmpDir = (0, path_1.join)((0, os_1.tmpdir)(), "meticulous-screenshots", `${replayDiffId}_${screenshotName}`);
23
- await (0, promises_1.mkdir)(tmpDir, { recursive: true });
47
+ const dir = getAgentImagesDir();
48
+ await (0, promises_1.mkdir)(dir, { recursive: true });
49
+ await cleanupOldImages(dir);
24
50
  console.log(`outcome: ${urls.outcome}`);
25
51
  const downloads = [];
26
52
  if (urls.screenshot) {
@@ -35,14 +61,16 @@ const handler = async ({ apiToken, replayDiffId, screenshotName, }) => {
35
61
  if (urls.diffImage) {
36
62
  downloads.push({ label: "diffImage", url: urls.diffImage });
37
63
  }
38
- const results = await Promise.all(downloads.map(({ label, url }) => downloadImageToTmpDir(tmpDir, label, url)));
64
+ const timestamp = Date.now();
65
+ const prefix = `${timestamp}_${replayDiffId}_${screenshotName}`;
66
+ const results = await Promise.all(downloads.map(({ label, url }) => downloadImage(dir, `${prefix}_${label}.png`, url)));
39
67
  for (let i = 0; i < downloads.length; i++) {
40
68
  console.log(`${downloads[i].label}: ${results[i]}`);
41
69
  }
42
70
  };
43
71
  exports.imageFilesCommand = {
44
72
  command: "image-files",
45
- describe: "Download screenshot images for a replay diff screenshot to local tmp files",
73
+ describe: "Download screenshot images for a replay diff screenshot to local files under ~/.meticulous/agent-images",
46
74
  builder: {
47
75
  apiToken: { string: true, description: "Meticulous API token" },
48
76
  replayDiffId: {
@@ -59,4 +87,4 @@ exports.imageFilesCommand = {
59
87
  handler: (0, sentry_utils_1.wrapHandler)(handler),
60
88
  };
61
89
  //# sourceMappingURL=screenshot-image-files.command.js.map
62
- //# debugId=eddc9a2a-df30-52e9-9a53-256bfdbd3541
90
+ //# debugId=9277f775-c52a-556c-99d0-389c4257c25c
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot-image-files.command.js","sources":["../../../src/commands/agent/screenshot-image-files.command.ts"],"sourceRoot":"","names":[],"mappings":"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","debugId":"eddc9a2a-df30-52e9-9a53-256bfdbd3541"}
1
+ {"version":3,"file":"screenshot-image-files.command.js","sources":["../../../src/commands/agent/screenshot-image-files.command.ts"],"sourceRoot":"","names":[],"mappings":"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","debugId":"9277f775-c52a-556c-99d0-389c4257c25c"}
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="be4c1da8-74d9-5650-845c-0adc017abafe")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="55f684ba-706c-5f96-aff2-b198119381aa")}catch(e){}}();
3
3
 
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.projectCommand = void 0;
6
6
  const show_command_1 = require("./show.command");
7
+ const upload_source_command_1 = require("./upload-source.command");
7
8
  exports.projectCommand = {
8
9
  command: "project",
9
10
  describe: "Project commands",
10
- builder: (yargs) => yargs.command(show_command_1.showCommand).demandCommand().help(),
11
+ builder: (yargs) => yargs.command(show_command_1.showCommand).command(upload_source_command_1.uploadSourceCommand).demandCommand().help(),
11
12
  handler: () => {
12
13
  // subcommand handles this
13
14
  },
14
15
  };
15
16
  //# sourceMappingURL=index.js.map
16
- //# debugId=be4c1da8-74d9-5650-845c-0adc017abafe
17
+ //# debugId=55f684ba-706c-5f96-aff2-b198119381aa
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/commands/project/index.ts"],"sourceRoot":"","names":[],"mappings":";;;;;AACA,iDAA6C;AAEhC,QAAA,cAAc,GAAkB;IAC3C,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,kBAAkB;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,0BAAW,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE;IACrE,OAAO,EAAE,GAAG,EAAE;QACZ,0BAA0B;IAC5B,CAAC;CACF,CAAC","debugId":"be4c1da8-74d9-5650-845c-0adc017abafe"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/commands/project/index.ts"],"sourceRoot":"","names":[],"mappings":";;;;;AACA,iDAA6C;AAC7C,mEAA8D;AAEjD,QAAA,cAAc,GAAkB;IAC3C,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,kBAAkB;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK,CAAC,OAAO,CAAC,0BAAW,CAAC,CAAC,OAAO,CAAC,2CAAmB,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE;IAChF,OAAO,EAAE,GAAG,EAAE;QACZ,0BAA0B;IAC5B,CAAC;CACF,CAAC","debugId":"55f684ba-706c-5f96-aff2-b198119381aa"}
@@ -0,0 +1,31 @@
1
+ import { CommandModule } from "yargs";
2
+ interface Options {
3
+ apiToken?: string | null | undefined;
4
+ commitSha: string;
5
+ sourceDir: string;
6
+ }
7
+ /**
8
+ * Packages `--sourceDir` as a `source.tar.gz` archive and uploads it to
9
+ * Meticulous so it can be used in place of `git clone` for projects that
10
+ * have source-code uploads enabled.
11
+ *
12
+ * The contents of the archive are exactly the contents of `--sourceDir` —
13
+ * we do not parse `.gitignore` or apply any filtering, so it is the
14
+ * caller's responsibility to point at a directory that contains only what
15
+ * Meticulous needs (i.e. exclude `.git/`, `node_modules/`, `dist/`, build
16
+ * artefacts, secrets, etc.). The recommended pattern is to invoke this
17
+ * after a fresh `git checkout` into a clean directory, or after a
18
+ * `git archive`/`rsync --exclude` step in CI.
19
+ *
20
+ * Usage (typically from the customer's CI on every commit):
21
+ *
22
+ * meticulous project upload-source \
23
+ * --commitSha "$(git rev-parse HEAD)" \
24
+ * --sourceDir ./checkout
25
+ *
26
+ * Requires a project API token (env `METICULOUS_API_TOKEN` or
27
+ * `--apiToken`). Calls from projects that don't have source-code uploads
28
+ * enabled are rejected with a 403.
29
+ */
30
+ export declare const uploadSourceCommand: CommandModule<unknown, Options>;
31
+ export {};
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="80bf9498-6e60-5fd3-8e7a-5798f20c3eed")}catch(e){}}();
3
+
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.uploadSourceCommand = void 0;
6
+ const fs_1 = require("fs");
7
+ const promises_1 = require("fs/promises");
8
+ const os_1 = require("os");
9
+ const path_1 = require("path");
10
+ const promises_2 = require("stream/promises");
11
+ const client_1 = require("@alwaysmeticulous/client");
12
+ const common_1 = require("@alwaysmeticulous/common");
13
+ const tar_1 = require("tar");
14
+ const sentry_utils_1 = require("../../command-utils/sentry.utils");
15
+ /**
16
+ * Packages `--sourceDir` as a `source.tar.gz` archive and uploads it to
17
+ * Meticulous so it can be used in place of `git clone` for projects that
18
+ * have source-code uploads enabled.
19
+ *
20
+ * The contents of the archive are exactly the contents of `--sourceDir` —
21
+ * we do not parse `.gitignore` or apply any filtering, so it is the
22
+ * caller's responsibility to point at a directory that contains only what
23
+ * Meticulous needs (i.e. exclude `.git/`, `node_modules/`, `dist/`, build
24
+ * artefacts, secrets, etc.). The recommended pattern is to invoke this
25
+ * after a fresh `git checkout` into a clean directory, or after a
26
+ * `git archive`/`rsync --exclude` step in CI.
27
+ *
28
+ * Usage (typically from the customer's CI on every commit):
29
+ *
30
+ * meticulous project upload-source \
31
+ * --commitSha "$(git rev-parse HEAD)" \
32
+ * --sourceDir ./checkout
33
+ *
34
+ * Requires a project API token (env `METICULOUS_API_TOKEN` or
35
+ * `--apiToken`). Calls from projects that don't have source-code uploads
36
+ * enabled are rejected with a 403.
37
+ */
38
+ exports.uploadSourceCommand = {
39
+ command: "upload-source",
40
+ describe: "Upload a source-code archive for a given commit to Meticulous",
41
+ builder: {
42
+ apiToken: {
43
+ string: true,
44
+ description: "Meticulous project API token. Defaults to METICULOUS_API_TOKEN.",
45
+ },
46
+ commitSha: {
47
+ string: true,
48
+ demandOption: true,
49
+ description: "Commit SHA the uploaded archive corresponds to",
50
+ },
51
+ sourceDir: {
52
+ string: true,
53
+ demandOption: true,
54
+ description: "Directory to package into source.tar.gz. The directory's contents " +
55
+ "are uploaded verbatim — exclude `.git`, `node_modules`, build " +
56
+ "artefacts and any other paths you don't want sent to Meticulous " +
57
+ "before invoking this command.",
58
+ },
59
+ },
60
+ handler: (0, sentry_utils_1.wrapHandler)(async ({ apiToken, commitSha, sourceDir }) => {
61
+ const logger = (0, common_1.initLogger)();
62
+ const client = (0, client_1.createClient)({ apiToken });
63
+ const tmpDir = await (0, promises_1.mkdtemp)((0, path_1.join)((0, os_1.tmpdir)(), "meticulous-source-"));
64
+ const archivePath = (0, path_1.join)(tmpDir, "source.tar.gz");
65
+ try {
66
+ logger.info(`Packaging ${sourceDir} into ${archivePath}...`);
67
+ // We package `sourceDir` verbatim: no `.gitignore` parsing, no
68
+ // filtering. The caller is responsible for pointing at a directory
69
+ // that contains only what Meticulous needs — see the JSDoc above.
70
+ // `portable` produces reproducible archives across platforms; `gzip`
71
+ // gives us the `.gz` wire format the cloud worker decompresses with
72
+ // `streamDownloadAndExtractTarGz`.
73
+ await (0, promises_2.pipeline)((0, tar_1.create)({
74
+ cwd: sourceDir,
75
+ gzip: true,
76
+ portable: true,
77
+ }, ["."]), (0, fs_1.createWriteStream)(archivePath));
78
+ const { size } = (0, fs_1.statSync)(archivePath);
79
+ logger.info(`Archive ready: ${(size / (1024 * 1024)).toFixed(2)} MiB. Requesting upload URL...`);
80
+ const { uploadUrl } = await (0, client_1.requestSourceCodeUploadUrl)({
81
+ client,
82
+ commitSha,
83
+ size,
84
+ });
85
+ logger.info(`Uploading source archive for commit ${commitSha}...`);
86
+ await (0, client_1.retryTransientUploadErrors)(() => (0, client_1.putFileToSignedUrl)({
87
+ filePath: archivePath,
88
+ signedUrl: uploadUrl,
89
+ size,
90
+ contentType: "application/gzip",
91
+ }), {
92
+ onRetry: (attempt, error) => {
93
+ const reason = error instanceof client_1.UploadError
94
+ ? `HTTP ${error.statusCode}`
95
+ : error instanceof Error
96
+ ? error.message
97
+ : String(error);
98
+ logger.warn(`Transient upload error on attempt ${attempt} (${reason}); will retry...`);
99
+ },
100
+ });
101
+ logger.info(`Successfully uploaded source archive for commit ${commitSha}.`);
102
+ }
103
+ finally {
104
+ await (0, promises_1.rm)(tmpDir, { recursive: true, force: true });
105
+ }
106
+ }),
107
+ };
108
+ //# sourceMappingURL=upload-source.command.js.map
109
+ //# debugId=80bf9498-6e60-5fd3-8e7a-5798f20c3eed
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-source.command.js","sources":["../../../src/commands/project/upload-source.command.ts"],"sourceRoot":"","names":[],"mappings":"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","debugId":"80bf9498-6e60-5fd3-8e7a-5798f20c3eed"}
@@ -1 +1,2 @@
1
1
  export declare const RECORDING_SNIPPET_PATH = "v1/meticulous.js";
2
+ export declare const BACKEND_RECORDING_SNIPPET_PATH = "backend-record-js/v1/manual-init.bundle.js";
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="07ec876f-a641-5fc6-b375-8f126b6afe4a")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="797d4326-b2e4-560d-8e44-4dc471c92cac")}catch(e){}}();
3
3
 
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.RECORDING_SNIPPET_PATH = void 0;
5
+ exports.BACKEND_RECORDING_SNIPPET_PATH = exports.RECORDING_SNIPPET_PATH = void 0;
6
6
  exports.RECORDING_SNIPPET_PATH = "v1/meticulous.js";
7
+ exports.BACKEND_RECORDING_SNIPPET_PATH = "backend-record-js/v1/manual-init.bundle.js";
7
8
  //# sourceMappingURL=constants.js.map
8
- //# debugId=07ec876f-a641-5fc6-b375-8f126b6afe4a
9
+ //# debugId=797d4326-b2e4-560d-8e44-4dc471c92cac
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../src/utils/constants.ts"],"sourceRoot":"","names":[],"mappings":";;;;;AAAa,QAAA,sBAAsB,GAAG,kBAAkB,CAAC","debugId":"07ec876f-a641-5fc6-b375-8f126b6afe4a"}
1
+ {"version":3,"file":"constants.js","sources":["../../src/utils/constants.ts"],"sourceRoot":"","names":[],"mappings":";;;;;AAAa,QAAA,sBAAsB,GAAG,kBAAkB,CAAC;AAC5C,QAAA,8BAA8B,GACzC,4CAA4C,CAAC","debugId":"797d4326-b2e4-560d-8e44-4dc471c92cac"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alwaysmeticulous/cli",
3
- "version": "2.278.0",
3
+ "version": "2.280.0",
4
4
  "description": "The Meticulous CLI",
5
5
  "license": "ISC",
6
6
  "main": "dist/index.js",
@@ -29,18 +29,18 @@
29
29
  "depcheck": "depcheck --ignore-patterns=dist"
30
30
  },
31
31
  "dependencies": {
32
- "@alwaysmeticulous/api": "2.276.2",
33
- "@alwaysmeticulous/client": "2.277.0",
34
- "@alwaysmeticulous/common": "2.277.0",
35
- "@alwaysmeticulous/debug-workspace": "2.278.0",
36
- "@alwaysmeticulous/downloading-helpers": "2.277.0",
37
- "@alwaysmeticulous/record": "2.277.0",
38
- "@alwaysmeticulous/remote-replay-launcher": "2.277.0",
39
- "@alwaysmeticulous/replay-debugger-ui": "2.277.0",
40
- "@alwaysmeticulous/replay-orchestrator-launcher": "2.277.0",
41
- "@alwaysmeticulous/sdk-bundles-api": "2.277.0",
42
- "@alwaysmeticulous/sentry": "2.277.0",
43
- "@alwaysmeticulous/tunnels-client": "2.277.0",
32
+ "@alwaysmeticulous/api": "2.280.0",
33
+ "@alwaysmeticulous/client": "2.280.0",
34
+ "@alwaysmeticulous/common": "2.280.0",
35
+ "@alwaysmeticulous/debug-workspace": "2.280.0",
36
+ "@alwaysmeticulous/downloading-helpers": "2.280.0",
37
+ "@alwaysmeticulous/record": "2.280.0",
38
+ "@alwaysmeticulous/remote-replay-launcher": "2.280.0",
39
+ "@alwaysmeticulous/replay-debugger-ui": "2.280.0",
40
+ "@alwaysmeticulous/replay-orchestrator-launcher": "2.280.0",
41
+ "@alwaysmeticulous/sdk-bundles-api": "2.280.0",
42
+ "@alwaysmeticulous/sentry": "2.280.0",
43
+ "@alwaysmeticulous/tunnels-client": "2.280.0",
44
44
  "@sentry/node": "^10.3.0",
45
45
  "chalk": "^4.1.2",
46
46
  "ci-info": "^4.0.0",
@@ -49,6 +49,7 @@
49
49
  "ora": "^5.4.1",
50
50
  "parse-diff": "^0.11.1",
51
51
  "puppeteer-core": "24.14.0",
52
+ "tar": "^7.5.8",
52
53
  "yargs": "^17.5.1"
53
54
  },
54
55
  "devDependencies": {
@@ -75,5 +76,5 @@
75
76
  "bugs": {
76
77
  "url": "https://github.com/alwaysmeticulous/meticulous-sdk/issues"
77
78
  },
78
- "gitHead": "018a659c723bb2c0be6de995357e974d2e7b8c3a"
79
+ "gitHead": "87ca975a232d16ea878caa5649a8b21221ebca02"
79
80
  }