Repository: elastic/synthetics (ts)

Issue:
Fix push command to only push monitors that were modified/deleted
+ Currently we push all the monitors when pushing monitors, even when the monitor configuration is unchanged which causes confusion to all users. We can filter down and push the modified monitors (Added/Updated/Deleted) ones instead of pushing the all the unchanged monitors as well - https://github.com/elastic/synthetics/blob/21b4b2f4b9243be04bad8105048ef398970a83f7/src/push/index.ts#L93

+ Same is also applicable to deleted monitor list. 

Pull request description:
fix: push only newly created/updated monitors
+ fix #936 

Patch:
diff --git a/.nvmrc b/.nvmrc
index 87ec884..561a1e9 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1,1 +1,1 @@
-18.18.2
+18.20.3
diff --git a/package-lock.json b/package-lock.json
index 4bb6f56..b345398 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,9 +19,9 @@
         "kleur": "^4.1.5",
         "micromatch": "^4.0.5",
         "pirates": "^4.0.5",
-        "playwright": "=1.43.1",
-        "playwright-chromium": "=1.43.1",
-        "playwright-core": "=1.43.1",
+        "playwright": "=1.45.1",
+        "playwright-chromium": "=1.45.1",
+        "playwright-core": "=1.45.1",
         "semver": "^7.5.4",
         "sharp": "^0.32.6",
         "snakecase-keys": "^4.0.1",
