@scrymore/scry-deployer 0.12.4-nightly.20261010032437 → 0.12.4
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/README.md +5 -1
- package/bin/cli.js +18 -13
- package/lib/errors.js +14 -0
- package/lib/imageUpload.js +2 -1
- package/lib/localImageProcessing.js +2 -1
- package/lib/telemetry.js +17 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1073,6 +1073,10 @@ otherwise quote in full.
|
|
|
1073
1073
|
|
|
1074
1074
|
Nothing is reported on a successful run.
|
|
1075
1075
|
|
|
1076
|
+
Your own mistakes (a missing or wrong `--dir`, a folder with no images, a missing key or
|
|
1077
|
+
env var) print a message and exit 1 but are not reported. Nothing is reported when
|
|
1078
|
+
`NODE_ENV=test` or `CI` is set to a true value.
|
|
1079
|
+
|
|
1076
1080
|
**To opt out**, set either variable:
|
|
1077
1081
|
|
|
1078
1082
|
```bash
|
|
@@ -1080,7 +1084,7 @@ export SCRY_TELEMETRY=0 # Scry-specific
|
|
|
1080
1084
|
export DO_NOT_TRACK=1 # respected across many CLI tools
|
|
1081
1085
|
```
|
|
1082
1086
|
|
|
1083
|
-
Both are honoured everywhere
|
|
1087
|
+
Both are honoured everywhere.
|
|
1084
1088
|
|
|
1085
1089
|
## 🔧 Troubleshooting the Init Command
|
|
1086
1090
|
|
package/bin/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ const os = require('os');
|
|
|
9
9
|
const { zipDirectory } = require('../lib/archive.js');
|
|
10
10
|
const { getApiClient, uploadBuild, sanitizeServerText } = require('../lib/apiClient.js');
|
|
11
11
|
const { createLogger } = require('../lib/logger.js');
|
|
12
|
-
const { ApiError } = require('../lib/errors.js');
|
|
12
|
+
const { ApiError, UserInputError } = require('../lib/errors.js');
|
|
13
13
|
const { loadConfig } = require('../lib/config.js');
|
|
14
14
|
const { captureScreenshots } = require('../lib/screencap.js');
|
|
15
15
|
const { analyzeStorybook } = require('../lib/analysis.js');
|
|
@@ -651,11 +651,16 @@ async function handleError(error, argv) {
|
|
|
651
651
|
logger.debug(err.stack);
|
|
652
652
|
}
|
|
653
653
|
|
|
654
|
-
//
|
|
655
|
-
//
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
654
|
+
// A user's own mistake (wrong folder, no images, missing env var) is printed above with
|
|
655
|
+
// how to fix it and exits 1; it is not a defect, so it is not reported (it only spent
|
|
656
|
+
// error-reporting quota). Everything else is reported.
|
|
657
|
+
if (!(err instanceof UserInputError)) {
|
|
658
|
+
// Report with an allowlisted subset of argv. Sending argv wholesale shipped
|
|
659
|
+
// the customer's --api-key to Sentry on every error.
|
|
660
|
+
captureCliError(err, argv);
|
|
661
|
+
// Ensure the event is sent before the process exits
|
|
662
|
+
try { await flushTelemetry(2000); } catch { /* telemetry must never mask the real error */ }
|
|
663
|
+
}
|
|
659
664
|
|
|
660
665
|
process.exit(1);
|
|
661
666
|
}
|
|
@@ -775,15 +780,15 @@ async function main() {
|
|
|
775
780
|
|
|
776
781
|
// Validate required fields
|
|
777
782
|
if (!config.dir) {
|
|
778
|
-
throw new
|
|
783
|
+
throw new UserInputError('--dir is required. You can provide it via CLI arguments, config file, or environment variables.');
|
|
779
784
|
}
|
|
780
785
|
|
|
781
786
|
// Validate directory exists and is valid
|
|
782
787
|
if (!fs.existsSync(config.dir)) {
|
|
783
|
-
throw new
|
|
788
|
+
throw new UserInputError(`Directory not found at path: ${config.dir}`);
|
|
784
789
|
}
|
|
785
790
|
if (!fs.lstatSync(config.dir).isDirectory()) {
|
|
786
|
-
throw new
|
|
791
|
+
throw new UserInputError(`Path is not a directory: ${config.dir}`);
|
|
787
792
|
}
|
|
788
793
|
|
|
789
794
|
// Advisory, bounded to 2 s, never fails the deploy.
|
|
@@ -1119,14 +1124,14 @@ async function main() {
|
|
|
1119
1124
|
const config = loadConfig(argv);
|
|
1120
1125
|
|
|
1121
1126
|
if (!config.dir) {
|
|
1122
|
-
throw new
|
|
1127
|
+
throw new UserInputError('--dir is required. Provide a path to the image directory.');
|
|
1123
1128
|
}
|
|
1124
1129
|
|
|
1125
1130
|
if (!fs.existsSync(config.dir)) {
|
|
1126
|
-
throw new
|
|
1131
|
+
throw new UserInputError(`Directory not found: ${config.dir}`);
|
|
1127
1132
|
}
|
|
1128
1133
|
if (!fs.lstatSync(config.dir).isDirectory()) {
|
|
1129
|
-
throw new
|
|
1134
|
+
throw new UserInputError(`Path is not a directory: ${config.dir}`);
|
|
1130
1135
|
}
|
|
1131
1136
|
|
|
1132
1137
|
if (config.local) {
|
|
@@ -1182,7 +1187,7 @@ function resolveLocalProcessingKeys(config) {
|
|
|
1182
1187
|
const envName = env.split(' ')[0];
|
|
1183
1188
|
resolved[key] = config[key] || process.env[envName] || (key === 'jinaApiKey' ? process.env.JINA_API_KEY : undefined);
|
|
1184
1189
|
if (!resolved[key]) {
|
|
1185
|
-
throw new
|
|
1190
|
+
throw new UserInputError(`${flag} or ${env} env var is required for local mode`);
|
|
1186
1191
|
}
|
|
1187
1192
|
}
|
|
1188
1193
|
|
package/lib/errors.js
CHANGED
|
@@ -43,8 +43,22 @@ class UploadError extends AppError {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The user's own mistake, with a message that already says how to fix it: a
|
|
48
|
+
* missing or wrong folder, a folder with no images, a required key or env var
|
|
49
|
+
* that was not given. The CLI prints the message and exits 1 like any other
|
|
50
|
+
* error, but it is not a defect in the CLI, so it is never sent to error
|
|
51
|
+
* reporting (it would only spend quota on something we cannot fix).
|
|
52
|
+
*/
|
|
53
|
+
class UserInputError extends AppError {
|
|
54
|
+
constructor(message) {
|
|
55
|
+
super(message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
module.exports = {
|
|
47
60
|
AppError,
|
|
61
|
+
UserInputError,
|
|
48
62
|
FileSystemError,
|
|
49
63
|
ApiError,
|
|
50
64
|
UploadError,
|
package/lib/imageUpload.js
CHANGED
|
@@ -4,6 +4,7 @@ const os = require('os');
|
|
|
4
4
|
const { zipDirectory } = require('./archive.js');
|
|
5
5
|
const { getApiClient, requestPresignedUrl, putToPresignedUrl } = require('./apiClient.js');
|
|
6
6
|
const { createLogger } = require('./logger.js');
|
|
7
|
+
const { UserInputError } = require('./errors.js');
|
|
7
8
|
|
|
8
9
|
const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg']);
|
|
9
10
|
|
|
@@ -59,7 +60,7 @@ async function runQueueImageUpload(config) {
|
|
|
59
60
|
logger.info('Scanning for images...');
|
|
60
61
|
const imageFiles = findImageFiles(config.dir);
|
|
61
62
|
if (imageFiles.length === 0) {
|
|
62
|
-
throw new
|
|
63
|
+
throw new UserInputError(`No image files (.png, .jpg, .jpeg) found in: ${config.dir}`);
|
|
63
64
|
}
|
|
64
65
|
logger.success(`Found ${imageFiles.length} images`);
|
|
65
66
|
|
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const { XMLParser } = require('fast-xml-parser');
|
|
5
5
|
const { createLogger } = require('./logger.js');
|
|
6
|
+
const { UserInputError } = require('./errors.js');
|
|
6
7
|
const { findImageFiles } = require('./imageUpload.js');
|
|
7
8
|
const { sanitizeServerText } = require('./apiClient.js');
|
|
8
9
|
|
|
@@ -659,7 +660,7 @@ async function runLocalImageProcessing(config) {
|
|
|
659
660
|
logger.info('Step 1: Scanning for images...');
|
|
660
661
|
const imageFiles = findImageFiles(config.dir);
|
|
661
662
|
if (imageFiles.length === 0) {
|
|
662
|
-
throw new
|
|
663
|
+
throw new UserInputError(`No image files (.png, .jpg, .jpeg) found in: ${config.dir}`);
|
|
663
664
|
}
|
|
664
665
|
logger.success(`Found ${imageFiles.length} images (${elapsed()})`);
|
|
665
666
|
|
package/lib/telemetry.js
CHANGED
|
@@ -22,6 +22,7 @@ const Sentry = require('@sentry/node');
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
const { version: PACKAGE_VERSION } = require('../package.json');
|
|
25
|
+
const { UserInputError } = require('./errors.js');
|
|
25
26
|
|
|
26
27
|
const DSN =
|
|
27
28
|
'https://c66ce229a1db2289f145eebd02436d9c@o4507889391828992.ingest.us.sentry.io/4510699330732032';
|
|
@@ -115,7 +116,19 @@ function scrub(value) {
|
|
|
115
116
|
function telemetryDisabled() {
|
|
116
117
|
const off = (v) => v === '1' || v === 'true' || v === 'yes';
|
|
117
118
|
return off(process.env.DO_NOT_TRACK) || process.env.SCRY_TELEMETRY === '0' ||
|
|
118
|
-
process.env.SCRY_TELEMETRY === 'false';
|
|
119
|
+
process.env.SCRY_TELEMETRY === 'false' || isAutomatedRun();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* A test run or a CI job: failures there are expected and routine (our own
|
|
124
|
+
* suites run the real CLI against deliberately broken input, and a CI job
|
|
125
|
+
* retries), so they never use error-reporting quota. `CI` counts when it is
|
|
126
|
+
* set to anything but an explicit false value.
|
|
127
|
+
*/
|
|
128
|
+
function isAutomatedRun() {
|
|
129
|
+
const ci = process.env.CI;
|
|
130
|
+
const ciOn = ci !== undefined && ci !== '' && ci !== '0' && ci.toLowerCase() !== 'false';
|
|
131
|
+
return process.env.NODE_ENV === 'test' || ciOn;
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
/** Only the fields on the allowlist, and scrubbed even then. */
|
|
@@ -185,6 +198,8 @@ function initTelemetry() {
|
|
|
185
198
|
/** Report an error with only the context that is safe to leave the machine. */
|
|
186
199
|
function captureCliError(error, argv) {
|
|
187
200
|
if (telemetryDisabled()) return;
|
|
201
|
+
// Second line of defence behind handleError: a user's own mistake is never reported.
|
|
202
|
+
if (error instanceof UserInputError) return;
|
|
188
203
|
|
|
189
204
|
Sentry.withScope((scope) => {
|
|
190
205
|
const safe = sanitizeArgv(argv);
|
|
@@ -210,6 +225,7 @@ module.exports = {
|
|
|
210
225
|
captureCliError,
|
|
211
226
|
flushTelemetry,
|
|
212
227
|
telemetryDisabled,
|
|
228
|
+
isAutomatedRun,
|
|
213
229
|
sanitizeArgv,
|
|
214
230
|
redactArgv,
|
|
215
231
|
scrub,
|