@elastic/synthetics 1.8.0 → 1.9.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/dist/cli.js +11 -9
- package/dist/cli.js.map +1 -1
- package/dist/common_types.d.ts +12 -3
- package/dist/common_types.d.ts.map +1 -1
- package/dist/core/expect.d.ts +1 -1
- package/dist/core/expect.d.ts.map +1 -1
- package/dist/core/expect.js +10 -1
- package/dist/core/expect.js.map +1 -1
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +12 -6
- package/dist/core/runner.js.map +1 -1
- package/dist/dsl/monitor.d.ts +4 -0
- package/dist/dsl/monitor.d.ts.map +1 -1
- package/dist/dsl/monitor.js +6 -0
- package/dist/dsl/monitor.js.map +1 -1
- package/dist/generator/index.d.ts.map +1 -1
- package/dist/generator/index.js +22 -16
- package/dist/generator/index.js.map +1 -1
- package/dist/options.d.ts +11 -2
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +66 -59
- package/dist/options.js.map +1 -1
- package/dist/push/index.d.ts.map +1 -1
- package/dist/push/index.js +14 -9
- package/dist/push/index.js.map +1 -1
- package/dist/push/monitor.d.ts.map +1 -1
- package/dist/push/monitor.js +9 -2
- package/dist/push/monitor.js.map +1 -1
- package/dist/push/request.d.ts.map +1 -1
- package/dist/push/request.js +3 -2
- package/dist/push/request.js.map +1 -1
- package/package.json +16 -6
- package/src/cli.ts +24 -13
- package/src/common_types.ts +13 -3
- package/src/core/expect.ts +13 -3
- package/src/core/runner.ts +17 -6
- package/src/dsl/monitor.ts +13 -1
- package/src/generator/index.ts +24 -20
- package/src/options.ts +81 -66
- package/src/push/index.ts +22 -9
- package/src/push/monitor.ts +12 -3
- package/src/push/request.ts +3 -6
- package/dist/bundles/lib/index.js +0 -430
package/src/core/expect.ts
CHANGED
|
@@ -23,8 +23,19 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
import { join } from 'path';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* This file is a workaround to extend the expect functionality from Playwright package
|
|
30
|
+
* with few extensions that we don't support in Synthetics.
|
|
31
|
+
*
|
|
32
|
+
* We are requiring the package using absolute path to workaround the Module
|
|
33
|
+
* resolution export issues.
|
|
34
|
+
*/
|
|
35
|
+
|
|
26
36
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
27
|
-
const
|
|
37
|
+
const PW_PATH = require.resolve('playwright').replace('index.js', '');
|
|
38
|
+
const expectLib = require(join(PW_PATH, 'lib/matchers/expect')).expect;
|
|
28
39
|
|
|
29
40
|
function notSupported(name: string) {
|
|
30
41
|
throw new Error(`expect.${name} is not supported in @elastic/synthetics.`);
|
|
@@ -39,5 +50,4 @@ expectLib.extend({
|
|
|
39
50
|
toMatchSnapshot: () => notSupported('toMatchSnapshot'),
|
|
40
51
|
});
|
|
41
52
|
|
|
42
|
-
export const expect: typeof import('
|
|
43
|
-
expectLib;
|
|
53
|
+
export const expect: typeof import('playwright/types/test').expect = expectLib;
|
package/src/core/runner.ts
CHANGED
|
@@ -404,8 +404,7 @@ export default class Runner {
|
|
|
404
404
|
|
|
405
405
|
buildMonitors(options: PushOptions) {
|
|
406
406
|
/**
|
|
407
|
-
* Update the global monitor configuration required for
|
|
408
|
-
* setting defaults
|
|
407
|
+
* Update the global monitor configuration required for setting defaults
|
|
409
408
|
*/
|
|
410
409
|
this.updateMonitor({
|
|
411
410
|
throttling: options.throttling,
|
|
@@ -430,11 +429,23 @@ export default class Runner {
|
|
|
430
429
|
);
|
|
431
430
|
}
|
|
432
431
|
/**
|
|
433
|
-
*
|
|
434
|
-
*
|
|
432
|
+
* Before pushing a browser monitor, three things need to be done:
|
|
433
|
+
*
|
|
434
|
+
* - execute callback `monitor.use` in particular to get monitor configurations
|
|
435
|
+
* - update the monitor config with global configuration
|
|
436
|
+
* - filter out monitors based on matched tags and name after applying both
|
|
437
|
+
* global and local monitor configurations
|
|
435
438
|
*/
|
|
436
439
|
journey.callback({ params: options.params } as any);
|
|
437
440
|
journey.monitor.update(this.monitor?.config);
|
|
441
|
+
if (
|
|
442
|
+
!journey.monitor.isMatch(
|
|
443
|
+
options.grepOpts?.match,
|
|
444
|
+
options.grepOpts?.tags
|
|
445
|
+
)
|
|
446
|
+
) {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
438
449
|
journey.monitor.validate();
|
|
439
450
|
monitors.push(journey.monitor);
|
|
440
451
|
}
|
|
@@ -454,7 +465,7 @@ export default class Runner {
|
|
|
454
465
|
params: options.params,
|
|
455
466
|
}).catch(e => (this.hookError = e));
|
|
456
467
|
|
|
457
|
-
const { dryRun,
|
|
468
|
+
const { dryRun, grepOpts } = options;
|
|
458
469
|
/**
|
|
459
470
|
* Skip other journeys when using `.only`
|
|
460
471
|
*/
|
|
@@ -471,7 +482,7 @@ export default class Runner {
|
|
|
471
482
|
this.#reporter.onJourneyRegister?.(journey);
|
|
472
483
|
continue;
|
|
473
484
|
}
|
|
474
|
-
if (!journey.isMatch(match, tags) || journey.skip) {
|
|
485
|
+
if (!journey.isMatch(grepOpts?.match, grepOpts?.tags) || journey.skip) {
|
|
475
486
|
continue;
|
|
476
487
|
}
|
|
477
488
|
const journeyResult: JourneyResult = this.hookError
|
package/src/dsl/monitor.ts
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
Params,
|
|
34
34
|
PlaywrightOptions,
|
|
35
35
|
} from '../common_types';
|
|
36
|
-
import { indent } from '../helpers';
|
|
36
|
+
import { indent, isMatch } from '../helpers';
|
|
37
37
|
import { LocationsMap } from '../locations/public-locations';
|
|
38
38
|
|
|
39
39
|
export type SyntheticsLocationsType = keyof typeof LocationsMap;
|
|
@@ -129,6 +129,18 @@ export class Monitor {
|
|
|
129
129
|
this.filter = filter;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Matches monitors based on the provided args. Proitize tags over match
|
|
134
|
+
*/
|
|
135
|
+
isMatch(matchPattern: string, tagsPattern: Array<string>) {
|
|
136
|
+
return isMatch(
|
|
137
|
+
this.config.tags,
|
|
138
|
+
this.config.name,
|
|
139
|
+
tagsPattern,
|
|
140
|
+
matchPattern
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
132
144
|
/**
|
|
133
145
|
* Hash is used to identify if the monitor has changed since the last time
|
|
134
146
|
* it was pushed to Kibana. Change is based on three factors:
|
package/src/generator/index.ts
CHANGED
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
* THE SOFTWARE.
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
|
+
import { URL } from 'url';
|
|
25
26
|
import { execSync } from 'child_process';
|
|
26
27
|
import { existsSync } from 'fs';
|
|
27
28
|
import { mkdir, readFile, writeFile } from 'fs/promises';
|
|
28
29
|
import { bold, cyan, yellow } from 'kleur/colors';
|
|
29
30
|
import { join, relative, dirname, basename } from 'path';
|
|
30
31
|
// @ts-ignore-next-line: has no exported member 'Input'
|
|
31
|
-
import { prompt, Input } from 'enquirer';
|
|
32
|
+
import { prompt, Input, Password } from 'enquirer';
|
|
32
33
|
import { getProjectApiKeyURL, progress, write as stdWrite } from '../helpers';
|
|
33
34
|
import {
|
|
34
35
|
getPackageManager,
|
|
@@ -60,6 +61,8 @@ export const REGULAR_FILES_PATH = [
|
|
|
60
61
|
];
|
|
61
62
|
export const CONFIG_PATH = 'synthetics.config.ts';
|
|
62
63
|
|
|
64
|
+
const IS_URL = new RegExp('^(https?:\\/\\/)');
|
|
65
|
+
|
|
63
66
|
export class Generator {
|
|
64
67
|
pkgManager = 'npm';
|
|
65
68
|
constructor(public projectDir: string) {}
|
|
@@ -80,29 +83,30 @@ export class Generator {
|
|
|
80
83
|
return JSON.parse(process.env.TEST_QUESTIONS);
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
const { onCloud } = await prompt<{ onCloud: string }>({
|
|
84
|
-
type: 'confirm',
|
|
85
|
-
name: 'onCloud',
|
|
86
|
-
initial: 'y',
|
|
87
|
-
message: 'Do you use Elastic Cloud',
|
|
88
|
-
});
|
|
89
86
|
const url = await new Input({
|
|
90
|
-
header: onCloud
|
|
91
|
-
? yellow(
|
|
92
|
-
'Get cloud.id from your deployment https://www.elastic.co/guide/en/cloud/current/ec-cloud-id.html'
|
|
93
|
-
)
|
|
94
|
-
: '',
|
|
95
|
-
message: onCloud
|
|
96
|
-
? 'What is your cloud.id'
|
|
97
|
-
: 'What is the url of your Kibana instance',
|
|
98
87
|
name: 'url',
|
|
88
|
+
message: 'Enter Elastic Kibana URL or Cloud ID',
|
|
99
89
|
required: true,
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
validate(value) {
|
|
91
|
+
try {
|
|
92
|
+
if (!IS_URL.test(value)) {
|
|
93
|
+
value = cloudIDToKibanaURL(value);
|
|
94
|
+
}
|
|
95
|
+
new URL(value);
|
|
96
|
+
return true;
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return 'Invalid URL or Cloud ID';
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
result(value: string) {
|
|
102
|
+
if (!IS_URL.test(value)) {
|
|
103
|
+
value = cloudIDToKibanaURL(value);
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
102
106
|
},
|
|
103
107
|
}).run();
|
|
104
108
|
|
|
105
|
-
const auth = await new
|
|
109
|
+
const auth = await new Password({
|
|
106
110
|
name: 'auth',
|
|
107
111
|
header: yellow(
|
|
108
112
|
`Generate API key from Kibana ${getProjectApiKeyURL(url)}`
|
|
@@ -249,7 +253,7 @@ export class Generator {
|
|
|
249
253
|
}
|
|
250
254
|
// Add push command
|
|
251
255
|
if (!pkgJSON.scripts.push) {
|
|
252
|
-
pkgJSON.scripts.push =
|
|
256
|
+
pkgJSON.scripts.push = `npx @elastic/synthetics push`;
|
|
253
257
|
}
|
|
254
258
|
|
|
255
259
|
await this.createFile(
|
|
@@ -287,7 +291,7 @@ All set, you can run below commands inside: ${this.projectDir}:
|
|
|
287
291
|
)}
|
|
288
292
|
|
|
289
293
|
${yellow(
|
|
290
|
-
'
|
|
294
|
+
'Configure API Key via `SYNTHETICS_API_KEY` env variable or --auth CLI flag.'
|
|
291
295
|
)}
|
|
292
296
|
|
|
293
297
|
Visit https://www.elastic.co/guide/en/observability/current/synthetic-run-tests.html to learn more.
|
package/src/options.ts
CHANGED
|
@@ -26,74 +26,49 @@
|
|
|
26
26
|
import merge from 'deepmerge';
|
|
27
27
|
import { createOption } from 'commander';
|
|
28
28
|
import { readConfig } from './config';
|
|
29
|
-
import type { CliArgs,
|
|
30
|
-
import { THROTTLING_WARNING_MSG,
|
|
29
|
+
import type { CliArgs, RunOptions } from './common_types';
|
|
30
|
+
import { THROTTLING_WARNING_MSG, warn } from './helpers';
|
|
31
31
|
|
|
32
32
|
type Mode = 'run' | 'push';
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Normalize the options passed via CLI and Synthetics config file
|
|
36
|
+
*
|
|
37
|
+
* Order of preference for options:
|
|
38
|
+
* 1. Local options configured via Runner API
|
|
39
|
+
* 2. CLI flags
|
|
40
|
+
* 3. Configuration file
|
|
41
|
+
*/
|
|
34
42
|
export async function normalizeOptions(
|
|
35
43
|
cliArgs: CliArgs,
|
|
36
44
|
mode: Mode = 'run'
|
|
37
45
|
): Promise<RunOptions> {
|
|
46
|
+
/**
|
|
47
|
+
* Move filtering flags from the top level to filter object
|
|
48
|
+
* and delete the old keys
|
|
49
|
+
*/
|
|
50
|
+
const grepOpts = {
|
|
51
|
+
pattern: cliArgs.pattern,
|
|
52
|
+
tags: cliArgs.tags,
|
|
53
|
+
match: cliArgs.match,
|
|
54
|
+
};
|
|
55
|
+
delete cliArgs.pattern;
|
|
56
|
+
delete cliArgs.tags;
|
|
57
|
+
delete cliArgs.match;
|
|
58
|
+
|
|
38
59
|
const options: RunOptions = {
|
|
39
60
|
...cliArgs,
|
|
61
|
+
grepOpts,
|
|
40
62
|
environment: process.env['NODE_ENV'] || 'development',
|
|
41
63
|
};
|
|
42
64
|
/**
|
|
43
|
-
*
|
|
44
|
-
* eventually by the Synthetics UI.
|
|
45
|
-
*/
|
|
46
|
-
if (cliArgs.richEvents) {
|
|
47
|
-
options.reporter = cliArgs.reporter ?? 'json';
|
|
48
|
-
options.ssblocks = true;
|
|
49
|
-
options.network = true;
|
|
50
|
-
options.trace = true;
|
|
51
|
-
options.quietExitCode = true;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (cliArgs.capability) {
|
|
55
|
-
const supportedCapabilities = [
|
|
56
|
-
'trace',
|
|
57
|
-
'network',
|
|
58
|
-
'filmstrips',
|
|
59
|
-
'metrics',
|
|
60
|
-
'ssblocks',
|
|
61
|
-
];
|
|
62
|
-
/**
|
|
63
|
-
* trace - record chrome trace events(LCP, FCP, CLS, etc.) for all journeys
|
|
64
|
-
* network - capture network information for all journeys
|
|
65
|
-
* filmstrips - record detailed filmstrips for all journeys
|
|
66
|
-
* metrics - capture performance metrics (DOM Nodes, Heap size, etc.) for each step
|
|
67
|
-
* ssblocks - Dedupes the screenshots in to blocks to save storage space
|
|
68
|
-
*/
|
|
69
|
-
for (const flag of cliArgs.capability) {
|
|
70
|
-
if (supportedCapabilities.includes(flag)) {
|
|
71
|
-
options[flag] = true;
|
|
72
|
-
} else {
|
|
73
|
-
console.warn(
|
|
74
|
-
`Missing capability "${flag}", current supported capabilities are ${supportedCapabilities.join(
|
|
75
|
-
', '
|
|
76
|
-
)}`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Validate and read synthetics config file
|
|
84
|
-
* based on the environment
|
|
65
|
+
* Validate and read synthetics config file based on the environment
|
|
85
66
|
*/
|
|
86
67
|
const config =
|
|
87
68
|
cliArgs.config || !cliArgs.inline
|
|
88
69
|
? await readConfig(options.environment, cliArgs.config)
|
|
89
70
|
: {};
|
|
90
71
|
|
|
91
|
-
/**
|
|
92
|
-
* Order of preference for options that are used while running are
|
|
93
|
-
* 1. Local options configured via Runner API
|
|
94
|
-
* 2. CLI flags
|
|
95
|
-
* 3. Configuration file
|
|
96
|
-
*/
|
|
97
72
|
options.params = Object.freeze(merge(config.params, cliArgs.params || {}));
|
|
98
73
|
|
|
99
74
|
/**
|
|
@@ -118,10 +93,49 @@ export async function normalizeOptions(
|
|
|
118
93
|
*/
|
|
119
94
|
switch (mode) {
|
|
120
95
|
case 'run':
|
|
96
|
+
if (cliArgs.capability) {
|
|
97
|
+
const supportedCapabilities = [
|
|
98
|
+
'trace',
|
|
99
|
+
'network',
|
|
100
|
+
'filmstrips',
|
|
101
|
+
'metrics',
|
|
102
|
+
'ssblocks',
|
|
103
|
+
];
|
|
104
|
+
/**
|
|
105
|
+
* trace - record chrome trace events(LCP, FCP, CLS, etc.) for all journeys
|
|
106
|
+
* network - capture network information for all journeys
|
|
107
|
+
* filmstrips - record detailed filmstrips for all journeys
|
|
108
|
+
* metrics - capture performance metrics (DOM Nodes, Heap size, etc.) for each step
|
|
109
|
+
* ssblocks - Dedupes the screenshots in to blocks to save storage space
|
|
110
|
+
*/
|
|
111
|
+
for (const flag of cliArgs.capability) {
|
|
112
|
+
if (supportedCapabilities.includes(flag)) {
|
|
113
|
+
options[flag] = true;
|
|
114
|
+
} else {
|
|
115
|
+
console.warn(
|
|
116
|
+
`Missing capability "${flag}", current supported capabilities are ${supportedCapabilities.join(
|
|
117
|
+
', '
|
|
118
|
+
)}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Group all events that can be consumed by heartbeat and
|
|
126
|
+
* eventually by the Synthetics UI.
|
|
127
|
+
*/
|
|
128
|
+
if (cliArgs.richEvents) {
|
|
129
|
+
options.reporter = cliArgs.reporter ?? 'json';
|
|
130
|
+
options.ssblocks = true;
|
|
131
|
+
options.network = true;
|
|
132
|
+
options.trace = true;
|
|
133
|
+
options.quietExitCode = true;
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
options.screenshots = cliArgs.screenshots ?? 'on';
|
|
122
137
|
break;
|
|
123
138
|
case 'push':
|
|
124
|
-
validatePushOptions(options as PushOptions);
|
|
125
139
|
/**
|
|
126
140
|
* Merge the default monitor config from synthetics.config.ts file
|
|
127
141
|
* with the CLI options passed via push command
|
|
@@ -152,14 +166,6 @@ export function getHeadlessFlag(
|
|
|
152
166
|
return configHeadless ?? true;
|
|
153
167
|
}
|
|
154
168
|
|
|
155
|
-
export function validatePushOptions(opts: PushOptions) {
|
|
156
|
-
if (opts.tags || opts.match) {
|
|
157
|
-
throw error(`Aborted. Invalid CLI flags.
|
|
158
|
-
|
|
159
|
-
Tags and Match are not supported in push command.`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
169
|
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
|
164
170
|
function toObject(value: boolean | Record<string, any>): Record<string, any> {
|
|
165
171
|
const defaulVal = {};
|
|
@@ -183,19 +189,17 @@ export function parseThrottling() {
|
|
|
183
189
|
export function getCommonCommandOpts() {
|
|
184
190
|
const params = createOption(
|
|
185
191
|
'-p, --params <jsonstring>',
|
|
186
|
-
'JSON object that
|
|
187
|
-
);
|
|
188
|
-
params.argParser(JSON.parse);
|
|
192
|
+
'JSON object that defines any variables your tests require.'
|
|
193
|
+
).argParser(JSON.parse);
|
|
189
194
|
|
|
190
195
|
const playwrightOpts = createOption(
|
|
191
196
|
'--playwright-options <jsonstring>',
|
|
192
197
|
'JSON object to pass in custom Playwright options for the agent. Options passed will be merged with Playwright options defined in your synthetics.config.js file.'
|
|
193
|
-
);
|
|
194
|
-
playwrightOpts.argParser(JSON.parse);
|
|
198
|
+
).argParser(JSON.parse);
|
|
195
199
|
|
|
196
200
|
const pattern = createOption(
|
|
197
201
|
'--pattern <pattern>',
|
|
198
|
-
'RegExp pattern to match journey
|
|
202
|
+
'RegExp pattern to match journey files in the current working directory (default: /*.journey.(ts|js)$/)'
|
|
199
203
|
);
|
|
200
204
|
|
|
201
205
|
const apiDocsLink =
|
|
@@ -210,7 +214,16 @@ export function getCommonCommandOpts() {
|
|
|
210
214
|
|
|
211
215
|
const configOpt = createOption(
|
|
212
216
|
'-c, --config <path>',
|
|
213
|
-
'configuration
|
|
217
|
+
'path to the configuration file (default: synthetics.config.(js|ts))'
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const tags = createOption(
|
|
221
|
+
'--tags <name...>',
|
|
222
|
+
'run/push tests with the tag(s) matching a pattern'
|
|
223
|
+
);
|
|
224
|
+
const match = createOption(
|
|
225
|
+
'--match <name>',
|
|
226
|
+
'run/push tests with a name or tags that matches a pattern'
|
|
214
227
|
);
|
|
215
228
|
|
|
216
229
|
return {
|
|
@@ -220,5 +233,7 @@ export function getCommonCommandOpts() {
|
|
|
220
233
|
playwrightOpts,
|
|
221
234
|
pattern,
|
|
222
235
|
configOpt,
|
|
236
|
+
tags,
|
|
237
|
+
match,
|
|
223
238
|
};
|
|
224
239
|
}
|
package/src/push/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
isLightweightMonitorSupported,
|
|
59
59
|
logDiff,
|
|
60
60
|
} from './utils';
|
|
61
|
+
import { log } from '../core/logger';
|
|
61
62
|
|
|
62
63
|
export async function push(monitors: Monitor[], options: PushOptions) {
|
|
63
64
|
const duplicates = trackDuplicates(monitors);
|
|
@@ -99,8 +100,17 @@ export async function push(monitors: Monitor[], options: PushOptions) {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
if (removedIDs.size > 0) {
|
|
103
|
+
log(`deleting monitor ids: ${Array.from(removedIDs.keys()).join(', ')}`);
|
|
102
104
|
if (updatedMonitors.size === 0 && unchangedIDs.size === 0) {
|
|
103
|
-
await
|
|
105
|
+
await confirmDelete(
|
|
106
|
+
`Pushing without any monitors will delete all monitors associated with the project.\n Do you want to continue?`,
|
|
107
|
+
options.yes
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
await confirmDelete(
|
|
111
|
+
`Deleting ${removedIDs.size} monitors. Do you want to continue?`,
|
|
112
|
+
options.yes
|
|
113
|
+
);
|
|
104
114
|
}
|
|
105
115
|
const chunks = getChunks(Array.from(removedIDs), CHUNK_SIZE);
|
|
106
116
|
for (const chunk of chunks) {
|
|
@@ -114,22 +124,22 @@ export async function push(monitors: Monitor[], options: PushOptions) {
|
|
|
114
124
|
done(`Pushed: ${grey(getMonitorManagementURL(options.url))}`);
|
|
115
125
|
}
|
|
116
126
|
|
|
117
|
-
async function
|
|
118
|
-
|
|
119
|
-
const { deleteAll } = await prompt<{ deleteAll: boolean }>({
|
|
127
|
+
async function confirmDelete(message: string, skip: boolean) {
|
|
128
|
+
const { deleteMonitors } = await prompt<{ deleteMonitors: boolean }>({
|
|
120
129
|
type: 'confirm',
|
|
121
130
|
skip() {
|
|
122
|
-
|
|
131
|
+
write('');
|
|
132
|
+
if (skip || !process.stdout.isTTY) {
|
|
123
133
|
this.initial = process.env.TEST_OVERRIDE ?? true;
|
|
124
134
|
return true;
|
|
125
135
|
}
|
|
126
136
|
return false;
|
|
127
137
|
},
|
|
128
|
-
name: '
|
|
129
|
-
message
|
|
138
|
+
name: 'deleteMonitors',
|
|
139
|
+
message,
|
|
130
140
|
initial: false,
|
|
131
141
|
});
|
|
132
|
-
if (!
|
|
142
|
+
if (!deleteMonitors) {
|
|
133
143
|
throw warn('Push command Aborted');
|
|
134
144
|
}
|
|
135
145
|
}
|
|
@@ -288,7 +298,10 @@ export async function pushLegacy(monitors: Monitor[], options: PushOptions) {
|
|
|
288
298
|
);
|
|
289
299
|
}
|
|
290
300
|
} else {
|
|
291
|
-
await
|
|
301
|
+
await confirmDelete(
|
|
302
|
+
`Pushing without any monitors will delete all monitors associated with the project.\n Do you want to continue?`,
|
|
303
|
+
options.yes
|
|
304
|
+
);
|
|
292
305
|
}
|
|
293
306
|
await liveProgress(
|
|
294
307
|
createMonitorsLegacy({ schemas, keepStale: false, options }),
|
package/src/push/monitor.ts
CHANGED
|
@@ -167,8 +167,8 @@ export async function createLightweightMonitors(
|
|
|
167
167
|
) {
|
|
168
168
|
const lwFiles = new Set<string>();
|
|
169
169
|
// Filter monitor files based on the provided pattern
|
|
170
|
-
const pattern = options.pattern
|
|
171
|
-
? new RegExp(options.pattern, 'i')
|
|
170
|
+
const pattern = options.grepOpts?.pattern
|
|
171
|
+
? new RegExp(options.grepOpts?.pattern, 'i')
|
|
172
172
|
: /.(yml|yaml)$/;
|
|
173
173
|
const ignore = /(node_modules|.github)/;
|
|
174
174
|
await totalist(workDir, (rel, abs) => {
|
|
@@ -211,7 +211,9 @@ export async function createLightweightMonitors(
|
|
|
211
211
|
offsets.push(monNode.srcToken.offset);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
const mergedConfig = parsedDoc.toJS()[
|
|
214
|
+
const mergedConfig = parsedDoc.toJS()[
|
|
215
|
+
'heartbeat.monitors'
|
|
216
|
+
] as Array<MonitorConfig>;
|
|
215
217
|
for (let i = 0; i < mergedConfig.length; i++) {
|
|
216
218
|
const monitor = mergedConfig[i];
|
|
217
219
|
// Skip browser monitors from the YML files
|
|
@@ -220,7 +222,14 @@ export async function createLightweightMonitors(
|
|
|
220
222
|
}
|
|
221
223
|
const { line, col } = lineCounter.linePos(offsets[i]);
|
|
222
224
|
try {
|
|
225
|
+
/**
|
|
226
|
+
* Build the monitor object from the yaml config along with global configuration
|
|
227
|
+
* and perform the match based on the provided filters
|
|
228
|
+
*/
|
|
223
229
|
const mon = buildMonitorFromYaml(monitor, options);
|
|
230
|
+
if (!mon.isMatch(options.grepOpts?.match, options.grepOpts?.tags)) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
224
233
|
mon.setSource({ file, line, column: col });
|
|
225
234
|
monitors.push(mon);
|
|
226
235
|
} catch (e) {
|
package/src/push/request.ts
CHANGED
|
@@ -81,13 +81,10 @@ export async function handleError(
|
|
|
81
81
|
} else if (!ok(statusCode)) {
|
|
82
82
|
let parsed: APIError;
|
|
83
83
|
try {
|
|
84
|
-
|
|
84
|
+
const resp = await body.text();
|
|
85
|
+
parsed = JSON.parse(resp) as APIError;
|
|
85
86
|
} catch (e) {
|
|
86
|
-
throw formatAPIError(
|
|
87
|
-
statusCode,
|
|
88
|
-
'unexpected non-JSON error',
|
|
89
|
-
await body.text()
|
|
90
|
-
);
|
|
87
|
+
throw formatAPIError(statusCode, 'unexpected error', e.message);
|
|
91
88
|
}
|
|
92
89
|
throw formatAPIError(statusCode, parsed.error, parsed.message);
|
|
93
90
|
}
|