@@ -13143,46 +13143,46 @@
       }
     },
     "node_modules/playwright": {
-      "version": "1.43.1",
-      "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
-      "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
+      "version": "1.45.1",
+      "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz",
+      "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==",
       "dependencies": {
-        "playwright-core": "1.43.1"
+        "playwright-core": "1.45.1"
       },
       "bin": {
         "playwright": "cli.js"
       },
       "engines": {
-        "node": ">=16"
+        "node": ">=18"
       },
       "optionalDependencies": {
         "fsevents": "2.3.2"
       }
     },
     "node_modules/playwright-chromium": {
-      "version": "1.43.1",
-      "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.43.1.tgz",
-      "integrity": "sha512-HL/11hcpIYVt/Rw7wTf5xwm+W0R76JGDDjRxGtBkgMuUqi0Q4UYmx+F/QxW/Z+aApSbDtHd3naRFcL/Jt7Aidg==",
+      "version": "1.45.1",
+      "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.45.1.tgz",
+      "integrity": "sha512-BlYo+kuMg4Jo40Nems2GGVMWdKI2GeHL85D7pkwEW3aq6iEDW3XL7udmoNLOIfluSCKzVRJMB0ta1mt67B3tGA==",
       "hasInstallScript": true,
       "dependencies": {
-        "playwright-core": "1.43.1"
+        "playwright-core": "1.45.1"
       },
       "bin": {
         "playwright": "cli.js"
       },
       "engines": {
-        "node": ">=16"
+        "node": ">=18"
       }
     },
     "node_modules/playwright-core": {
-      "version": "1.43.1",
-      "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
-      "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
+      "version": "1.45.1",
+      "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz",
+      "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==",
       "bin": {
         "playwright-core": "cli.js"
       },
       "engines": {
-        "node": ">=16"
+        "node": ">=18"
       }
     },
     "node_modules/please-upgrade-node": {
diff --git a/package.json b/package.json
index 40b46cc..b253b12 100644
--- a/package.json
+++ b/package.json
@@ -56,9 +56,9 @@
     "kleur": "^4.1.5",
     "micromatch": "^4.0.5",
     "pirates": "^4.0.5",
-    "playwright": "=1.43.1",
-    "playwright-chromium": "=1.43.1",
-    "playwright-core": "=1.43.1",
+    "playwright": "=1.45.1",
+    "playwright-chromium": "=1.45.1",
+    "playwright-core": "=1.45.1",
     "semver": "^7.5.4",
     "sharp": "^0.32.6",
     "snakecase-keys": "^4.0.1",
diff --git a/src/push/index.ts b/src/push/index.ts
index 5b86b9e..15a4309 100644
--- a/src/push/index.ts
+++ b/src/push/index.ts
@@ -78,7 +78,7 @@ export async function push(monitors: Monitor[], options: PushOptions) {
 
   const { monitors: remote } = await bulkGetMonitors(options);
 
-  progress(`bundling ${monitors.length} monitors`);
+  progress(`preparing ${monitors.length} monitors`);
   const schemas = await buildMonitorSchema(monitors, true);
   const local = getLocalMonitors(schemas);
 
@@ -90,7 +90,8 @@ export async function push(monitors: Monitor[], options: PushOptions) {
 
   const updatedMonitors = new Set<string>([...changedIDs, ...newIDs]);
   if (updatedMonitors.size > 0) {
-    const chunks = getChunks(schemas, CHUNK_SIZE);
+    const updatedMonSchemas = schemas.filter(s => updatedMonitors.has(s.id));
+    const chunks = getChunks(updatedMonSchemas, CHUNK_SIZE);
     for (const chunk of chunks) {
       await liveProgress(
         bulkPutMonitors(options, chunk),
@@ -217,9 +218,8 @@ export function validateSettings(opts: PushOptions) {
   - CLI '--schedule <mins>'
   - Config file 'monitors.schedule' field`;
   } else if (opts.schedule && !ALLOWED_SCHEDULES.includes(opts.schedule)) {
-    reason = `Set default schedule(${
-      opts.schedule
-    }) to one of the allowed values - ${ALLOWED_SCHEDULES.join(',')}`;
+    reason = `Set default schedule(${opts.schedule
+      }) to one of the allowed values - ${ALLOWED_SCHEDULES.join(',')}`;
   }
 
   if (!reason) return;
@@ -288,7 +288,7 @@ export async function pushLegacy(monitors: Monitor[], options: PushOptions) {
 
   let schemas: MonitorSchema[] = [];
   if (monitors.length > 0) {
-    progress(`bundling ${monitors.length} monitors`);
+    progress(`preparing ${monitors.length} monitors`);
     schemas = await buildMonitorSchema(monitors, false);
     const chunks = getChunks(schemas, 10);
     for (const chunk of chunks) {
diff --git a/src/push/utils.ts b/src/push/utils.ts
index ddeff38..7f0b70c 100644
--- a/src/push/utils.ts
+++ b/src/push/utils.ts
@@ -37,14 +37,14 @@ export function logDiff<T extends Set<string>>(
 ) {
   progress(
     'Monitor Diff: ' +
-      green(`Added(${newIDs.size}) `) +
-      yellow(`Updated(${changedIDs.size}) `) +
-      red(`Removed(${removedIDs.size}) `) +
-      grey(`Unchanged(${unchangedIDs.size})`)
+    green(`Added(${newIDs.size}) `) +
+    yellow(`Updated(${changedIDs.size}) `) +
+    red(`Removed(${removedIDs.size}) `) +
+    grey(`Unchanged(${unchangedIDs.size})`)
   );
 }
 
-export function getChunks(arr: any[], size: number) {
+export function getChunks<T>(arr: Array<T>, size: number): Array<T[]> {
   const chunks = [];
   for (let i = 0; i < arr.length; i += size) {
     chunks.push(arr.slice(i, i + size));


Test patch:
diff --git a/__tests__/options.test.ts b/__tests__/options.test.ts
index 5361ec8..283a755 100644
--- a/__tests__/options.test.ts
+++ b/__tests__/options.test.ts
@@ -66,7 +66,7 @@ describe('options', () => {
         ignoreHTTPSErrors: undefined,
         isMobile: true,
         userAgent:
-          'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36',
+          'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.17 Mobile Safari/537.36',
         viewport: {
           height: 658,
           width: 320,
diff --git a/__tests__/push/index.test.ts b/__tests__/push/index.test.ts
index b79e9ad..95e33a5 100644
--- a/__tests__/push/index.test.ts
+++ b/__tests__/push/index.test.ts
@@ -267,7 +267,7 @@ heartbeat.monitors:
         expect(output).toContain(
           "Pushing monitors for 'test-project' project in kibana 'dummy' space"
         );
-        expect(output).toContain('bundling 2 monitors');
+        expect(output).toContain('preparing 2 monitors');
         expect(output).toContain('creating or updating 2 monitors');
         expect(output).toContain(deleteProgress);
         expect(output).toContain('✓ Pushed:');