@postman-cse/onboarding-bootstrap 0.9.1 → 0.10.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.
package/dist/index.cjs CHANGED
@@ -22777,6 +22777,7 @@ var require_stringify = __commonJS({
22777
22777
  nullStr: "null",
22778
22778
  simpleKeys: false,
22779
22779
  singleQuote: null,
22780
+ trailingComma: false,
22780
22781
  trueStr: "true",
22781
22782
  verifyAliasOrder: true
22782
22783
  }, doc.schema.toStringOptions, options);
@@ -23294,12 +23295,19 @@ ${indent}${line}` : "\n";
23294
23295
  if (comment)
23295
23296
  reqNewline = true;
23296
23297
  let str = stringify2.stringify(item, itemCtx, () => comment = null);
23297
- if (i < items.length - 1)
23298
+ reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
23299
+ if (i < items.length - 1) {
23298
23300
  str += ",";
23301
+ } else if (ctx.options.trailingComma) {
23302
+ if (ctx.options.lineWidth > 0) {
23303
+ reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
23304
+ }
23305
+ if (reqNewline) {
23306
+ str += ",";
23307
+ }
23308
+ }
23299
23309
  if (comment)
23300
23310
  str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
23301
- if (!reqNewline && (lines.length > linesAtValue || str.includes("\n")))
23302
- reqNewline = true;
23303
23311
  lines.push(str);
23304
23312
  linesAtValue = lines.length;
23305
23313
  }
@@ -26313,17 +26321,22 @@ var require_compose_node = __commonJS({
26313
26321
  case "block-map":
26314
26322
  case "block-seq":
26315
26323
  case "flow-collection":
26316
- node = composeCollection.composeCollection(CN, ctx, token, props, onError);
26317
- if (anchor)
26318
- node.anchor = anchor.source.substring(1);
26324
+ try {
26325
+ node = composeCollection.composeCollection(CN, ctx, token, props, onError);
26326
+ if (anchor)
26327
+ node.anchor = anchor.source.substring(1);
26328
+ } catch (error) {
26329
+ const message = error instanceof Error ? error.message : String(error);
26330
+ onError(token, "RESOURCE_EXHAUSTION", message);
26331
+ }
26319
26332
  break;
26320
26333
  default: {
26321
26334
  const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
26322
26335
  onError(token, "UNEXPECTED_TOKEN", message);
26323
- node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
26324
26336
  isSrcToken = false;
26325
26337
  }
26326
26338
  }
26339
+ node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
26327
26340
  if (anchor && node.anchor === "")
26328
26341
  onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
26329
26342
  if (atKey && ctx.options.stringKeys && (!identity.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
@@ -28671,7 +28684,6 @@ var index_exports = {};
28671
28684
  __export(index_exports, {
28672
28685
  createBootstrapDependencies: () => createBootstrapDependencies,
28673
28686
  createPlannedOutputs: () => createPlannedOutputs,
28674
- extractRepositorySlug: () => extractRepositorySlug,
28675
28687
  getInput: () => getInput,
28676
28688
  lintSpecViaCli: () => lintSpecViaCli,
28677
28689
  normalizeSpecDocument: () => normalizeSpecDocument,
@@ -28684,6 +28696,7 @@ module.exports = __toCommonJS(index_exports);
28684
28696
  var core = __toESM(require_core(), 1);
28685
28697
  var exec = __toESM(require_exec(), 1);
28686
28698
  var io = __toESM(require_io(), 1);
28699
+ var import_node_fs = require("node:fs");
28687
28700
  var import_yaml = __toESM(require_dist(), 1);
28688
28701
 
28689
28702
  // src/contracts.ts
@@ -28711,6 +28724,22 @@ var openAlphaActionContract = {
28711
28724
  description: "Existing contract collection ID.",
28712
28725
  required: false
28713
28726
  },
28727
+ "collection-sync-mode": {
28728
+ description: "Collection lifecycle policy: reuse existing collections, refresh them from the latest spec, or version them by release label.",
28729
+ required: false,
28730
+ default: "refresh",
28731
+ allowedValues: ["reuse", "refresh", "version"]
28732
+ },
28733
+ "spec-sync-mode": {
28734
+ description: "Spec lifecycle policy: update the canonical spec or create/reuse a versioned spec for the resolved release label.",
28735
+ required: false,
28736
+ default: "update",
28737
+ allowedValues: ["update", "version"]
28738
+ },
28739
+ "release-label": {
28740
+ description: "Optional release label. When omitted for versioned sync, the action derives one from GitHub ref metadata.",
28741
+ required: false
28742
+ },
28714
28743
  "project-name": {
28715
28744
  description: "Service project name.",
28716
28745
  required: true
@@ -28731,20 +28760,14 @@ var openAlphaActionContract = {
28731
28760
  description: "Comma-separated workspace admin user ids.",
28732
28761
  required: false
28733
28762
  },
28763
+ "workspace-team-id": {
28764
+ description: "Numeric sub-team ID for org-mode workspace creation.",
28765
+ required: false
28766
+ },
28734
28767
  "spec-url": {
28735
28768
  description: "HTTPS URL to the OpenAPI document.",
28736
28769
  required: true
28737
28770
  },
28738
- "environments-json": {
28739
- description: "JSON array of environment slugs to preserve in bootstrap outputs.",
28740
- required: false,
28741
- default: '["prod"]'
28742
- },
28743
- "system-env-map-json": {
28744
- description: "JSON map of environment slug to system environment id.",
28745
- required: false,
28746
- default: "{}"
28747
- },
28748
28771
  "governance-mapping-json": {
28749
28772
  description: "JSON map of business domain to governance group name.",
28750
28773
  required: false,
@@ -28758,19 +28781,6 @@ var openAlphaActionContract = {
28758
28781
  description: "Postman access token used for governance and workspace mutations.",
28759
28782
  required: false
28760
28783
  },
28761
- "github-token": {
28762
- description: "GitHub token for repository variable persistence.",
28763
- required: false
28764
- },
28765
- "gh-fallback-token": {
28766
- description: "Fallback token for repository variable APIs.",
28767
- required: false
28768
- },
28769
- "github-auth-mode": {
28770
- description: "GitHub auth mode for repository variable APIs.",
28771
- required: false,
28772
- default: "github_token_first"
28773
- },
28774
28784
  "integration-backend": {
28775
28785
  description: "Integration backend for downstream workspace connectivity.",
28776
28786
  required: false,
@@ -28816,8 +28826,8 @@ var openAlphaActionContract = {
28816
28826
  "OpenAPI operation summary normalization before upload (missing or oversized summaries)",
28817
28827
  "spec linting by UID",
28818
28828
  "baseline, smoke, and contract collection generation",
28829
+ "collection refresh and versioning policies",
28819
28830
  "collection tagging",
28820
- "GitHub repository variable persistence for downstream sync steps",
28821
28831
  "workspace, spec, and collection outputs"
28822
28832
  ],
28823
28833
  removedBehavior: [
@@ -28908,189 +28918,6 @@ function sanitizeHeaders(headers, secretValues) {
28908
28918
  return sanitized;
28909
28919
  }
28910
28920
 
28911
- // src/lib/github/github-api-client.ts
28912
- function buildErrorMessage(method, path, response, body, masker) {
28913
- const status = `${response.status}${response.statusText ? ` ${response.statusText}` : ""}`;
28914
- const sanitizedBody = masker(body || "");
28915
- return sanitizedBody ? masker(`${method} ${path} failed with ${status} - ${sanitizedBody}`) : masker(`${method} ${path} failed with ${status} - [REDACTED]`);
28916
- }
28917
- var GitHubApiClient = class {
28918
- apiBase;
28919
- authMode;
28920
- appToken;
28921
- fallbackToken;
28922
- fetchImpl;
28923
- owner;
28924
- repo;
28925
- repository;
28926
- secretMasker;
28927
- token;
28928
- constructor(options) {
28929
- this.apiBase = String(options.apiBase || "https://api.github.com").replace(
28930
- /\/+$/,
28931
- ""
28932
- );
28933
- this.appToken = String(options.appToken || "").trim();
28934
- this.authMode = options.authMode || "github_token_first";
28935
- this.fallbackToken = String(options.fallbackToken || "").trim();
28936
- this.fetchImpl = options.fetch ?? fetch;
28937
- this.repository = options.repository;
28938
- const [owner, repo] = options.repository.split("/");
28939
- this.owner = owner;
28940
- this.repo = repo;
28941
- this.token = String(options.token || "").trim();
28942
- this.secretMasker = options.secretMasker ?? createSecretMasker([this.token, this.fallbackToken, this.appToken]);
28943
- }
28944
- getTokenOrder() {
28945
- const ordered = [];
28946
- if (this.authMode === "app_token") {
28947
- if (this.appToken) ordered.push(this.appToken);
28948
- if (this.token && this.token !== this.appToken) ordered.push(this.token);
28949
- if (this.fallbackToken && this.fallbackToken !== this.appToken && this.fallbackToken !== this.token) {
28950
- ordered.push(this.fallbackToken);
28951
- }
28952
- return ordered;
28953
- }
28954
- if (this.authMode === "fallback_pat_first") {
28955
- if (this.fallbackToken) ordered.push(this.fallbackToken);
28956
- if (this.token && this.token !== this.fallbackToken) ordered.push(this.token);
28957
- return ordered;
28958
- }
28959
- if (this.token) ordered.push(this.token);
28960
- if (this.fallbackToken && this.fallbackToken !== this.token) {
28961
- ordered.push(this.fallbackToken);
28962
- }
28963
- return ordered;
28964
- }
28965
- isVariablesEndpoint(path) {
28966
- return path.startsWith(`/repos/${this.owner}/${this.repo}/actions/variables`);
28967
- }
28968
- canUseFallback(path) {
28969
- return this.isVariablesEndpoint(path) || path.includes(`/repos/${this.owner}/${this.repo}/contents`) || path.includes("/dispatches");
28970
- }
28971
- rateLimitDelayMs(response, attempt) {
28972
- const retryAfter = Number(response.headers.get("retry-after") || "");
28973
- if (Number.isFinite(retryAfter) && retryAfter > 0) {
28974
- return Math.min(retryAfter * 1e3, 12e4);
28975
- }
28976
- const resetAtSeconds = Number(response.headers.get("x-ratelimit-reset") || "");
28977
- if (Number.isFinite(resetAtSeconds) && resetAtSeconds > 0) {
28978
- const delta = resetAtSeconds * 1e3 - Date.now();
28979
- if (delta > 0) {
28980
- return Math.min(delta + 250, 12e4);
28981
- }
28982
- }
28983
- const base = Math.min(5e3 * Math.pow(2, attempt), 12e4);
28984
- const jitter = Math.floor(Math.random() * 250);
28985
- return Math.min(base + jitter, 12e4);
28986
- }
28987
- async requestWithToken(path, init, token) {
28988
- const MAX_RETRIES = 5;
28989
- const normalizedToken = String(token || "").trim();
28990
- if (!normalizedToken) {
28991
- throw new Error(`Missing GitHub auth token for request ${path}`);
28992
- }
28993
- for (let attempt = 0; ; attempt++) {
28994
- const response = await this.fetchImpl(`${this.apiBase}${path}`, {
28995
- ...init,
28996
- headers: {
28997
- Accept: "application/vnd.github+json",
28998
- Authorization: `Bearer ${normalizedToken}`,
28999
- "Content-Type": "application/json",
29000
- ...init.headers || {}
29001
- }
29002
- });
29003
- if (attempt < MAX_RETRIES && (response.status === 403 || response.status === 429)) {
29004
- const body = await response.clone().text().catch(() => "");
29005
- if (isRateLimitedResponse(response, body)) {
29006
- const delay = this.rateLimitDelayMs(response, attempt);
29007
- console.log(
29008
- `GitHub API rate limited, retrying in ${Math.ceil(delay / 1e3)}s (attempt ${attempt + 1}/${MAX_RETRIES})...`
29009
- );
29010
- await new Promise((r) => setTimeout(r, delay));
29011
- continue;
29012
- }
29013
- }
29014
- return response;
29015
- }
29016
- }
29017
- async request(path, init = {}) {
29018
- const orderedTokens = this.getTokenOrder();
29019
- if (orderedTokens.length === 0) {
29020
- throw new Error("No GitHub auth token configured");
29021
- }
29022
- const first = await this.requestWithToken(path, init, orderedTokens[0]);
29023
- if (orderedTokens.length < 2 || !this.canUseFallback(path)) {
29024
- return first;
29025
- }
29026
- const isVariableGet404 = first.status === 404 && (!init.method || init.method === "GET") && this.isVariablesEndpoint(path);
29027
- if (first.status !== 403 && !isVariableGet404) {
29028
- return first;
29029
- }
29030
- return this.requestWithToken(path, init, orderedTokens[1]);
29031
- }
29032
- async setRepositoryVariable(name, value) {
29033
- if (!value) {
29034
- throw new Error(`Repo variable ${name} is empty`);
29035
- }
29036
- const path = `/repos/${this.repository}/actions/variables`;
29037
- const body = JSON.stringify({ name, value: String(value) });
29038
- const createResponse = await this.request(path, {
29039
- method: "POST",
29040
- body
29041
- });
29042
- if (createResponse.ok || createResponse.status === 201) {
29043
- return;
29044
- }
29045
- if (createResponse.status === 409 || createResponse.status === 422) {
29046
- const updatePath = `/repos/${this.repository}/actions/variables/${name}`;
29047
- const updateResponse = await this.request(updatePath, {
29048
- method: "PATCH",
29049
- body
29050
- });
29051
- if (updateResponse.ok) {
29052
- return;
29053
- }
29054
- const text2 = await updateResponse.text().catch(() => "");
29055
- throw new Error(
29056
- buildErrorMessage("PATCH", updatePath, updateResponse, text2, this.secretMasker)
29057
- );
29058
- }
29059
- const text = await createResponse.text().catch(() => "");
29060
- throw new Error(
29061
- buildErrorMessage("POST", path, createResponse, text, this.secretMasker)
29062
- );
29063
- }
29064
- async getRepositoryVariable(name) {
29065
- const path = `/repos/${this.repository}/actions/variables/${name}`;
29066
- const response = await this.request(path, {
29067
- method: "GET"
29068
- });
29069
- if (response.status === 404) {
29070
- return "";
29071
- }
29072
- if (!response.ok) {
29073
- const text = await response.text().catch(() => "");
29074
- throw new Error(
29075
- buildErrorMessage("GET", path, response, text, this.secretMasker)
29076
- );
29077
- }
29078
- const data = await response.json();
29079
- return String(data.value || "");
29080
- }
29081
- };
29082
- function isRateLimitedResponse(response, body) {
29083
- if (response.status !== 403 && response.status !== 429) return false;
29084
- const remaining = response.headers.get("x-ratelimit-remaining");
29085
- const retryAfter = response.headers.get("retry-after");
29086
- if (remaining === "0") return true;
29087
- if (retryAfter) return true;
29088
- const message = body.toLowerCase();
29089
- if (message.includes("secondary rate limit")) return true;
29090
- if (message.includes("api rate limit exceeded")) return true;
29091
- return response.status === 429;
29092
- }
29093
-
29094
28921
  // src/lib/http-error.ts
29095
28922
  function truncate(value, limit) {
29096
28923
  if (value.length <= limit) {
@@ -29273,6 +29100,16 @@ var PostmanAssetsClient = class {
29273
29100
  }
29274
29101
  return void 0;
29275
29102
  }
29103
+ async getTeams() {
29104
+ const data = await this.request("/teams");
29105
+ const teams = data?.data ?? [];
29106
+ return Array.isArray(teams) ? teams.filter((t) => t?.id && t?.name).map((t) => ({
29107
+ id: Number(t.id),
29108
+ name: String(t.name),
29109
+ handle: String(t.handle || ""),
29110
+ ...t.organizationId != null ? { organizationId: Number(t.organizationId) } : {}
29111
+ })) : [];
29112
+ }
29276
29113
  async request(path, init = {}) {
29277
29114
  const url = path.startsWith("http") ? path : `${this.baseUrl}${path}`;
29278
29115
  const response = await this.fetchImpl(url, {
@@ -29301,13 +29138,14 @@ var PostmanAssetsClient = class {
29301
29138
  return null;
29302
29139
  }
29303
29140
  }
29304
- async createWorkspace(name, about) {
29141
+ async createWorkspace(name, about, targetTeamId) {
29305
29142
  return retry(async () => {
29306
29143
  const payload = {
29307
29144
  workspace: {
29308
29145
  about,
29309
29146
  name,
29310
- type: "team"
29147
+ type: "team",
29148
+ ...targetTeamId != null && !Number.isNaN(targetTeamId) ? { teamId: targetTeamId } : {}
29311
29149
  }
29312
29150
  };
29313
29151
  let created;
@@ -29319,7 +29157,7 @@ var PostmanAssetsClient = class {
29319
29157
  } catch (err) {
29320
29158
  if (err instanceof Error && err.message.includes("Only personal workspaces")) {
29321
29159
  throw new Error(
29322
- "Workspace creation failed: Your team may have Org Mode enabled. Org-level workspaces require a different API request schema which is currently unsupported in this alpha version."
29160
+ "Workspace creation failed: This may be an Org-mode account that requires a workspace-team-id input. The Postman API does not allow creating team workspaces at the organization level. Use the workspace-team-id input to specify which sub-team should own this workspace."
29323
29161
  );
29324
29162
  }
29325
29163
  throw err;
@@ -29338,7 +29176,11 @@ var PostmanAssetsClient = class {
29338
29176
  return {
29339
29177
  id: workspaceId
29340
29178
  };
29341
- }, { maxAttempts: 3, delayMs: 2e3 });
29179
+ }, {
29180
+ maxAttempts: 3,
29181
+ delayMs: 2e3,
29182
+ shouldRetry: (err) => !(err instanceof Error && err.message.includes("workspace-team-id"))
29183
+ });
29342
29184
  }
29343
29185
  async listWorkspaces() {
29344
29186
  const data = await this.request("/workspaces");
@@ -30150,31 +29992,17 @@ function requireInput(actionCore, name) {
30150
29992
  function optionalInput(actionCore, name) {
30151
29993
  return normalizeInputValue(actionCore.getInput(name));
30152
29994
  }
30153
- function parseJsonValue(raw, fallback, inputName) {
30154
- try {
30155
- return JSON.parse(raw || JSON.stringify(fallback)) ?? fallback;
30156
- } catch (error) {
30157
- throw new Error(
30158
- `Invalid JSON for ${inputName}: ${error instanceof Error ? error.message : String(error)}`
30159
- );
29995
+ function parseCollectionSyncMode(value) {
29996
+ if (value === "reuse" || value === "version") {
29997
+ return value;
30160
29998
  }
29999
+ return "refresh";
30161
30000
  }
30162
- function asStringArray(value, inputName) {
30163
- if (!Array.isArray(value)) {
30164
- throw new Error(`${inputName} must be a JSON array`);
30001
+ function parseSpecSyncMode(value) {
30002
+ if (value === "version") {
30003
+ return value;
30165
30004
  }
30166
- return value.map((entry) => String(entry));
30167
- }
30168
- function asStringMap(value, inputName) {
30169
- if (!value || typeof value !== "object" || Array.isArray(value)) {
30170
- throw new Error(`${inputName} must be a JSON object`);
30171
- }
30172
- return Object.fromEntries(
30173
- Object.entries(value).map(([key, entry]) => [
30174
- key,
30175
- String(entry)
30176
- ])
30177
- );
30005
+ return "update";
30178
30006
  }
30179
30007
  function resolveInputs(env = process.env) {
30180
30008
  const repoContext = detectRepoContext(
@@ -30202,28 +30030,31 @@ function resolveInputs(env = process.env) {
30202
30030
  }
30203
30031
  }
30204
30032
  return {
30205
- projectName: getInput("project-name", env) ?? "",
30033
+ projectName: getInput("project-name", env) ?? env.GITHUB_REPOSITORY?.split("/").pop() ?? env.CI_PROJECT_NAME ?? "",
30206
30034
  workspaceId: getInput("workspace-id", env),
30207
30035
  specId: getInput("spec-id", env),
30208
30036
  baselineCollectionId: getInput("baseline-collection-id", env),
30209
30037
  smokeCollectionId: getInput("smoke-collection-id", env),
30210
30038
  contractCollectionId: getInput("contract-collection-id", env),
30039
+ collectionSyncMode: parseCollectionSyncMode(getInput("collection-sync-mode", env)),
30040
+ specSyncMode: parseSpecSyncMode(getInput("spec-sync-mode", env)),
30041
+ releaseLabel: getInput("release-label", env),
30211
30042
  domain: getInput("domain", env),
30212
30043
  domainCode: getInput("domain-code", env),
30213
30044
  requesterEmail: getInput("requester-email", env),
30214
30045
  workspaceAdminUserIds: getInput("workspace-admin-user-ids", env) || env.WORKSPACE_ADMIN_USER_IDS || "",
30046
+ workspaceTeamId: getInput("workspace-team-id", env) || env.POSTMAN_WORKSPACE_TEAM_ID,
30215
30047
  teamId: getInput("team-id", env) || env.POSTMAN_TEAM_ID || "",
30216
30048
  repoUrl: repoContext.repoUrl || "",
30217
30049
  specUrl,
30218
- environmentsJson: getInput("environments-json", env) ?? openAlphaActionContract.inputs["environments-json"].default ?? '["prod"]',
30219
- systemEnvMapJson: getInput("system-env-map-json", env) ?? openAlphaActionContract.inputs["system-env-map-json"].default ?? "{}",
30220
30050
  governanceMappingJson: getInput("governance-mapping-json", env) ?? openAlphaActionContract.inputs["governance-mapping-json"].default ?? "{}",
30221
30051
  postmanApiKey: getInput("postman-api-key", env) ?? "",
30222
30052
  postmanAccessToken: getInput("postman-access-token", env),
30223
- githubToken: getInput("github-token", env),
30224
- ghFallbackToken: getInput("gh-fallback-token", env),
30225
- githubAuthMode: getInput("github-auth-mode", env) ?? openAlphaActionContract.inputs["github-auth-mode"].default ?? "github_token_first",
30226
- integrationBackend
30053
+ integrationBackend,
30054
+ githubRefName: env.GITHUB_REF_NAME,
30055
+ githubHeadRef: env.GITHUB_HEAD_REF,
30056
+ githubRef: env.GITHUB_REF,
30057
+ githubSha: env.GITHUB_SHA
30227
30058
  };
30228
30059
  }
30229
30060
  function createPlannedOutputs(inputs) {
@@ -30254,12 +30085,8 @@ function readActionInputs(actionCore) {
30254
30085
  const specUrl = requireInput(actionCore, "spec-url");
30255
30086
  const postmanApiKey = requireInput(actionCore, "postman-api-key");
30256
30087
  const postmanAccessToken = optionalInput(actionCore, "postman-access-token");
30257
- const githubToken = optionalInput(actionCore, "github-token");
30258
- const ghFallbackToken = optionalInput(actionCore, "gh-fallback-token");
30259
30088
  actionCore.setSecret(postmanApiKey);
30260
30089
  if (postmanAccessToken) actionCore.setSecret(postmanAccessToken);
30261
- if (githubToken) actionCore.setSecret(githubToken);
30262
- if (ghFallbackToken) actionCore.setSecret(ghFallbackToken);
30263
30090
  const inputs = resolveInputs({
30264
30091
  ...process.env,
30265
30092
  INPUT_PROJECT_NAME: projectName,
@@ -30268,6 +30095,9 @@ function readActionInputs(actionCore) {
30268
30095
  INPUT_BASELINE_COLLECTION_ID: optionalInput(actionCore, "baseline-collection-id"),
30269
30096
  INPUT_SMOKE_COLLECTION_ID: optionalInput(actionCore, "smoke-collection-id"),
30270
30097
  INPUT_CONTRACT_COLLECTION_ID: optionalInput(actionCore, "contract-collection-id"),
30098
+ INPUT_COLLECTION_SYNC_MODE: optionalInput(actionCore, "collection-sync-mode") ?? openAlphaActionContract.inputs["collection-sync-mode"].default,
30099
+ INPUT_SPEC_SYNC_MODE: optionalInput(actionCore, "spec-sync-mode") ?? openAlphaActionContract.inputs["spec-sync-mode"].default,
30100
+ INPUT_RELEASE_LABEL: optionalInput(actionCore, "release-label"),
30271
30101
  INPUT_DOMAIN: optionalInput(actionCore, "domain"),
30272
30102
  INPUT_DOMAIN_CODE: optionalInput(actionCore, "domain-code"),
30273
30103
  INPUT_REQUESTER_EMAIL: optionalInput(actionCore, "requester-email"),
@@ -30275,17 +30105,13 @@ function readActionInputs(actionCore) {
30275
30105
  actionCore,
30276
30106
  "workspace-admin-user-ids"
30277
30107
  ),
30108
+ INPUT_WORKSPACE_TEAM_ID: optionalInput(actionCore, "workspace-team-id") || process.env.POSTMAN_WORKSPACE_TEAM_ID,
30278
30109
  INPUT_TEAM_ID: optionalInput(actionCore, "postman-team-id") || process.env.POSTMAN_TEAM_ID,
30279
30110
  INPUT_REPO_URL: optionalInput(actionCore, "repo-url"),
30280
30111
  INPUT_SPEC_URL: specUrl,
30281
- INPUT_ENVIRONMENTS_JSON: optionalInput(actionCore, "environments-json") ?? openAlphaActionContract.inputs["environments-json"].default,
30282
- INPUT_SYSTEM_ENV_MAP_JSON: optionalInput(actionCore, "system-env-map-json") ?? openAlphaActionContract.inputs["system-env-map-json"].default,
30283
30112
  INPUT_GOVERNANCE_MAPPING_JSON: optionalInput(actionCore, "governance-mapping-json") ?? openAlphaActionContract.inputs["governance-mapping-json"].default,
30284
30113
  INPUT_POSTMAN_API_KEY: postmanApiKey,
30285
30114
  INPUT_POSTMAN_ACCESS_TOKEN: postmanAccessToken,
30286
- INPUT_GITHUB_TOKEN: githubToken,
30287
- INPUT_GH_FALLBACK_TOKEN: ghFallbackToken,
30288
- INPUT_GITHUB_AUTH_MODE: optionalInput(actionCore, "github-auth-mode") ?? openAlphaActionContract.inputs["github-auth-mode"].default,
30289
30115
  INPUT_INTEGRATION_BACKEND: optionalInput(actionCore, "integration-backend") ?? openAlphaActionContract.inputs["integration-backend"].default
30290
30116
  });
30291
30117
  return inputs;
@@ -30362,6 +30188,45 @@ async function fetchSpecDocument(specUrl, specFetcher) {
30362
30188
  }
30363
30189
  );
30364
30190
  }
30191
+ function normalizeReleaseLabel(value) {
30192
+ const trimmed = String(value || "").trim();
30193
+ if (!trimmed) {
30194
+ return void 0;
30195
+ }
30196
+ return trimmed.replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/^refs\/pull\//, "pull-").replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || void 0;
30197
+ }
30198
+ function deriveReleaseLabel(inputs) {
30199
+ if (inputs.releaseLabel) {
30200
+ return normalizeReleaseLabel(inputs.releaseLabel);
30201
+ }
30202
+ return normalizeReleaseLabel(inputs.githubRefName) ?? normalizeReleaseLabel(inputs.githubHeadRef) ?? normalizeReleaseLabel(inputs.githubRef);
30203
+ }
30204
+ function createAssetProjectName(inputs, releaseLabel) {
30205
+ if (!releaseLabel) {
30206
+ return inputs.projectName;
30207
+ }
30208
+ return `${inputs.projectName} ${releaseLabel}`;
30209
+ }
30210
+ function readResourcesState() {
30211
+ try {
30212
+ return (0, import_yaml.parse)((0, import_node_fs.readFileSync)(".postman/resources.yaml", "utf8"));
30213
+ } catch {
30214
+ return null;
30215
+ }
30216
+ }
30217
+ function getFirstCloudResourceId(map) {
30218
+ if (!map) {
30219
+ return void 0;
30220
+ }
30221
+ return Object.values(map)[0];
30222
+ }
30223
+ function findCloudResourceId(map, matcher) {
30224
+ if (!map) {
30225
+ return void 0;
30226
+ }
30227
+ const match = Object.entries(map).find(([filePath]) => matcher(filePath));
30228
+ return match?.[1];
30229
+ }
30365
30230
  var SPEC_SUMMARY_MAX_LEN = 200;
30366
30231
  var SPEC_HTTP_METHODS = /* @__PURE__ */ new Set([
30367
30232
  "get",
@@ -30450,122 +30315,28 @@ function validateSpecStructure(content) {
30450
30315
  throw new Error('Spec is missing "openapi" or "swagger" version field');
30451
30316
  }
30452
30317
  }
30453
- function varName(projectName, baseName) {
30454
- const slug = projectName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
30455
- return `POSTMAN_${slug}_${baseName}`;
30456
- }
30457
- async function readVariable(github, projectName, baseName) {
30458
- if (!github) {
30459
- return void 0;
30460
- }
30461
- const namespaced = await github.getRepositoryVariable(varName(projectName, baseName)).catch(() => void 0);
30462
- if (namespaced) {
30463
- return namespaced;
30464
- }
30465
- const legacy = await github.getRepositoryVariable(`POSTMAN_${baseName}`).catch(() => void 0);
30466
- return legacy || void 0;
30467
- }
30468
- async function persistVariable(github, name, value, actionCore) {
30469
- if (!github || !value) {
30470
- return;
30471
- }
30472
- try {
30473
- await github.setRepositoryVariable(name, value);
30474
- } catch (err) {
30475
- actionCore.warning(
30476
- `Failed to persist ${name}: ${err instanceof Error ? err.message : String(err)}`
30477
- );
30478
- }
30479
- }
30480
- async function writeVariable(github, projectName, baseName, value, actionCore) {
30481
- if (!github || !value) {
30482
- return;
30483
- }
30484
- await persistVariable(github, varName(projectName, baseName), value, actionCore);
30485
- await persistVariable(github, `POSTMAN_${baseName}`, value, actionCore);
30486
- }
30487
- async function persistBootstrapRepositoryVariables(github, projectName, outputs, systemEnvMap, environments, lintSummary, actionCore) {
30488
- await persistVariable(
30489
- github,
30490
- "LINT_WARNINGS",
30491
- String(lintSummary.lintWarnings),
30492
- actionCore
30493
- );
30494
- await persistVariable(
30495
- github,
30496
- "LINT_ERRORS",
30497
- String(lintSummary.lintErrors),
30498
- actionCore
30499
- );
30500
- await writeVariable(
30501
- github,
30502
- projectName,
30503
- "WORKSPACE_ID",
30504
- outputs["workspace-id"],
30505
- actionCore
30506
- );
30507
- await writeVariable(github, projectName, "SPEC_UID", outputs["spec-id"], actionCore);
30508
- await writeVariable(
30509
- github,
30510
- projectName,
30511
- "BASELINE_COLLECTION_UID",
30512
- outputs["baseline-collection-id"],
30513
- actionCore
30514
- );
30515
- await writeVariable(
30516
- github,
30517
- projectName,
30518
- "SMOKE_COLLECTION_UID",
30519
- outputs["smoke-collection-id"],
30520
- actionCore
30521
- );
30522
- await writeVariable(
30523
- github,
30524
- projectName,
30525
- "CONTRACT_COLLECTION_UID",
30526
- outputs["contract-collection-id"],
30527
- actionCore
30528
- );
30529
- for (const envName of environments) {
30530
- const systemEnvId = systemEnvMap[envName];
30531
- if (!systemEnvId) {
30532
- continue;
30533
- }
30534
- await writeVariable(
30535
- github,
30536
- projectName,
30537
- `SYSTEM_ENV_${envName.toUpperCase()}`,
30538
- systemEnvId,
30539
- actionCore
30540
- );
30541
- }
30542
- }
30543
30318
  async function runBootstrap(inputs, dependencies) {
30544
30319
  const outputs = createPlannedOutputs(inputs);
30545
- const environments = asStringArray(
30546
- parseJsonValue(inputs.environmentsJson, ["prod"], "environments-json"),
30547
- "environments-json"
30548
- );
30549
- const systemEnvMap = asStringMap(
30550
- parseJsonValue(inputs.systemEnvMapJson, {}, "system-env-map-json"),
30551
- "system-env-map-json"
30552
- );
30320
+ const requiresReleaseLabel = inputs.collectionSyncMode === "version" || inputs.specSyncMode === "version";
30321
+ const releaseLabel = requiresReleaseLabel ? deriveReleaseLabel(inputs) : void 0;
30322
+ if (requiresReleaseLabel && !releaseLabel) {
30323
+ throw new Error(
30324
+ "Versioned spec or collection sync requires a release-label or derivable GitHub ref metadata"
30325
+ );
30326
+ }
30553
30327
  const workspaceName = createWorkspaceName(inputs);
30554
30328
  const aboutText = `Auto-provisioned by Postman CS open-alpha for ${inputs.projectName}`;
30555
30329
  await runGroup(dependencies.core, "Install Postman CLI", async () => {
30556
30330
  await ensurePostmanCli(dependencies, inputs.postmanApiKey);
30557
30331
  });
30558
- const explicitWorkspaceId = inputs.workspaceId;
30559
- let repoWorkspaceId;
30560
- let workspaceId = explicitWorkspaceId;
30561
- if (!workspaceId && dependencies.github) {
30562
- repoWorkspaceId = await readVariable(
30563
- dependencies.github,
30564
- inputs.projectName,
30565
- "WORKSPACE_ID"
30566
- );
30567
- workspaceId = repoWorkspaceId;
30332
+ const resourcesState = readResourcesState();
30333
+ let explicitWorkspaceId = inputs.workspaceId;
30334
+ if (!explicitWorkspaceId && resourcesState?.workspace?.id) {
30335
+ explicitWorkspaceId = resourcesState.workspace.id;
30336
+ dependencies.core.info("Resolved workspace-id from .postman/resources.yaml");
30568
30337
  }
30338
+ const repoWorkspaceId = explicitWorkspaceId;
30339
+ let workspaceId = explicitWorkspaceId;
30569
30340
  let teamId = inputs.teamId || "";
30570
30341
  if (!teamId) {
30571
30342
  teamId = await dependencies.postman.getAutoDerivedTeamId() || "";
@@ -30599,24 +30370,65 @@ async function runBootstrap(inputs, dependencies) {
30599
30370
  } else if (workspaceId) {
30600
30371
  dependencies.core.info(`Using existing workspace: ${workspaceId}`);
30601
30372
  }
30373
+ let workspaceTeamId;
30374
+ if (inputs.workspaceTeamId) {
30375
+ workspaceTeamId = parseInt(inputs.workspaceTeamId, 10);
30376
+ if (Number.isNaN(workspaceTeamId)) {
30377
+ throw new Error(`workspace-team-id must be a numeric sub-team ID, got: ${inputs.workspaceTeamId}`);
30378
+ }
30379
+ }
30380
+ if (!workspaceId && !workspaceTeamId) {
30381
+ try {
30382
+ const teams = await dependencies.postman.getTeams();
30383
+ if (teams.length > 1 && teams.every((t) => t.organizationId == null)) {
30384
+ dependencies.core.warning(
30385
+ "GET /teams returned multiple teams but none include organizationId. Org-mode detection may be degraded due to an upstream API change. If workspace creation fails, set workspace-team-id explicitly."
30386
+ );
30387
+ }
30388
+ const orgIds = new Set(teams.filter((t) => t.organizationId != null).map((t) => t.organizationId));
30389
+ const meTeamId = parseInt(teamId, 10);
30390
+ const isOrgMode = teams.length > 1 && orgIds.size === 1 && orgIds.has(meTeamId);
30391
+ if (isOrgMode) {
30392
+ const teamList = teams.map((t) => ` ${t.id} ${t.name}`).join("\n");
30393
+ throw new Error(
30394
+ `Org-mode account detected. Workspace creation requires a specific sub-team ID.
30395
+
30396
+ Available sub-teams:
30397
+ ${teamList}
30398
+
30399
+ To fix this, set the workspace-team-id input in your workflow:
30400
+ workspace-team-id: '<id>'
30401
+
30402
+ Or for reuse across runs, create a repository variable and reference it:
30403
+ workspace-team-id: \${{ vars.POSTMAN_WORKSPACE_TEAM_ID }}
30404
+
30405
+ For CLI usage, pass --workspace-team-id <id> or export POSTMAN_WORKSPACE_TEAM_ID=<id>.`
30406
+ );
30407
+ } else if (teams.length > 1) {
30408
+ dependencies.core.warning(
30409
+ `API key has access to ${teams.length} teams but org-mode could not be confirmed. Proceeding without teamId. If workspace creation fails, set workspace-team-id explicitly.`
30410
+ );
30411
+ }
30412
+ } catch (err) {
30413
+ if (err instanceof Error && err.message.includes("Org-mode account detected")) {
30414
+ throw err;
30415
+ }
30416
+ dependencies.core.warning(
30417
+ `Could not check for org-mode sub-teams: ${err instanceof Error ? err.message : String(err)}`
30418
+ );
30419
+ }
30420
+ }
30602
30421
  if (!workspaceId) {
30603
30422
  const workspace = await runGroup(
30604
30423
  dependencies.core,
30605
30424
  "Create Postman Workspace",
30606
- async () => dependencies.postman.createWorkspace(workspaceName, aboutText)
30425
+ async () => dependencies.postman.createWorkspace(workspaceName, aboutText, workspaceTeamId)
30607
30426
  );
30608
30427
  workspaceId = workspace.id;
30609
30428
  }
30610
30429
  outputs["workspace-id"] = workspaceId || "";
30611
30430
  outputs["workspace-url"] = `https://go.postman.co/workspace/${workspaceId}`;
