@postman-cse/onboarding-repo-sync 2.1.0 → 2.1.2

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/action.cjs CHANGED
@@ -122063,7 +122063,7 @@ function getIDToken(aud) {
122063
122063
  }
122064
122064
 
122065
122065
  // src/index.ts
122066
- var import_node_fs2 = require("node:fs");
122066
+ var import_node_fs3 = require("node:fs");
122067
122067
  var path8 = __toESM(require("node:path"), 1);
122068
122068
 
122069
122069
  // node_modules/js-yaml/dist/js-yaml.mjs
@@ -125366,6 +125366,7 @@ function getCiWorkflowTemplate(provider, options = {}) {
125366
125366
  }
125367
125367
 
125368
125368
  // src/lib/github/repo-mutation.ts
125369
+ var import_node_fs = require("node:fs");
125369
125370
  var import_node_path = __toESM(require("node:path"), 1);
125370
125371
 
125371
125372
  // src/lib/secrets.ts
@@ -125607,17 +125608,21 @@ function normalizeStagePaths(stagePaths) {
125607
125608
  if (hasControlCharacter(rawPath) || import_node_path.default.isAbsolute(stagePath) || import_node_path.default.win32.isAbsolute(stagePath) || segments.includes("..") || stagePath.startsWith(":") || hasControlCharacter(stagePath)) {
125608
125609
  throw new Error(`Unsafe git stage path: ${stagePath}`);
125609
125610
  }
125610
- normalized.push(stagePath);
125611
+ if (!normalized.includes(stagePath)) {
125612
+ normalized.push(stagePath);
125613
+ }
125611
125614
  }
125612
125615
  return normalized;
125613
125616
  }
