@postman-cse/onboarding-bootstrap 0.9.1 → 0.11.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/.github/workflows/contract-smoke.yml +155 -0
- package/.omc/sessions/b36ac16d-ce26-4e94-ae7e-dd817f2430a3.json +8 -0
- package/CLAUDE.md +57 -0
- package/README.md +133 -12
- package/action.yml +21 -18
- package/dist/cli.cjs +370 -518
- package/dist/index.cjs +364 -509
- package/package.json +3 -2
- package/src/cli.ts +6 -11
- package/src/contracts.ts +30 -24
- package/src/index.ts +302 -322
- package/src/lib/postman/internal-integration-adapter.ts +116 -30
- package/src/lib/postman/postman-assets-client.ts +27 -4
- package/tests/bootstrap-action.test.ts +647 -77
- package/tests/cli.test.ts +15 -6
- package/tests/contract.test.ts +28 -3
- package/tests/internal-integration-adapter.test.ts +69 -0
- package/tests/postman-assets-client.test.ts +153 -0
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
|
-
|
|
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
|
-
|
|
26317
|
-
|
|
26318
|
-
|
|
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,28 @@ var openAlphaActionContract = {
|
|
|
28711
28724
|
description: "Existing contract collection ID.",
|
|
28712
28725
|
required: false
|
|
28713
28726
|
},
|
|
28727
|
+
"sync-examples": {
|
|
28728
|
+
description: "Whether linked spec/collection relations should enable example syncing.",
|
|
28729
|
+
required: false,
|
|
28730
|
+
default: "true",
|
|
28731
|
+
allowedValues: ["true", "false"]
|
|
28732
|
+
},
|
|
28733
|
+
"collection-sync-mode": {
|
|
28734
|
+
description: "Collection lifecycle policy: reuse existing collections, refresh them from the latest spec, or version them by release label.",
|
|
28735
|
+
required: false,
|
|
28736
|
+
default: "refresh",
|
|
28737
|
+
allowedValues: ["reuse", "refresh", "version"]
|
|
28738
|
+
},
|
|
28739
|
+
"spec-sync-mode": {
|
|
28740
|
+
description: "Spec lifecycle policy: update the canonical spec or create/reuse a versioned spec for the resolved release label.",
|
|
28741
|
+
required: false,
|
|
28742
|
+
default: "update",
|
|
28743
|
+
allowedValues: ["update", "version"]
|
|
28744
|
+
},
|
|
28745
|
+
"release-label": {
|
|
28746
|
+
description: "Optional release label. When omitted for versioned sync, the action derives one from GitHub ref metadata.",
|
|
28747
|
+
required: false
|
|
28748
|
+
},
|
|
28714
28749
|
"project-name": {
|
|
28715
28750
|
description: "Service project name.",
|
|
28716
28751
|
required: true
|
|
@@ -28731,20 +28766,14 @@ var openAlphaActionContract = {
|
|
|
28731
28766
|
description: "Comma-separated workspace admin user ids.",
|
|
28732
28767
|
required: false
|
|
28733
28768
|
},
|
|
28769
|
+
"workspace-team-id": {
|
|
28770
|
+
description: "Numeric sub-team ID for org-mode workspace creation.",
|
|
28771
|
+
required: false
|
|
28772
|
+
},
|
|
28734
28773
|
"spec-url": {
|
|
28735
28774
|
description: "HTTPS URL to the OpenAPI document.",
|
|
28736
28775
|
required: true
|
|
28737
28776
|
},
|
|
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
28777
|
"governance-mapping-json": {
|
|
28749
28778
|
description: "JSON map of business domain to governance group name.",
|
|
28750
28779
|
required: false,
|
|
@@ -28758,19 +28787,6 @@ var openAlphaActionContract = {
|
|
|
28758
28787
|
description: "Postman access token used for governance and workspace mutations.",
|
|
28759
28788
|
required: false
|
|
28760
28789
|
},
|
|
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
28790
|
"integration-backend": {
|
|
28775
28791
|
description: "Integration backend for downstream workspace connectivity.",
|
|
28776
28792
|
required: false,
|
|
@@ -28816,8 +28832,8 @@ var openAlphaActionContract = {
|
|
|
28816
28832
|
"OpenAPI operation summary normalization before upload (missing or oversized summaries)",
|
|
28817
28833
|
"spec linting by UID",
|
|
28818
28834
|
"baseline, smoke, and contract collection generation",
|
|
28835
|
+
"collection refresh and versioning policies",
|
|
28819
28836
|
"collection tagging",
|
|
28820
|
-
"GitHub repository variable persistence for downstream sync steps",
|
|
28821
28837
|
"workspace, spec, and collection outputs"
|
|
28822
28838
|
],
|
|
28823
28839
|
removedBehavior: [
|
|
@@ -28908,189 +28924,6 @@ function sanitizeHeaders(headers, secretValues) {
|
|
|
28908
28924
|
return sanitized;
|
|
28909
28925
|
}
|
|
28910
28926
|
|
|
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
28927
|
// src/lib/http-error.ts
|
|
29095
28928
|
function truncate(value, limit) {
|
|
29096
28929
|
if (value.length <= limit) {
|
|
@@ -29273,6 +29106,16 @@ var PostmanAssetsClient = class {
|
|
|
29273
29106
|
}
|
|
29274
29107
|
return void 0;
|
|
29275
29108
|
}
|
|
29109
|
+
async getTeams() {
|
|
29110
|
+
const data = await this.request("/teams");
|
|
29111
|
+
const teams = data?.data ?? [];
|
|
29112
|
+
return Array.isArray(teams) ? teams.filter((t) => t?.id && t?.name).map((t) => ({
|
|
29113
|
+
id: Number(t.id),
|
|
29114
|
+
name: String(t.name),
|
|
29115
|
+
handle: String(t.handle || ""),
|
|
29116
|
+
...t.organizationId != null ? { organizationId: Number(t.organizationId) } : {}
|
|
29117
|
+
})) : [];
|
|
29118
|
+
}
|
|
29276
29119
|
async request(path, init = {}) {
|
|
29277
29120
|
const url = path.startsWith("http") ? path : `${this.baseUrl}${path}`;
|
|
29278
29121
|
const response = await this.fetchImpl(url, {
|
|
@@ -29301,13 +29144,14 @@ var PostmanAssetsClient = class {
|
|
|
29301
29144
|
return null;
|
|
29302
29145
|
}
|
|
29303
29146
|
}
|
|
29304
|
-
async createWorkspace(name, about) {
|
|
29147
|
+
async createWorkspace(name, about, targetTeamId) {
|
|
29305
29148
|
return retry(async () => {
|
|
29306
29149
|
const payload = {
|
|
29307
29150
|
workspace: {
|
|
29308
29151
|
about,
|
|
29309
29152
|
name,
|
|
29310
|
-
type: "team"
|
|
29153
|
+
type: "team",
|
|
29154
|
+
...targetTeamId != null && !Number.isNaN(targetTeamId) ? { teamId: targetTeamId } : {}
|
|
29311
29155
|
}
|
|
29312
29156
|
};
|
|
29313
29157
|
let created;
|
|
@@ -29319,7 +29163,7 @@ var PostmanAssetsClient = class {
|
|
|
29319
29163
|
} catch (err) {
|
|
29320
29164
|
if (err instanceof Error && err.message.includes("Only personal workspaces")) {
|
|
29321
29165
|
throw new Error(
|
|
29322
|
-
"Workspace creation failed:
|
|
29166
|
+
"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
29167
|
);
|
|
29324
29168
|
}
|
|
29325
29169
|
throw err;
|
|
@@ -29338,7 +29182,11 @@ var PostmanAssetsClient = class {
|
|
|
29338
29182
|
return {
|
|
29339
29183
|
id: workspaceId
|
|
29340
29184
|
};
|
|
29341
|
-
}, {
|
|
29185
|
+
}, {
|
|
29186
|
+
maxAttempts: 3,
|
|
29187
|
+
delayMs: 2e3,
|
|
29188
|
+
shouldRetry: (err) => !(err instanceof Error && err.message.includes("workspace-team-id"))
|
|
29189
|
+
});
|
|
29342
29190
|
}
|
|
29343
29191
|
async listWorkspaces() {
|
|
29344
29192
|
const data = await this.request("/workspaces");
|
|
@@ -29813,6 +29661,26 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
29813
29661
|
options.workerBaseUrl || "https://catalog-admin.postman-account2009.workers.dev"
|
|
29814
29662
|
).replace(/\/+$/, "");
|
|
29815
29663
|
}
|
|
29664
|
+
async proxyRequest(service, method, requestPath, body) {
|
|
29665
|
+
const url = "https://bifrost-premium-https-v4.gw.postman.com/ws/proxy";
|
|
29666
|
+
const headers = {
|
|
29667
|
+
"Content-Type": "application/json",
|
|
29668
|
+
"x-access-token": this.accessToken
|
|
29669
|
+
};
|
|
29670
|
+
if (this.teamId) {
|
|
29671
|
+
headers["x-entity-team-id"] = this.teamId;
|
|
29672
|
+
}
|
|
29673
|
+
return this.fetchImpl(url, {
|
|
29674
|
+
method: "POST",
|
|
29675
|
+
headers,
|
|
29676
|
+
body: JSON.stringify({
|
|
29677
|
+
service,
|
|
29678
|
+
method,
|
|
29679
|
+
path: requestPath,
|
|
29680
|
+
...body !== void 0 ? { body } : {}
|
|
29681
|
+
})
|
|
29682
|
+
});
|
|
29683
|
+
}
|
|
29816
29684
|
async assignWorkspaceToGovernanceGroup(workspaceId, domain, mappingJson) {
|
|
29817
29685
|
let mapping;
|
|
29818
29686
|
try {
|
|
@@ -29906,14 +29774,6 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
29906
29774
|
}
|
|
29907
29775
|
}
|
|
29908
29776
|
async connectWorkspaceToRepository(workspaceId, repoUrl) {
|
|
29909
|
-
const url = "https://bifrost-premium-https-v4.gw.postman.com/ws/proxy";
|
|
29910
|
-
const headers = {
|
|
29911
|
-
"Content-Type": "application/json",
|
|
29912
|
-
"x-access-token": this.accessToken
|
|
29913
|
-
};
|
|
29914
|
-
if (this.teamId) {
|
|
29915
|
-
headers["x-entity-team-id"] = this.teamId;
|
|
29916
|
-
}
|
|
29917
29777
|
const payload = {
|
|
29918
29778
|
service: "workspaces",
|
|
29919
29779
|
method: "POST",
|
|
@@ -29924,11 +29784,12 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
29924
29784
|
versionControl: true
|
|
29925
29785
|
}
|
|
29926
29786
|
};
|
|
29927
|
-
const response = await this.
|
|
29928
|
-
|
|
29929
|
-
|
|
29930
|
-
|
|
29931
|
-
|
|
29787
|
+
const response = await this.proxyRequest(
|
|
29788
|
+
payload.service,
|
|
29789
|
+
payload.method,
|
|
29790
|
+
payload.path,
|
|
29791
|
+
payload.body
|
|
29792
|
+
);
|
|
29932
29793
|
if (response.ok) return;
|
|
29933
29794
|
if (response.status === 400) {
|
|
29934
29795
|
const body = await response.text();
|
|
@@ -29945,29 +29806,68 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
29945
29806
|
}
|
|
29946
29807
|
throw await HttpError.fromResponse(response, {
|
|
29947
29808
|
method: "POST",
|
|
29948
|
-
requestHeaders:
|
|
29809
|
+
requestHeaders: {
|
|
29810
|
+
"Content-Type": "application/json",
|
|
29811
|
+
"x-access-token": this.accessToken,
|
|
29812
|
+
...this.teamId ? { "x-entity-team-id": this.teamId } : {}
|
|
29813
|
+
},
|
|
29949
29814
|
secretValues: [this.accessToken],
|
|
29950
|
-
url
|
|
29815
|
+
url: "https://bifrost-premium-https-v4.gw.postman.com/ws/proxy"
|
|
29951
29816
|
});
|
|
29952
29817
|
}
|
|
29953
|
-
async
|
|
29954
|
-
|
|
29955
|
-
|
|
29956
|
-
"Content-Type": "application/json",
|
|
29957
|
-
"x-access-token": this.accessToken
|
|
29958
|
-
};
|
|
29959
|
-
if (this.teamId) {
|
|
29960
|
-
headers["x-entity-team-id"] = this.teamId;
|
|
29818
|
+
async linkCollectionsToSpecification(specificationId, collections) {
|
|
29819
|
+
if (collections.length === 0) {
|
|
29820
|
+
return;
|
|
29961
29821
|
}
|
|
29962
|
-
const response = await this.
|
|
29822
|
+
const response = await this.proxyRequest(
|
|
29823
|
+
"specification",
|
|
29824
|
+
"put",
|
|
29825
|
+
`/specifications/${specificationId}/collections`,
|
|
29826
|
+
collections.map((collection) => ({
|
|
29827
|
+
collectionId: collection.collectionId,
|
|
29828
|
+
...collection.syncOptions ? { syncOptions: collection.syncOptions } : {}
|
|
29829
|
+
}))
|
|
29830
|
+
);
|
|
29831
|
+
if (response.ok) {
|
|
29832
|
+
return;
|
|
29833
|
+
}
|
|
29834
|
+
throw await HttpError.fromResponse(response, {
|
|
29963
29835
|
method: "POST",
|
|
29964
|
-
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
29969
|
-
|
|
29836
|
+
requestHeaders: {
|
|
29837
|
+
"Content-Type": "application/json",
|
|
29838
|
+
"x-access-token": this.accessToken,
|
|
29839
|
+
...this.teamId ? { "x-entity-team-id": this.teamId } : {}
|
|
29840
|
+
},
|
|
29841
|
+
secretValues: [this.accessToken],
|
|
29842
|
+
url: "https://bifrost-premium-https-v4.gw.postman.com/ws/proxy"
|
|
29970
29843
|
});
|
|
29844
|
+
}
|
|
29845
|
+
async syncCollection(specificationId, collectionId) {
|
|
29846
|
+
const response = await this.proxyRequest(
|
|
29847
|
+
"specification",
|
|
29848
|
+
"post",
|
|
29849
|
+
`/specifications/${specificationId}/collections/${collectionId}/sync`
|
|
29850
|
+
);
|
|
29851
|
+
if (response.ok) {
|
|
29852
|
+
return;
|
|
29853
|
+
}
|
|
29854
|
+
throw await HttpError.fromResponse(response, {
|
|
29855
|
+
method: "POST",
|
|
29856
|
+
requestHeaders: {
|
|
29857
|
+
"Content-Type": "application/json",
|
|
29858
|
+
"x-access-token": this.accessToken,
|
|
29859
|
+
...this.teamId ? { "x-entity-team-id": this.teamId } : {}
|
|
29860
|
+
},
|
|
29861
|
+
secretValues: [this.accessToken],
|
|
29862
|
+
url: "https://bifrost-premium-https-v4.gw.postman.com/ws/proxy"
|
|
29863
|
+
});
|
|
29864
|
+
}
|
|
29865
|
+
async getWorkspaceGitRepoUrl(workspaceId) {
|
|
29866
|
+
const response = await this.proxyRequest(
|
|
29867
|
+
"workspaces",
|
|
29868
|
+
"GET",
|
|
29869
|
+
`/workspaces/${workspaceId}/filesystem`
|
|
29870
|
+
);
|
|
29971
29871
|
if (response.status === 404) return null;
|
|
29972
29872
|
if (!response.ok) return null;
|
|
29973
29873
|
const body = await response.text();
|
|
@@ -30150,31 +30050,24 @@ function requireInput(actionCore, name) {
|
|
|
30150
30050
|
function optionalInput(actionCore, name) {
|
|
30151
30051
|
return normalizeInputValue(actionCore.getInput(name));
|
|
30152
30052
|
}
|
|
30153
|
-
function
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
);
|
|
30160
|
-
}
|
|
30053
|
+
function parseBooleanInput(value, defaultValue) {
|
|
30054
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
30055
|
+
if (!normalized) return defaultValue;
|
|
30056
|
+
if (["true", "1", "yes", "on"].includes(normalized)) return true;
|
|
30057
|
+
if (["false", "0", "no", "off"].includes(normalized)) return false;
|
|
30058
|
+
return defaultValue;
|
|
30161
30059
|
}
|
|
30162
|
-
function
|
|
30163
|
-
if (
|
|
30164
|
-
|
|
30060
|
+
function parseCollectionSyncMode(value) {
|
|
30061
|
+
if (value === "reuse" || value === "version") {
|
|
30062
|
+
return value;
|
|
30165
30063
|
}
|
|
30166
|
-
return
|
|
30064
|
+
return "refresh";
|
|
30167
30065
|
}
|
|
30168
|
-
function
|
|
30169
|
-
if (
|
|
30170
|
-
|
|
30171
|
-
}
|
|
30172
|
-
return
|
|
30173
|
-
Object.entries(value).map(([key, entry]) => [
|
|
30174
|
-
key,
|
|
30175
|
-
String(entry)
|
|
30176
|
-
])
|
|
30177
|
-
);
|
|
30066
|
+
function parseSpecSyncMode(value) {
|
|
30067
|
+
if (value === "version") {
|
|
30068
|
+
return value;
|
|
30069
|
+
}
|
|
30070
|
+
return "update";
|
|
30178
30071
|
}
|
|
30179
30072
|
function resolveInputs(env = process.env) {
|
|
30180
30073
|
const repoContext = detectRepoContext(
|
|
@@ -30202,28 +30095,32 @@ function resolveInputs(env = process.env) {
|
|
|
30202
30095
|
}
|
|
30203
30096
|
}
|
|
30204
30097
|
return {
|
|
30205
|
-
projectName: getInput("project-name", env) ?? "",
|
|
30098
|
+
projectName: getInput("project-name", env) ?? env.GITHUB_REPOSITORY?.split("/").pop() ?? env.CI_PROJECT_NAME ?? "",
|
|
30206
30099
|
workspaceId: getInput("workspace-id", env),
|
|
30207
30100
|
specId: getInput("spec-id", env),
|
|
30208
30101
|
baselineCollectionId: getInput("baseline-collection-id", env),
|
|
30209
30102
|
smokeCollectionId: getInput("smoke-collection-id", env),
|
|
30210
30103
|
contractCollectionId: getInput("contract-collection-id", env),
|
|
30104
|
+
syncExamples: parseBooleanInput(getInput("sync-examples", env), true),
|
|
30105
|
+
collectionSyncMode: parseCollectionSyncMode(getInput("collection-sync-mode", env)),
|
|
30106
|
+
specSyncMode: parseSpecSyncMode(getInput("spec-sync-mode", env)),
|
|
30107
|
+
releaseLabel: getInput("release-label", env),
|
|
30211
30108
|
domain: getInput("domain", env),
|
|
30212
30109
|
domainCode: getInput("domain-code", env),
|
|
30213
30110
|
requesterEmail: getInput("requester-email", env),
|
|
30214
30111
|
workspaceAdminUserIds: getInput("workspace-admin-user-ids", env) || env.WORKSPACE_ADMIN_USER_IDS || "",
|
|
30112
|
+
workspaceTeamId: getInput("workspace-team-id", env) || env.POSTMAN_WORKSPACE_TEAM_ID,
|
|
30215
30113
|
teamId: getInput("team-id", env) || env.POSTMAN_TEAM_ID || "",
|
|
30216
30114
|
repoUrl: repoContext.repoUrl || "",
|
|
30217
30115
|
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
30116
|
governanceMappingJson: getInput("governance-mapping-json", env) ?? openAlphaActionContract.inputs["governance-mapping-json"].default ?? "{}",
|
|
30221
30117
|
postmanApiKey: getInput("postman-api-key", env) ?? "",
|
|
30222
30118
|
postmanAccessToken: getInput("postman-access-token", env),
|
|
30223
|
-
|
|
30224
|
-
|
|
30225
|
-
|
|
30226
|
-
|
|
30119
|
+
integrationBackend,
|
|
30120
|
+
githubRefName: env.GITHUB_REF_NAME,
|
|
30121
|
+
githubHeadRef: env.GITHUB_HEAD_REF,
|
|
30122
|
+
githubRef: env.GITHUB_REF,
|
|
30123
|
+
githubSha: env.GITHUB_SHA
|
|
30227
30124
|
};
|
|
30228
30125
|
}
|
|
30229
30126
|
function createPlannedOutputs(inputs) {
|
|
@@ -30254,12 +30151,8 @@ function readActionInputs(actionCore) {
|
|
|
30254
30151
|
const specUrl = requireInput(actionCore, "spec-url");
|
|
30255
30152
|
const postmanApiKey = requireInput(actionCore, "postman-api-key");
|
|
30256
30153
|
const postmanAccessToken = optionalInput(actionCore, "postman-access-token");
|
|
30257
|
-
const githubToken = optionalInput(actionCore, "github-token");
|
|
30258
|
-
const ghFallbackToken = optionalInput(actionCore, "gh-fallback-token");
|
|
30259
30154
|
actionCore.setSecret(postmanApiKey);
|
|
30260
30155
|
if (postmanAccessToken) actionCore.setSecret(postmanAccessToken);
|
|
30261
|
-
if (githubToken) actionCore.setSecret(githubToken);
|
|
30262
|
-
if (ghFallbackToken) actionCore.setSecret(ghFallbackToken);
|
|
30263
30156
|
const inputs = resolveInputs({
|
|
30264
30157
|
...process.env,
|
|
30265
30158
|
INPUT_PROJECT_NAME: projectName,
|
|
@@ -30268,6 +30161,10 @@ function readActionInputs(actionCore) {
|
|
|
30268
30161
|
INPUT_BASELINE_COLLECTION_ID: optionalInput(actionCore, "baseline-collection-id"),
|
|
30269
30162
|
INPUT_SMOKE_COLLECTION_ID: optionalInput(actionCore, "smoke-collection-id"),
|
|
30270
30163
|
INPUT_CONTRACT_COLLECTION_ID: optionalInput(actionCore, "contract-collection-id"),
|
|
30164
|
+
INPUT_SYNC_EXAMPLES: optionalInput(actionCore, "sync-examples") ?? openAlphaActionContract.inputs["sync-examples"].default,
|
|
30165
|
+
INPUT_COLLECTION_SYNC_MODE: optionalInput(actionCore, "collection-sync-mode") ?? openAlphaActionContract.inputs["collection-sync-mode"].default,
|
|
30166
|
+
INPUT_SPEC_SYNC_MODE: optionalInput(actionCore, "spec-sync-mode") ?? openAlphaActionContract.inputs["spec-sync-mode"].default,
|
|
30167
|
+
INPUT_RELEASE_LABEL: optionalInput(actionCore, "release-label"),
|
|
30271
30168
|
INPUT_DOMAIN: optionalInput(actionCore, "domain"),
|
|
30272
30169
|
INPUT_DOMAIN_CODE: optionalInput(actionCore, "domain-code"),
|
|
30273
30170
|
INPUT_REQUESTER_EMAIL: optionalInput(actionCore, "requester-email"),
|
|
@@ -30275,17 +30172,13 @@ function readActionInputs(actionCore) {
|
|
|
30275
30172
|
actionCore,
|
|
30276
30173
|
"workspace-admin-user-ids"
|
|
30277
30174
|
),
|
|
30175
|
+
INPUT_WORKSPACE_TEAM_ID: optionalInput(actionCore, "workspace-team-id") || process.env.POSTMAN_WORKSPACE_TEAM_ID,
|
|
30278
30176
|
INPUT_TEAM_ID: optionalInput(actionCore, "postman-team-id") || process.env.POSTMAN_TEAM_ID,
|
|
30279
30177
|
INPUT_REPO_URL: optionalInput(actionCore, "repo-url"),
|
|
30280
30178
|
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
30179
|
INPUT_GOVERNANCE_MAPPING_JSON: optionalInput(actionCore, "governance-mapping-json") ?? openAlphaActionContract.inputs["governance-mapping-json"].default,
|
|
30284
30180
|
INPUT_POSTMAN_API_KEY: postmanApiKey,
|
|
30285
30181
|
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
30182
|
INPUT_INTEGRATION_BACKEND: optionalInput(actionCore, "integration-backend") ?? openAlphaActionContract.inputs["integration-backend"].default
|
|
30290
30183
|
});
|
|
30291
30184
|
return inputs;
|
|
@@ -30362,6 +30255,45 @@ async function fetchSpecDocument(specUrl, specFetcher) {
|
|
|
30362
30255
|
}
|
|
30363
30256
|
);
|
|
30364
30257
|
}
|
|
30258
|
+
function normalizeReleaseLabel(value) {
|
|
30259
|
+
const trimmed = String(value || "").trim();
|
|
30260
|
+
if (!trimmed) {
|
|
30261
|
+
return void 0;
|
|
30262
|
+
}
|
|
30263
|
+
return trimmed.replace(/^refs\/heads\//, "").replace(/^refs\/tags\//, "").replace(/^refs\/pull\//, "pull-").replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || void 0;
|
|
30264
|
+
}
|
|
30265
|
+
function deriveReleaseLabel(inputs) {
|
|
30266
|
+
if (inputs.releaseLabel) {
|
|
30267
|
+
return normalizeReleaseLabel(inputs.releaseLabel);
|
|
30268
|
+
}
|
|
30269
|
+
return normalizeReleaseLabel(inputs.githubRefName) ?? normalizeReleaseLabel(inputs.githubHeadRef) ?? normalizeReleaseLabel(inputs.githubRef);
|
|
30270
|
+
}
|
|
30271
|
+
function createAssetProjectName(inputs, releaseLabel) {
|
|
30272
|
+
if (!releaseLabel) {
|
|
30273
|
+
return inputs.projectName;
|
|
30274
|
+
}
|
|
30275
|
+
return `${inputs.projectName} ${releaseLabel}`;
|
|
30276
|
+
}
|
|
30277
|
+
function readResourcesState() {
|
|
30278
|
+
try {
|
|
30279
|
+
return (0, import_yaml.parse)((0, import_node_fs.readFileSync)(".postman/resources.yaml", "utf8"));
|
|
30280
|
+
} catch {
|
|
30281
|
+
return null;
|
|
30282
|
+
}
|
|
30283
|
+
}
|
|
30284
|
+
function getFirstCloudResourceId(map) {
|
|
30285
|
+
if (!map) {
|
|
30286
|
+
return void 0;
|
|
30287
|
+
}
|
|
30288
|
+
return Object.values(map)[0];
|
|
30289
|
+
}
|
|
30290
|
+
function findCloudResourceId(map, matcher) {
|
|
30291
|
+
if (!map) {
|
|
30292
|
+
return void 0;
|
|
30293
|
+
}
|
|
30294
|
+
const match = Object.entries(map).find(([filePath]) => matcher(filePath));
|
|
30295
|
+
return match?.[1];
|
|
30296
|
+
}
|
|
30365
30297
|
var SPEC_SUMMARY_MAX_LEN = 200;
|
|
30366
30298
|
var SPEC_HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
30367
30299
|
"get",
|
|
@@ -30450,122 +30382,28 @@ function validateSpecStructure(content) {
|
|
|
30450
30382
|
throw new Error('Spec is missing "openapi" or "swagger" version field');
|
|
30451
30383
|
}
|
|
30452
30384
|
}
|
|
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
30385
|
async function runBootstrap(inputs, dependencies) {
|
|
30544
30386
|
const outputs = createPlannedOutputs(inputs);
|
|
30545
|
-
const
|
|
30546
|
-
|
|
30547
|
-
|
|
30548
|
-
|
|
30549
|
-
|
|
30550
|
-
|
|
30551
|
-
|
|
30552
|
-
);
|
|
30387
|
+
const requiresReleaseLabel = inputs.collectionSyncMode === "version" || inputs.specSyncMode === "version";
|
|
30388
|
+
const releaseLabel = requiresReleaseLabel ? deriveReleaseLabel(inputs) : void 0;
|
|
30389
|
+
if (requiresReleaseLabel && !releaseLabel) {
|
|
30390
|
+
throw new Error(
|
|
30391
|
+
"Versioned spec or collection sync requires a release-label or derivable GitHub ref metadata"
|
|
30392
|
+
);
|
|
30393
|
+
}
|
|
30553
30394
|
const workspaceName = createWorkspaceName(inputs);
|
|
30554
30395
|
const aboutText = `Auto-provisioned by Postman CS open-alpha for ${inputs.projectName}`;
|
|
30555
30396
|
await runGroup(dependencies.core, "Install Postman CLI", async () => {
|
|
30556
30397
|
await ensurePostmanCli(dependencies, inputs.postmanApiKey);
|
|
30557
30398
|
});
|
|
30558
|
-
const
|
|
30559
|
-
let
|
|
30560
|
-
|
|
30561
|
-
|
|
30562
|
-
|
|
30563
|
-
dependencies.github,
|
|
30564
|
-
inputs.projectName,
|
|
30565
|
-
"WORKSPACE_ID"
|
|
30566
|
-
);
|
|
30567
|
-
workspaceId = repoWorkspaceId;
|
|
30399
|
+
const resourcesState = readResourcesState();
|
|
30400
|
+
let explicitWorkspaceId = inputs.workspaceId;
|
|
30401
|
+
if (!explicitWorkspaceId && resourcesState?.workspace?.id) {
|
|
30402
|
+
explicitWorkspaceId = resourcesState.workspace.id;
|
|
30403
|
+
dependencies.core.info("Resolved workspace-id from .postman/resources.yaml");
|
|
30568
30404
|
}
|
|
30405
|
+
const repoWorkspaceId = explicitWorkspaceId;
|
|
30406
|
+
let workspaceId = explicitWorkspaceId;
|
|
30569
30407
|
let teamId = inputs.teamId || "";
|
|
30570
30408
|
if (!teamId) {
|
|
30571
30409
|
teamId = await dependencies.postman.getAutoDerivedTeamId() || "";
|
|
@@ -30599,24 +30437,65 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30599
30437
|
} else if (workspaceId) {
|
|
30600
30438
|
dependencies.core.info(`Using existing workspace: ${workspaceId}`);
|
|
30601
30439
|
}
|
|
30440
|
+
let workspaceTeamId;
|
|
30441
|
+
if (inputs.workspaceTeamId) {
|
|
30442
|
+
workspaceTeamId = parseInt(inputs.workspaceTeamId, 10);
|
|
30443
|
+
if (Number.isNaN(workspaceTeamId)) {
|
|
30444
|
+
throw new Error(`workspace-team-id must be a numeric sub-team ID, got: ${inputs.workspaceTeamId}`);
|
|
30445
|
+
}
|
|
30446
|
+
}
|
|
30447
|
+
if (!workspaceId && !workspaceTeamId) {
|
|
30448
|
+
try {
|
|
30449
|
+
const teams = await dependencies.postman.getTeams();
|
|
30450
|
+
if (teams.length > 1 && teams.every((t) => t.organizationId == null)) {
|
|
30451
|
+
dependencies.core.warning(
|
|
30452
|
+
"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."
|
|
30453
|
+
);
|
|
30454
|
+
}
|
|
30455
|
+
const orgIds = new Set(teams.filter((t) => t.organizationId != null).map((t) => t.organizationId));
|
|
30456
|
+
const meTeamId = parseInt(teamId, 10);
|
|
30457
|
+
const isOrgMode = teams.length > 1 && orgIds.size === 1 && orgIds.has(meTeamId);
|
|
30458
|
+
if (isOrgMode) {
|
|
30459
|
+
const teamList = teams.map((t) => ` ${t.id} ${t.name}`).join("\n");
|
|
30460
|
+
throw new Error(
|
|
30461
|
+
`Org-mode account detected. Workspace creation requires a specific sub-team ID.
|
|
30462
|
+
|
|
30463
|
+
Available sub-teams:
|
|
30464
|
+
${teamList}
|
|
30465
|
+
|
|
30466
|
+
To fix this, set the workspace-team-id input in your workflow:
|
|
30467
|
+
workspace-team-id: '<id>'
|
|
30468
|
+
|
|
30469
|
+
Or for reuse across runs, create a repository variable and reference it:
|
|
30470
|
+
workspace-team-id: \${{ vars.POSTMAN_WORKSPACE_TEAM_ID }}
|
|
30471
|
+
|
|
30472
|
+
For CLI usage, pass --workspace-team-id <id> or export POSTMAN_WORKSPACE_TEAM_ID=<id>.`
|
|
30473
|
+
);
|
|
30474
|
+
} else if (teams.length > 1) {
|
|
30475
|
+
dependencies.core.warning(
|
|
30476
|
+
`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.`
|
|
30477
|
+
);
|
|
30478
|
+
}
|
|
30479
|
+
} catch (err) {
|
|
30480
|
+
if (err instanceof Error && err.message.includes("Org-mode account detected")) {
|
|
30481
|
+
throw err;
|
|
30482
|
+
}
|
|
30483
|
+
dependencies.core.warning(
|
|
30484
|
+
`Could not check for org-mode sub-teams: ${err instanceof Error ? err.message : String(err)}`
|
|
30485
|
+
);
|
|
30486
|
+
}
|
|
30487
|
+
}
|
|
30602
30488
|
if (!workspaceId) {
|
|
30603
30489
|
const workspace = await runGroup(
|
|
30604
30490
|
dependencies.core,
|
|
30605
30491
|
"Create Postman Workspace",
|
|
30606
|
-
async () => dependencies.postman.createWorkspace(workspaceName, aboutText)
|
|
30492
|
+
async () => dependencies.postman.createWorkspace(workspaceName, aboutText, workspaceTeamId)
|
|
30607
30493
|
);
|
|
30608
30494
|
workspaceId = workspace.id;
|
|
30609
30495
|
}
|
|
30610
30496
|
outputs["workspace-id"] = workspaceId || "";
|
|
30611
30497
|
outputs["workspace-url"] = `https://go.postman.co/workspace/${workspaceId}`;
|
|
30612
30498
|
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
30499
|
if (inputs.domain && dependencies.internalIntegration) {
|
|
30621
30500
|
await runGroup(
|
|
30622
30501
|
dependencies.core,
|
|
@@ -30671,33 +30550,43 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30671
30550
|
);
|
|
30672
30551
|
}
|
|
30673
30552
|
let specId = inputs.specId;
|
|
30674
|
-
if (!specId
|
|
30675
|
-
specId =
|
|
30553
|
+
if (!specId) {
|
|
30554
|
+
specId = getFirstCloudResourceId(resourcesState?.cloudResources?.specs);
|
|
30555
|
+
if (specId) {
|
|
30556
|
+
dependencies.core.info("Resolved spec-id from .postman/resources.yaml");
|
|
30557
|
+
}
|
|
30676
30558
|
}
|
|
30677
|
-
let baselineCollectionId = inputs.baselineCollectionId;
|
|
30678
|
-
let smokeCollectionId = inputs.smokeCollectionId;
|
|
30679
|
-
let contractCollectionId = inputs.contractCollectionId;
|
|
30680
|
-
if (
|
|
30559
|
+
let baselineCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.baselineCollectionId;
|
|
30560
|
+
let smokeCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.smokeCollectionId;
|
|
30561
|
+
let contractCollectionId = inputs.collectionSyncMode === "refresh" ? void 0 : inputs.contractCollectionId;
|
|
30562
|
+
if (inputs.collectionSyncMode !== "refresh") {
|
|
30563
|
+
const cloudCollections = resourcesState?.cloudResources?.collections;
|
|
30681
30564
|
if (!baselineCollectionId) {
|
|
30682
|
-
baselineCollectionId =
|
|
30683
|
-
|
|
30684
|
-
|
|
30685
|
-
"BASELINE_COLLECTION_UID"
|
|
30565
|
+
baselineCollectionId = findCloudResourceId(
|
|
30566
|
+
cloudCollections,
|
|
30567
|
+
(filePath) => filePath.includes("[Baseline]")
|
|
30686
30568
|
);
|
|
30569
|
+
if (baselineCollectionId) {
|
|
30570
|
+
dependencies.core.info("Resolved baseline-collection-id from .postman/resources.yaml");
|
|
30571
|
+
}
|
|
30687
30572
|
}
|
|
30688
30573
|
if (!smokeCollectionId) {
|
|
30689
|
-
smokeCollectionId =
|
|
30690
|
-
|
|
30691
|
-
|
|
30692
|
-
"SMOKE_COLLECTION_UID"
|
|
30574
|
+
smokeCollectionId = findCloudResourceId(
|
|
30575
|
+
cloudCollections,
|
|
30576
|
+
(filePath) => filePath.includes("[Smoke]")
|
|
30693
30577
|
);
|
|
30578
|
+
if (smokeCollectionId) {
|
|
30579
|
+
dependencies.core.info("Resolved smoke-collection-id from .postman/resources.yaml");
|
|
30580
|
+
}
|
|
30694
30581
|
}
|
|
30695
30582
|
if (!contractCollectionId) {
|
|
30696
|
-
contractCollectionId =
|
|
30697
|
-
|
|
30698
|
-
|
|
30699
|
-
"CONTRACT_COLLECTION_UID"
|
|
30583
|
+
contractCollectionId = findCloudResourceId(
|
|
30584
|
+
cloudCollections,
|
|
30585
|
+
(filePath) => filePath.includes("[Contract]")
|
|
30700
30586
|
);
|
|
30587
|
+
if (contractCollectionId) {
|
|
30588
|
+
dependencies.core.info("Resolved contract-collection-id from .postman/resources.yaml");
|
|
30589
|
+
}
|
|
30701
30590
|
}
|
|
30702
30591
|
}
|
|
30703
30592
|
if (specId) {
|
|
@@ -30721,7 +30610,10 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30721
30610
|
} else {
|
|
30722
30611
|
specId = await dependencies.postman.uploadSpec(
|
|
30723
30612
|
workspaceId || "",
|
|
30724
|
-
|
|
30613
|
+
createAssetProjectName(
|
|
30614
|
+
inputs,
|
|
30615
|
+
inputs.specSyncMode === "version" ? releaseLabel : void 0
|
|
30616
|
+
),
|
|
30725
30617
|
document
|
|
30726
30618
|
);
|
|
30727
30619
|
}
|
|
@@ -30730,13 +30622,6 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30730
30622
|
}
|
|
30731
30623
|
);
|
|
30732
30624
|
void specContent;
|
|
30733
|
-
await writeVariable(
|
|
30734
|
-
dependencies.github,
|
|
30735
|
-
inputs.projectName,
|
|
30736
|
-
"SPEC_UID",
|
|
30737
|
-
outputs["spec-id"],
|
|
30738
|
-
dependencies.core
|
|
30739
|
-
);
|
|
30740
30625
|
const lintSummary = await runGroup(
|
|
30741
30626
|
dependencies.core,
|
|
30742
30627
|
"Lint Spec via Postman CLI",
|
|
@@ -30774,13 +30659,15 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30774
30659
|
dependencies.core,
|
|
30775
30660
|
"Generate Collections from Spec",
|
|
30776
30661
|
async () => {
|
|
30777
|
-
|
|
30778
|
-
|
|
30779
|
-
outputs["
|
|
30662
|
+
const shouldReuseCollections = inputs.collectionSyncMode !== "refresh";
|
|
30663
|
+
const assetProjectName = inputs.collectionSyncMode === "version" ? createAssetProjectName(inputs, releaseLabel) : inputs.projectName;
|
|
30664
|
+
outputs["baseline-collection-id"] = shouldReuseCollections ? baselineCollectionId || "" : "";
|
|
30665
|
+
outputs["smoke-collection-id"] = shouldReuseCollections ? smokeCollectionId || "" : "";
|
|
30666
|
+
outputs["contract-collection-id"] = shouldReuseCollections ? contractCollectionId || "" : "";
|
|
30780
30667
|
if (!outputs["baseline-collection-id"]) {
|
|
30781
30668
|
outputs["baseline-collection-id"] = await dependencies.postman.generateCollection(
|
|
30782
30669
|
outputs["spec-id"],
|
|
30783
|
-
|
|
30670
|
+
assetProjectName,
|
|
30784
30671
|
"[Baseline]"
|
|
30785
30672
|
);
|
|
30786
30673
|
} else {
|
|
@@ -30788,17 +30675,10 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30788
30675
|
`Using existing baseline collection: ${outputs["baseline-collection-id"]}`
|
|
30789
30676
|
);
|
|
30790
30677
|
}
|
|
30791
|
-
await writeVariable(
|
|
30792
|
-
dependencies.github,
|
|
30793
|
-
inputs.projectName,
|
|
30794
|
-
"BASELINE_COLLECTION_UID",
|
|
30795
|
-
outputs["baseline-collection-id"],
|
|
30796
|
-
dependencies.core
|
|
30797
|
-
);
|
|
30798
30678
|
if (!outputs["smoke-collection-id"]) {
|
|
30799
30679
|
outputs["smoke-collection-id"] = await dependencies.postman.generateCollection(
|
|
30800
30680
|
outputs["spec-id"],
|
|
30801
|
-
|
|
30681
|
+
assetProjectName,
|
|
30802
30682
|
"[Smoke]"
|
|
30803
30683
|
);
|
|
30804
30684
|
} else {
|
|
@@ -30806,17 +30686,10 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30806
30686
|
`Using existing smoke collection: ${outputs["smoke-collection-id"]}`
|
|
30807
30687
|
);
|
|
30808
30688
|
}
|
|
30809
|
-
await writeVariable(
|
|
30810
|
-
dependencies.github,
|
|
30811
|
-
inputs.projectName,
|
|
30812
|
-
"SMOKE_COLLECTION_UID",
|
|
30813
|
-
outputs["smoke-collection-id"],
|
|
30814
|
-
dependencies.core
|
|
30815
|
-
);
|
|
30816
30689
|
if (!outputs["contract-collection-id"]) {
|
|
30817
30690
|
outputs["contract-collection-id"] = await dependencies.postman.generateCollection(
|
|
30818
30691
|
outputs["spec-id"],
|
|
30819
|
-
|
|
30692
|
+
assetProjectName,
|
|
30820
30693
|
"[Contract]"
|
|
30821
30694
|
);
|
|
30822
30695
|
} else {
|
|
@@ -30824,13 +30697,6 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30824
30697
|
`Using existing contract collection: ${outputs["contract-collection-id"]}`
|
|
30825
30698
|
);
|
|
30826
30699
|
}
|
|
30827
|
-
await writeVariable(
|
|
30828
|
-
dependencies.github,
|
|
30829
|
-
inputs.projectName,
|
|
30830
|
-
"CONTRACT_COLLECTION_UID",
|
|
30831
|
-
outputs["contract-collection-id"],
|
|
30832
|
-
dependencies.core
|
|
30833
|
-
);
|
|
30834
30700
|
}
|
|
30835
30701
|
);
|
|
30836
30702
|
outputs["collections-json"] = JSON.stringify({
|
|
@@ -30868,26 +30734,47 @@ async function runBootstrap(inputs, dependencies) {
|
|
|
30868
30734
|
]);
|
|
30869
30735
|
}
|
|
30870
30736
|
);
|
|
30871
|
-
|
|
30872
|
-
|
|
30873
|
-
|
|
30874
|
-
|
|
30875
|
-
|
|
30876
|
-
|
|
30877
|
-
|
|
30878
|
-
|
|
30879
|
-
|
|
30880
|
-
|
|
30881
|
-
|
|
30882
|
-
|
|
30883
|
-
|
|
30884
|
-
|
|
30885
|
-
|
|
30886
|
-
|
|
30887
|
-
|
|
30888
|
-
|
|
30889
|
-
|
|
30890
|
-
|
|
30737
|
+
const linkedCollectionIds = [
|
|
30738
|
+
outputs["baseline-collection-id"],
|
|
30739
|
+
outputs["smoke-collection-id"],
|
|
30740
|
+
outputs["contract-collection-id"]
|
|
30741
|
+
].filter(Boolean);
|
|
30742
|
+
if (linkedCollectionIds.length > 0) {
|
|
30743
|
+
if (dependencies.internalIntegration) {
|
|
30744
|
+
await runGroup(
|
|
30745
|
+
dependencies.core,
|
|
30746
|
+
"Link Collections to Specification",
|
|
30747
|
+
async () => {
|
|
30748
|
+
await dependencies.internalIntegration?.linkCollectionsToSpecification(
|
|
30749
|
+
outputs["spec-id"],
|
|
30750
|
+
linkedCollectionIds.map((collectionId) => ({
|
|
30751
|
+
collectionId,
|
|
30752
|
+
syncOptions: {
|
|
30753
|
+
syncExamples: inputs.syncExamples
|
|
30754
|
+
}
|
|
30755
|
+
}))
|
|
30756
|
+
);
|
|
30757
|
+
}
|
|
30758
|
+
);
|
|
30759
|
+
await runGroup(
|
|
30760
|
+
dependencies.core,
|
|
30761
|
+
"Sync Linked Collections",
|
|
30762
|
+
async () => {
|
|
30763
|
+
await Promise.all(
|
|
30764
|
+
linkedCollectionIds.map(
|
|
30765
|
+
(collectionId) => dependencies.internalIntegration.syncCollection(
|
|
30766
|
+
outputs["spec-id"],
|
|
30767
|
+
collectionId
|
|
30768
|
+
)
|
|
30769
|
+
)
|
|
30770
|
+
);
|
|
30771
|
+
}
|
|
30772
|
+
);
|
|
30773
|
+
} else {
|
|
30774
|
+
dependencies.core.warning(
|
|
30775
|
+
"Skipping cloud spec-to-collection linking and sync because postman-access-token is not configured"
|
|
30776
|
+
);
|
|
30777
|
+
}
|
|
30891
30778
|
}
|
|
30892
30779
|
for (const [name, value] of Object.entries(outputs)) {
|
|
30893
30780
|
dependencies.core.setOutput(name, value);
|
|
@@ -30902,9 +30789,6 @@ async function runAction(actionCore = core, actionExec = exec, actionIo = io) {
|
|
|
30902
30789
|
io: actionIo,
|
|
30903
30790
|
specFetcher: fetch
|
|
30904
30791
|
});
|
|
30905
|
-
if (!dependencies.github) {
|
|
30906
|
-
actionCore.info("GitHub repository variable persistence disabled for this run");
|
|
30907
|
-
}
|
|
30908
30792
|
if (inputs.domain && !dependencies.internalIntegration) {
|
|
30909
30793
|
actionCore.warning(
|
|
30910
30794
|
"Skipping governance assignment because postman-access-token is not configured"
|
|
@@ -30915,22 +30799,12 @@ async function runAction(actionCore = core, actionExec = exec, actionIo = io) {
|
|
|
30915
30799
|
function createBootstrapDependencies(inputs, factories) {
|
|
30916
30800
|
const secretMasker = createSecretMasker([
|
|
30917
30801
|
inputs.postmanApiKey,
|
|
30918
|
-
inputs.postmanAccessToken
|
|
30919
|
-
inputs.githubToken,
|
|
30920
|
-
inputs.ghFallbackToken
|
|
30802
|
+
inputs.postmanAccessToken
|
|
30921
30803
|
]);
|
|
30922
30804
|
const postman = new PostmanAssetsClient({
|
|
30923
30805
|
apiKey: inputs.postmanApiKey,
|
|
30924
30806
|
secretMasker
|
|
30925
30807
|
});
|
|
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
30808
|
const internalIntegration = inputs.postmanAccessToken ? createInternalIntegrationAdapter({
|
|
30935
30809
|
accessToken: inputs.postmanAccessToken,
|
|
30936
30810
|
backend: inputs.integrationBackend,
|
|
@@ -30940,30 +30814,12 @@ function createBootstrapDependencies(inputs, factories) {
|
|
|
30940
30814
|
return {
|
|
30941
30815
|
core: factories.core,
|
|
30942
30816
|
exec: factories.exec,
|
|
30943
|
-
github,
|
|
30944
30817
|
io: factories.io,
|
|
30945
30818
|
internalIntegration,
|
|
30946
30819
|
postman,
|
|
30947
30820
|
specFetcher: factories.specFetcher ?? fetch
|
|
30948
30821
|
};
|
|
30949
30822
|
}
|
|
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
30823
|
var currentModulePath = typeof __filename === "string" ? __filename : "";
|
|
30968
30824
|
var entrypoint = process.argv[1];
|
|
30969
30825
|
if (entrypoint && currentModulePath === entrypoint) {
|
|
@@ -30979,7 +30835,6 @@ if (entrypoint && currentModulePath === entrypoint) {
|
|
|
30979
30835
|
0 && (module.exports = {
|
|
30980
30836
|
createBootstrapDependencies,
|
|
30981
30837
|
createPlannedOutputs,
|
|
30982
|
-
extractRepositorySlug,
|
|
30983
30838
|
getInput,
|
|
30984
30839
|
lintSpecViaCli,
|
|
30985
30840
|
normalizeSpecDocument,
|