30612
30431
  outputs["workspace-name"] = workspaceName;
30613
- await writeVariable(
30614
- dependencies.github,
30615
- inputs.projectName,
30616
- "WORKSPACE_ID",
30617
- outputs["workspace-id"],
30618
- dependencies.core
30619
- );
30620
30432
  if (inputs.domain && dependencies.internalIntegration) {
30621
30433
  await runGroup(
30622
30434
  dependencies.core,
@@ -30671,33 +30483,43 @@ async function runBootstrap(inputs, dependencies) {
30671
30483
  );
30672
30484
  }
30673
30485
  let specId = inputs.specId;
30674
- if (!specId && dependencies.github) {
30675
- specId = await readVariable(dependencies.github, inputs.projectName, "SPEC_UID");
30486
+ if (!specId) {
30487
+ specId = getFirstCloudResourceId(resourcesState?.cloudResources?.specs);
30488
+ if (specId) {
30489
+ dependencies.core.info("Resolved spec-id from .postman/resources.yaml");
30490
+ }
30676
30491
  }
30677
- let baselineCollectionId = inputs.baselineCollectionId;
30678
- let smokeCollectionId = inputs.smokeCollectionId;
30679
- let contractCollectionId = inputs.contractCollectionId;
30680
- if (dependencies.github) {
30492
+ let baselineCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.baselineCollectionId;
30493
+ let smokeCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.smokeCollectionId;
30494
+ let contractCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.contractCollectionId;
30495
+ if (inputs.collectionSyncMode !== "refresh") {
30496
+ const cloudCollections = resourcesState?.cloudResources?.collections;
30681
30497
  if (!baselineCollectionId) {
30682
- baselineCollectionId = await readVariable(
30683
- dependencies.github,
30684
- inputs.projectName,
30685
- "BASELINE_COLLECTION_UID"
30498
+ baselineCollectionId = findCloudResourceId(
30499
+ cloudCollections,
30500
+ (filePath) => filePath.includes("[Baseline]")
30686
30501
  );
30502
+ if (baselineCollectionId) {
30503
+ dependencies.core.info("Resolved baseline-collection-id from .postman/resources.yaml");
30504
+ }
30687
30505
  }
30688
30506
  if (!smokeCollectionId) {
30689
- smokeCollectionId = await readVariable(
30690
- dependencies.github,
30691
- inputs.projectName,
30692
- "SMOKE_COLLECTION_UID"
30507
+ smokeCollectionId = findCloudResourceId(
30508
+ cloudCollections,
30509
+ (filePath) => filePath.includes("[Smoke]")
30693
30510
  );
30511
+ if (smokeCollectionId) {
30512
+ dependencies.core.info("Resolved smoke-collection-id from .postman/resources.yaml");
30513
+ }
30694
30514
  }
30695
30515
  if (!contractCollectionId) {
30696
- contractCollectionId = await readVariable(
30697
- dependencies.github,
30698
- inputs.projectName,
30699
- "CONTRACT_COLLECTION_UID"
30516
+ contractCollectionId = findCloudResourceId(
30517
+ cloudCollections,
30518
+ (filePath) => filePath.includes("[Contract]")
30700
30519
  );
30520
+ if (contractCollectionId) {
30521
+ dependencies.core.info("Resolved contract-collection-id from .postman/resources.yaml");
30522
+ }
30701
30523
  }
30702
30524
  }
30703
30525
  if (specId) {
@@ -30721,7 +30543,10 @@ async function runBootstrap(inputs, dependencies) {
30721
30543
  } else {
30722
30544
  specId = await dependencies.postman.uploadSpec(
30723
30545
  workspaceId || "",
30724
- inputs.projectName,
30546
+ createAssetProjectName(
30547
+ inputs,
30548
+ inputs.specSyncMode === "version" ? releaseLabel : void 0
30549
+ ),
30725
30550
  document
30726
30551
  );
30727
30552
  }
@@ -30730,13 +30555,6 @@ async function runBootstrap(inputs, dependencies) {
30730
30555
  }
30731
30556
  );
30732
30557
  void specContent;
30733
- await writeVariable(
30734
- dependencies.github,
30735
- inputs.projectName,
30736
- "SPEC_UID",
30737
- outputs["spec-id"],
30738
- dependencies.core
30739
- );
30740
30558
  const lintSummary = await runGroup(
30741
30559
  dependencies.core,
30742
30560
  "Lint Spec via Postman CLI",
@@ -30774,13 +30592,15 @@ async function runBootstrap(inputs, dependencies) {
30774
30592
  dependencies.core,
30775
30593
  "Generate Collections from Spec",
30776
30594
  async () => {
30777
- outputs["baseline-collection-id"] = baselineCollectionId || "";
30778
- outputs["smoke-collection-id"] = smokeCollectionId || "";
30779
- outputs["contract-collection-id"] = contractCollectionId || "";
30595
+ const shouldReuseCollections = inputs.collectionSyncMode !== "refresh";
30596
+ const assetProjectName = inputs.collectionSyncMode === "version" ? createAssetProjectName(inputs, releaseLabel) : inputs.projectName;
30597
+ outputs["baseline-collection-id"] = shouldReuseCollections ? baselineCollectionId || "" : "";
30598
+ outputs["smoke-collection-id"] = shouldReuseCollections ? smokeCollectionId || "" : "";
30599
+ outputs["contract-collection-id"] = shouldReuseCollections ? contractCollectionId || "" : "";
30780
30600
  if (!outputs["baseline-collection-id"]) {
30781
30601
  outputs["baseline-collection-id"] = await dependencies.postman.generateCollection(
30782
30602
  outputs["spec-id"],
30783
- inputs.projectName,
30603
+ assetProjectName,
30784
30604
  "[Baseline]"
30785
30605
  );
30786
30606
  } else {
@@ -30788,17 +30608,10 @@ async function runBootstrap(inputs, dependencies) {
30788
30608
  `Using existing baseline collection: ${outputs["baseline-collection-id"]}`
30789
30609
  );
30790
30610
  }
30791
- await writeVariable(
30792
- dependencies.github,
30793
- inputs.projectName,
30794
- "BASELINE_COLLECTION_UID",
30795
- outputs["baseline-collection-id"],
30796
- dependencies.core
30797
- );
30798
30611
  if (!outputs["smoke-collection-id"]) {
30799
30612
  outputs["smoke-collection-id"] = await dependencies.postman.generateCollection(
30800
30613
  outputs["spec-id"],
30801
- inputs.projectName,
30614
+ assetProjectName,
30802
30615
  "[Smoke]"
30803
30616
  );
30804
30617
  } else {
@@ -30806,17 +30619,10 @@ async function runBootstrap(inputs, dependencies) {
30806
30619
  `Using existing smoke collection: ${outputs["smoke-collection-id"]}`
30807
30620
  );
30808
30621
  }
30809
- await writeVariable(
30810
- dependencies.github,
30811
- inputs.projectName,
30812
- "SMOKE_COLLECTION_UID",
30813
- outputs["smoke-collection-id"],
30814
- dependencies.core
30815
- );
30816
30622
  if (!outputs["contract-collection-id"]) {
30817
30623
  outputs["contract-collection-id"] = await dependencies.postman.generateCollection(
30818
30624
  outputs["spec-id"],
30819
- inputs.projectName,
30625
+ assetProjectName,
30820
30626
  "[Contract]"
30821
30627
  );
30822
30628
  } else {
@@ -30824,13 +30630,6 @@ async function runBootstrap(inputs, dependencies) {
30824
30630
  `Using existing contract collection: ${outputs["contract-collection-id"]}`
30825
30631
  );
30826
30632
  }
30827
- await writeVariable(
30828
- dependencies.github,
30829
- inputs.projectName,
30830
- "CONTRACT_COLLECTION_UID",
30831
- outputs["contract-collection-id"],
30832
- dependencies.core
30833
- );
30834
30633
  }
30835
30634
  );
30836
30635
  outputs["collections-json"] = JSON.stringify({
@@ -30868,27 +30667,6 @@ async function runBootstrap(inputs, dependencies) {
30868
30667
  ]);
30869
30668
  }
30870
30669
  );
30871
- if (dependencies.github) {
30872
- const github = dependencies.github;
30873
- await runGroup(
30874
- dependencies.core,
30875
- "Store Postman UIDs as Repo Variables",
30876
- async () => {
30877
- await persistBootstrapRepositoryVariables(
30878
- github,
30879
- inputs.projectName,
30880
- outputs,
30881
- systemEnvMap,
30882
- environments,
30883
- {
30884
- lintErrors: lintSummary.errors,
30885
- lintWarnings: lintSummary.warnings
30886
- },
30887
- dependencies.core
30888
- );
30889
- }
30890
- );
30891
- }
30892
30670
  for (const [name, value] of Object.entries(outputs)) {
30893
30671
  dependencies.core.setOutput(name, value);
30894
30672
  }
@@ -30902,9 +30680,6 @@ async function runAction(actionCore = core, actionExec = exec, actionIo = io) {
30902
30680
  io: actionIo,
30903
30681
  specFetcher: fetch
30904
30682
  });
30905
- if (!dependencies.github) {
30906
- actionCore.info("GitHub repository variable persistence disabled for this run");
30907
- }
30908
30683
  if (inputs.domain && !dependencies.internalIntegration) {
30909
30684
  actionCore.warning(
30910
30685
  "Skipping governance assignment because postman-access-token is not configured"
@@ -30915,22 +30690,12 @@ async function runAction(actionCore = core, actionExec = exec, actionIo = io) {
30915
30690
  function createBootstrapDependencies(inputs, factories) {
30916
30691
  const secretMasker = createSecretMasker([
30917
30692
  inputs.postmanApiKey,
30918
- inputs.postmanAccessToken,
30919
- inputs.githubToken,
30920
- inputs.ghFallbackToken
30693
+ inputs.postmanAccessToken
30921
30694
  ]);
30922
30695
  const postman = new PostmanAssetsClient({
30923
30696
  apiKey: inputs.postmanApiKey,
30924
30697
  secretMasker
30925
30698
  });
30926
- const repository = extractRepositorySlug(inputs.repoUrl);
30927
- const github = inputs.githubToken && inputs.repoUrl && repository ? new GitHubApiClient({
30928
- authMode: inputs.githubAuthMode,
30929
- fallbackToken: inputs.ghFallbackToken,
30930
- repository,
30931
- secretMasker,
30932
- token: inputs.githubToken
30933
- }) : void 0;
30934
30699
  const internalIntegration = inputs.postmanAccessToken ? createInternalIntegrationAdapter({
30935
30700
  accessToken: inputs.postmanAccessToken,
30936
30701
  backend: inputs.integrationBackend,
@@ -30940,30 +30705,12 @@ function createBootstrapDependencies(inputs, factories) {
30940
30705
  return {
30941
30706
  core: factories.core,
30942
30707
  exec: factories.exec,
30943
- github,
30944
30708
  io: factories.io,
30945
30709
  internalIntegration,
30946
30710
  postman,
30947
30711
  specFetcher: factories.specFetcher ?? fetch
30948
30712
  };
30949
30713
  }
30950
- function extractRepositorySlug(repoUrl) {
30951
- const normalized = normalizeInputValue(repoUrl);
30952
- if (!normalized) {
30953
- return void 0;
30954
- }
30955
- try {
30956
- const parsed = new URL(normalized);
30957
- const pathname = parsed.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
30958
- const segments = pathname.split("/").filter(Boolean);
30959
- if (segments.length >= 2) {
30960
- return `${segments[0]}/${segments[1]}`;
30961
- }
30962
- return void 0;
30963
- } catch {
30964
- return void 0;
30965
- }
30966
- }
30967
30714
  var currentModulePath = typeof __filename === "string" ? __filename : "";
30968
30715
  var entrypoint = process.argv[1];
30969
30716
  if (entrypoint && currentModulePath === entrypoint) {
@@ -30979,7 +30726,6 @@ if (entrypoint && currentModulePath === entrypoint) {
30979
30726
  0 && (module.exports = {
30980
30727
  createBootstrapDependencies,
30981
30728
  createPlannedOutputs,
30982
- extractRepositorySlug,
30983
30729
  getInput,
30984
30730
  lintSpecViaCli,
30985
30731
  normalizeSpecDocument,