125614
125617
  var RepoMutationService = class {
125618
+ cwd;
125615
125619
  execute;
125616
125620
  provider;
125617
125621
  repository;
125618
125622
  repoUrl;
125619
125623
  secretMasker;
125620
125624
  constructor(options) {
125625
+ this.cwd = options.cwd ?? process.cwd();
125621
125626
  this.execute = options.execute;
125622
125627
  this.provider = options.provider ?? "github";
125623
125628
  this.repository = options.repository;
@@ -125626,7 +125631,8 @@ var RepoMutationService = class {
125626
125631
  }
125627
125632
  async commitAndPush(options) {
125628
125633
  const resolvedCurrentRef = resolveCurrentRef(options);
125629
- const stagePaths = normalizeStagePaths(options.stagePaths);
125634
+ const removePaths = normalizeStagePaths(options.removePaths ?? []);
125635
+ const stagePaths = normalizeStagePaths([...options.stagePaths, ...removePaths]);
125630
125636
  const tokens = this.provider === "azure-devops" ? buildPushTokenOrder({ adoToken: options.adoToken }) : buildPushTokenOrder({
125631
125637
  fallbackToken: options.fallbackToken,
125632
125638
  githubToken: options.githubToken
@@ -125639,8 +125645,43 @@ var RepoMutationService = class {
125639
125645
  resolvedCurrentRef
125640
125646
  };
125641
125647
  }
125648
+ const changed = await this.execute("git", [
125649
+ "status",
125650
+ "--porcelain=v1",
125651
+ "--untracked-files=all",
125652
+ "--",
125653
+ ...stagePaths
125654
+ ]);
125655
+ if (changed.exitCode !== 0) {
125656
+ throw new Error(this.secretMasker(changed.stderr || changed.stdout || "Failed to inspect generated changes"));
125657
+ }
125658
+ const hasPlannedRemoval = removePaths.some(
125659
+ (removePath) => (0, import_node_fs.existsSync)(import_node_path.default.resolve(this.cwd, removePath))
125660
+ );
125661
+ if (!changed.stdout.trim() && !hasPlannedRemoval) {
125662
+ return {
125663
+ commitSha: "",
125664
+ pushed: false,
125665
+ resolvedCurrentRef
125666
+ };
125667
+ }
125668
+ const usePersistedCredentials = tokens.length === 0 && this.provider === "azure-devops";
125669
+ if (options.repoWriteMode === "commit-and-push") {
125670
+ if (!supportsTokenRemote(this.provider)) {
125671
+ throw new Error(`repo-write-mode=commit-and-push is not supported for git provider "${this.provider}"`);
125672
+ }
125673
+ if (!resolvedCurrentRef) {
125674
+ throw new Error("No current ref could be resolved for repo-write-mode=commit-and-push");
125675
+ }
125676
+ if (tokens.length === 0 && !usePersistedCredentials) {
125677
+ throw new Error("No push token configured for repo-write-mode=commit-and-push");
125678
+ }
125679
+ }
125642
125680
  await this.execute("git", ["config", "user.name", options.committerName]);
125643
125681
  await this.execute("git", ["config", "user.email", options.committerEmail]);
125682
+ for (const removePath of removePaths) {
125683
+ (0, import_node_fs.rmSync)(import_node_path.default.resolve(this.cwd, removePath), { force: true });
125684
+ }
125644
125685
  await this.execute("git", ["add", "-A", "--", ...stagePaths]);
125645
125686
  const staged = await this.execute("git", ["diff", "--cached", "--quiet"]);
125646
125687
  if (staged.exitCode === 0) {
@@ -125663,16 +125704,6 @@ var RepoMutationService = class {
125663
125704
  resolvedCurrentRef
125664
125705
  };
125665
125706
  }
125666
- if (!resolvedCurrentRef) {
125667
- throw new Error("No current ref could be resolved for repo-write-mode=commit-and-push");
125668
- }
125669
- const usePersistedCredentials = tokens.length === 0 && this.provider === "azure-devops";
125670
- if (tokens.length === 0 && !usePersistedCredentials) {
125671
- throw new Error("No push token configured for repo-write-mode=commit-and-push");
125672
- }
125673
- if (tokens.length > 0 && !supportsTokenRemote(this.provider)) {
125674
- throw new Error(`repo-write-mode=commit-and-push is not supported for git provider "${this.provider}"`);
125675
- }
125676
125707
  const originalRemote = (await this.execute("git", ["remote", "get-url", "origin"])).stdout.trim();
125677
125708
  let pushed = false;
125678
125709
  let lastError = "";
@@ -126192,11 +126223,11 @@ function createTelemetryContext(options) {
126192
126223
  }
126193
126224
 
126194
126225
  // src/action-version.ts
126195
- var import_node_fs = require("node:fs");
126226
+ var import_node_fs2 = require("node:fs");
126196
126227
  var import_node_path2 = require("node:path");
126197
126228
  function resolveActionVersion2() {
126198
126229
  try {
126199
- const raw = (0, import_node_fs.readFileSync)((0, import_node_path2.join)(__dirname, "..", "package.json"), "utf8");
126230
+ const raw = (0, import_node_fs2.readFileSync)((0, import_node_path2.join)(__dirname, "..", "package.json"), "utf8");
126200
126231
  return JSON.parse(raw).version ?? "unknown";
126201
126232
  } catch {
126202
126233
  return "unknown";
@@ -127260,12 +127291,20 @@ async function retry(operation, options = {}) {
127260
127291
  }
127261
127292
 
127262
127293
  // src/lib/postman/postman-gateway-assets-client.ts
127294
+ var MAX_CREATE_FLIGHTS = 256;
127295
+ var createFlights = /* @__PURE__ */ new Map();
127263
127296
  var PostmanGatewayAssetsClient = class {
127264
127297
  gateway;
127265
127298
  workspaceId;
127299
+ sleep;
127300
+ reconcileAttempts;
127301
+ reconcileDelayMs;
127266
127302
  constructor(options) {
127267
127303
  this.gateway = options.gateway;
127268
127304
  this.workspaceId = String(options.workspaceId || "").trim();
127305
+ this.sleep = options.sleep ?? sleep;
127306
+ this.reconcileAttempts = Math.max(1, options.reconcileAttempts ?? 3);
127307
+ this.reconcileDelayMs = Math.max(0, options.reconcileDelayMs ?? 500);
127269
127308
  }
127270
127309
  asRecord(value) {
127271
127310
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -127295,8 +127334,64 @@ var PostmanGatewayAssetsClient = class {
127295
127334
  const parts = trimmed.split("-");
127296
127335
  return parts.length >= 6 ? parts.slice(1).join("-") : trimmed;
127297
127336
  }
127298
- isTransient(error2) {
127299
- return error2 instanceof HttpError && (error2.status === 429 || error2.status >= 500);
127337
+ isAmbiguousCreateOutcome(error2) {
127338
+ if (error2 instanceof HttpError) {
127339
+ return error2.status === 408 || error2.status === 429 || error2.status >= 500;
127340
+ }
127341
+ return error2 instanceof Error;
127342
+ }
127343
+ isRetryableIdempotentWriteOutcome(error2) {
127344
+ if (error2 instanceof HttpError) {
127345
+ return error2.status === 408 || error2.status === 429 || error2.status >= 500;
127346
+ }
127347
+ return error2 instanceof Error;
127348
+ }
127349
+ selectExactMatch(kind, identity, matches) {
127350
+ if (matches.length > 1) {
127351
+ const ids = matches.map((match) => match.uid).join(", ");
127352
+ throw new Error(
127353
+ `Multiple ${kind}s match ${identity}: ${ids}. Refusing to choose one; remove duplicates or pass an explicit asset ID.`
127354
+ );
127355
+ }
127356
+ return matches[0] ?? null;
127357
+ }
127358
+ async singleFlight(key, fingerprint, kind, operation) {
127359
+ const existing = createFlights.get(key);
127360
+ if (existing) {
127361
+ if (existing.fingerprint !== fingerprint) {
127362
+ throw new Error(`Incompatible concurrent ${kind} create for ${key}`);
127363
+ }
127364
+ return existing.promise;
127365
+ }
127366
+ if (createFlights.size >= MAX_CREATE_FLIGHTS) {
127367
+ throw new Error(`Too many concurrent Postman asset creates (limit ${MAX_CREATE_FLIGHTS})`);
127368
+ }
127369
+ const pending = operation().finally(() => {
127370
+ if (createFlights.get(key)?.promise === pending) {
127371
+ createFlights.delete(key);
127372
+ }
127373
+ });
127374
+ createFlights.set(key, { fingerprint, promise: pending });
127375
+ return pending;
127376
+ }
127377
+ async discoverAfterAmbiguousCreate(discover, error2) {
127378
+ if (!this.isAmbiguousCreateOutcome(error2)) {
127379
+ return null;
127380
+ }
127381
+ for (let attempt = 0; attempt < this.reconcileAttempts; attempt += 1) {
127382
+ if (attempt > 0) {
127383
+ await this.sleep(this.reconcileDelayMs);
127384
+ }
127385
+ const found = await discover();
127386
+ if (found) {
127387
+ return found;
127388
+ }
127389
+ }
127390
+ return null;
127391
+ }
127392
+ publicEnvironmentUid(data, bareId) {
127393
+ const owner = String(data?.owner ?? "").trim();
127394
+ return owner && !bareId.startsWith(`${owner}-`) ? `${owner}-${bareId}` : bareId;
127300
127395
  }
127301
127396
  // --- environments (service: sync) ---
127302
127397
  //
@@ -127307,9 +127402,10 @@ var PostmanGatewayAssetsClient = class {
127307
127402
  /**
127308
127403
  * Create/upsert an environment through the sync service.
127309
127404
  * POST /environment/import?workspace=:ws { id:<uuid>, name, values } ->
127310
- * { data:{ id:<bare uuid>, owner } }. The id is generated once and reused
127311
- * across retries so the import is idempotent (a retry upserts the same
127312
- * environment instead of duplicating it).
127405
+ * { data:{ id:<bare uuid>, owner } }. The id is generated once for the
127406
+ * operation. Unsafe creates submit once (no blind retry); on an ambiguous
127407
+ * response the client discovers by exact workspace-scoped name before
127408
+ * failing.
127313
127409
  *
127314
127410
  * Returns the PUBLIC uid (`<owner>-<uuid>`), not the bare model id the sync
127315
127411
  * import echoes: mock/monitor create reference the environment by its public
@@ -127319,33 +127415,54 @@ var PostmanGatewayAssetsClient = class {
127319
127415
  */
127320
127416
  async createEnvironment(workspaceId, name, values) {
127321
127417
  const ws = workspaceId || this.workspaceId;
127322
- const id = crypto.randomUUID();
127323
- const body = {
127324
- id,
127325
- name,
127326
- values: values.map((v) => ({
127327
- key: v.key,
127328
- value: v.value,
127329
- type: v.type ?? "default",
127330
- enabled: v.enabled ?? true
127331
- }))
127332
- };
127333
- const response = await retry(
127334
- () => this.gateway.requestJson({
127335
- service: "sync",
127336
- method: "post",
127337
- path: `/environment/import?workspace=${ws}`,
127338
- body
127339
- }),
127340
- { maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isTransient(e) }
127341
- );
127342
- const data = this.dataOf(response);
127343
- const bareId = this.idOf(data);
127344
- if (!bareId) {
127345
- throw new Error("Environment import did not return a UID");
127346
- }
127347
- const owner = String(data?.owner ?? "").trim();
127348
- return owner && !bareId.startsWith(`${owner}-`) ? `${owner}-${bareId}` : bareId;
127418
+ const envName = String(name ?? "").trim();
127419
+ const flightKey = `environment:${ws}:${envName}`;
127420
+ const normalizedValues = values.map((v) => ({
127421
+ key: v.key,
127422
+ value: v.value,
127423
+ type: v.type ?? "default",
127424
+ enabled: v.enabled ?? true
127425
+ }));
127426
+ return this.singleFlight(flightKey, JSON.stringify(normalizedValues), "environment", async () => {
127427
+ const existing = await this.findEnvironmentByName(ws, envName);
127428
+ if (existing?.uid) {
127429
+ await this.updateEnvironment(existing.uid, envName, values);
127430
+ return existing.uid;
127431
+ }
127432
+ const id = crypto.randomUUID();
127433
+ const body = {
127434
+ id,
127435
+ name: envName,
127436
+ values: normalizedValues
127437
+ };
127438
+ try {
127439
+ const response = await this.gateway.requestJson(
127440
+ {
127441
+ service: "sync",
127442
+ method: "post",
127443
+ path: `/environment/import?workspace=${ws}`,
127444
+ body
127445
+ },
127446
+ { retryTransient: false }
127447
+ );
127448
+ const data = this.dataOf(response);
127449
+ const bareId = this.idOf(data);
127450
+ if (!bareId) {
127451
+ throw new Error("Environment import did not return a UID");
127452
+ }
127453
+ return this.publicEnvironmentUid(data, bareId);
127454
+ } catch (error2) {
127455
+ const adopted = await this.discoverAfterAmbiguousCreate(async () => {
127456
+ const match = await this.findEnvironmentByName(ws, envName);
127457
+ return match?.uid ?? null;
127458
+ }, error2);
127459
+ if (adopted) {
127460
+ await this.updateEnvironment(adopted, envName, values);
127461
+ return adopted;
127462
+ }
127463
+ throw error2;
127464
+ }
127465
+ });
127349
127466
  }
127350
127467
  /**
127351
127468
  * Update an existing environment through the sync service.
@@ -127375,7 +127492,7 @@ var PostmanGatewayAssetsClient = class {
127375
127492
  path: `/environment/${id}`,
127376
127493
  body
127377
127494
  }),
127378
- { maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isTransient(e) }
127495
+ { maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isRetryableIdempotentWriteOutcome(e) }
127379
127496
  );
127380
127497
  }
127381
127498
  /**
@@ -127399,13 +127516,37 @@ var PostmanGatewayAssetsClient = class {
127399
127516
  */
127400
127517
  async listEnvironments(workspaceId) {
127401
127518
  const ws = workspaceId || this.workspaceId;
127402
- const response = await this.gateway.requestJson({
127403
- service: "sync",
127404
- method: "post",
127405
- path: `/list/environment?workspace=${ws}`
127406
- });
127519
+ const response = await this.gateway.requestJson(
127520
+ {
127521
+ service: "sync",
127522
+ method: "post",
127523
+ path: `/list/environment?workspace=${ws}`
127524
+ },
127525
+ { retryTransient: true }
127526
+ );
127407
127527
  const items = Array.isArray(response?.data) ? response.data : [];
127408
- return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) => ({ name: String(e.name ?? ""), uid: this.idOf(e) }));
127528
+ return items.map((raw) => this.asRecord(raw)).filter((e) => e !== null).map((e) => {
127529
+ const bareOrPublic = this.idOf(e);
127530
+ return {
127531
+ name: String(e.name ?? ""),
127532
+ uid: this.publicEnvironmentUid(e, bareOrPublic)
127533
+ };
127534
+ });
127535
+ }
127536
+ /** Exact name match within a workspace. Prefer tracked UIDs before calling. */
127537
+ async findEnvironmentByName(workspaceId, name) {
127538
+ const want = String(name ?? "").trim();
127539
+ if (!want) {
127540
+ return null;
127541
+ }
127542
+ const environments = await this.listEnvironments(workspaceId);
127543
+ const matches = environments.filter((entry) => entry.name === want);
127544
+ const match = this.selectExactMatch(
127545
+ "environment",
127546
+ `workspace ${workspaceId} and name "${want}"`,
127547
+ matches
127548
+ );
127549
+ return match?.uid ? { uid: match.uid, name: match.name } : null;
127409
127550
  }
127410
127551
  // --- collection read (service: collection, v3 export) ---
127411
127552
  //
@@ -127435,32 +127576,51 @@ var PostmanGatewayAssetsClient = class {
127435
127576
  // --- mocks (service: mock) ---
127436
127577
  async createMock(workspaceId, name, collectionUid, environmentUid) {
127437
127578
  const ws = workspaceId || this.workspaceId;
127579
+ const mockName = String(name ?? "").trim();
127438
127580
  const collection = String(collectionUid ?? "").trim();
127439
127581
  const environment = String(environmentUid ?? "").trim();
127440
- const body = {
127441
- name,
127442
- collection,
127443
- private: false,
127444
- ...environment ? { environment } : {}
127445
- };
127446
- const response = await retry(
127447
- () => this.gateway.requestJson({
127448
- service: "mock",
127449
- method: "post",
127450
- path: `/mocks?workspace=${ws}`,
127451
- body
127452
- }),
127453
- { maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isTransient(e) }
127454
- );
127455
- const record = this.dataOf(response);
127456
- const uid = this.idOf(record);
127457
- if (!uid) {
127458
- throw new Error("Mock create did not return a UID");
127459
- }
127460
- return {
127461
- uid,
127462
- url: String(record?.url ?? record?.mockUrl ?? "").trim()
127463
- };
127582
+ const flightKey = `mock:${ws}:${collection}:${environment}:${mockName}`;
127583
+ return this.singleFlight(flightKey, flightKey, "mock", async () => {
127584
+ const existing = await this.findMockByCollection(collection, environment, mockName);
127585
+ if (existing) {
127586
+ return { uid: existing.uid, url: existing.mockUrl };
127587
+ }
127588
+ const body = {
127589
+ name: mockName,
127590
+ collection,
127591
+ private: false,
127592
+ ...environment ? { environment } : {}
127593
+ };
127594
+ try {
127595
+ const response = await this.gateway.requestJson(
127596
+ {
127597
+ service: "mock",
127598
+ method: "post",
127599
+ path: `/mocks?workspace=${ws}`,
127600
+ body
127601
+ },
127602
+ { retryTransient: false }
127603
+ );
127604
+ const record = this.dataOf(response);
127605
+ const uid = this.idOf(record);
127606
+ if (!uid) {
127607
+ throw new Error("Mock create did not return a UID");
127608
+ }
127609
+ return {
127610
+ uid,
127611
+ url: String(record?.url ?? record?.mockUrl ?? "").trim()
127612
+ };
127613
+ } catch (error2) {
127614
+ const adopted = await this.discoverAfterAmbiguousCreate(
127615
+ () => this.findMockByCollection(collection, environment, mockName),
127616
+ error2
127617
+ );
127618
+ if (adopted) {
127619
+ return { uid: adopted.uid, url: adopted.mockUrl };
127620
+ }
127621
+ throw error2;
127622
+ }
127623
+ });
127464
127624
  }
127465
127625
  async listMocks() {
127466
127626
  const response = await this.gateway.requestJson({
@@ -127489,10 +127649,19 @@ var PostmanGatewayAssetsClient = class {
127489
127649
  return false;
127490
127650
  }
127491
127651
  }
127492
- async findMockByCollection(collectionUid) {
127652
+ async findMockByCollection(collectionUid, environmentUid, name) {
127493
127653
  const mocks = await this.listMocks();
127494
127654
  const want = String(collectionUid ?? "").trim();
127495
- const match = mocks.find((m) => m.collection === want);
127655
+ const environment = String(environmentUid ?? "").trim();
127656
+ const mockName = String(name ?? "").trim();
127657
+ const matches = mocks.filter(
127658
+ (mock) => mock.collection === want && mock.environment === environment && mock.name === mockName
127659
+ );
127660
+ const match = this.selectExactMatch(
127661
+ "mock",
127662
+ `workspace ${this.workspaceId}, name "${mockName}", collection ${want}, and environment ${environment || "(none)"}`,
127663
+ matches
127664
+ );
127496
127665
  return match ? { uid: match.uid, mockUrl: match.mockUrl } : null;
127497
127666
  }
127498
127667
  // --- monitors (service: monitors; collection-based = jobTemplates) ---
@@ -127509,32 +127678,51 @@ var PostmanGatewayAssetsClient = class {
127509
127678
  async createMonitor(workspaceId, name, collectionUid, environmentUid, cronSchedule) {
127510
127679
  const ws = workspaceId || this.workspaceId;
127511
127680
  const effectiveCron = cronSchedule && cronSchedule.trim() ? cronSchedule.trim() : "0 0 * * 0";
127681
+ const monitorName = String(name ?? "").trim();
127512
127682
  const collection = String(collectionUid ?? "").trim();
127513
127683
  const environment = String(environmentUid ?? "").trim();
127514
- const body = {
127515
- name,
127516
- collection,
127517
- options: { strictSSL: false, followRedirects: true, requestTimeout: null, requestDelay: 0 },
127518
- notifications: { onFailure: [], onError: [] },
127519
- retry: {},
127520
- schedule: { cronPattern: effectiveCron, timeZone: "UTC" },
127521
- distribution: null,
127522
- ...environment ? { environment } : {}
127523
- };
127524
- const response = await retry(
127525
- () => this.gateway.requestJson({
127526
- service: "monitors",
127527
- method: "post",
127528
- path: `/jobTemplates?workspace=${ws}`,
127529
- body
127530
- }),
127531
- { maxAttempts: 5, delayMs: 2e3, backoffMultiplier: 2, maxDelayMs: 15e3, shouldRetry: (e) => this.isTransient(e) }
127532
- );
127533
- const uid = this.idOf(this.dataOf(response));
127534
- if (!uid) {
127535
- throw new Error("Monitor create did not return a UID");
127536
- }
127537
- return uid;
127684
+ const flightKey = `monitor:${ws}:${collection}:${environment}:${monitorName}`;
127685
+ return this.singleFlight(flightKey, effectiveCron, "monitor", async () => {
127686
+ const existing = await this.findMonitorByCollection(collection, environment, monitorName);
127687
+ if (existing?.uid) {
127688
+ return existing.uid;
127689
+ }
127690
+ const body = {
127691
+ name: monitorName,
127692
+ collection,
127693
+ options: { strictSSL: false, followRedirects: true, requestTimeout: null, requestDelay: 0 },
127694
+ notifications: { onFailure: [], onError: [] },
127695
+ retry: {},
127696
+ schedule: { cronPattern: effectiveCron, timeZone: "UTC" },
127697
+ distribution: null,
127698
+ ...environment ? { environment } : {}
127699
+ };
127700
+ try {
127701
+ const response = await this.gateway.requestJson(
127702
+ {
127703
+ service: "monitors",
127704
+ method: "post",
127705
+ path: `/jobTemplates?workspace=${ws}`,
127706
+ body
127707
+ },
127708
+ { retryTransient: false }
127709
+ );
127710
+ const uid = this.idOf(this.dataOf(response));
127711
+ if (!uid) {
127712
+ throw new Error("Monitor create did not return a UID");
127713
+ }
127714
+ return uid;
127715
+ } catch (error2) {
127716
+ const adopted = await this.discoverAfterAmbiguousCreate(
127717
+ () => this.findMonitorByCollection(collection, environment, monitorName),
127718
+ error2
127719
+ );
127720
+ if (adopted?.uid) {
127721
+ return adopted.uid;
127722
+ }
127723
+ throw error2;
127724
+ }
127725
+ });
127538
127726
  }
127539
127727
  async listMonitors() {
127540
127728
  const response = await this.gateway.requestJson({
@@ -127557,24 +127745,30 @@ var PostmanGatewayAssetsClient = class {
127557
127745
  return false;
127558
127746
  }
127559
127747
  }
127560
- async findMonitorByCollection(collectionUid) {
127748
+ async findMonitorByCollection(collectionUid, environmentUid, name) {
127561
127749
  const want = String(collectionUid ?? "").trim();
127562
- const response = await this.gateway.requestJson({
127563
- service: "monitors",
127564
- method: "get",
127565
- path: `/collections/${want}/jobTemplates?_etc=true`
127566
- });
127567
- const data = response?.data;
127568
- const monitors = this.mapJobTemplates(Array.isArray(data) ? data : []);
127569
- const match = monitors.find((m) => m.collectionUid === want) ?? monitors[0];
127750
+ const environment = String(environmentUid ?? "").trim();
127751
+ const monitorName = String(name ?? "").trim();
127752
+ const monitors = await this.listMonitors();
127753
+ const matches = monitors.filter(
127754
+ (monitor) => monitor.collectionUid === want && monitor.environmentUid === environment && monitor.name === monitorName
127755
+ );
127756
+ const match = this.selectExactMatch(
127757
+ "monitor",
127758
+ `workspace ${this.workspaceId}, name "${monitorName}", collection ${want}, and environment ${environment || "(none)"}`,
127759
+ matches
127760
+ );
127570
127761
  return match?.uid ? { uid: match.uid, name: match.name } : null;
127571
127762
  }
127572
127763
  async runMonitor(uid) {
127573
- await this.gateway.requestJson({
127574
- service: "monitors",
127575
- method: "post",
127576
- path: `/jobTemplates/${uid}/jobs`
127577
- });
127764
+ await this.gateway.requestJson(
127765
+ {
127766
+ service: "monitors",
127767
+ method: "post",
127768
+ path: `/jobTemplates/${uid}/jobs`
127769
+ },
127770
+ { retryTransient: false }
127771
+ );
127578
127772
  }
127579
127773
  };
127580
127774
 
@@ -127740,12 +127934,8 @@ async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetc
127740
127934
  function isExpiredAuthError(status, body) {
127741
127935
  return status === 401 || body.includes("UNAUTHENTICATED") || body.includes("authenticationError");
127742
127936
  }
127743
- function isTransientGatewayError(status, body) {
127744
- if (status === 502 || status === 503 || status === 504) return true;
127745
- if (status >= 500 && (body.includes("ESOCKETTIMEDOUT") || body.includes("ETIMEDOUT") || body.includes("ECONNRESET") || body.includes("serverError") || body.includes("downstream"))) {
127746
- return true;
127747
- }
127748
- return false;
127937
+ function isRetryableSafeReadResponse(status) {
127938
+ return status === 408 || status === 429 || status >= 500;
127749
127939
  }
127750
127940
  function defaultSleep(ms) {
127751
127941
  return new Promise((resolve3) => setTimeout(resolve3, ms));
@@ -127804,14 +127994,28 @@ var AccessTokenGatewayClient = class {
127804
127994
  }
127805
127995
  /**
127806
127996
  * Send a gateway request, refreshing the token once on an auth failure and
127807
- * retrying transient downstream failures (5xx / Bifrost read timeouts) with
127808
- * exponential backoff. The auth-refresh-once path is independent of the
127809
- * transient-retry budget.
127997
+ * optionally retrying transient downstream failures (5xx / Bifrost read
127998
+ * timeouts) with exponential backoff. Safe reads keep transient retries;
127999
+ * unsafe creates pass `{ retryTransient: false }` and reconcile after an
128000
+ * ambiguous response instead of re-POSTing. Auth refresh remains independent
128001
+ * of the transient-retry budget.
127810
128002
  */
127811
- async request(request) {
128003
+ async request(request, options = {}) {
128004
+ const retryTransient = options.retryTransient ?? request.method === "get";
127812
128005
  let attempt = 0;
127813
128006
  for (; ; ) {
127814
- let response = await this.send(request);
128007
+ let response;
128008
+ try {
128009
+ response = await this.send(request);
128010
+ } catch (error2) {
128011
+ if (retryTransient && attempt < this.maxRetries) {
128012
+ const delay = this.retryBaseDelayMs * 2 ** attempt;
128013
+ attempt += 1;
128014
+ await this.sleepImpl(delay);
128015
+ continue;
128016
+ }
128017
+ throw error2;
128018
+ }
127815
128019
  if (response.ok) {
127816
128020
  return response;
127817
128021
  }
@@ -127825,7 +128029,7 @@ var AccessTokenGatewayClient = class {
127825
128029
  const retryBody = await response.text().catch(() => "");
127826
128030
  throw this.toHttpError(request, response, retryBody);
127827
128031
  }
127828
- if (isTransientGatewayError(response.status, body) && attempt < this.maxRetries) {
128032
+ if (retryTransient && isRetryableSafeReadResponse(response.status) && attempt < this.maxRetries) {
127829
128033
  const delay = this.retryBaseDelayMs * 2 ** attempt;
127830
128034
  attempt += 1;
127831
128035
  await this.sleepImpl(delay);
@@ -127835,8 +128039,8 @@ var AccessTokenGatewayClient = class {
127835
128039
  }
127836
128040
  }
127837
128041
  /** Send a gateway request and parse the JSON body, or null when empty. */
127838
- async requestJson(request) {
127839
- const response = await this.request(request);
128042
+ async requestJson(request, options = {}) {
128043
+ const response = await this.request(request, options);
127840
128044
  const text = await response.text().catch(() => "");
127841
128045
  if (!text.trim()) {
127842
128046
  return null;
@@ -127951,8 +128155,27 @@ function normalizeInputValue(value) {
127951
128155
  return String(value ?? "").trim();
127952
128156
  }
127953
128157
  function getInput2(name, env = process.env) {
127954
- const envName = `INPUT_${name.replace(/-/g, "_").toUpperCase()}`;
127955
- return normalizeInputValue(env[envName]);
128158
+ const normalizedName = `INPUT_${name.replace(/-/g, "_").toUpperCase()}`;
128159
+ const runnerName = `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
128160
+ const normalizedRaw = env[normalizedName];
128161
+ const runnerRaw = runnerName === normalizedName ? void 0 : env[runnerName];
128162
+ const hasNormalized = normalizedRaw !== void 0;
128163
+ const hasRunner = runnerRaw !== void 0;
128164
+ if (hasNormalized && hasRunner) {
128165
+ const normalizedValue = normalizeInputValue(normalizedRaw);
128166
+ const runnerValue = normalizeInputValue(runnerRaw);
128167
+ if (normalizedValue !== runnerValue) {
128168
+ throw new Error(
128169
+ `Conflicting values for ${name}: ${normalizedName}=${JSON.stringify(normalizedValue)} vs ${runnerName}=${JSON.stringify(runnerValue)}`
128170
+ );
128171
+ }
128172
+ }
128173
+ return normalizeInputValue(hasNormalized ? normalizedRaw : runnerRaw);
128174
+ }
128175
+ function hasInput(name, env = process.env) {
128176
+ const normalizedName = `INPUT_${name.replace(/-/g, "_").toUpperCase()}`;
128177
+ const runnerName = `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
128178
+ return env[normalizedName] !== void 0 || runnerName !== normalizedName && env[runnerName] !== void 0;
127956
128179
  }
127957
128180
  function parseJsonMap(raw) {
127958
128181
  if (!raw.trim()) return {};
@@ -127982,7 +128205,9 @@ function normalizeRepoWriteMode(value) {
127982
128205
  if (value === "none" || value === "commit-only" || value === "commit-and-push") {
127983
128206
  return value;
127984
128207
  }
127985
- return "commit-and-push";
128208
+ throw new Error(
128209
+ `Unsupported repo-write-mode "${value}". Allowed values: none, commit-only, commit-and-push`
128210
+ );
127986
128211
  }
127987
128212
  function normalizeCollectionSyncMode(value) {
127988
128213
  if (value === "refresh" || value === "version") {
@@ -128064,7 +128289,7 @@ function resolveInputs(env = process.env) {
128064
128289
  environmentUids,
128065
128290
  envRuntimeUrls,
128066
128291
  artifactDir: getInput2("artifact-dir", env) || "postman",
128067
- repoWriteMode: normalizeRepoWriteMode(getInput2("repo-write-mode", env) || "commit-and-push"),
128292
+ repoWriteMode: hasInput("repo-write-mode", env) ? normalizeRepoWriteMode(getInput2("repo-write-mode", env)) : "commit-and-push",
128068
128293
  currentRef: getInput2("current-ref", env) || normalizeInputValue(env.GITHUB_REF) || normalizeInputValue(env.BUILD_SOURCEBRANCH),
128069
128294
  githubHeadRef: getInput2("github-head-ref", env) || normalizeInputValue(env.GITHUB_HEAD_REF) || normalizeInputValue(env.SYSTEM_PULLREQUEST_SOURCEBRANCH),
128070
128295
  githubRefName: getInput2("github-ref-name", env) || normalizeInputValue(env.GITHUB_REF_NAME) || normalizeInputValue(repoContext.ref),
@@ -128113,7 +128338,7 @@ function buildEnvironmentValues(envName, baseUrl) {
128113
128338
  var LEGACY_BASELINE_COLLECTION_PREFIX = "[Baseline]";
128114
128339
  function readResourcesState() {
128115
128340
  try {
128116
- return load((0, import_node_fs2.readFileSync)(".postman/resources.yaml", "utf8"));
128341
+ return load((0, import_node_fs3.readFileSync)(".postman/resources.yaml", "utf8"));
128117
128342
  } catch {
128118
128343
  return null;
128119
128344
  }
@@ -128151,7 +128376,7 @@ function isOpenApiSpecFile(filePath) {
128151
128376
  return false;
128152
128377
  }
128153
128378
  try {
128154
- const raw = (0, import_node_fs2.readFileSync)(filePath, "utf8");
128379
+ const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8");
128155
128380
  const parsed = filePath.endsWith(".json") ? JSON.parse(raw) : load(raw);
128156
128381
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
128157
128382
  return false;
@@ -128180,7 +128405,7 @@ function scanLocalSpecReferences(baseDir = ".") {
128180
128405
  const found = /* @__PURE__ */ new Set();
128181
128406
  const refs = [];
128182
128407
  const visit2 = (currentDir) => {
128183
- for (const entry of (0, import_node_fs2.readdirSync)(currentDir, { withFileTypes: true })) {
128408
+ for (const entry of (0, import_node_fs3.readdirSync)(currentDir, { withFileTypes: true })) {
128184
128409
  if (ignoredDirs.has(entry.name)) {
128185
128410
  continue;
128186
128411
  }
@@ -128210,7 +128435,7 @@ function resolveMappedSpecReference(explicitSpecPath, discoveredSpecs) {
128210
128435
  const normalizedExplicitPath = normalizeToPosix(explicitSpecPath.trim());
128211
128436
  if (normalizedExplicitPath) {
128212
128437
  const explicitFullPath = path8.resolve(normalizedExplicitPath);
128213
- if ((0, import_node_fs2.existsSync)(explicitFullPath) && (0, import_node_fs2.statSync)(explicitFullPath).isFile()) {
128438
+ if ((0, import_node_fs3.existsSync)(explicitFullPath) && (0, import_node_fs3.statSync)(explicitFullPath).isFile()) {
128214
128439
  return {
128215
128440
  repoRelativePath: normalizedExplicitPath,
128216
128441
  configRelativePath: normalizeToPosix(path8.join("..", normalizedExplicitPath))
@@ -128407,25 +128632,35 @@ async function upsertEnvironments(inputs, dependencies, resourcesState) {
128407
128632
  for (const envName of inputs.environments) {
128408
128633
  const runtimeUrl = String(inputs.envRuntimeUrls[envName] || "").trim();
128409
128634
  const values = buildEnvironmentValues(envName, runtimeUrl);
128410
- const existingUid = envUids[envName];
128411
- if (existingUid) {
128412
- await dependencies.postman.updateEnvironment(
128413
- existingUid,
128414
- `${inputs.projectName} - ${envName}`,
128415
- values
128635
+ const displayName = `${inputs.projectName} - ${envName}`;
128636
+ let existingUid = String(envUids[envName] || "").trim();
128637
+ if (!existingUid) {
128638
+ const discovered = await dependencies.postman.findEnvironmentByName(
128639
+ inputs.workspaceId,
128640
+ displayName
128416
128641
  );
128642
+ if (discovered?.uid) {
128643
+ existingUid = discovered.uid;
128644
+ dependencies.core.info(
128645
+ `Discovered existing environment for ${displayName}: ${existingUid}`
128646
+ );
128647
+ }
128648
+ }
128649
+ if (existingUid) {
128650
+ await dependencies.postman.updateEnvironment(existingUid, displayName, values);
128651
+ envUids[envName] = existingUid;
128417
128652
  continue;
128418
128653
  }
128419
128654
  envUids[envName] = await dependencies.postman.createEnvironment(
128420
128655
  inputs.workspaceId,
128421
- `${inputs.projectName} - ${envName}`,
128656
+ displayName,
128422
128657
  values
128423
128658
  );
128424
128659
  }
128425
128660
  return envUids;
128426
128661
  }
128427
128662
  function ensureDir(path9) {
128428
- (0, import_node_fs2.mkdirSync)(path9, { recursive: true });
128663
+ (0, import_node_fs3.mkdirSync)(path9, { recursive: true });
128429
128664
  }
128430
128665
  function getCollectionDirectoryName(kind, projectName) {
128431
128666
  if (kind === "Baseline") {
@@ -128462,7 +128697,7 @@ function stripVolatileFields(obj) {
128462
128697
  }
128463
128698
  function writeJsonFile(path9, content, normalize3 = false) {
128464
128699
  const data = normalize3 ? stripVolatileFields(content) : content;
128465
- (0, import_node_fs2.writeFileSync)(path9, JSON.stringify(data, null, 2));
128700
+ (0, import_node_fs3.writeFileSync)(path9, JSON.stringify(data, null, 2));
128466
128701
  }
128467
128702
  function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir, localSpecRefs, mappedSpecRef, specId) {
128468
128703
  const manifest = {
@@ -128536,21 +128771,21 @@ function assertPathWithinCwd(targetPath, fieldName) {
128536
128771
  if (!rawPath || hasControlCharacter2(originalPath) || path8.isAbsolute(rawPath) || path8.win32.isAbsolute(rawPath) || segments.includes("..") || rawPath.startsWith(":") || hasControlCharacter2(rawPath)) {
128537
128772
  throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
128538
128773
  }
128539
- const base = (0, import_node_fs2.realpathSync)(process.cwd());
128774
+ const base = (0, import_node_fs3.realpathSync)(process.cwd());
128540
128775
  const resolved = path8.resolve(base, rawPath);
128541
128776
  const relative3 = path8.relative(base, resolved);
128542
128777
  if (relative3.startsWith("..") || path8.isAbsolute(relative3)) {
128543
128778
  throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
128544
128779
  }
128545
128780
  let existingPath = resolved;
128546
- while (!(0, import_node_fs2.existsSync)(existingPath)) {
128781
+ while (!(0, import_node_fs3.existsSync)(existingPath)) {
128547
128782
  const parent = path8.dirname(existingPath);
128548
128783
  if (parent === existingPath) {
128549
128784
  break;
128550
128785
  }
128551
128786
  existingPath = parent;
128552
128787
  }
128553
- const realExistingPath = (0, import_node_fs2.realpathSync)(existingPath);
128788
+ const realExistingPath = (0, import_node_fs3.realpathSync)(existingPath);
128554
128789
  const realRelative = path8.relative(base, realExistingPath);
128555
128790
  if (realRelative.startsWith("..") || path8.isAbsolute(realRelative)) {
128556
128791
  throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
@@ -128578,8 +128813,8 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
128578
128813
  ensureDir(specsDir);
128579
128814
  ensureDir(".postman");
128580
128815
  const globalsFilePath = `${globalsDir}/workspace.globals.yaml`;
128581
- if (!(0, import_node_fs2.existsSync)(globalsFilePath)) {
128582
- (0, import_node_fs2.writeFileSync)(globalsFilePath, "name: Globals\nvalues: []\n");
128816
+ if (!(0, import_node_fs3.existsSync)(globalsFilePath)) {
128817
+ (0, import_node_fs3.writeFileSync)(globalsFilePath, "name: Globals\nvalues: []\n");
128583
128818
  }
128584
128819
  if (inputs.generateCiWorkflow) {
128585
128820
  const ciDir = inputs.ciWorkflowPath.split("/").slice(0, -1).join("/");
@@ -128615,7 +128850,7 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
128615
128850
  true
128616
128851
  );
128617
128852
  }
128618
- (0, import_node_fs2.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
128853
+ (0, import_node_fs3.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
128619
128854
  inputs.workspaceId,
128620
128855
  manifestCollections,
128621
128856
  envUids,
@@ -128625,7 +128860,7 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName)
128625
128860
  inputs.specId || void 0
128626
128861
  ));
128627
128862
  if (mappedSpec && Object.keys(manifestCollections).length > 0) {
128628
- (0, import_node_fs2.writeFileSync)(
128863
+ (0, import_node_fs3.writeFileSync)(
128629
128864
  ".postman/workflows.yaml",
128630
128865
  buildSpecCollectionWorkflowManifest(
128631
128866
  mappedSpec.configRelativePath,
@@ -128662,29 +128897,27 @@ function createRepoSummary(outputs, envUids, pushed) {
128662
128897
  });
128663
128898
  }
128664
128899
  async function commitAndPushGeneratedFiles(inputs, dependencies) {
128665
- if (!dependencies.repoMutation || inputs.repoWriteMode === "none") {
128666
- return { commitSha: "", resolvedCurrentRef: "", pushed: false };
128667
- }
128668
128900
  if (inputs.generateCiWorkflow) {
128901
+ assertPathWithinCwd(inputs.ciWorkflowPath, "ci-workflow-path");
128669
128902
  const ciWorkflow = renderCiWorkflow(inputs);
128670
128903
  const parts = inputs.ciWorkflowPath.split("/");
128671
128904
  if (parts.length > 1) {
128672
128905
  const dir = parts.slice(0, -1).join("/");
128673
128906
  ensureDir(dir);
128674
128907
  }
128675
- (0, import_node_fs2.writeFileSync)(inputs.ciWorkflowPath, ciWorkflow);
128908
+ (0, import_node_fs3.writeFileSync)(inputs.ciWorkflowPath, ciWorkflow);
128676
128909
  }
128677
- const provisionPath = ".github/workflows/provision.yml";
128678
- const provisionExists = inputs.provider === "github" && (0, import_node_fs2.existsSync)(provisionPath);
128679
- if (provisionExists) {
128680
- (0, import_node_fs2.rmSync)(provisionPath);
128910
+ if (!dependencies.repoMutation || inputs.repoWriteMode === "none") {
128911
+ return { commitSha: "", resolvedCurrentRef: "", pushed: false };
128681
128912
  }
128913
+ const provisionPath = ".github/workflows/provision.yml";
128914
+ const provisionExists = inputs.provider === "github" && (0, import_node_fs3.existsSync)(provisionPath);
128682
128915
  const stagePaths = [
128683
128916
  inputs.artifactDir,
128684
128917
  ".postman",
128685
128918
  inputs.generateCiWorkflow ? inputs.ciWorkflowPath : null,
128686
128919
  provisionExists ? provisionPath : null
128687
- ].filter((entry) => typeof entry === "string" && ((0, import_node_fs2.existsSync)(entry) || entry === provisionPath));
128920
+ ].filter((entry) => typeof entry === "string" && ((0, import_node_fs3.existsSync)(entry) || entry === provisionPath));
128688
128921
  if (stagePaths.length === 0) {
128689
128922
  dependencies.core.info("No generated repository paths were found; skipping repo mutation.");
128690
128923
  return {
@@ -128708,6 +128941,7 @@ async function commitAndPushGeneratedFiles(inputs, dependencies) {
128708
128941
  adoToken: inputs.provider === "azure-devops" ? inputs.adoToken : void 0,
128709
128942
  githubToken: inputs.provider === "azure-devops" ? void 0 : inputs.githubToken,
128710
128943
  fallbackToken: inputs.provider === "azure-devops" ? void 0 : inputs.ghFallbackToken,
128944
+ removePaths: provisionExists ? [provisionPath] : [],
128711
128945
  stagePaths
128712
128946
  });
128713
128947
  return {
@@ -128790,12 +129024,17 @@ async function runRepoSyncInner(inputs, dependencies) {
128790
129024
  const mockEnvUid = envUids.dev || envUids.prod || Object.values(envUids)[0];
128791
129025
  if (mockEnvUid) {
128792
129026
  let resolvedMockUrl = "";
129027
+ const mockName = `${assetProjectName} Mock`;
128793
129028
  if (inputs.mockUrl) {
128794
129029
  resolvedMockUrl = inputs.mockUrl;
128795
129030
  dependencies.core.info(`Reusing mock from explicit input: ${resolvedMockUrl}`);
128796
129031
  }
128797
129032
  if (!resolvedMockUrl && inputs.baselineCollectionId) {
128798
- const discovered = await dependencies.postman.findMockByCollection(inputs.baselineCollectionId);
129033
+ const discovered = await dependencies.postman.findMockByCollection(
129034
+ inputs.baselineCollectionId,
129035
+ mockEnvUid,
129036
+ mockName
129037
+ );
128799
129038
  if (discovered) {
128800
129039
  resolvedMockUrl = discovered.mockUrl;
128801
129040
  dependencies.core.info(`Discovered existing mock for collection ${inputs.baselineCollectionId}: ${resolvedMockUrl}`);
@@ -128804,7 +129043,7 @@ async function runRepoSyncInner(inputs, dependencies) {
128804
129043
  if (!resolvedMockUrl) {
128805
129044
  const mock = await dependencies.postman.createMock(
128806
129045
  inputs.workspaceId,
128807
- `${assetProjectName} Mock`,
129046
+ mockName,
128808
129047
  inputs.baselineCollectionId,
128809
129048
  mockEnvUid
128810
129049
  );
@@ -128819,6 +129058,7 @@ async function runRepoSyncInner(inputs, dependencies) {
128819
129058
  const effectiveCron = inputs.monitorCron && inputs.monitorCron.trim() ? inputs.monitorCron.trim() : "";
128820
129059
  if (monitorEnvUid && inputs.monitorType !== "cli") {
128821
129060
  let resolvedMonitorId = "";
129061
+ const monitorName = `${assetProjectName} - Smoke Monitor`;
128822
129062
  if (inputs.monitorId) {
128823
129063
  const valid = await dependencies.postman.monitorExists(inputs.monitorId);
128824
129064
  if (valid) {
@@ -128829,7 +129069,11 @@ async function runRepoSyncInner(inputs, dependencies) {
128829
129069
  }
128830
129070
  }
128831
129071
  if (!resolvedMonitorId && inputs.smokeCollectionId) {
128832
- const discovered = await dependencies.postman.findMonitorByCollection(inputs.smokeCollectionId);
129072
+ const discovered = await dependencies.postman.findMonitorByCollection(
129073
+ inputs.smokeCollectionId,
129074
+ monitorEnvUid,
129075
+ monitorName
129076
+ );
128833
129077
  if (discovered) {
128834
129078
  resolvedMonitorId = discovered.uid;
128835
129079
  dependencies.core.info(`Discovered existing monitor for collection ${inputs.smokeCollectionId}: ${resolvedMonitorId}`);
@@ -128838,7 +129082,7 @@ async function runRepoSyncInner(inputs, dependencies) {
128838
129082
  if (!resolvedMonitorId) {
128839
129083
  resolvedMonitorId = await dependencies.postman.createMonitor(
128840
129084
  inputs.workspaceId,
128841
- `${assetProjectName} - Smoke Monitor`,
129085
+ monitorName,
128842
129086
  inputs.smokeCollectionId,
128843
129087
  monitorEnvUid,
128844
129088
  effectiveCron || void 0
@@ -129051,6 +129295,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
129051
129295
  createEnvironment: gatewayAssets.createEnvironment.bind(gatewayAssets),
129052
129296
  getEnvironment: gatewayAssets.getEnvironment.bind(gatewayAssets),
129053
129297
  updateEnvironment: gatewayAssets.updateEnvironment.bind(gatewayAssets),
129298
+ findEnvironmentByName: gatewayAssets.findEnvironmentByName.bind(gatewayAssets),
129054
129299
  // Collection read via the v3 export endpoint — returns canonical v3 IR,
129055
129300
  // written to disk by `convertAndSplitAnyCollection`. PMAK is never used for
129056
129301
  // collection reads.