@postman-cse/onboarding-repo-sync 2.1.10 → 2.1.14
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/README.md +2 -1
- package/action.yml +4 -0
- package/dist/action.cjs +957 -163
- package/dist/cli.cjs +1092 -185
- package/dist/index.cjs +959 -163
- package/package.json +5 -4
- package/scripts/verify-release-artifacts.mjs +239 -0
package/dist/cli.cjs
CHANGED
|
@@ -19747,7 +19747,7 @@ var require_response = __commonJS({
|
|
|
19747
19747
|
var assert = require("node:assert");
|
|
19748
19748
|
var { isomorphicEncode, serializeJavascriptValueToJSONString } = require_infra();
|
|
19749
19749
|
var textEncoder = new TextEncoder("utf-8");
|
|
19750
|
-
var
|
|
19750
|
+
var Response2 = class _Response {
|
|
19751
19751
|
/** @type {Headers} */
|
|
19752
19752
|
#headers;
|
|
19753
19753
|
#state;
|
|
@@ -19917,13 +19917,13 @@ var require_response = __commonJS({
|
|
|
19917
19917
|
response.#state = newState;
|
|
19918
19918
|
}
|
|
19919
19919
|
};
|
|
19920
|
-
var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } =
|
|
19921
|
-
Reflect.deleteProperty(
|
|
19922
|
-
Reflect.deleteProperty(
|
|
19923
|
-
Reflect.deleteProperty(
|
|
19924
|
-
Reflect.deleteProperty(
|
|
19925
|
-
mixinBody(
|
|
19926
|
-
Object.defineProperties(
|
|
19920
|
+
var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response2;
|
|
19921
|
+
Reflect.deleteProperty(Response2, "getResponseHeaders");
|
|
19922
|
+
Reflect.deleteProperty(Response2, "setResponseHeaders");
|
|
19923
|
+
Reflect.deleteProperty(Response2, "getResponseState");
|
|
19924
|
+
Reflect.deleteProperty(Response2, "setResponseState");
|
|
19925
|
+
mixinBody(Response2, getResponseState);
|
|
19926
|
+
Object.defineProperties(Response2.prototype, {
|
|
19927
19927
|
type: kEnumerableProperty,
|
|
19928
19928
|
url: kEnumerableProperty,
|
|
19929
19929
|
status: kEnumerableProperty,
|
|
@@ -19939,7 +19939,7 @@ var require_response = __commonJS({
|
|
|
19939
19939
|
configurable: true
|
|
19940
19940
|
}
|
|
19941
19941
|
});
|
|
19942
|
-
Object.defineProperties(
|
|
19942
|
+
Object.defineProperties(Response2, {
|
|
19943
19943
|
json: kEnumerableProperty,
|
|
19944
19944
|
redirect: kEnumerableProperty,
|
|
19945
19945
|
error: kEnumerableProperty
|
|
@@ -20072,7 +20072,7 @@ var require_response = __commonJS({
|
|
|
20072
20072
|
}
|
|
20073
20073
|
}
|
|
20074
20074
|
function fromInnerResponse(innerResponse, guard) {
|
|
20075
|
-
const response = new
|
|
20075
|
+
const response = new Response2(kConstruct);
|
|
20076
20076
|
setResponseState(response, innerResponse);
|
|
20077
20077
|
const headers = new Headers3(kConstruct);
|
|
20078
20078
|
setResponseHeaders(response, headers);
|
|
@@ -20126,14 +20126,14 @@ var require_response = __commonJS({
|
|
|
20126
20126
|
converter: webidl.converters.HeadersInit
|
|
20127
20127
|
}
|
|
20128
20128
|
]);
|
|
20129
|
-
webidl.is.Response = webidl.util.MakeTypeAssertion(
|
|
20129
|
+
webidl.is.Response = webidl.util.MakeTypeAssertion(Response2);
|
|
20130
20130
|
module2.exports = {
|
|
20131
20131
|
isNetworkError,
|
|
20132
20132
|
makeNetworkError,
|
|
20133
20133
|
makeResponse,
|
|
20134
20134
|
makeAppropriateNetworkError,
|
|
20135
20135
|
filterResponse,
|
|
20136
|
-
Response,
|
|
20136
|
+
Response: Response2,
|
|
20137
20137
|
cloneResponse,
|
|
20138
20138
|
fromInnerResponse,
|
|
20139
20139
|
getResponseState
|
|
@@ -26571,7 +26571,7 @@ var require_util7 = __commonJS({
|
|
|
26571
26571
|
exports2.esc = esc;
|
|
26572
26572
|
exports2.slugify = slugify;
|
|
26573
26573
|
exports2.isObject = isObject;
|
|
26574
|
-
exports2.isPlainObject =
|
|
26574
|
+
exports2.isPlainObject = isPlainObject3;
|
|
26575
26575
|
exports2.shallowClone = shallowClone;
|
|
26576
26576
|
exports2.numKeys = numKeys;
|
|
26577
26577
|
exports2.escapeRegex = escapeRegex;
|
|
@@ -26754,7 +26754,7 @@ var require_util7 = __commonJS({
|
|
|
26754
26754
|
return false;
|
|
26755
26755
|
}
|
|
26756
26756
|
});
|
|
26757
|
-
function
|
|
26757
|
+
function isPlainObject3(o) {
|
|
26758
26758
|
if (isObject(o) === false)
|
|
26759
26759
|
return false;
|
|
26760
26760
|
const ctor = o.constructor;
|
|
@@ -26771,7 +26771,7 @@ var require_util7 = __commonJS({
|
|
|
26771
26771
|
return true;
|
|
26772
26772
|
}
|
|
26773
26773
|
function shallowClone(o) {
|
|
26774
|
-
if (
|
|
26774
|
+
if (isPlainObject3(o))
|
|
26775
26775
|
return { ...o };
|
|
26776
26776
|
if (Array.isArray(o))
|
|
26777
26777
|
return [...o];
|
|
@@ -26976,7 +26976,7 @@ var require_util7 = __commonJS({
|
|
|
26976
26976
|
return clone(schema, def);
|
|
26977
26977
|
}
|
|
26978
26978
|
function extend(schema, shape) {
|
|
26979
|
-
if (!
|
|
26979
|
+
if (!isPlainObject3(shape)) {
|
|
26980
26980
|
throw new Error("Invalid input to extend: expected a plain object");
|
|
26981
26981
|
}
|
|
26982
26982
|
const checks = schema._zod.def.checks;
|
|
@@ -26999,7 +26999,7 @@ var require_util7 = __commonJS({
|
|
|
26999
26999
|
return clone(schema, def);
|
|
27000
27000
|
}
|
|
27001
27001
|
function safeExtend(schema, shape) {
|
|
27002
|
-
if (!
|
|
27002
|
+
if (!isPlainObject3(shape)) {
|
|
27003
27003
|
throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
27004
27004
|
}
|
|
27005
27005
|
const def = mergeDefs(schema._zod.def, {
|
|
@@ -54818,7 +54818,7 @@ var require_lodash = __commonJS({
|
|
|
54818
54818
|
} else {
|
|
54819
54819
|
newValue = [];
|
|
54820
54820
|
}
|
|
54821
|
-
} else if (
|
|
54821
|
+
} else if (isPlainObject3(srcValue) || isArguments(srcValue)) {
|
|
54822
54822
|
newValue = objValue;
|
|
54823
54823
|
if (isArguments(objValue)) {
|
|
54824
54824
|
newValue = toPlainObject(objValue);
|
|
@@ -55782,7 +55782,7 @@ var require_lodash = __commonJS({
|
|
|
55782
55782
|
return objValue;
|
|
55783
55783
|
}
|
|
55784
55784
|
function customOmitClone(value) {
|
|
55785
|
-
return
|
|
55785
|
+
return isPlainObject3(value) ? undefined2 : value;
|
|
55786
55786
|
}
|
|
55787
55787
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
|
|
55788
55788
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
|
|
@@ -57283,7 +57283,7 @@ var require_lodash = __commonJS({
|
|
|
57283
57283
|
var isBuffer = nativeIsBuffer || stubFalse;
|
|
57284
57284
|
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
|
|
57285
57285
|
function isElement(value) {
|
|
57286
|
-
return isObjectLike(value) && value.nodeType === 1 && !
|
|
57286
|
+
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject3(value);
|
|
57287
57287
|
}
|
|
57288
57288
|
function isEmpty(value) {
|
|
57289
57289
|
if (value == null) {
|
|
@@ -57319,7 +57319,7 @@ var require_lodash = __commonJS({
|
|
|
57319
57319
|
return false;
|
|
57320
57320
|
}
|
|
57321
57321
|
var tag = baseGetTag(value);
|
|
57322
|
-
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !
|
|
57322
|
+
return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject3(value);
|
|
57323
57323
|
}
|
|
57324
57324
|
function isFinite2(value) {
|
|
57325
57325
|
return typeof value == "number" && nativeIsFinite(value);
|
|
@@ -57370,7 +57370,7 @@ var require_lodash = __commonJS({
|
|
|
57370
57370
|
function isNumber(value) {
|
|
57371
57371
|
return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
|
|
57372
57372
|
}
|
|
57373
|
-
function
|
|
57373
|
+
function isPlainObject3(value) {
|
|
57374
57374
|
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
|
|
57375
57375
|
return false;
|
|
57376
57376
|
}
|
|
@@ -58441,7 +58441,7 @@ var require_lodash = __commonJS({
|
|
|
58441
58441
|
lodash.isNumber = isNumber;
|
|
58442
58442
|
lodash.isObject = isObject;
|
|
58443
58443
|
lodash.isObjectLike = isObjectLike;
|
|
58444
|
-
lodash.isPlainObject =
|
|
58444
|
+
lodash.isPlainObject = isPlainObject3;
|
|
58445
58445
|
lodash.isRegExp = isRegExp;
|
|
58446
58446
|
lodash.isSafeInteger = isSafeInteger;
|
|
58447
58447
|
lodash.isSet = isSet;
|
|
@@ -99441,7 +99441,7 @@ var require_response2 = __commonJS({
|
|
|
99441
99441
|
}
|
|
99442
99442
|
return stream;
|
|
99443
99443
|
};
|
|
99444
|
-
var
|
|
99444
|
+
var Response2;
|
|
99445
99445
|
_.inherit(
|
|
99446
99446
|
/**
|
|
99447
99447
|
* Response holds data related to the request body. By default, it provides a nice wrapper for url-encoded,
|
|
@@ -99452,14 +99452,14 @@ var require_response2 = __commonJS({
|
|
|
99452
99452
|
*
|
|
99453
99453
|
* @param {Response.definition} options -
|
|
99454
99454
|
*/
|
|
99455
|
-
|
|
99456
|
-
|
|
99455
|
+
Response2 = function PostmanResponse(options) {
|
|
99456
|
+
Response2.super_.apply(this, arguments);
|
|
99457
99457
|
this.update(options || {});
|
|
99458
99458
|
},
|
|
99459
99459
|
Property
|
|
99460
99460
|
);
|
|
99461
99461
|
_.assign(
|
|
99462
|
-
|
|
99462
|
+
Response2.prototype,
|
|
99463
99463
|
/** @lends Response.prototype */
|
|
99464
99464
|
{
|
|
99465
99465
|
update(options) {
|
|
@@ -99525,7 +99525,7 @@ var require_response2 = __commonJS({
|
|
|
99525
99525
|
}
|
|
99526
99526
|
);
|
|
99527
99527
|
_.assign(
|
|
99528
|
-
|
|
99528
|
+
Response2.prototype,
|
|
99529
99529
|
/** @lends Response.prototype */
|
|
99530
99530
|
{
|
|
99531
99531
|
/**
|
|
@@ -99703,7 +99703,7 @@ var require_response2 = __commonJS({
|
|
|
99703
99703
|
}
|
|
99704
99704
|
);
|
|
99705
99705
|
_.assign(
|
|
99706
|
-
|
|
99706
|
+
Response2,
|
|
99707
99707
|
/** @lends Response */
|
|
99708
99708
|
{
|
|
99709
99709
|
/**
|
|
@@ -99721,7 +99721,7 @@ var require_response2 = __commonJS({
|
|
|
99721
99721
|
* @returns {Boolean}
|
|
99722
99722
|
*/
|
|
99723
99723
|
isResponse: function(obj) {
|
|
99724
|
-
return Boolean(obj) && (obj instanceof
|
|
99724
|
+
return Boolean(obj) && (obj instanceof Response2 || _.inSuperChain(obj.constructor, "_postman_propertyName", Response2._postman_propertyName));
|
|
99725
99725
|
},
|
|
99726
99726
|
/**
|
|
99727
99727
|
* Converts the response object from the request module to the postman responseBody format
|
|
@@ -99732,7 +99732,7 @@ var require_response2 = __commonJS({
|
|
|
99732
99732
|
* @todo Add a key: `originalRequest` to the returned object as well, referring to response.request
|
|
99733
99733
|
*/
|
|
99734
99734
|
createFromNode: function(response, cookies) {
|
|
99735
|
-
return new
|
|
99735
|
+
return new Response2({
|
|
99736
99736
|
cookie: cookies,
|
|
99737
99737
|
body: response.body.toString(),
|
|
99738
99738
|
stream: response.body,
|
|
@@ -99811,7 +99811,7 @@ var require_response2 = __commonJS({
|
|
|
99811
99811
|
}
|
|
99812
99812
|
);
|
|
99813
99813
|
module2.exports = {
|
|
99814
|
-
Response
|
|
99814
|
+
Response: Response2
|
|
99815
99815
|
};
|
|
99816
99816
|
}
|
|
99817
99817
|
});
|
|
@@ -99825,7 +99825,7 @@ var require_item = __commonJS({
|
|
|
99825
99825
|
var EventList = require_event_list().EventList;
|
|
99826
99826
|
var Request = require_request13().Request;
|
|
99827
99827
|
var RequestAuth = require_request_auth().RequestAuth;
|
|
99828
|
-
var
|
|
99828
|
+
var Response2 = require_response2().Response;
|
|
99829
99829
|
var Item;
|
|
99830
99830
|
var OBJECT = "object";
|
|
99831
99831
|
var STRING = "string";
|
|
@@ -99892,7 +99892,7 @@ var require_item = __commonJS({
|
|
|
99892
99892
|
*
|
|
99893
99893
|
* @type {PropertyList<Response>}
|
|
99894
99894
|
*/
|
|
99895
|
-
responses: new PropertyList(
|
|
99895
|
+
responses: new PropertyList(Response2, this, definition && definition.response),
|
|
99896
99896
|
/**
|
|
99897
99897
|
* Events are a set of of {@link Script}s that are executed when certain activities are triggered on an
|
|
99898
99898
|
* Item. For example, on defining an event that listens to the "test" event, would cause the associated
|
|
@@ -128814,11 +128814,12 @@ __export(cli_exports, {
|
|
|
128814
128814
|
normalizeCliFlag: () => normalizeCliFlag,
|
|
128815
128815
|
parseCliArgs: () => parseCliArgs,
|
|
128816
128816
|
runCli: () => runCli,
|
|
128817
|
-
toDotenv: () => toDotenv
|
|
128817
|
+
toDotenv: () => toDotenv,
|
|
128818
|
+
writeOptionalFileAtomic: () => writeOptionalFileAtomic
|
|
128818
128819
|
});
|
|
128819
128820
|
module.exports = __toCommonJS(cli_exports);
|
|
128820
128821
|
var import_node_child_process = require("node:child_process");
|
|
128821
|
-
var
|
|
128822
|
+
var import_node_fs6 = require("node:fs");
|
|
128822
128823
|
var import_promises = require("node:fs/promises");
|
|
128823
128824
|
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
128824
128825
|
var import_node_util = require("node:util");
|
|
@@ -129186,7 +129187,8 @@ var ExitCode;
|
|
|
129186
129187
|
})(ExitCode || (ExitCode = {}));
|
|
129187
129188
|
|
|
129188
129189
|
// src/index.ts
|
|
129189
|
-
var
|
|
129190
|
+
var import_node_crypto3 = require("node:crypto");
|
|
129191
|
+
var import_node_fs5 = require("node:fs");
|
|
129190
129192
|
var path3 = __toESM(require("node:path"), 1);
|
|
129191
129193
|
|
|
129192
129194
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
@@ -132102,6 +132104,7 @@ function dump(input, options = {}) {
|
|
|
132102
132104
|
}
|
|
132103
132105
|
|
|
132104
132106
|
// src/postman-v3/converter.ts
|
|
132107
|
+
var import_node_fs = require("node:fs");
|
|
132105
132108
|
var fs2 = __toESM(require("node:fs/promises"), 1);
|
|
132106
132109
|
var path = __toESM(require("node:path"), 1);
|
|
132107
132110
|
var V2 = __toESM(require_v2(), 1);
|
|
@@ -132172,6 +132175,72 @@ function structuredCloneSafe(value) {
|
|
|
132172
132175
|
if (typeof structuredClone === "function") return structuredClone(value);
|
|
132173
132176
|
return JSON.parse(JSON.stringify(value));
|
|
132174
132177
|
}
|
|
132178
|
+
var ArtifactDigestStreamError = class extends Error {
|
|
132179
|
+
code = "ARTIFACT_DIGEST_STREAM";
|
|
132180
|
+
constructor(message, options) {
|
|
132181
|
+
super(message, options);
|
|
132182
|
+
this.name = "ArtifactDigestStreamError";
|
|
132183
|
+
}
|
|
132184
|
+
};
|
|
132185
|
+
function sameFileIdentity(left, right) {
|
|
132186
|
+
return left.dev === right.dev && left.ino === right.ino && left.size === right.size;
|
|
132187
|
+
}
|
|
132188
|
+
async function appendArtifactDigestFileStreaming(hash, relative3, absolute, expected) {
|
|
132189
|
+
const flags = typeof import_node_fs.constants.O_NOFOLLOW === "number" ? import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NOFOLLOW : import_node_fs.constants.O_RDONLY;
|
|
132190
|
+
let handle;
|
|
132191
|
+
try {
|
|
132192
|
+
handle = await fs2.open(absolute, flags);
|
|
132193
|
+
} catch (error) {
|
|
132194
|
+
const code = error?.code;
|
|
132195
|
+
if (code === "ELOOP" || code === "EMLINK" || code === "EINVAL") {
|
|
132196
|
+
throw new ArtifactDigestStreamError(
|
|
132197
|
+
`prebuilt collection tree file became a symlink or unsupported node at ${relative3}`,
|
|
132198
|
+
{ cause: error }
|
|
132199
|
+
);
|
|
132200
|
+
}
|
|
132201
|
+
throw new ArtifactDigestStreamError(
|
|
132202
|
+
`prebuilt collection tree file changed or became unsupported at ${relative3}`,
|
|
132203
|
+
{ cause: error }
|
|
132204
|
+
);
|
|
132205
|
+
}
|
|
132206
|
+
try {
|
|
132207
|
+
const before = await handle.stat();
|
|
132208
|
+
if (!before.isFile() || !sameFileIdentity(before, expected)) {
|
|
132209
|
+
throw new ArtifactDigestStreamError(
|
|
132210
|
+
`prebuilt collection tree file changed or became unsupported at ${relative3}`
|
|
132211
|
+
);
|
|
132212
|
+
}
|
|
132213
|
+
hash.update(relative3);
|
|
132214
|
+
hash.update("\0");
|
|
132215
|
+
const content = Buffer.allocUnsafe(expected.size);
|
|
132216
|
+
let total = 0;
|
|
132217
|
+
const buffer = Buffer.alloc(64 * 1024);
|
|
132218
|
+
for (; ; ) {
|
|
132219
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);
|
|
132220
|
+
if (bytesRead === 0) {
|
|
132221
|
+
break;
|
|
132222
|
+
}
|
|
132223
|
+
if (total + bytesRead > expected.size) {
|
|
132224
|
+
throw new ArtifactDigestStreamError(
|
|
132225
|
+
`prebuilt collection tree file changed while reading at ${relative3}`
|
|
132226
|
+
);
|
|
132227
|
+
}
|
|
132228
|
+
buffer.copy(content, total, 0, bytesRead);
|
|
132229
|
+
hash.update(buffer.subarray(0, bytesRead));
|
|
132230
|
+
total += bytesRead;
|
|
132231
|
+
}
|
|
132232
|
+
hash.update("\0");
|
|
132233
|
+
const after = await handle.stat();
|
|
132234
|
+
if (!after.isFile() || !sameFileIdentity(after, expected) || total !== expected.size) {
|
|
132235
|
+
throw new ArtifactDigestStreamError(
|
|
132236
|
+
`prebuilt collection tree file changed while reading at ${relative3}`
|
|
132237
|
+
);
|
|
132238
|
+
}
|
|
132239
|
+
return total === expected.size ? content : content.subarray(0, total);
|
|
132240
|
+
} finally {
|
|
132241
|
+
await handle.close();
|
|
132242
|
+
}
|
|
132243
|
+
}
|
|
132175
132244
|
async function listFilesRelative(dir, base) {
|
|
132176
132245
|
let entries;
|
|
132177
132246
|
try {
|
|
@@ -132732,7 +132801,7 @@ function getCiWorkflowTemplate(provider, options = {}) {
|
|
|
132732
132801
|
}
|
|
132733
132802
|
|
|
132734
132803
|
// src/lib/github/repo-mutation.ts
|
|
132735
|
-
var
|
|
132804
|
+
var import_node_fs2 = require("node:fs");
|
|
132736
132805
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
132737
132806
|
|
|
132738
132807
|
// src/lib/secrets.ts
|
|
@@ -133022,7 +133091,7 @@ var RepoMutationService = class {
|
|
|
133022
133091
|
throw new Error(this.secretMasker(changed.stderr || changed.stdout || "Failed to inspect generated changes"));
|
|
133023
133092
|
}
|
|
133024
133093
|
const hasPlannedRemoval = removePaths.some(
|
|
133025
|
-
(removePath) => (0,
|
|
133094
|
+
(removePath) => (0, import_node_fs2.existsSync)(import_node_path.default.resolve(this.cwd, removePath))
|
|
133026
133095
|
);
|
|
133027
133096
|
if (!changed.stdout.trim() && !hasPlannedRemoval) {
|
|
133028
133097
|
return {
|
|
@@ -133046,7 +133115,7 @@ var RepoMutationService = class {
|
|
|
133046
133115
|
await this.execute("git", ["config", "user.name", options.committerName]);
|
|
133047
133116
|
await this.execute("git", ["config", "user.email", options.committerEmail]);
|
|
133048
133117
|
for (const removePath of removePaths) {
|
|
133049
|
-
(0,
|
|
133118
|
+
(0, import_node_fs2.rmSync)(import_node_path.default.resolve(this.cwd, removePath), { force: true });
|
|
133050
133119
|
}
|
|
133051
133120
|
await this.execute("git", ["add", "-A", "--", ...stagePaths]);
|
|
133052
133121
|
const staged = await this.execute("git", ["diff", "--cached", "--quiet"]);
|
|
@@ -133589,14 +133658,14 @@ function createTelemetryContext(options) {
|
|
|
133589
133658
|
}
|
|
133590
133659
|
|
|
133591
133660
|
// src/action-version.ts
|
|
133592
|
-
var
|
|
133661
|
+
var import_node_fs3 = require("node:fs");
|
|
133593
133662
|
var import_node_path2 = require("node:path");
|
|
133594
133663
|
function resolveActionVersion2() {
|
|
133595
133664
|
if (false) {
|
|
133596
133665
|
return void 0;
|
|
133597
133666
|
}
|
|
133598
133667
|
try {
|
|
133599
|
-
const raw = (0,
|
|
133668
|
+
const raw = (0, import_node_fs3.readFileSync)((0, import_node_path2.join)(__dirname, "..", "package.json"), "utf8");
|
|
133600
133669
|
return JSON.parse(raw).version ?? "unknown";
|
|
133601
133670
|
} catch {
|
|
133602
133671
|
return "unknown";
|
|
@@ -133661,6 +133730,54 @@ var HttpError = class _HttpError extends Error {
|
|
|
133661
133730
|
}
|
|
133662
133731
|
};
|
|
133663
133732
|
|
|
133733
|
+
// src/lib/postman/pmak-diagnostics.ts
|
|
133734
|
+
var memo = /* @__PURE__ */ new Map();
|
|
133735
|
+
var normalize3 = (value) => new URL(value.trim()).toString().replace(/\/+$/, "");
|
|
133736
|
+
function maskPmakDiagnostic(message, secrets) {
|
|
133737
|
+
let masked = String(message);
|
|
133738
|
+
for (const secret of secrets) if (secret) masked = masked.split(secret).join("***");
|
|
133739
|
+
return Array.from(masked, (character) => {
|
|
133740
|
+
const code = character.codePointAt(0) ?? 0;
|
|
133741
|
+
return code <= 31 || code >= 127 && code <= 159 ? " " : character;
|
|
133742
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
133743
|
+
}
|
|
133744
|
+
function formatRejectedMint(original, result) {
|
|
133745
|
+
const teamId = typeof result.payload?.user?.teamId === "number" ? ` (team ${(result.payload?.user).teamId})` : "";
|
|
133746
|
+
if (result.kind === "personal") return `Personal API key detected, cannot mint a service-account access token${teamId}.`;
|
|
133747
|
+
if (result.kind === "service-account") return `The postman-api-key authenticates (GET /me OK) but was rejected by POST /service-account-tokens${teamId} and lacks permission to mint access tokens.`;
|
|
133748
|
+
if (result.kind === "invalid") return "The postman-api-key is invalid, disabled, or expired.";
|
|
133749
|
+
return original;
|
|
133750
|
+
}
|
|
133751
|
+
async function inspectPmakIdentity(options) {
|
|
133752
|
+
const apiBaseUrl = normalize3(options.apiBaseUrl);
|
|
133753
|
+
const key = `${apiBaseUrl}\0${options.apiKey}`;
|
|
133754
|
+
let pending = memo.get(key);
|
|
133755
|
+
if (!pending) {
|
|
133756
|
+
pending = (async () => {
|
|
133757
|
+
try {
|
|
133758
|
+
const timeout = AbortSignal.timeout(options.timeoutMs ?? 2e3);
|
|
133759
|
+
const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
|
|
133760
|
+
const response = await (options.fetchImpl ?? fetch)(`${apiBaseUrl}/me`, { method: "GET", headers: { "X-Api-Key": options.apiKey }, signal });
|
|
133761
|
+
if (response.status === 401 || response.status === 403) return { kind: "invalid", status: response.status };
|
|
133762
|
+
if (!response.ok) return { kind: "inconclusive", status: response.status };
|
|
133763
|
+
const payload = await response.json().catch(() => void 0);
|
|
133764
|
+
const user = payload?.user;
|
|
133765
|
+
if (!user || typeof user !== "object" || Array.isArray(user)) return { kind: "inconclusive", payload };
|
|
133766
|
+
const record = user;
|
|
133767
|
+
if (typeof record.username === "string" && record.username || typeof record.email === "string" && record.email) return { kind: "personal", status: response.status, payload };
|
|
133768
|
+
if ("username" in record && "email" in record && (record.username == null || record.username === "") && (record.email == null || record.email === "")) return { kind: "service-account", status: response.status, payload };
|
|
133769
|
+
return { kind: "inconclusive", payload };
|
|
133770
|
+
} catch {
|
|
133771
|
+
return { kind: "inconclusive" };
|
|
133772
|
+
}
|
|
133773
|
+
})();
|
|
133774
|
+
memo.set(key, pending);
|
|
133775
|
+
}
|
|
133776
|
+
const result = await pending;
|
|
133777
|
+
if (options.mode === "preflight" && result.kind === "inconclusive") memo.delete(key);
|
|
133778
|
+
return result;
|
|
133779
|
+
}
|
|
133780
|
+
|
|
133664
133781
|
// src/lib/postman/credential-identity.ts
|
|
133665
133782
|
var sessionPath = "/api/sessions/current";
|
|
133666
133783
|
var SESSION_MAX_ATTEMPTS = 3;
|
|
@@ -133754,14 +133871,8 @@ async function resolvePmakIdentity(opts) {
|
|
|
133754
133871
|
}
|
|
133755
133872
|
async function probePmakIdentity(baseUrl, apiKey, fetchImpl) {
|
|
133756
133873
|
try {
|
|
133757
|
-
const
|
|
133758
|
-
|
|
133759
|
-
headers: { "X-Api-Key": apiKey }
|
|
133760
|
-
});
|
|
133761
|
-
if (!response.ok) {
|
|
133762
|
-
return void 0;
|
|
133763
|
-
}
|
|
133764
|
-
const payload = asRecord(await response.json());
|
|
133874
|
+
const diagnostic = await inspectPmakIdentity({ apiBaseUrl: baseUrl, apiKey, fetchImpl });
|
|
133875
|
+
const payload = asRecord(diagnostic.payload);
|
|
133765
133876
|
const user = asRecord(payload?.user);
|
|
133766
133877
|
if (!user) {
|
|
133767
133878
|
return void 0;
|
|
@@ -133793,7 +133904,8 @@ async function resolveSessionIdentity(opts) {
|
|
|
133793
133904
|
opts.fetchImpl ?? fetch,
|
|
133794
133905
|
Math.max(1, opts.maxAttempts ?? SESSION_MAX_ATTEMPTS),
|
|
133795
133906
|
opts.sleepImpl ?? defaultSessionSleep,
|
|
133796
|
-
opts.randomImpl ?? defaultRandom
|
|
133907
|
+
opts.randomImpl ?? defaultRandom,
|
|
133908
|
+
opts.onRetryEvent
|
|
133797
133909
|
);
|
|
133798
133910
|
sessionMemo.set(memoKey, pending);
|
|
133799
133911
|
}
|
|
@@ -133827,7 +133939,7 @@ async function parseSessionResponse(response) {
|
|
|
133827
133939
|
consumerType: coerceText(root.consumerType) ?? coerceText(data?.consumerType) ?? coerceText(user?.consumerType)
|
|
133828
133940
|
};
|
|
133829
133941
|
}
|
|
133830
|
-
async function probeSessionIdentity(baseUrl, accessToken, fetchImpl, maxAttempts, sleepImpl, random) {
|
|
133942
|
+
async function probeSessionIdentity(baseUrl, accessToken, fetchImpl, maxAttempts, sleepImpl, random, onRetryEvent) {
|
|
133831
133943
|
let failure = "unavailable";
|
|
133832
133944
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
133833
133945
|
let response;
|
|
@@ -133839,7 +133951,9 @@ async function probeSessionIdentity(baseUrl, accessToken, fetchImpl, maxAttempts
|
|
|
133839
133951
|
} catch {
|
|
133840
133952
|
failure = "unavailable";
|
|
133841
133953
|
if (attempt < maxAttempts) {
|
|
133842
|
-
|
|
133954
|
+
const delay = computeSessionRetryDelayMs(void 0, attempt, random);
|
|
133955
|
+
onRetryEvent?.({ class: "transport", attempt, delay });
|
|
133956
|
+
await sleepImpl(delay);
|
|
133843
133957
|
continue;
|
|
133844
133958
|
}
|
|
133845
133959
|
break;
|
|
@@ -133861,7 +133975,9 @@ async function probeSessionIdentity(baseUrl, accessToken, fetchImpl, maxAttempts
|
|
|
133861
133975
|
if (response.status === 429 || response.status >= 500) {
|
|
133862
133976
|
failure = "unavailable";
|
|
133863
133977
|
if (attempt < maxAttempts) {
|
|
133864
|
-
|
|
133978
|
+
const delay = computeSessionRetryDelayMs(response, attempt, random);
|
|
133979
|
+
onRetryEvent?.({ class: "http", status: response.status, attempt, delay });
|
|
133980
|
+
await sleepImpl(delay);
|
|
133865
133981
|
continue;
|
|
133866
133982
|
}
|
|
133867
133983
|
break;
|
|
@@ -133963,7 +134079,8 @@ async function runCredentialPreflight(args) {
|
|
|
133963
134079
|
accessToken,
|
|
133964
134080
|
fetchImpl: args.fetchImpl,
|
|
133965
134081
|
...args.sleepImpl ? { sleepImpl: args.sleepImpl } : {},
|
|
133966
|
-
...args.randomImpl ? { randomImpl: args.randomImpl } : {}
|
|
134082
|
+
...args.randomImpl ? { randomImpl: args.randomImpl } : {},
|
|
134083
|
+
onRetryEvent: args.retryEvent ?? args.log.retryEvent
|
|
133967
134084
|
});
|
|
133968
134085
|
} catch (error) {
|
|
133969
134086
|
args.log.warning(
|
|
@@ -134063,6 +134180,39 @@ function adviseFromHttpError(err, ctx) {
|
|
|
134063
134180
|
return new Error(ctx.mask(advice), { cause: err });
|
|
134064
134181
|
}
|
|
134065
134182
|
|
|
134183
|
+
// src/lib/postman/app-version.ts
|
|
134184
|
+
var UPDATE_URL = "https://dl.pstmn.io/update/status?currentVersion=12.0.0&platform=osx_arm64";
|
|
134185
|
+
var FLOOR_VERSION = "12.0.0";
|
|
134186
|
+
var VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
134187
|
+
var PostmanAppVersionProvider = class {
|
|
134188
|
+
fetchImpl;
|
|
134189
|
+
requestTimeoutMs;
|
|
134190
|
+
pending;
|
|
134191
|
+
constructor(options = {}) {
|
|
134192
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
134193
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 2e3;
|
|
134194
|
+
}
|
|
134195
|
+
async get() {
|
|
134196
|
+
if (process.env.POSTMAN_GATEWAY_APP_VERSION === "off") return void 0;
|
|
134197
|
+
this.pending ??= this.resolve();
|
|
134198
|
+
return this.pending;
|
|
134199
|
+
}
|
|
134200
|
+
async resolve() {
|
|
134201
|
+
try {
|
|
134202
|
+
const response = await this.fetchImpl(UPDATE_URL, {
|
|
134203
|
+
signal: AbortSignal.timeout(this.requestTimeoutMs)
|
|
134204
|
+
});
|
|
134205
|
+
if (!response.ok) return FLOOR_VERSION;
|
|
134206
|
+
const payload = await response.json();
|
|
134207
|
+
const version = typeof payload.version === "string" ? payload.version : "";
|
|
134208
|
+
return VERSION_PATTERN.test(version) ? version : FLOOR_VERSION;
|
|
134209
|
+
} catch {
|
|
134210
|
+
return FLOOR_VERSION;
|
|
134211
|
+
}
|
|
134212
|
+
}
|
|
134213
|
+
};
|
|
134214
|
+
var defaultPostmanAppVersionProvider = new PostmanAppVersionProvider();
|
|
134215
|
+
|
|
134066
134216
|
// src/lib/postman/internal-integration-adapter.ts
|
|
134067
134217
|
function extractDuplicateWorkspaceId(body) {
|
|
134068
134218
|
try {
|
|
@@ -134082,6 +134232,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134082
134232
|
secretMasker;
|
|
134083
134233
|
teamId;
|
|
134084
134234
|
workerBaseUrl;
|
|
134235
|
+
gateway;
|
|
134236
|
+
appVersionProvider;
|
|
134085
134237
|
constructor(options) {
|
|
134086
134238
|
this.accessToken = String(options.accessToken || "").trim();
|
|
134087
134239
|
this.getAccessToken = options.getAccessToken;
|
|
@@ -134094,6 +134246,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134094
134246
|
this.workerBaseUrl = String(
|
|
134095
134247
|
options.workerBaseUrl || "https://catalog-admin.postman-account2009.workers.dev"
|
|
134096
134248
|
).replace(/\/+$/, "");
|
|
134249
|
+
this.gateway = options.gateway;
|
|
134250
|
+
this.appVersionProvider = options.appVersionProvider ?? defaultPostmanAppVersionProvider;
|
|
134097
134251
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.accessToken]);
|
|
134098
134252
|
}
|
|
134099
134253
|
/** Live access token: re-minted value when a provider accessor is wired, else the captured one. */
|
|
@@ -134101,7 +134255,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134101
134255
|
return this.getAccessToken ? String(this.getAccessToken() || "").trim() : this.accessToken;
|
|
134102
134256
|
}
|
|
134103
134257
|
/** Build Bifrost proxy headers. Only includes x-entity-team-id for org-mode teams. */
|
|
134104
|
-
bifrostHeaders() {
|
|
134258
|
+
async bifrostHeaders() {
|
|
134105
134259
|
const headers = {
|
|
134106
134260
|
"Content-Type": "application/json",
|
|
134107
134261
|
"x-access-token": this.currentToken()
|
|
@@ -134109,6 +134263,8 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134109
134263
|
if (this.teamId && this.orgMode) {
|
|
134110
134264
|
headers["x-entity-team-id"] = this.teamId;
|
|
134111
134265
|
}
|
|
134266
|
+
const appVersion = await this.appVersionProvider.get();
|
|
134267
|
+
if (appVersion) headers["x-app-version"] = appVersion;
|
|
134112
134268
|
return headers;
|
|
134113
134269
|
}
|
|
134114
134270
|
/** Reactive error-advice context, enriched with the preflight session memo when present. */
|
|
@@ -134139,6 +134295,58 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134139
134295
|
if (associations.length === 0) {
|
|
134140
134296
|
return;
|
|
134141
134297
|
}
|
|
134298
|
+
const mode = process.env.POSTMAN_SYSTEM_ENV_ASSOCIATION_MODE ?? "direct";
|
|
134299
|
+
if (mode !== "direct" && mode !== "worker") {
|
|
134300
|
+
throw new Error("POSTMAN_SYSTEM_ENV_ASSOCIATION_MODE must be direct or worker");
|
|
134301
|
+
}
|
|
134302
|
+
if (mode === "direct") {
|
|
134303
|
+
if (!this.gateway) {
|
|
134304
|
+
throw new Error("Direct system-environment association requires the access-token gateway");
|
|
134305
|
+
}
|
|
134306
|
+
const groups = /* @__PURE__ */ new Map();
|
|
134307
|
+
for (const association of associations) {
|
|
134308
|
+
const systemEnvId = String(association.systemEnvId || "").trim();
|
|
134309
|
+
const uid = String(association.envUid || "").trim();
|
|
134310
|
+
if (!systemEnvId || !uid) continue;
|
|
134311
|
+
const key = `${systemEnvId}\0${workspaceId}`;
|
|
134312
|
+
const uids = groups.get(key) ?? /* @__PURE__ */ new Set();
|
|
134313
|
+
uids.add(uid);
|
|
134314
|
+
groups.set(key, uids);
|
|
134315
|
+
}
|
|
134316
|
+
for (const [key, uids] of [...groups.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
134317
|
+
const [systemEnvironmentId, groupedWorkspaceId] = key.split("\0");
|
|
134318
|
+
const postmanEnvironmentIds = [...uids].sort();
|
|
134319
|
+
let response2;
|
|
134320
|
+
try {
|
|
134321
|
+
response2 = await this.gateway.requestJson({
|
|
134322
|
+
service: "api-catalog",
|
|
134323
|
+
method: "post",
|
|
134324
|
+
path: "/api/system-envs/associations",
|
|
134325
|
+
body: {
|
|
134326
|
+
systemEnvironmentId,
|
|
134327
|
+
workspaceEntries: [{ workspaceId: groupedWorkspaceId, postmanEnvironmentIds }]
|
|
134328
|
+
},
|
|
134329
|
+
fallback: "none"
|
|
134330
|
+
}, { retryTransient: true });
|
|
134331
|
+
} catch (error) {
|
|
134332
|
+
if (error instanceof HttpError) {
|
|
134333
|
+
throw adviseFromHttpError(error, this.adviceContext("system environment association")) ?? error;
|
|
134334
|
+
}
|
|
134335
|
+
throw error;
|
|
134336
|
+
}
|
|
134337
|
+
if (!response2 || response2.success !== true) {
|
|
134338
|
+
throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134339
|
+
}
|
|
134340
|
+
if (response2.data !== void 0) {
|
|
134341
|
+
if (!Array.isArray(response2.data)) throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134342
|
+
const seen = new Set(response2.data.filter((row) => !!row && typeof row === "object").map((row) => `${row.systemEnvironmentId}\0${row.workspaceId}\0${row.postmanEnvironmentId}`));
|
|
134343
|
+
if (!postmanEnvironmentIds.every((uid) => seen.has(`${systemEnvironmentId}\0${groupedWorkspaceId}\0${uid}`))) {
|
|
134344
|
+
throw new Error("SYSTEM_ENV_ASSOCIATION_INCOMPLETE");
|
|
134345
|
+
}
|
|
134346
|
+
}
|
|
134347
|
+
}
|
|
134348
|
+
return;
|
|
134349
|
+
}
|
|
134142
134350
|
const token = this.currentToken();
|
|
134143
134351
|
const response = await this.fetchImpl(
|
|
134144
134352
|
`${this.workerBaseUrl}/api/internal/system-envs/associate`,
|
|
@@ -134196,7 +134404,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134196
134404
|
try {
|
|
134197
134405
|
const response = await this.fetchImpl(url, {
|
|
134198
134406
|
method: "POST",
|
|
134199
|
-
headers: this.bifrostHeaders(),
|
|
134407
|
+
headers: await this.bifrostHeaders(),
|
|
134200
134408
|
body: JSON.stringify(payload)
|
|
134201
134409
|
});
|
|
134202
134410
|
let parsed = {};
|
|
@@ -134285,7 +134493,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134285
134493
|
versionControl: true
|
|
134286
134494
|
}
|
|
134287
134495
|
};
|
|
134288
|
-
const headers = this.bifrostHeaders();
|
|
134496
|
+
const headers = await this.bifrostHeaders();
|
|
134289
134497
|
const response = await this.fetchImpl(url, {
|
|
134290
134498
|
method: "POST",
|
|
134291
134499
|
headers,
|
|
@@ -134340,7 +134548,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134340
134548
|
try {
|
|
134341
134549
|
const response = await this.fetchImpl(`${this.bifrostBaseUrl}/ws/proxy`, {
|
|
134342
134550
|
method: "POST",
|
|
134343
|
-
headers: this.bifrostHeaders(),
|
|
134551
|
+
headers: await this.bifrostHeaders(),
|
|
134344
134552
|
body: JSON.stringify({
|
|
134345
134553
|
service: "workspaces",
|
|
134346
134554
|
method: "GET",
|
|
@@ -134371,7 +134579,7 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
134371
134579
|
}
|
|
134372
134580
|
async createApiKey(name) {
|
|
134373
134581
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
134374
|
-
const headers = this.bifrostHeaders();
|
|
134582
|
+
const headers = await this.bifrostHeaders();
|
|
134375
134583
|
const payload = {
|
|
134376
134584
|
service: "identity",
|
|
134377
134585
|
method: "POST",
|
|
@@ -134456,6 +134664,16 @@ async function retry(operation, options = {}) {
|
|
|
134456
134664
|
}
|
|
134457
134665
|
throw new Error("Retry exhausted without returning or throwing");
|
|
134458
134666
|
}
|
|
134667
|
+
function fullJitterDelayMs(attempt, baseMs, capMs, random = Math.random) {
|
|
134668
|
+
return Math.floor(random() * Math.max(0, Math.min(capMs, baseMs * 2 ** Math.max(0, attempt))));
|
|
134669
|
+
}
|
|
134670
|
+
function parseRetryAfterMs2(value) {
|
|
134671
|
+
const trimmed = value?.trim();
|
|
134672
|
+
if (!trimmed) return void 0;
|
|
134673
|
+
if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1e3;
|
|
134674
|
+
const time = Date.parse(trimmed);
|
|
134675
|
+
return Number.isNaN(time) ? void 0 : Math.max(0, time - Date.now());
|
|
134676
|
+
}
|
|
134459
134677
|
|
|
134460
134678
|
// src/contracts.ts
|
|
134461
134679
|
var postmanRepoSyncActionContract = {
|
|
@@ -134514,6 +134732,11 @@ var postmanRepoSyncActionContract = {
|
|
|
134514
134732
|
description: "Contract collection ID used for exported artifacts.",
|
|
134515
134733
|
required: false
|
|
134516
134734
|
},
|
|
134735
|
+
"prebuilt-collections-json": {
|
|
134736
|
+
description: "Optional digest-bound JSON manifest of unique baseline, smoke, or contract roles with confined repo-relative path, SHA-256 artifact digest of the on-disk v3 collection tree (sorted relative-path + NUL + bytes + NUL), and canonical cloud ID. The optional payloadDigest field is the semantic v2 payload digest carried for provenance (format-validated only, not the reuse gate). Exact role, path, cloudId, and artifactDigest matches reuse the on-disk tree without cloud export.",
|
|
134737
|
+
required: false,
|
|
134738
|
+
default: ""
|
|
134739
|
+
},
|
|
134517
134740
|
"collection-sync-mode": {
|
|
134518
134741
|
description: "Collection sync lifecycle mode (refresh or version).",
|
|
134519
134742
|
required: false,
|
|
@@ -134756,7 +134979,7 @@ var postmanRepoSyncActionContract = {
|
|
|
134756
134979
|
"Create or update Postman environments from runtime URLs.",
|
|
134757
134980
|
"Associate Postman environments to system environments through Postman integration APIs.",
|
|
134758
134981
|
"Create mock servers and smoke monitors from generated collections.",
|
|
134759
|
-
"Export Postman collections in the Collection v3 multi-file YAML directory structure under `postman/collections/` (
|
|
134982
|
+
"Export Postman collections in the Collection v3 multi-file YAML directory structure under `postman/collections/` (canonical `.resources/definition.yaml` plus request/resource YAML files), and export environments plus `.postman/resources.yaml` into the repository.",
|
|
134760
134983
|
"Link the Postman workspace to the repository (GitHub or GitLab) through Postman integration APIs.",
|
|
134761
134984
|
"Commit synced artifacts and push them back to the current checked out ref."
|
|
134762
134985
|
],
|
|
@@ -134885,6 +135108,17 @@ var PostmanGatewayAssetsClient = class {
|
|
|
134885
135108
|
return data.map((entry) => this.asRecord(entry)).filter((entry) => entry !== null).map((entry) => ({ uid: String(entry.id ?? entry.uid ?? "").trim(), name: String(entry.name ?? "").trim() })).filter((entry) => entry.uid && entry.name);
|
|
134886
135109
|
}
|
|
134887
135110
|
async getSpecContent(specId) {
|
|
135111
|
+
if (process.env.POSTMAN_SPEC_TREE_FAST_PATH !== "off") {
|
|
135112
|
+
try {
|
|
135113
|
+
const treeContent = await this.getSpecContentFromTree(specId);
|
|
135114
|
+
if (treeContent !== void 0) return treeContent;
|
|
135115
|
+
} catch (error) {
|
|
135116
|
+
if (!(error instanceof HttpError) || ![403, 404, 405, 501].includes(error.status)) throw error;
|
|
135117
|
+
}
|
|
135118
|
+
}
|
|
135119
|
+
return this.getSpecContentLegacy(specId);
|
|
135120
|
+
}
|
|
135121
|
+
async getSpecContentLegacy(specId) {
|
|
134888
135122
|
const files = await this.gateway.requestJson({
|
|
134889
135123
|
service: "specification",
|
|
134890
135124
|
method: "get",
|
|
@@ -134903,6 +135137,46 @@ var PostmanGatewayAssetsClient = class {
|
|
|
134903
135137
|
const record = this.dataOf(file);
|
|
134904
135138
|
return typeof record?.content === "string" ? record.content : void 0;
|
|
134905
135139
|
}
|
|
135140
|
+
/** Minimal `/tree` reader: validate the entire returned inventory before selecting ROOT. */
|
|
135141
|
+
async getSpecContentFromTree(specId) {
|
|
135142
|
+
const rows = [];
|
|
135143
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
135144
|
+
let cursor;
|
|
135145
|
+
for (let page = 0; page < 100; page += 1) {
|
|
135146
|
+
const response = await this.gateway.requestJson({
|
|
135147
|
+
service: "specification",
|
|
135148
|
+
method: "get",
|
|
135149
|
+
path: `/specifications/${specId}/tree`,
|
|
135150
|
+
query: { fields: "id,name,type,path,parentId,fileType,content", limit: 100, ...cursor ? { cursor } : {} }
|
|
135151
|
+
});
|
|
135152
|
+
if (!Array.isArray(response?.data)) return void 0;
|
|
135153
|
+
for (const value of response.data) {
|
|
135154
|
+
const row = this.asRecord(value);
|
|
135155
|
+
if (!row || row.type === "FOLDER") continue;
|
|
135156
|
+
if (row.type !== "FILE" || typeof row.id !== "string" || !row.id.trim() || typeof row.path !== "string" || !row.path.trim() || typeof row.content !== "string" || typeof row.fileType !== "string" || !row.fileType.trim()) return void 0;
|
|
135157
|
+
const path5 = row.path.replace(/\\/g, "/").normalize("NFC");
|
|
135158
|
+
if (path5.startsWith("/") || path5.split("/").some((part) => part === ".." || !part)) throw new Error("CONTRACT_DEFINITION_PATH_INVALID");
|
|
135159
|
+
rows.push({ ...row, path: path5 });
|
|
135160
|
+
}
|
|
135161
|
+
const meta = this.asRecord(response?.meta);
|
|
135162
|
+
const cursorValue = this.asRecord(meta?.cursor)?.next;
|
|
135163
|
+
const next = typeof cursorValue === "string" && cursorValue.trim() ? cursorValue.trim() : void 0;
|
|
135164
|
+
if (!next) break;
|
|
135165
|
+
if (cursors.has(next)) throw new Error("SPEC_TREE_CURSOR_REPEATED");
|
|
135166
|
+
cursors.add(next);
|
|
135167
|
+
if (page === 99) throw new Error("SPEC_TREE_PAGE_LIMIT_EXCEEDED");
|
|
135168
|
+
cursor = next;
|
|
135169
|
+
}
|
|
135170
|
+
const paths = /* @__PURE__ */ new Set();
|
|
135171
|
+
for (const row of rows) {
|
|
135172
|
+
const path5 = String(row.path).toLocaleLowerCase();
|
|
135173
|
+
if (paths.has(path5)) throw new Error("CONTRACT_DEFINITION_DUPLICATE_PATH");
|
|
135174
|
+
paths.add(path5);
|
|
135175
|
+
}
|
|
135176
|
+
const roots = rows.filter((row) => row.fileType === "ROOT");
|
|
135177
|
+
if (roots.length !== 1) throw new Error("CONTRACT_DEFINITION_INVENTORY_INVALID");
|
|
135178
|
+
return String(roots[0]?.content);
|
|
135179
|
+
}
|
|
134906
135180
|
async listSpecCollections(specId) {
|
|
134907
135181
|
const response = await this.gateway.requestJson({
|
|
134908
135182
|
service: "specification",
|
|
@@ -135462,10 +135736,12 @@ var PostmanGatewayAssetsClient = class {
|
|
|
135462
135736
|
// src/lib/postman/token-provider.ts
|
|
135463
135737
|
var MintError = class extends Error {
|
|
135464
135738
|
permanent;
|
|
135465
|
-
|
|
135739
|
+
status;
|
|
135740
|
+
constructor(message, permanent, status) {
|
|
135466
135741
|
super(message);
|
|
135467
135742
|
this.name = "MintError";
|
|
135468
135743
|
this.permanent = permanent;
|
|
135744
|
+
this.status = status;
|
|
135469
135745
|
}
|
|
135470
135746
|
};
|
|
135471
135747
|
function extractAccessToken(payload) {
|
|
@@ -135488,6 +135764,7 @@ var AccessTokenProvider = class {
|
|
|
135488
135764
|
maxAttempts;
|
|
135489
135765
|
onToken;
|
|
135490
135766
|
sleep;
|
|
135767
|
+
onRetryEvent;
|
|
135491
135768
|
inflight;
|
|
135492
135769
|
constructor(options) {
|
|
135493
135770
|
this.token = String(options.accessToken || "").trim();
|
|
@@ -135499,6 +135776,7 @@ var AccessTokenProvider = class {
|
|
|
135499
135776
|
this.maxAttempts = Math.max(1, options.maxAttempts ?? 2);
|
|
135500
135777
|
this.onToken = options.onToken;
|
|
135501
135778
|
this.sleep = options.sleep;
|
|
135779
|
+
this.onRetryEvent = options.onRetryEvent;
|
|
135502
135780
|
}
|
|
135503
135781
|
current() {
|
|
135504
135782
|
return this.token;
|
|
@@ -135524,7 +135802,12 @@ var AccessTokenProvider = class {
|
|
|
135524
135802
|
delayMs: 1e3,
|
|
135525
135803
|
backoffMultiplier: 2,
|
|
135526
135804
|
...this.sleep ? { sleep: this.sleep } : {},
|
|
135527
|
-
shouldRetry: (error) => !(error instanceof MintError && error.permanent)
|
|
135805
|
+
shouldRetry: (error) => !(error instanceof MintError && error.permanent),
|
|
135806
|
+
onRetry: ({ attempt, delayMs, error }) => {
|
|
135807
|
+
const status = error instanceof MintError ? error.status : void 0;
|
|
135808
|
+
const retryClass = status === void 0 ? "transport" : "http";
|
|
135809
|
+
this.onRetryEvent?.({ class: retryClass, ...status === void 0 ? {} : { status }, attempt, delay: Math.max(0, delayMs) });
|
|
135810
|
+
}
|
|
135528
135811
|
});
|
|
135529
135812
|
this.token = token;
|
|
135530
135813
|
this.onToken?.(token);
|
|
@@ -135545,7 +135828,8 @@ var AccessTokenProvider = class {
|
|
|
135545
135828
|
if (status === 401 || status === 403) {
|
|
135546
135829
|
throw new MintError(
|
|
135547
135830
|
`postman: re-mint failed because the postman-api-key was rejected (PMAK rejected, HTTP ${status}); confirm it is a valid, enabled service-account PMAK for the intended team.`,
|
|
135548
|
-
true
|
|
135831
|
+
true,
|
|
135832
|
+
status
|
|
135549
135833
|
);
|
|
135550
135834
|
}
|
|
135551
135835
|
if (status === 400 && body.toLowerCase().includes("service accounts not enabled")) {
|
|
@@ -135554,7 +135838,7 @@ var AccessTokenProvider = class {
|
|
|
135554
135838
|
true
|
|
135555
135839
|
);
|
|
135556
135840
|
}
|
|
135557
|
-
throw new MintError(`postman: re-mint failed (service-account-tokens HTTP ${status}).`, false);
|
|
135841
|
+
throw new MintError(`postman: re-mint failed (service-account-tokens HTTP ${status}).`, false, status);
|
|
135558
135842
|
}
|
|
135559
135843
|
let parsed;
|
|
135560
135844
|
try {
|
|
@@ -135570,26 +135854,9 @@ var AccessTokenProvider = class {
|
|
|
135570
135854
|
}
|
|
135571
135855
|
};
|
|
135572
135856
|
async function describeMintFailure(mintError, apiKey, apiBaseUrl, fetchImpl) {
|
|
135573
|
-
const raw = mintError instanceof Error ? mintError.message : String(mintError);
|
|
135574
|
-
|
|
135575
|
-
|
|
135576
|
-
return raw;
|
|
135577
|
-
}
|
|
135578
|
-
try {
|
|
135579
|
-
const me = await fetchImpl(`${apiBaseUrl}/me`, { headers: { "x-api-key": apiKey } });
|
|
135580
|
-
if (me.ok) {
|
|
135581
|
-
const body = await me.json().catch(() => void 0);
|
|
135582
|
-
const user = body?.user;
|
|
135583
|
-
const looksPersonal = Boolean(user && (user.username || user.email));
|
|
135584
|
-
if (looksPersonal) {
|
|
135585
|
-
return "Personal API key detected, cannot mint a service-account access token. POST /service-account-tokens only accepts a SERVICE-ACCOUNT API key; this postman-api-key belongs to a user account" + (user?.teamId ? ` (team ${user.teamId})` : "") + ". Create a service account in Team Settings and use its PMAK, or mint the token elsewhere and pass postman-access-token.";
|
|
135586
|
-
}
|
|
135587
|
-
return "The postman-api-key authenticates (GET /me OK) but was rejected by POST /service-account-tokens" + (user?.teamId ? ` (team ${user.teamId})` : "") + ". The service account likely lacks permission to mint access tokens, or service accounts are restricted for this team. Check the service account role in Team Settings, or pass a pre-minted postman-access-token.";
|
|
135588
|
-
}
|
|
135589
|
-
return "The postman-api-key is invalid, disabled, or expired (rejected by both POST /service-account-tokens and GET /me). Generate a fresh service-account PMAK in Team Settings and update the secret.";
|
|
135590
|
-
} catch {
|
|
135591
|
-
return raw;
|
|
135592
|
-
}
|
|
135857
|
+
const raw = maskPmakDiagnostic(mintError instanceof Error ? mintError.message : String(mintError), [apiKey]);
|
|
135858
|
+
if (!(mintError instanceof MintError) || mintError.status !== 401 && mintError.status !== 403) return raw;
|
|
135859
|
+
return formatRejectedMint(raw, await inspectPmakIdentity({ apiBaseUrl, apiKey, fetchImpl }));
|
|
135593
135860
|
}
|
|
135594
135861
|
async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetch) {
|
|
135595
135862
|
if (inputs.postmanAccessToken || !inputs.postmanApiKey) {
|
|
@@ -135602,7 +135869,8 @@ async function mintAccessTokenIfNeeded(inputs, log, setSecret2, fetchImpl = fetc
|
|
|
135602
135869
|
apiKey: inputs.postmanApiKey,
|
|
135603
135870
|
apiBaseUrl,
|
|
135604
135871
|
fetchImpl,
|
|
135605
|
-
onToken: (token) => setSecret2?.(token)
|
|
135872
|
+
onToken: (token) => setSecret2?.(token),
|
|
135873
|
+
onRetryEvent: (event) => log.retryEvent?.(event)
|
|
135606
135874
|
});
|
|
135607
135875
|
try {
|
|
135608
135876
|
inputs.postmanAccessToken = await provider.refresh();
|
|
@@ -135638,6 +135906,11 @@ var AccessTokenGatewayClient = class {
|
|
|
135638
135906
|
fallbackBaseUrl;
|
|
135639
135907
|
retryBaseDelayMs;
|
|
135640
135908
|
sleepImpl;
|
|
135909
|
+
appVersionProvider;
|
|
135910
|
+
requestTimeoutMs;
|
|
135911
|
+
retryMaxDelayMs;
|
|
135912
|
+
randomImpl;
|
|
135913
|
+
onRetryEvent;
|
|
135641
135914
|
constructor(options) {
|
|
135642
135915
|
this.tokenProvider = options.tokenProvider;
|
|
135643
135916
|
this.bifrostBaseUrl = String(
|
|
@@ -135652,16 +135925,23 @@ var AccessTokenGatewayClient = class {
|
|
|
135652
135925
|
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
135653
135926
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
135654
135927
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
135928
|
+
this.appVersionProvider = options.appVersionProvider ?? defaultPostmanAppVersionProvider;
|
|
135929
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 3e4;
|
|
135930
|
+
this.retryMaxDelayMs = options.retryMaxDelayMs ?? 5e3;
|
|
135931
|
+
this.randomImpl = options.randomImpl ?? Math.random;
|
|
135932
|
+
this.onRetryEvent = options.onRetryEvent;
|
|
135655
135933
|
}
|
|
135656
135934
|
configureTeamContext(teamId, orgMode) {
|
|
135657
135935
|
this.teamId = String(teamId || "").trim();
|
|
135658
135936
|
this.orgMode = orgMode;
|
|
135659
135937
|
}
|
|
135660
|
-
buildHeaders(extra) {
|
|
135938
|
+
async buildHeaders(extra) {
|
|
135939
|
+
const appVersion = await this.appVersionProvider.get();
|
|
135661
135940
|
const headers = {
|
|
135662
135941
|
"Content-Type": "application/json",
|
|
135663
135942
|
"x-access-token": this.tokenProvider.current(),
|
|
135664
|
-
...extra || {}
|
|
135943
|
+
...extra || {},
|
|
135944
|
+
...appVersion ? { "x-app-version": appVersion } : {}
|
|
135665
135945
|
};
|
|
135666
135946
|
if (this.teamId && this.orgMode) {
|
|
135667
135947
|
headers["x-entity-team-id"] = this.teamId;
|
|
@@ -135670,17 +135950,24 @@ var AccessTokenGatewayClient = class {
|
|
|
135670
135950
|
}
|
|
135671
135951
|
async send(request, baseUrl) {
|
|
135672
135952
|
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
135673
|
-
|
|
135674
|
-
|
|
135675
|
-
|
|
135676
|
-
|
|
135677
|
-
|
|
135678
|
-
|
|
135679
|
-
|
|
135680
|
-
|
|
135681
|
-
|
|
135682
|
-
|
|
135683
|
-
|
|
135953
|
+
const controller = new AbortController();
|
|
135954
|
+
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
135955
|
+
try {
|
|
135956
|
+
return await this.fetchImpl(url, {
|
|
135957
|
+
method: "POST",
|
|
135958
|
+
headers: await this.buildHeaders(request.headers),
|
|
135959
|
+
signal: controller.signal,
|
|
135960
|
+
body: JSON.stringify({
|
|
135961
|
+
service: request.service,
|
|
135962
|
+
method: request.method,
|
|
135963
|
+
path: request.path,
|
|
135964
|
+
...request.query !== void 0 ? { query: request.query } : {},
|
|
135965
|
+
...request.body !== void 0 ? { body: request.body } : {}
|
|
135966
|
+
})
|
|
135967
|
+
});
|
|
135968
|
+
} finally {
|
|
135969
|
+
clearTimeout(timer);
|
|
135970
|
+
}
|
|
135684
135971
|
}
|
|
135685
135972
|
/**
|
|
135686
135973
|
* One cold, serial attempt against the fallback base URL after the primary
|
|
@@ -135707,11 +135994,13 @@ var AccessTokenGatewayClient = class {
|
|
|
135707
135994
|
* they are the freshest authoritative answer.
|
|
135708
135995
|
*/
|
|
135709
135996
|
fallbackEligible(request, retryTransient) {
|
|
135997
|
+
if (request.fallback === "none") return false;
|
|
135710
135998
|
if (!this.fallbackBaseUrl) return false;
|
|
135711
135999
|
return retryTransient || request.fallback === "auto";
|
|
135712
136000
|
}
|
|
135713
|
-
async attemptFallback(request, retryTransient) {
|
|
136001
|
+
async attemptFallback(request, retryTransient, status) {
|
|
135714
136002
|
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
136003
|
+
this.emitRetryEvent("fallback", status, 1, 0);
|
|
135715
136004
|
const response = await this.tryFallback(request);
|
|
135716
136005
|
if (!response) return null;
|
|
135717
136006
|
if (response.ok) return response;
|
|
@@ -135736,7 +136025,8 @@ var AccessTokenGatewayClient = class {
|
|
|
135736
136025
|
response = await this.send(request);
|
|
135737
136026
|
} catch (error) {
|
|
135738
136027
|
if (retryTransient && attempt < this.maxRetries) {
|
|
135739
|
-
const delay = this.
|
|
136028
|
+
const delay = this.retryDelayMs(attempt);
|
|
136029
|
+
this.emitRetryEvent("transport", void 0, attempt + 1, delay);
|
|
135740
136030
|
attempt += 1;
|
|
135741
136031
|
await this.sleepImpl(delay);
|
|
135742
136032
|
continue;
|
|
@@ -135746,10 +136036,23 @@ var AccessTokenGatewayClient = class {
|
|
|
135746
136036
|
throw error;
|
|
135747
136037
|
}
|
|
135748
136038
|
if (response.ok) {
|
|
135749
|
-
|
|
136039
|
+
const okBody = await response.text().catch(() => "");
|
|
136040
|
+
const inner = this.innerStatus(okBody);
|
|
136041
|
+
if (inner !== void 0) {
|
|
136042
|
+
if (retryTransient && this.isTransient(inner, okBody) && attempt < this.maxRetries) {
|
|
136043
|
+
const delay = this.retryDelayMs(attempt);
|
|
136044
|
+
this.emitRetryEvent("inner", inner, attempt + 1, delay);
|
|
136045
|
+
await this.sleepImpl(delay);
|
|
136046
|
+
attempt += 1;
|
|
136047
|
+
continue;
|
|
136048
|
+
}
|
|
136049
|
+
throw this.toInnerHttpError(request, inner, okBody);
|
|
136050
|
+
}
|
|
136051
|
+
return this.rebuildResponse(response, okBody);
|
|
135750
136052
|
}
|
|
135751
136053
|
const body = await response.text().catch(() => "");
|
|
135752
136054
|
if (isExpiredAuthError(response.status, body) && this.tokenProvider.canRefresh()) {
|
|
136055
|
+
this.emitRetryEvent("auth", response.status, 1, 0);
|
|
135753
136056
|
await this.tokenProvider.refresh();
|
|
135754
136057
|
response = await this.send(request);
|
|
135755
136058
|
if (response.ok) {
|
|
@@ -135758,17 +136061,44 @@ var AccessTokenGatewayClient = class {
|
|
|
135758
136061
|
const retryBody = await response.text().catch(() => "");
|
|
135759
136062
|
throw this.toHttpError(request, response, retryBody);
|
|
135760
136063
|
}
|
|
135761
|
-
if (retryTransient &&
|
|
135762
|
-
const delay = this.
|
|
136064
|
+
if (retryTransient && this.isTransient(response.status, body) && attempt < this.maxRetries) {
|
|
136065
|
+
const delay = this.retryDelayMs(attempt, parseRetryAfterMs2(response.headers.get("retry-after")));
|
|
136066
|
+
this.emitRetryEvent("http", response.status, attempt + 1, delay);
|
|
135763
136067
|
attempt += 1;
|
|
135764
136068
|
await this.sleepImpl(delay);
|
|
135765
136069
|
continue;
|
|
135766
136070
|
}
|
|
135767
|
-
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
136071
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient, response.status);
|
|
135768
136072
|
if (fallbackResponse) return fallbackResponse;
|
|
135769
136073
|
throw this.toHttpError(request, response, body);
|
|
135770
136074
|
}
|
|
135771
136075
|
}
|
|
136076
|
+
retryDelayMs(attempt, retryAfter) {
|
|
136077
|
+
return retryAfter === void 0 ? fullJitterDelayMs(attempt, this.retryBaseDelayMs, this.retryMaxDelayMs, this.randomImpl) : Math.min(this.retryMaxDelayMs, retryAfter);
|
|
136078
|
+
}
|
|
136079
|
+
emitRetryEvent(retryClass, status, attempt, delay) {
|
|
136080
|
+
this.onRetryEvent?.({
|
|
136081
|
+
class: retryClass,
|
|
136082
|
+
...status === void 0 ? {} : { status },
|
|
136083
|
+
attempt: Math.max(1, attempt),
|
|
136084
|
+
delay: Math.max(0, delay)
|
|
136085
|
+
});
|
|
136086
|
+
}
|
|
136087
|
+
isTransient(status, body) {
|
|
136088
|
+
return status === 408 || status === 429 || status >= 500 || /ESOCKETTIMEDOUT|ETIMEDOUT|ECONNRESET|serverError|downstream/.test(body);
|
|
136089
|
+
}
|
|
136090
|
+
innerStatus(body) {
|
|
136091
|
+
try {
|
|
136092
|
+
const value = JSON.parse(body);
|
|
136093
|
+
const status = Number(value.status ?? value.statusCode);
|
|
136094
|
+
return value.error || value.success === false || status >= 400 ? status >= 400 ? status : 502 : void 0;
|
|
136095
|
+
} catch {
|
|
136096
|
+
return void 0;
|
|
136097
|
+
}
|
|
136098
|
+
}
|
|
136099
|
+
rebuildResponse(response, body) {
|
|
136100
|
+
return new Response([204, 205, 304].includes(response.status) ? null : body, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
136101
|
+
}
|
|
135772
136102
|
/** Send a gateway request and parse the JSON body, or null when empty. */
|
|
135773
136103
|
async requestJson(request, options = {}) {
|
|
135774
136104
|
const response = await this.request(request, options);
|
|
@@ -135815,15 +136145,23 @@ var AccessTokenGatewayClient = class {
|
|
|
135815
136145
|
url: `${this.bifrostBaseUrl}/ws/proxy (${request.service}: ${request.method} ${request.path})`,
|
|
135816
136146
|
status: response.status,
|
|
135817
136147
|
statusText: response.statusText,
|
|
135818
|
-
requestHeaders:
|
|
136148
|
+
requestHeaders: {
|
|
136149
|
+
"Content-Type": "application/json",
|
|
136150
|
+
"x-access-token": this.tokenProvider.current(),
|
|
136151
|
+
...request.headers || {},
|
|
136152
|
+
...this.teamId && this.orgMode ? { "x-entity-team-id": this.teamId } : {}
|
|
136153
|
+
},
|
|
135819
136154
|
responseBody: this.secretMasker(body),
|
|
135820
136155
|
secretValues: [this.tokenProvider.current()]
|
|
135821
136156
|
});
|
|
135822
136157
|
}
|
|
136158
|
+
toInnerHttpError(request, status, body) {
|
|
136159
|
+
return new HttpError({ method: request.method.toUpperCase(), url: `${this.bifrostBaseUrl}/ws/proxy (${request.service}: ${request.method} ${request.path}) [inner]`, status, statusText: "Inner Error", requestHeaders: { "x-access-token": this.tokenProvider.current() }, responseBody: this.secretMasker(body), secretValues: [this.tokenProvider.current()] });
|
|
136160
|
+
}
|
|
135823
136161
|
};
|
|
135824
136162
|
|
|
135825
136163
|
// src/lib/repo/branch-decision.ts
|
|
135826
|
-
var
|
|
136164
|
+
var import_node_fs4 = require("node:fs");
|
|
135827
136165
|
var import_node_crypto2 = require("node:crypto");
|
|
135828
136166
|
var ContractError = class extends Error {
|
|
135829
136167
|
code;
|
|
@@ -135864,7 +136202,7 @@ function readGithubEvent(env) {
|
|
|
135864
136202
|
const path5 = clean(env.GITHUB_EVENT_PATH);
|
|
135865
136203
|
if (!path5) return void 0;
|
|
135866
136204
|
try {
|
|
135867
|
-
return JSON.parse((0,
|
|
136205
|
+
return JSON.parse((0, import_node_fs4.readFileSync)(path5, "utf8"));
|
|
135868
136206
|
} catch {
|
|
135869
136207
|
return void 0;
|
|
135870
136208
|
}
|
|
@@ -136317,6 +136655,7 @@ function resolveInputs(env = process.env) {
|
|
|
136317
136655
|
baselineCollectionId: getInput("baseline-collection-id", env),
|
|
136318
136656
|
smokeCollectionId: getInput("smoke-collection-id", env),
|
|
136319
136657
|
contractCollectionId: getInput("contract-collection-id", env),
|
|
136658
|
+
prebuiltCollectionsJson: getInput("prebuilt-collections-json", env),
|
|
136320
136659
|
specId: getInput("spec-id", env),
|
|
136321
136660
|
specContentChanged: parseBooleanInput(getInput("spec-content-changed", env), true),
|
|
136322
136661
|
specPath: getInput("spec-path", env),
|
|
@@ -136432,7 +136771,7 @@ var StateUnreadableError = class extends Error {
|
|
|
136432
136771
|
function readResourcesState() {
|
|
136433
136772
|
let raw;
|
|
136434
136773
|
try {
|
|
136435
|
-
raw = (0,
|
|
136774
|
+
raw = (0, import_node_fs5.readFileSync)(".postman/resources.yaml", "utf8");
|
|
136436
136775
|
} catch {
|
|
136437
136776
|
return null;
|
|
136438
136777
|
}
|
|
@@ -136491,12 +136830,15 @@ function getEnvironmentUidsFromResources(resourcesState) {
|
|
|
136491
136830
|
function normalizeToPosix(filePath) {
|
|
136492
136831
|
return filePath.split(path3.sep).join("/").replace(/\\/g, "/");
|
|
136493
136832
|
}
|
|
136833
|
+
function canonicalizeRelativePath(value) {
|
|
136834
|
+
return normalizeToPosix(String(value ?? "").trim()).replace(/^\.\/+/, "").replace(/\/{2,}/g, "/").replace(/\/+$/g, "");
|
|
136835
|
+
}
|
|
136494
136836
|
function isOpenApiSpecFile(filePath) {
|
|
136495
136837
|
if (!(filePath.endsWith(".json") || filePath.endsWith(".yaml") || filePath.endsWith(".yml"))) {
|
|
136496
136838
|
return false;
|
|
136497
136839
|
}
|
|
136498
136840
|
try {
|
|
136499
|
-
const raw = (0,
|
|
136841
|
+
const raw = (0, import_node_fs5.readFileSync)(filePath, "utf8");
|
|
136500
136842
|
const parsed = filePath.endsWith(".json") ? JSON.parse(raw) : load(raw);
|
|
136501
136843
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
136502
136844
|
return false;
|
|
@@ -136525,7 +136867,7 @@ function scanLocalSpecReferences(baseDir = ".") {
|
|
|
136525
136867
|
const found = /* @__PURE__ */ new Set();
|
|
136526
136868
|
const refs = [];
|
|
136527
136869
|
const visit2 = (currentDir) => {
|
|
136528
|
-
for (const entry of (0,
|
|
136870
|
+
for (const entry of (0, import_node_fs5.readdirSync)(currentDir, { withFileTypes: true })) {
|
|
136529
136871
|
if (ignoredDirs.has(entry.name)) {
|
|
136530
136872
|
continue;
|
|
136531
136873
|
}
|
|
@@ -136555,7 +136897,7 @@ function resolveMappedSpecReference(explicitSpecPath, discoveredSpecs) {
|
|
|
136555
136897
|
const normalizedExplicitPath = normalizeToPosix(explicitSpecPath.trim());
|
|
136556
136898
|
if (normalizedExplicitPath) {
|
|
136557
136899
|
const explicitFullPath = path3.resolve(normalizedExplicitPath);
|
|
136558
|
-
if ((0,
|
|
136900
|
+
if ((0, import_node_fs5.existsSync)(explicitFullPath) && (0, import_node_fs5.statSync)(explicitFullPath).isFile()) {
|
|
136559
136901
|
return {
|
|
136560
136902
|
repoRelativePath: normalizedExplicitPath,
|
|
136561
136903
|
configRelativePath: normalizeToPosix(path3.join("..", normalizedExplicitPath))
|
|
@@ -136681,6 +137023,7 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
136681
137023
|
);
|
|
136682
137024
|
}
|
|
136683
137025
|
envUids[envName] = existingUid;
|
|
137026
|
+
dependencies.core.setOutput("environment-uids-json", JSON.stringify(envUids));
|
|
136684
137027
|
continue;
|
|
136685
137028
|
}
|
|
136686
137029
|
const values = buildEnvironmentValues(envName, runtimeUrl);
|
|
@@ -136691,6 +137034,7 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
136691
137034
|
displayName,
|
|
136692
137035
|
values
|
|
136693
137036
|
);
|
|
137037
|
+
dependencies.core.setOutput("environment-uids-json", JSON.stringify(envUids));
|
|
136694
137038
|
} catch (error) {
|
|
136695
137039
|
throw new Error(
|
|
136696
137040
|
formatOrchestrationIssue({
|
|
@@ -136707,7 +137051,7 @@ async function upsertEnvironments(inputs, dependencies, resourcesState, assetMar
|
|
|
136707
137051
|
return envUids;
|
|
136708
137052
|
}
|
|
136709
137053
|
function ensureDir(path5) {
|
|
136710
|
-
(0,
|
|
137054
|
+
(0, import_node_fs5.mkdirSync)(path5, { recursive: true });
|
|
136711
137055
|
}
|
|
136712
137056
|
function getCollectionDirectoryName(kind, projectName) {
|
|
136713
137057
|
if (kind === "Baseline") {
|
|
@@ -136742,9 +137086,9 @@ function stripVolatileFields(obj) {
|
|
|
136742
137086
|
}
|
|
136743
137087
|
return obj;
|
|
136744
137088
|
}
|
|
136745
|
-
function writeJsonFile(path5, content,
|
|
136746
|
-
const data =
|
|
136747
|
-
(0,
|
|
137089
|
+
function writeJsonFile(path5, content, normalize4 = false) {
|
|
137090
|
+
const data = normalize4 ? stripVolatileFields(content) : content;
|
|
137091
|
+
(0, import_node_fs5.writeFileSync)(path5, JSON.stringify(data, null, 2));
|
|
136748
137092
|
}
|
|
136749
137093
|
function buildMappedSpecCloudKey(mappedSource, specSyncMode, releaseLabel) {
|
|
136750
137094
|
if (specSyncMode !== "version") {
|
|
@@ -136808,22 +137152,422 @@ function buildResourcesManifest(workspaceId, collectionMap, envMap, artifactDir,
|
|
|
136808
137152
|
sortKeys: false
|
|
136809
137153
|
});
|
|
136810
137154
|
}
|
|
136811
|
-
function
|
|
136812
|
-
return
|
|
136813
|
-
|
|
136814
|
-
|
|
136815
|
-
|
|
136816
|
-
|
|
136817
|
-
|
|
136818
|
-
|
|
137155
|
+
function isPlainObject2(value) {
|
|
137156
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
137157
|
+
}
|
|
137158
|
+
function buildSpecCollectionWorkflowManifest(specRef, collectionRefs, existingRaw) {
|
|
137159
|
+
const pairs = collectionRefs.map((collectionRef) => ({
|
|
137160
|
+
spec: specRef,
|
|
137161
|
+
collection: collectionRef
|
|
137162
|
+
}));
|
|
137163
|
+
let root = {};
|
|
137164
|
+
if (typeof existingRaw === "string" && existingRaw.trim()) {
|
|
137165
|
+
let parsed;
|
|
137166
|
+
try {
|
|
137167
|
+
parsed = load(existingRaw);
|
|
137168
|
+
} catch (error) {
|
|
137169
|
+
throw new Error(
|
|
137170
|
+
`CONTRACT_WORKFLOWS_UNREADABLE: .postman/workflows.yaml exists but is not parseable YAML (${error instanceof Error ? error.message : String(error)}). Fix or delete the file; refusing to overwrite unrelated workflow data.`,
|
|
137171
|
+
{ cause: error }
|
|
137172
|
+
);
|
|
137173
|
+
}
|
|
137174
|
+
if (parsed === null || parsed === void 0) {
|
|
137175
|
+
root = {};
|
|
137176
|
+
} else if (!isPlainObject2(parsed)) {
|
|
137177
|
+
throw new Error(
|
|
137178
|
+
"CONTRACT_WORKFLOWS_UNREADABLE: .postman/workflows.yaml exists but does not contain a YAML mapping. Fix or delete the file; refusing to overwrite unrelated workflow data."
|
|
137179
|
+
);
|
|
137180
|
+
} else {
|
|
137181
|
+
root = { ...parsed };
|
|
137182
|
+
}
|
|
137183
|
+
}
|
|
137184
|
+
const workflows = isPlainObject2(root.workflows) ? { ...root.workflows } : {};
|
|
137185
|
+
const desiredCollections = new Set(collectionRefs);
|
|
137186
|
+
const currentPairs = (Array.isArray(workflows.syncSpecToCollection) ? workflows.syncSpecToCollection : []).map((entry) => isPlainObject2(entry) ? { ...entry } : null).filter((entry) => Boolean(entry)).filter(
|
|
137187
|
+
(entry) => String(entry.spec ?? "") !== specRef || desiredCollections.has(String(entry.collection ?? ""))
|
|
137188
|
+
);
|
|
137189
|
+
for (const pair of pairs) {
|
|
137190
|
+
const index = currentPairs.findIndex(
|
|
137191
|
+
(entry) => String(entry.spec ?? "") === pair.spec && String(entry.collection ?? "") === pair.collection
|
|
137192
|
+
);
|
|
137193
|
+
if (index >= 0) {
|
|
137194
|
+
const previous = currentPairs[index];
|
|
137195
|
+
currentPairs[index] = { ...previous, spec: pair.spec, collection: pair.collection };
|
|
137196
|
+
} else {
|
|
137197
|
+
currentPairs.push({ spec: pair.spec, collection: pair.collection });
|
|
137198
|
+
}
|
|
137199
|
+
}
|
|
137200
|
+
workflows.syncSpecToCollection = currentPairs;
|
|
137201
|
+
root.workflows = workflows;
|
|
137202
|
+
return dump(root, {
|
|
137203
|
+
lineWidth: -1,
|
|
137204
|
+
noRefs: true,
|
|
137205
|
+
sortKeys: false
|
|
137206
|
+
});
|
|
137207
|
+
}
|
|
137208
|
+
var PREBUILT_COLLECTION_ROLES = /* @__PURE__ */ new Set([
|
|
137209
|
+
"baseline",
|
|
137210
|
+
"smoke",
|
|
137211
|
+
"contract"
|
|
137212
|
+
]);
|
|
137213
|
+
var SHA256_HEX = /^[a-f0-9]{64}$/;
|
|
137214
|
+
var PREBUILT_CLOUD_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/;
|
|
137215
|
+
function failPrebuiltCollections(detail) {
|
|
137216
|
+
throw new Error(`CONTRACT_PREBUILT_COLLECTIONS_INVALID: ${detail}`);
|
|
137217
|
+
}
|
|
137218
|
+
function parsePrebuiltCollectionsJson(raw) {
|
|
137219
|
+
const trimmed = String(raw ?? "").trim();
|
|
137220
|
+
if (!trimmed) {
|
|
137221
|
+
return [];
|
|
137222
|
+
}
|
|
137223
|
+
let parsed;
|
|
137224
|
+
try {
|
|
137225
|
+
parsed = JSON.parse(trimmed);
|
|
137226
|
+
} catch (error) {
|
|
137227
|
+
throw new Error(
|
|
137228
|
+
`CONTRACT_PREBUILT_COLLECTIONS_INVALID: malformed JSON (${error instanceof Error ? error.message : String(error)})`,
|
|
137229
|
+
{ cause: error }
|
|
137230
|
+
);
|
|
137231
|
+
}
|
|
137232
|
+
let entriesRaw;
|
|
137233
|
+
if (Array.isArray(parsed)) {
|
|
137234
|
+
entriesRaw = parsed;
|
|
137235
|
+
} else if (isPlainObject2(parsed)) {
|
|
137236
|
+
if (parsed.schemaVersion !== 1) {
|
|
137237
|
+
failPrebuiltCollections("schemaVersion must be 1");
|
|
137238
|
+
}
|
|
137239
|
+
if (!Array.isArray(parsed.collections)) {
|
|
137240
|
+
failPrebuiltCollections("collections must be an array when schemaVersion is set");
|
|
137241
|
+
}
|
|
137242
|
+
entriesRaw = parsed.collections;
|
|
137243
|
+
} else {
|
|
137244
|
+
failPrebuiltCollections("expected a JSON array or {schemaVersion:1,collections:[]}");
|
|
137245
|
+
}
|
|
137246
|
+
const seenRoles = /* @__PURE__ */ new Set();
|
|
137247
|
+
const entries = [];
|
|
137248
|
+
for (const [index, value] of entriesRaw.entries()) {
|
|
137249
|
+
if (!isPlainObject2(value)) {
|
|
137250
|
+
failPrebuiltCollections(`collections[${index}] must be an object`);
|
|
137251
|
+
}
|
|
137252
|
+
const roleRaw = String(value.role ?? "").trim();
|
|
137253
|
+
if (!PREBUILT_COLLECTION_ROLES.has(roleRaw)) {
|
|
137254
|
+
failPrebuiltCollections(
|
|
137255
|
+
`collections[${index}].role must be one of baseline|smoke|contract`
|
|
137256
|
+
);
|
|
137257
|
+
}
|
|
137258
|
+
const role = roleRaw;
|
|
137259
|
+
if (seenRoles.has(role)) {
|
|
137260
|
+
failPrebuiltCollections(`duplicate role ${role}`);
|
|
137261
|
+
}
|
|
137262
|
+
seenRoles.add(role);
|
|
137263
|
+
const collectionPath = String(
|
|
137264
|
+
value.collectionPath ?? value.path ?? ""
|
|
137265
|
+
).trim();
|
|
137266
|
+
if (!collectionPath || hasControlCharacter2(collectionPath)) {
|
|
137267
|
+
failPrebuiltCollections(
|
|
137268
|
+
`collections[${index}].collectionPath must be a non-empty confined relative path`
|
|
137269
|
+
);
|
|
137270
|
+
}
|
|
137271
|
+
const cloudId = String(value.cloudId ?? "").trim();
|
|
137272
|
+
if (!cloudId || !PREBUILT_CLOUD_ID.test(cloudId)) {
|
|
137273
|
+
failPrebuiltCollections(
|
|
137274
|
+
`collections[${index}].cloudId must be a non-empty Postman collection id`
|
|
137275
|
+
);
|
|
137276
|
+
}
|
|
137277
|
+
let payloadDigest;
|
|
137278
|
+
if (Object.prototype.hasOwnProperty.call(value, "payloadDigest")) {
|
|
137279
|
+
const payloadDigestRaw = value.payloadDigest;
|
|
137280
|
+
if (payloadDigestRaw !== void 0 && payloadDigestRaw !== null) {
|
|
137281
|
+
payloadDigest = String(payloadDigestRaw).trim();
|
|
137282
|
+
if (!SHA256_HEX.test(payloadDigest)) {
|
|
137283
|
+
failPrebuiltCollections(
|
|
137284
|
+
`collections[${index}].payloadDigest must be lowercase 64-hex`
|
|
137285
|
+
);
|
|
137286
|
+
}
|
|
136819
137287
|
}
|
|
136820
|
-
},
|
|
136821
|
-
{
|
|
136822
|
-
lineWidth: -1,
|
|
136823
|
-
noRefs: true,
|
|
136824
|
-
sortKeys: false
|
|
136825
137288
|
}
|
|
137289
|
+
const artifactDigest = String(value.artifactDigest ?? "").trim();
|
|
137290
|
+
if (!SHA256_HEX.test(artifactDigest)) {
|
|
137291
|
+
failPrebuiltCollections(
|
|
137292
|
+
`collections[${index}].artifactDigest must be lowercase 64-hex`
|
|
137293
|
+
);
|
|
137294
|
+
}
|
|
137295
|
+
entries.push({
|
|
137296
|
+
role,
|
|
137297
|
+
collectionPath,
|
|
137298
|
+
cloudId,
|
|
137299
|
+
...payloadDigest !== void 0 ? { payloadDigest } : {},
|
|
137300
|
+
artifactDigest
|
|
137301
|
+
});
|
|
137302
|
+
}
|
|
137303
|
+
return entries;
|
|
137304
|
+
}
|
|
137305
|
+
function assertPathWithinArtifactRoot(targetPath, artifactDir, fieldName) {
|
|
137306
|
+
assertPathWithinCwd(targetPath, fieldName);
|
|
137307
|
+
assertPathWithinCwd(artifactDir, "artifact-dir");
|
|
137308
|
+
const cwd = (0, import_node_fs5.realpathSync)(process.cwd());
|
|
137309
|
+
const artifactRoot = path3.resolve(cwd, artifactDir.trim());
|
|
137310
|
+
const resolved = path3.resolve(cwd, targetPath.trim());
|
|
137311
|
+
const relativeToArtifact = path3.relative(artifactRoot, resolved);
|
|
137312
|
+
if (!relativeToArtifact || relativeToArtifact.startsWith("..") || path3.isAbsolute(relativeToArtifact)) {
|
|
137313
|
+
failPrebuiltCollections(
|
|
137314
|
+
`${fieldName} must stay under artifact-dir (${artifactDir}); received ${targetPath}`
|
|
137315
|
+
);
|
|
137316
|
+
}
|
|
137317
|
+
let existingPath = resolved;
|
|
137318
|
+
while (!(0, import_node_fs5.existsSync)(existingPath)) {
|
|
137319
|
+
const parent = path3.dirname(existingPath);
|
|
137320
|
+
if (parent === existingPath) {
|
|
137321
|
+
break;
|
|
137322
|
+
}
|
|
137323
|
+
existingPath = parent;
|
|
137324
|
+
}
|
|
137325
|
+
const realExisting = (0, import_node_fs5.realpathSync)(existingPath);
|
|
137326
|
+
const realRelative = path3.relative(artifactRoot, realExisting);
|
|
137327
|
+
if (realRelative.startsWith("..") || path3.isAbsolute(realRelative)) {
|
|
137328
|
+
failPrebuiltCollections(
|
|
137329
|
+
`${fieldName} resolves outside artifact-dir via symlink; received ${targetPath}`
|
|
137330
|
+
);
|
|
137331
|
+
}
|
|
137332
|
+
return normalizeToPosix(path3.relative(cwd, resolved));
|
|
137333
|
+
}
|
|
137334
|
+
function prebuiltDirectoryTraversalIdentity(absolutePath, stats, options = {}) {
|
|
137335
|
+
const platform2 = options.platform ?? process.platform;
|
|
137336
|
+
const inodeIsZero = stats.ino === 0 || stats.ino === 0n;
|
|
137337
|
+
if (platform2 !== "win32" && !inodeIsZero) {
|
|
137338
|
+
return `${stats.dev}:${stats.ino}`;
|
|
137339
|
+
}
|
|
137340
|
+
const resolveCanonicalPath = options.resolveCanonicalPath ?? ((candidate) => import_node_fs5.realpathSync.native(candidate));
|
|
137341
|
+
const canonical = resolveCanonicalPath(absolutePath);
|
|
137342
|
+
return platform2 === "win32" ? canonical.toLowerCase() : canonical;
|
|
137343
|
+
}
|
|
137344
|
+
function listPrebuiltCollectionTreeFiles(collectionPath, artifactDir) {
|
|
137345
|
+
const confined = assertPathWithinArtifactRoot(
|
|
137346
|
+
collectionPath,
|
|
137347
|
+
artifactDir,
|
|
137348
|
+
"prebuilt collection path"
|
|
136826
137349
|
);
|
|
137350
|
+
const absRoot = path3.resolve(process.cwd(), confined);
|
|
137351
|
+
if (!(0, import_node_fs5.existsSync)(absRoot)) {
|
|
137352
|
+
return [];
|
|
137353
|
+
}
|
|
137354
|
+
let rootStat;
|
|
137355
|
+
try {
|
|
137356
|
+
rootStat = (0, import_node_fs5.lstatSync)(absRoot);
|
|
137357
|
+
} catch {
|
|
137358
|
+
return [];
|
|
137359
|
+
}
|
|
137360
|
+
if (rootStat.isSymbolicLink()) {
|
|
137361
|
+
failPrebuiltCollections(
|
|
137362
|
+
`prebuilt collection path must not be a symlink; received ${collectionPath}`
|
|
137363
|
+
);
|
|
137364
|
+
}
|
|
137365
|
+
if (!rootStat.isDirectory()) {
|
|
137366
|
+
return [];
|
|
137367
|
+
}
|
|
137368
|
+
const files = [];
|
|
137369
|
+
const pendingDirectories = [absRoot];
|
|
137370
|
+
const seenDirectories = /* @__PURE__ */ new Set();
|
|
137371
|
+
while (pendingDirectories.length > 0) {
|
|
137372
|
+
const currentAbsolute = pendingDirectories.pop();
|
|
137373
|
+
if (!currentAbsolute) {
|
|
137374
|
+
break;
|
|
137375
|
+
}
|
|
137376
|
+
const currentStat = (0, import_node_fs5.lstatSync)(currentAbsolute);
|
|
137377
|
+
if (currentStat.isSymbolicLink() || !currentStat.isDirectory()) {
|
|
137378
|
+
failPrebuiltCollections(
|
|
137379
|
+
`prebuilt collection tree directory changed or became unsupported at ${normalizeToPosix(path3.relative(absRoot, currentAbsolute)) || "."}`
|
|
137380
|
+
);
|
|
137381
|
+
}
|
|
137382
|
+
const currentKey = prebuiltDirectoryTraversalIdentity(currentAbsolute, currentStat);
|
|
137383
|
+
if (seenDirectories.has(currentKey)) {
|
|
137384
|
+
failPrebuiltCollections(
|
|
137385
|
+
`prebuilt collection tree directory cycle detected at ${normalizeToPosix(path3.relative(absRoot, currentAbsolute)) || "."}`
|
|
137386
|
+
);
|
|
137387
|
+
}
|
|
137388
|
+
seenDirectories.add(currentKey);
|
|
137389
|
+
const entries = (0, import_node_fs5.readdirSync)(currentAbsolute, { withFileTypes: true });
|
|
137390
|
+
for (const entry of entries) {
|
|
137391
|
+
const abs = path3.join(currentAbsolute, entry.name);
|
|
137392
|
+
if (entry.isSymbolicLink()) {
|
|
137393
|
+
failPrebuiltCollections(
|
|
137394
|
+
`prebuilt collection tree must not contain symlinks; received ${normalizeToPosix(path3.relative(absRoot, abs))}`
|
|
137395
|
+
);
|
|
137396
|
+
}
|
|
137397
|
+
if (entry.isDirectory()) {
|
|
137398
|
+
pendingDirectories.push(abs);
|
|
137399
|
+
continue;
|
|
137400
|
+
}
|
|
137401
|
+
if (!entry.isFile()) {
|
|
137402
|
+
failPrebuiltCollections(
|
|
137403
|
+
`prebuilt collection tree contains unsupported entry type at ${normalizeToPosix(path3.relative(absRoot, abs))}`
|
|
137404
|
+
);
|
|
137405
|
+
}
|
|
137406
|
+
const fileLstat = (0, import_node_fs5.lstatSync)(abs);
|
|
137407
|
+
if (fileLstat.isSymbolicLink() || !fileLstat.isFile()) {
|
|
137408
|
+
failPrebuiltCollections(
|
|
137409
|
+
`prebuilt collection tree file changed or became unsupported at ${normalizeToPosix(path3.relative(absRoot, abs))}`
|
|
137410
|
+
);
|
|
137411
|
+
}
|
|
137412
|
+
files.push({
|
|
137413
|
+
absolute: abs,
|
|
137414
|
+
relative: normalizeToPosix(path3.relative(absRoot, abs)),
|
|
137415
|
+
dev: fileLstat.dev,
|
|
137416
|
+
ino: fileLstat.ino,
|
|
137417
|
+
size: fileLstat.size
|
|
137418
|
+
});
|
|
137419
|
+
}
|
|
137420
|
+
}
|
|
137421
|
+
files.sort((a, b) => a.relative.localeCompare(b.relative));
|
|
137422
|
+
return files;
|
|
137423
|
+
}
|
|
137424
|
+
function validateCanonicalV3CollectionFile(relative3, bytes) {
|
|
137425
|
+
let expectedKind;
|
|
137426
|
+
if (/(^|\/)\.resources\/definition\.yaml$/.test(relative3)) {
|
|
137427
|
+
expectedKind = "collection";
|
|
137428
|
+
} else if (relative3.endsWith(".request.yaml")) {
|
|
137429
|
+
expectedKind = "request";
|
|
137430
|
+
} else if (relative3.endsWith(".example.yaml")) {
|
|
137431
|
+
expectedKind = "example";
|
|
137432
|
+
} else if (relative3.endsWith(".message.yaml")) {
|
|
137433
|
+
expectedKind = "message";
|
|
137434
|
+
} else {
|
|
137435
|
+
failPrebuiltCollections(`prebuilt collection tree contains unexpected file ${relative3}`);
|
|
137436
|
+
}
|
|
137437
|
+
let parsed;
|
|
137438
|
+
try {
|
|
137439
|
+
parsed = load(bytes.toString("utf8"));
|
|
137440
|
+
} catch (error) {
|
|
137441
|
+
failPrebuiltCollections(
|
|
137442
|
+
`prebuilt collection tree contains malformed YAML at ${relative3} (${error instanceof Error ? error.message : String(error)})`
|
|
137443
|
+
);
|
|
137444
|
+
}
|
|
137445
|
+
if (!isPlainObject2(parsed)) {
|
|
137446
|
+
failPrebuiltCollections(`prebuilt collection tree file ${relative3} must contain a YAML mapping`);
|
|
137447
|
+
}
|
|
137448
|
+
const kind = typeof parsed.$kind === "string" ? parsed.$kind.trim() : "";
|
|
137449
|
+
if (!kind) {
|
|
137450
|
+
failPrebuiltCollections(`prebuilt collection tree file ${relative3} must contain a nonempty $kind`);
|
|
137451
|
+
}
|
|
137452
|
+
const agrees = expectedKind === "collection" ? kind === "collection" : kind.endsWith(`-${expectedKind}`);
|
|
137453
|
+
if (!agrees) {
|
|
137454
|
+
failPrebuiltCollections(
|
|
137455
|
+
`prebuilt collection tree file ${relative3} has $kind ${kind} inconsistent with its filename`
|
|
137456
|
+
);
|
|
137457
|
+
}
|
|
137458
|
+
}
|
|
137459
|
+
async function digestAndValidatePrebuiltCollectionTree(files) {
|
|
137460
|
+
if (!files.some((file) => file.relative === ".resources/definition.yaml")) {
|
|
137461
|
+
failPrebuiltCollections("prebuilt collection tree is missing .resources/definition.yaml");
|
|
137462
|
+
}
|
|
137463
|
+
const hash = (0, import_node_crypto3.createHash)("sha256");
|
|
137464
|
+
for (const file of files) {
|
|
137465
|
+
let bytes;
|
|
137466
|
+
try {
|
|
137467
|
+
bytes = await appendArtifactDigestFileStreaming(hash, file.relative, file.absolute, {
|
|
137468
|
+
dev: file.dev,
|
|
137469
|
+
ino: file.ino,
|
|
137470
|
+
size: file.size
|
|
137471
|
+
});
|
|
137472
|
+
} catch (error) {
|
|
137473
|
+
if (error instanceof ArtifactDigestStreamError) {
|
|
137474
|
+
failPrebuiltCollections(error.message);
|
|
137475
|
+
}
|
|
137476
|
+
const code = error?.code;
|
|
137477
|
+
if (code === "ELOOP" || code === "EPERM") {
|
|
137478
|
+
failPrebuiltCollections(
|
|
137479
|
+
`prebuilt collection tree file became a symlink or unsupported node at ${file.relative}`
|
|
137480
|
+
);
|
|
137481
|
+
}
|
|
137482
|
+
failPrebuiltCollections(
|
|
137483
|
+
`prebuilt collection tree file changed or became unsupported at ${file.relative}`
|
|
137484
|
+
);
|
|
137485
|
+
}
|
|
137486
|
+
validateCanonicalV3CollectionFile(file.relative, bytes);
|
|
137487
|
+
}
|
|
137488
|
+
return hash.digest("hex");
|
|
137489
|
+
}
|
|
137490
|
+
async function preparePrebuiltCollections(inputs) {
|
|
137491
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
137492
|
+
for (const entry of parsePrebuiltCollectionsJson(inputs.prebuiltCollectionsJson ?? "")) {
|
|
137493
|
+
const confinedPath = assertPathWithinArtifactRoot(
|
|
137494
|
+
entry.collectionPath,
|
|
137495
|
+
inputs.artifactDir,
|
|
137496
|
+
`prebuilt ${entry.role} collection path`
|
|
137497
|
+
);
|
|
137498
|
+
const absolute = path3.resolve(process.cwd(), confinedPath);
|
|
137499
|
+
if (!(0, import_node_fs5.existsSync)(absolute)) {
|
|
137500
|
+
prepared.set(entry.role, { entry, confinedPath });
|
|
137501
|
+
continue;
|
|
137502
|
+
}
|
|
137503
|
+
const files = listPrebuiltCollectionTreeFiles(confinedPath, inputs.artifactDir);
|
|
137504
|
+
const artifactDigest = await digestAndValidatePrebuiltCollectionTree(files);
|
|
137505
|
+
prepared.set(entry.role, {
|
|
137506
|
+
entry,
|
|
137507
|
+
confinedPath,
|
|
137508
|
+
artifactDigest
|
|
137509
|
+
});
|
|
137510
|
+
}
|
|
137511
|
+
return prepared;
|
|
137512
|
+
}
|
|
137513
|
+
function tryReusePrebuiltCollection(options) {
|
|
137514
|
+
const { prepared, expectedPath, expectedCloudId } = options;
|
|
137515
|
+
const { entry } = prepared;
|
|
137516
|
+
if (!expectedCloudId || entry.cloudId !== expectedCloudId) {
|
|
137517
|
+
return false;
|
|
137518
|
+
}
|
|
137519
|
+
const expectedNormalized = canonicalizeRelativePath(expectedPath);
|
|
137520
|
+
const entryNormalized = canonicalizeRelativePath(entry.collectionPath);
|
|
137521
|
+
if (entryNormalized !== expectedNormalized) {
|
|
137522
|
+
return false;
|
|
137523
|
+
}
|
|
137524
|
+
const confined = canonicalizeRelativePath(prepared.confinedPath);
|
|
137525
|
+
if (confined !== expectedNormalized) {
|
|
137526
|
+
return false;
|
|
137527
|
+
}
|
|
137528
|
+
const expectedName = path3.posix.basename(expectedNormalized);
|
|
137529
|
+
if (path3.posix.basename(confined) !== expectedName) {
|
|
137530
|
+
return false;
|
|
137531
|
+
}
|
|
137532
|
+
return prepared.artifactDigest === entry.artifactDigest;
|
|
137533
|
+
}
|
|
137534
|
+
async function exportCollectionArtifact(options) {
|
|
137535
|
+
const {
|
|
137536
|
+
role,
|
|
137537
|
+
collectionId,
|
|
137538
|
+
dirName,
|
|
137539
|
+
collectionsDir,
|
|
137540
|
+
prebuiltByRole,
|
|
137541
|
+
postman,
|
|
137542
|
+
core
|
|
137543
|
+
} = options;
|
|
137544
|
+
if (!collectionId) {
|
|
137545
|
+
return void 0;
|
|
137546
|
+
}
|
|
137547
|
+
const expectedPath = `${collectionsDir}/${dirName}`;
|
|
137548
|
+
const entry = prebuiltByRole.get(role);
|
|
137549
|
+
if (entry) {
|
|
137550
|
+
const reused = tryReusePrebuiltCollection({
|
|
137551
|
+
prepared: entry,
|
|
137552
|
+
expectedPath,
|
|
137553
|
+
expectedCloudId: collectionId
|
|
137554
|
+
});
|
|
137555
|
+
if (reused) {
|
|
137556
|
+
core.info(
|
|
137557
|
+
`Reusing prebuilt ${role} collection tree at ${expectedPath} (artifactDigest match)`
|
|
137558
|
+
);
|
|
137559
|
+
return `../${expectedPath}`;
|
|
137560
|
+
}
|
|
137561
|
+
core.info(
|
|
137562
|
+
`Prebuilt ${role} collection entry present but did not exactly match; exporting from cloud`
|
|
137563
|
+
);
|
|
137564
|
+
}
|
|
137565
|
+
const col = await postman.getCollection(collectionId);
|
|
137566
|
+
await convertAndSplitAnyCollection(
|
|
137567
|
+
col,
|
|
137568
|
+
expectedPath
|
|
137569
|
+
);
|
|
137570
|
+
return `../${expectedPath}`;
|
|
136827
137571
|
}
|
|
136828
137572
|
function hasControlCharacter2(value) {
|
|
136829
137573
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -136841,21 +137585,21 @@ function assertPathWithinCwd(targetPath, fieldName) {
|
|
|
136841
137585
|
if (!rawPath || hasControlCharacter2(originalPath) || path3.isAbsolute(rawPath) || path3.win32.isAbsolute(rawPath) || segments.includes("..") || rawPath.startsWith(":") || hasControlCharacter2(rawPath)) {
|
|
136842
137586
|
throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
|
|
136843
137587
|
}
|
|
136844
|
-
const base = (0,
|
|
137588
|
+
const base = (0, import_node_fs5.realpathSync)(process.cwd());
|
|
136845
137589
|
const resolved = path3.resolve(base, rawPath);
|
|
136846
137590
|
const relative3 = path3.relative(base, resolved);
|
|
136847
137591
|
if (relative3.startsWith("..") || path3.isAbsolute(relative3)) {
|
|
136848
137592
|
throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
|
|
136849
137593
|
}
|
|
136850
137594
|
let existingPath = resolved;
|
|
136851
|
-
while (!(0,
|
|
137595
|
+
while (!(0, import_node_fs5.existsSync)(existingPath)) {
|
|
136852
137596
|
const parent = path3.dirname(existingPath);
|
|
136853
137597
|
if (parent === existingPath) {
|
|
136854
137598
|
break;
|
|
136855
137599
|
}
|
|
136856
137600
|
existingPath = parent;
|
|
136857
137601
|
}
|
|
136858
|
-
const realExistingPath = (0,
|
|
137602
|
+
const realExistingPath = (0, import_node_fs5.realpathSync)(existingPath);
|
|
136859
137603
|
const realRelative = path3.relative(base, realExistingPath);
|
|
136860
137604
|
if (realRelative.startsWith("..") || path3.isAbsolute(realRelative)) {
|
|
136861
137605
|
throw new Error(`${fieldName} must stay within the repository root; received ${targetPath}`);
|
|
@@ -136883,8 +137627,8 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
136883
137627
|
ensureDir(specsDir);
|
|
136884
137628
|
ensureDir(".postman");
|
|
136885
137629
|
const globalsFilePath = `${globalsDir}/workspace.globals.yaml`;
|
|
136886
|
-
if (!(0,
|
|
136887
|
-
(0,
|
|
137630
|
+
if (!(0, import_node_fs5.existsSync)(globalsFilePath)) {
|
|
137631
|
+
(0, import_node_fs5.writeFileSync)(globalsFilePath, "name: Globals\nvalues: []\n");
|
|
136888
137632
|
}
|
|
136889
137633
|
if (inputs.generateCiWorkflow) {
|
|
136890
137634
|
const ciDir = inputs.ciWorkflowPath.split("/").slice(0, -1).join("/");
|
|
@@ -136900,23 +137644,42 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
136900
137644
|
inputs.specSyncMode,
|
|
136901
137645
|
options.releaseLabel
|
|
136902
137646
|
) : void 0;
|
|
136903
|
-
|
|
136904
|
-
|
|
136905
|
-
|
|
136906
|
-
|
|
136907
|
-
|
|
136908
|
-
|
|
136909
|
-
|
|
136910
|
-
|
|
136911
|
-
|
|
136912
|
-
|
|
136913
|
-
|
|
136914
|
-
|
|
136915
|
-
|
|
136916
|
-
|
|
136917
|
-
|
|
136918
|
-
|
|
136919
|
-
|
|
137647
|
+
const prebuiltByRole = options.preparedPrebuiltCollections;
|
|
137648
|
+
const baselineRef = await exportCollectionArtifact({
|
|
137649
|
+
role: "baseline",
|
|
137650
|
+
collectionId: inputs.baselineCollectionId,
|
|
137651
|
+
dirName: getCollectionDirectoryName("Baseline", assetProjectName),
|
|
137652
|
+
collectionsDir,
|
|
137653
|
+
prebuiltByRole,
|
|
137654
|
+
postman: dependencies.postman,
|
|
137655
|
+
core: dependencies.core
|
|
137656
|
+
});
|
|
137657
|
+
if (baselineRef) {
|
|
137658
|
+
manifestCollections[baselineRef] = inputs.baselineCollectionId;
|
|
137659
|
+
}
|
|
137660
|
+
const smokeRef = await exportCollectionArtifact({
|
|
137661
|
+
role: "smoke",
|
|
137662
|
+
collectionId: inputs.smokeCollectionId,
|
|
137663
|
+
dirName: getCollectionDirectoryName("Smoke", assetProjectName),
|
|
137664
|
+
collectionsDir,
|
|
137665
|
+
prebuiltByRole,
|
|
137666
|
+
postman: dependencies.postman,
|
|
137667
|
+
core: dependencies.core
|
|
137668
|
+
});
|
|
137669
|
+
if (smokeRef) {
|
|
137670
|
+
manifestCollections[smokeRef] = inputs.smokeCollectionId;
|
|
137671
|
+
}
|
|
137672
|
+
const contractRef = await exportCollectionArtifact({
|
|
137673
|
+
role: "contract",
|
|
137674
|
+
collectionId: inputs.contractCollectionId,
|
|
137675
|
+
dirName: getCollectionDirectoryName("Contract", assetProjectName),
|
|
137676
|
+
collectionsDir,
|
|
137677
|
+
prebuiltByRole,
|
|
137678
|
+
postman: dependencies.postman,
|
|
137679
|
+
core: dependencies.core
|
|
137680
|
+
});
|
|
137681
|
+
if (contractRef) {
|
|
137682
|
+
manifestCollections[contractRef] = inputs.contractCollectionId;
|
|
136920
137683
|
}
|
|
136921
137684
|
for (const [envName, envUid] of Object.entries(envUids)) {
|
|
136922
137685
|
writeJsonFile(
|
|
@@ -136931,7 +137694,7 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
136931
137694
|
workspaceLinkEnabled: inputs.workspaceLinkEnabled,
|
|
136932
137695
|
workspaceLinkStatus: options.workspaceLinkStatus
|
|
136933
137696
|
});
|
|
136934
|
-
(0,
|
|
137697
|
+
(0, import_node_fs5.writeFileSync)(".postman/resources.yaml", buildResourcesManifest(
|
|
136935
137698
|
durableWorkspaceId,
|
|
136936
137699
|
manifestCollections,
|
|
136937
137700
|
envUids,
|
|
@@ -136943,11 +137706,18 @@ async function exportArtifacts(inputs, dependencies, envUids, assetProjectName,
|
|
|
136943
137706
|
options.priorState
|
|
136944
137707
|
));
|
|
136945
137708
|
if (mappedSpec && Object.keys(manifestCollections).length > 0) {
|
|
136946
|
-
|
|
137709
|
+
let existingWorkflows;
|
|
137710
|
+
try {
|
|
137711
|
+
existingWorkflows = (0, import_node_fs5.readFileSync)(".postman/workflows.yaml", "utf8");
|
|
137712
|
+
} catch {
|
|
137713
|
+
existingWorkflows = void 0;
|
|
137714
|
+
}
|
|
137715
|
+
(0, import_node_fs5.writeFileSync)(
|
|
136947
137716
|
".postman/workflows.yaml",
|
|
136948
137717
|
buildSpecCollectionWorkflowManifest(
|
|
136949
137718
|
mappedSpec.configRelativePath,
|
|
136950
|
-
Object.keys(manifestCollections)
|
|
137719
|
+
Object.keys(manifestCollections),
|
|
137720
|
+
existingWorkflows
|
|
136951
137721
|
)
|
|
136952
137722
|
);
|
|
136953
137723
|
}
|
|
@@ -136992,12 +137762,12 @@ async function commitAndPushGeneratedFiles(inputs, dependencies) {
|
|
|
136992
137762
|
const dir = parts.slice(0, -1).join("/");
|
|
136993
137763
|
ensureDir(dir);
|
|
136994
137764
|
}
|
|
136995
|
-
(0,
|
|
137765
|
+
(0, import_node_fs5.writeFileSync)(inputs.ciWorkflowPath, ciWorkflow);
|
|
136996
137766
|
if (inputs.provider === "github" || inputs.provider === "unknown") {
|
|
136997
137767
|
const gcPath = ".github/workflows/postman-preview-gc.yml";
|
|
136998
137768
|
if (inputs.ciWorkflowPath.endsWith(".github/workflows/ci.yml") || inputs.ciWorkflowPath === ".github/workflows/ci.yml") {
|
|
136999
137769
|
ensureDir(".github/workflows");
|
|
137000
|
-
(0,
|
|
137770
|
+
(0, import_node_fs5.writeFileSync)(gcPath, renderGcWorkflowTemplate());
|
|
137001
137771
|
}
|
|
137002
137772
|
}
|
|
137003
137773
|
}
|
|
@@ -137005,16 +137775,16 @@ async function commitAndPushGeneratedFiles(inputs, dependencies) {
|
|
|
137005
137775
|
return { commitSha: "", resolvedCurrentRef: "", pushed: false };
|
|
137006
137776
|
}
|
|
137007
137777
|
const provisionPath = ".github/workflows/provision.yml";
|
|
137008
|
-
const provisionExists = inputs.provider === "github" && (0,
|
|
137778
|
+
const provisionExists = inputs.provider === "github" && (0, import_node_fs5.existsSync)(provisionPath);
|
|
137009
137779
|
const gcWorkflowPath = ".github/workflows/postman-preview-gc.yml";
|
|
137010
|
-
const gcExists = inputs.generateCiWorkflow && (0,
|
|
137780
|
+
const gcExists = inputs.generateCiWorkflow && (0, import_node_fs5.existsSync)(gcWorkflowPath);
|
|
137011
137781
|
const stagePaths = [
|
|
137012
137782
|
inputs.artifactDir,
|
|
137013
137783
|
".postman",
|
|
137014
137784
|
inputs.generateCiWorkflow ? inputs.ciWorkflowPath : null,
|
|
137015
137785
|
gcExists ? gcWorkflowPath : null,
|
|
137016
137786
|
provisionExists ? provisionPath : null
|
|
137017
|
-
].filter((entry) => typeof entry === "string" && ((0,
|
|
137787
|
+
].filter((entry) => typeof entry === "string" && ((0, import_node_fs5.existsSync)(entry) || entry === provisionPath));
|
|
137018
137788
|
if (stagePaths.length === 0) {
|
|
137019
137789
|
dependencies.core.info("No generated repository paths were found; skipping repo mutation.");
|
|
137020
137790
|
return {
|
|
@@ -137122,6 +137892,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
137122
137892
|
}
|
|
137123
137893
|
}
|
|
137124
137894
|
}
|
|
137895
|
+
const preparedPrebuiltCollections = await preparePrebuiltCollections(inputs);
|
|
137125
137896
|
let skipRepositoryLinkPost = false;
|
|
137126
137897
|
let repositoryLinkPreflightWasFree = false;
|
|
137127
137898
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
@@ -137158,6 +137929,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
137158
137929
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
137159
137930
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
137160
137931
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
137932
|
+
dependencies.core.setOutput("environment-uids-json", outputs["environment-uids-json"]);
|
|
137161
137933
|
if (inputs.environmentSyncEnabled && inputs.workspaceId && dependencies.internalIntegration) {
|
|
137162
137934
|
const associations = Object.entries(envUids).map(([envName, envUid]) => ({
|
|
137163
137935
|
envUid,
|
|
@@ -137276,6 +138048,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
137276
138048
|
}
|
|
137277
138049
|
}
|
|
137278
138050
|
outputs["mock-url"] = resolvedMockUrl;
|
|
138051
|
+
dependencies.core.setOutput("mock-url", resolvedMockUrl);
|
|
137279
138052
|
}
|
|
137280
138053
|
}
|
|
137281
138054
|
if (inputs.workspaceId && inputs.smokeCollectionId && Object.keys(envUids).length > 0) {
|
|
@@ -137351,6 +138124,7 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
137351
138124
|
}
|
|
137352
138125
|
}
|
|
137353
138126
|
outputs["monitor-id"] = resolvedMonitorId;
|
|
138127
|
+
dependencies.core.setOutput("monitor-id", resolvedMonitorId);
|
|
137354
138128
|
if (!effectiveCron && resolvedMonitorId) {
|
|
137355
138129
|
try {
|
|
137356
138130
|
await dependencies.postman.runMonitor(resolvedMonitorId);
|
|
@@ -137408,7 +138182,8 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
137408
138182
|
priorWorkspaceId: resourcesState?.workspace?.id,
|
|
137409
138183
|
existingSpecs: resourcesState?.cloudResources?.specs,
|
|
137410
138184
|
releaseLabel,
|
|
137411
|
-
priorState: resourcesState
|
|
138185
|
+
priorState: resourcesState,
|
|
138186
|
+
preparedPrebuiltCollections
|
|
137412
138187
|
});
|
|
137413
138188
|
const commit = await commitAndPushGeneratedFiles(inputs, dependencies);
|
|
137414
138189
|
outputs["commit-sha"] = commit.commitSha;
|
|
@@ -137634,7 +138409,12 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
137634
138409
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
137635
138410
|
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
137636
138411
|
// surface verbatim, not be re-fired against the /_api alias.
|
|
137637
|
-
secretMasker: masker
|
|
138412
|
+
secretMasker: masker,
|
|
138413
|
+
onRetryEvent: (event) => {
|
|
138414
|
+
actionCore.info(
|
|
138415
|
+
`[postman retry] action=repo-sync class=${event.class} status=${event.status ?? "none"} attempt=${event.attempt} delayMs=${event.delay}`
|
|
138416
|
+
);
|
|
138417
|
+
}
|
|
137638
138418
|
});
|
|
137639
138419
|
const squads = await gateway.getSquads(teamId);
|
|
137640
138420
|
if (squads.length > 0) {
|
|
@@ -137698,7 +138478,12 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
137698
138478
|
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
137699
138479
|
teamId: resolved.teamId,
|
|
137700
138480
|
orgMode: inputs.orgMode,
|
|
137701
|
-
secretMasker: masker
|
|
138481
|
+
secretMasker: masker,
|
|
138482
|
+
onRetryEvent: (event) => {
|
|
138483
|
+
factories.core.info(
|
|
138484
|
+
`[postman retry] action=repo-sync class=${event.class} status=${event.status ?? "none"} attempt=${event.attempt} delayMs=${event.delay}`
|
|
138485
|
+
);
|
|
138486
|
+
}
|
|
137702
138487
|
});
|
|
137703
138488
|
const gatewayAssets = new PostmanGatewayAssetsClient({
|
|
137704
138489
|
gateway,
|
|
@@ -137766,7 +138551,8 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
137766
138551
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
137767
138552
|
orgMode: inputs.orgMode,
|
|
137768
138553
|
teamId: resolved.teamId,
|
|
137769
|
-
secretMasker: masker
|
|
138554
|
+
secretMasker: masker,
|
|
138555
|
+
gateway
|
|
137770
138556
|
});
|
|
137771
138557
|
return {
|
|
137772
138558
|
teamId: resolved.teamId,
|
|
@@ -138180,6 +138966,7 @@ var CLI_INPUT_NAMES = [
|
|
|
138180
138966
|
"baseline-collection-id",
|
|
138181
138967
|
"smoke-collection-id",
|
|
138182
138968
|
"contract-collection-id",
|
|
138969
|
+
"prebuilt-collections-json",
|
|
138183
138970
|
"collection-sync-mode",
|
|
138184
138971
|
"spec-sync-mode",
|
|
138185
138972
|
"release-label",
|
|
@@ -138251,17 +139038,38 @@ Examples:
|
|
|
138251
139038
|
postman-repo-sync --repo-write-mode none --workspace-id <id> ...
|
|
138252
139039
|
`;
|
|
138253
139040
|
var ConsoleReporter = class {
|
|
139041
|
+
constructor(onOutput) {
|
|
139042
|
+
this.onOutput = onOutput;
|
|
139043
|
+
}
|
|
139044
|
+
onOutput;
|
|
138254
139045
|
info(message) {
|
|
138255
139046
|
console.error(message);
|
|
138256
139047
|
}
|
|
138257
139048
|
warning(message) {
|
|
138258
139049
|
console.error(`warning: ${message}`);
|
|
138259
139050
|
}
|
|
138260
|
-
|
|
139051
|
+
retryEvent(event) {
|
|
139052
|
+
this.info(
|
|
139053
|
+
`[postman retry] action=repo-sync class=${event.class} status=${event.status ?? "none"} attempt=${event.attempt} delayMs=${event.delay}`
|
|
139054
|
+
);
|
|
139055
|
+
}
|
|
139056
|
+
setOutput(name, value) {
|
|
139057
|
+
this.onOutput?.(name, value);
|
|
138261
139058
|
}
|
|
138262
139059
|
setSecret() {
|
|
138263
139060
|
}
|
|
138264
139061
|
};
|
|
139062
|
+
async function timedStage(reporter, stage, operation) {
|
|
139063
|
+
const started = performance.now();
|
|
139064
|
+
try {
|
|
139065
|
+
const result = await operation();
|
|
139066
|
+
reporter.info(`[repo-sync timing] ${JSON.stringify({ stage, ms: Math.max(0, performance.now() - started), status: "success" })}`);
|
|
139067
|
+
return result;
|
|
139068
|
+
} catch (error) {
|
|
139069
|
+
reporter.info(`[repo-sync timing] ${JSON.stringify({ stage, ms: Math.max(0, performance.now() - started), status: "error" })}`);
|
|
139070
|
+
throw error;
|
|
139071
|
+
}
|
|
139072
|
+
}
|
|
138265
139073
|
function normalizeCliFlag(name) {
|
|
138266
139074
|
return `INPUT_${name.replace(/-/g, "_").toUpperCase()}`;
|
|
138267
139075
|
}
|
|
@@ -138335,7 +139143,7 @@ function resolvePackageVersion() {
|
|
|
138335
139143
|
candidates.push(import_node_path3.default.join(process.cwd(), "package.json"));
|
|
138336
139144
|
for (const packageJsonPath of candidates) {
|
|
138337
139145
|
try {
|
|
138338
|
-
const packageJson = JSON.parse((0,
|
|
139146
|
+
const packageJson = JSON.parse((0, import_node_fs6.readFileSync)(packageJsonPath, "utf8"));
|
|
138339
139147
|
if (packageJson.name === "@postman-cse/onboarding-repo-sync" && packageJson.version) {
|
|
138340
139148
|
return String(packageJson.version).trim();
|
|
138341
139149
|
}
|
|
@@ -138446,20 +139254,107 @@ function toDotenv(outputs) {
|
|
|
138446
139254
|
String(value ?? "")
|
|
138447
139255
|
]).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
138448
139256
|
}
|
|
138449
|
-
|
|
138450
|
-
|
|
138451
|
-
return;
|
|
138452
|
-
}
|
|
138453
|
-
const workspaceRoot = import_node_path3.default.resolve(process.cwd());
|
|
139257
|
+
function assertOutputFileAllowed(filePath) {
|
|
139258
|
+
const workspaceRoot = (0, import_node_fs6.realpathSync)(import_node_path3.default.resolve(process.cwd()));
|
|
138454
139259
|
const resolved = import_node_path3.default.resolve(workspaceRoot, filePath);
|
|
138455
139260
|
const relative3 = import_node_path3.default.relative(workspaceRoot, resolved);
|
|
138456
139261
|
if (relative3.startsWith("..") || import_node_path3.default.isAbsolute(relative3)) {
|
|
138457
139262
|
throw new Error(`Output path must stay within workspace: ${filePath}`);
|
|
138458
139263
|
}
|
|
138459
|
-
|
|
139264
|
+
let existingParent = import_node_path3.default.dirname(resolved);
|
|
139265
|
+
while (!(0, import_node_fs6.existsSync)(existingParent)) {
|
|
139266
|
+
const parent = import_node_path3.default.dirname(existingParent);
|
|
139267
|
+
if (parent === existingParent) break;
|
|
139268
|
+
existingParent = parent;
|
|
139269
|
+
}
|
|
139270
|
+
const parentReal = (0, import_node_fs6.realpathSync)(existingParent);
|
|
139271
|
+
const parentRelative = import_node_path3.default.relative(workspaceRoot, parentReal);
|
|
139272
|
+
if (parentRelative.startsWith("..") || import_node_path3.default.isAbsolute(parentRelative)) {
|
|
139273
|
+
throw new Error(`Output path must stay within workspace: ${filePath}`);
|
|
139274
|
+
}
|
|
139275
|
+
if ((0, import_node_fs6.existsSync)(resolved) || (() => {
|
|
139276
|
+
try {
|
|
139277
|
+
(0, import_node_fs6.lstatSync)(resolved);
|
|
139278
|
+
return true;
|
|
139279
|
+
} catch {
|
|
139280
|
+
return false;
|
|
139281
|
+
}
|
|
139282
|
+
})()) {
|
|
139283
|
+
const targetReal = (0, import_node_fs6.realpathSync)(resolved);
|
|
139284
|
+
const targetRelative = import_node_path3.default.relative(workspaceRoot, targetReal);
|
|
139285
|
+
if (targetRelative.startsWith("..") || import_node_path3.default.isAbsolute(targetRelative)) {
|
|
139286
|
+
throw new Error(`Output path must stay within workspace: ${filePath}`);
|
|
139287
|
+
}
|
|
139288
|
+
}
|
|
139289
|
+
return { resolved, directory: import_node_path3.default.dirname(resolved) };
|
|
139290
|
+
}
|
|
139291
|
+
function resolveSymlinkAwarePath(filePath) {
|
|
139292
|
+
const workspaceRoot = (0, import_node_fs6.realpathSync)(import_node_path3.default.resolve(process.cwd()));
|
|
139293
|
+
const resolved = import_node_path3.default.resolve(workspaceRoot, filePath);
|
|
139294
|
+
let existing = resolved;
|
|
139295
|
+
while (!(0, import_node_fs6.existsSync)(existing)) {
|
|
139296
|
+
const parent = import_node_path3.default.dirname(existing);
|
|
139297
|
+
if (parent === existing) break;
|
|
139298
|
+
existing = parent;
|
|
139299
|
+
}
|
|
139300
|
+
return import_node_path3.default.resolve((0, import_node_fs6.realpathSync)(existing), import_node_path3.default.relative(existing, resolved));
|
|
139301
|
+
}
|
|
139302
|
+
function assertResultPathOutsideGeneratedPaths(resultJsonPath, inputs) {
|
|
139303
|
+
const result = assertOutputFileAllowed(resultJsonPath).resolved;
|
|
139304
|
+
const resultReal = resolveSymlinkAwarePath(result);
|
|
139305
|
+
for (const root of [inputs.artifactDir, ".postman"].map(resolveSymlinkAwarePath)) {
|
|
139306
|
+
const relative3 = import_node_path3.default.relative(root, resultReal);
|
|
139307
|
+
if (!relative3 || !relative3.startsWith("..") && !import_node_path3.default.isAbsolute(relative3)) {
|
|
139308
|
+
throw new Error(
|
|
139309
|
+
`--result-json must not overlap a generated or staged repository path: ${resultJsonPath}`
|
|
139310
|
+
);
|
|
139311
|
+
}
|
|
139312
|
+
}
|
|
139313
|
+
const generatedFiles = [];
|
|
139314
|
+
if (inputs.generateCiWorkflow) {
|
|
139315
|
+
generatedFiles.push(inputs.ciWorkflowPath);
|
|
139316
|
+
if ((inputs.provider === "github" || inputs.provider === "unknown") && (inputs.ciWorkflowPath.endsWith(".github/workflows/ci.yml") || inputs.ciWorkflowPath === ".github/workflows/ci.yml")) {
|
|
139317
|
+
generatedFiles.push(".github/workflows/postman-preview-gc.yml");
|
|
139318
|
+
}
|
|
139319
|
+
}
|
|
139320
|
+
if (inputs.provider === "github" && (0, import_node_fs6.existsSync)(".github/workflows/provision.yml")) {
|
|
139321
|
+
generatedFiles.push(".github/workflows/provision.yml");
|
|
139322
|
+
}
|
|
139323
|
+
for (const generatedFile of generatedFiles) {
|
|
139324
|
+
if (resultReal === resolveSymlinkAwarePath(generatedFile)) {
|
|
139325
|
+
throw new Error(
|
|
139326
|
+
`--result-json must not overlap a generated or staged repository path: ${resultJsonPath}`
|
|
139327
|
+
);
|
|
139328
|
+
}
|
|
139329
|
+
}
|
|
139330
|
+
}
|
|
139331
|
+
async function writeOptionalFile(filePath, content) {
|
|
139332
|
+
if (!filePath) {
|
|
139333
|
+
return;
|
|
139334
|
+
}
|
|
139335
|
+
const { resolved, directory } = assertOutputFileAllowed(filePath);
|
|
139336
|
+
await (0, import_promises.mkdir)(directory, { recursive: true });
|
|
139337
|
+
const validated = assertOutputFileAllowed(filePath);
|
|
139338
|
+
if (validated.resolved !== resolved) throw new Error(`Output path changed during validation: ${filePath}`);
|
|
138460
139339
|
await (0, import_promises.writeFile)(resolved, content, "utf8");
|
|
138461
139340
|
}
|
|
138462
|
-
function
|
|
139341
|
+
function writeOptionalFileAtomic(filePath, content) {
|
|
139342
|
+
if (!filePath) return;
|
|
139343
|
+
const { resolved, directory } = assertOutputFileAllowed(filePath);
|
|
139344
|
+
(0, import_node_fs6.mkdirSync)(directory, { recursive: true });
|
|
139345
|
+
const validated = assertOutputFileAllowed(filePath);
|
|
139346
|
+
const temporaryDirectory = (0, import_node_fs6.mkdtempSync)(
|
|
139347
|
+
import_node_path3.default.join((0, import_node_fs6.realpathSync)(validated.directory), `.${import_node_path3.default.basename(resolved)}.`)
|
|
139348
|
+
);
|
|
139349
|
+
const temporary = import_node_path3.default.join(temporaryDirectory, import_node_path3.default.basename(resolved));
|
|
139350
|
+
try {
|
|
139351
|
+
(0, import_node_fs6.writeFileSync)(temporary, content, "utf8");
|
|
139352
|
+
(0, import_node_fs6.renameSync)(temporary, resolved);
|
|
139353
|
+
} finally {
|
|
139354
|
+
(0, import_node_fs6.rmSync)(temporaryDirectory, { recursive: true, force: true });
|
|
139355
|
+
}
|
|
139356
|
+
}
|
|
139357
|
+
function createCliDependencies(inputs, resolved, reporter = new ConsoleReporter()) {
|
|
138463
139358
|
const secretMasker = createSecretMasker([
|
|
138464
139359
|
resolved.apiKey,
|
|
138465
139360
|
inputs.postmanAccessToken,
|
|
@@ -138476,7 +139371,7 @@ function createCliDependencies(inputs, resolved) {
|
|
|
138476
139371
|
inputs,
|
|
138477
139372
|
resolved,
|
|
138478
139373
|
{
|
|
138479
|
-
core:
|
|
139374
|
+
core: reporter,
|
|
138480
139375
|
exec: cliExec
|
|
138481
139376
|
},
|
|
138482
139377
|
{
|
|
@@ -138506,17 +139401,24 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
138506
139401
|
}
|
|
138507
139402
|
const config = parseCliArgs(argv, env);
|
|
138508
139403
|
const inputs = resolveInputs(config.inputEnv);
|
|
138509
|
-
const reporter = new ConsoleReporter();
|
|
138510
139404
|
const branchDecision = decideBranchTier(inputs, config.inputEnv);
|
|
139405
|
+
if (branchDecision.tier !== "gated") {
|
|
139406
|
+
assertResultPathOutsideGeneratedPaths(config.resultJsonPath, inputs);
|
|
139407
|
+
}
|
|
139408
|
+
const partialOutputs = {};
|
|
139409
|
+
const reporter = new ConsoleReporter((name, value) => {
|
|
139410
|
+
partialOutputs[name] = String(value ?? "");
|
|
139411
|
+
writeOptionalFileAtomic(config.resultJsonPath, JSON.stringify(partialOutputs, null, 2));
|
|
139412
|
+
});
|
|
138511
139413
|
if (branchDecision.tier === "gated") {
|
|
138512
139414
|
const result2 = runGatedSkip(inputs, branchDecision, reporter);
|
|
138513
|
-
|
|
139415
|
+
writeOptionalFileAtomic(config.resultJsonPath, JSON.stringify(result2, null, 2));
|
|
138514
139416
|
await writeOptionalFile(config.dotenvPath, toDotenv(result2));
|
|
138515
139417
|
writeStdout(`${JSON.stringify(result2, null, 2)}
|
|
138516
139418
|
`);
|
|
138517
139419
|
return;
|
|
138518
139420
|
}
|
|
138519
|
-
await mintAccessTokenIfNeeded(inputs, reporter);
|
|
139421
|
+
await timedStage(reporter, "access-token mint", () => mintAccessTokenIfNeeded(inputs, reporter));
|
|
138520
139422
|
const initialMasker = createSecretMasker([
|
|
138521
139423
|
inputs.postmanApiKey,
|
|
138522
139424
|
inputs.postmanAccessToken,
|
|
@@ -138528,7 +139430,7 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
138528
139430
|
inputs.sslClientPassphrase,
|
|
138529
139431
|
inputs.sslExtraCaCerts
|
|
138530
139432
|
]);
|
|
138531
|
-
await runCredentialPreflight({
|
|
139433
|
+
await timedStage(reporter, "credential preflight", () => runCredentialPreflight({
|
|
138532
139434
|
apiBaseUrl: inputs.postmanApiBase,
|
|
138533
139435
|
iapubBaseUrl: inputs.postmanIapubBase,
|
|
138534
139436
|
postmanApiKey: inputs.postmanApiKey,
|
|
@@ -138537,9 +139439,9 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
138537
139439
|
mode: inputs.credentialPreflight,
|
|
138538
139440
|
mask: initialMasker,
|
|
138539
139441
|
log: reporter
|
|
138540
|
-
});
|
|
139442
|
+
}));
|
|
138541
139443
|
const resolvingExec = createCliExec(initialMasker);
|
|
138542
|
-
const resolved = await resolvePostmanApiKeyAndTeamId(
|
|
139444
|
+
const resolved = await timedStage(reporter, "API-key/team resolution", () => resolvePostmanApiKeyAndTeamId(
|
|
138543
139445
|
inputs,
|
|
138544
139446
|
reporter,
|
|
138545
139447
|
resolvingExec,
|
|
@@ -138548,8 +139450,8 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
138548
139450
|
persistGeneratedApiKeySecret: false,
|
|
138549
139451
|
env
|
|
138550
139452
|
}
|
|
138551
|
-
);
|
|
138552
|
-
const dependencies = createCliDependencies(inputs, resolved);
|
|
139453
|
+
));
|
|
139454
|
+
const dependencies = createCliDependencies(inputs, resolved, reporter);
|
|
138553
139455
|
if (inputs.environmentSyncEnabled && !dependencies.internalIntegration) {
|
|
138554
139456
|
dependencies.core.warning(
|
|
138555
139457
|
"Skipping system environment association because postman-access-token is not configured"
|
|
@@ -138560,8 +139462,12 @@ async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
138560
139462
|
"Skipping workspace linking because postman-access-token is not configured"
|
|
138561
139463
|
);
|
|
138562
139464
|
}
|
|
138563
|
-
const result = await (
|
|
138564
|
-
|
|
139465
|
+
const result = await timedStage(
|
|
139466
|
+
reporter,
|
|
139467
|
+
"runRepoSync finalize",
|
|
139468
|
+
() => (runtime.executeRepoSync ?? runRepoSync)(inputs, dependencies)
|
|
139469
|
+
);
|
|
139470
|
+
writeOptionalFileAtomic(config.resultJsonPath, JSON.stringify(result, null, 2));
|
|
138565
139471
|
await writeOptionalFile(config.dotenvPath, toDotenv(result));
|
|
138566
139472
|
writeStdout(`${JSON.stringify(result, null, 2)}
|
|
138567
139473
|
`);
|
|
@@ -138647,7 +139553,7 @@ function isEntrypoint(currentPath, entrypointPath) {
|
|
|
138647
139553
|
return false;
|
|
138648
139554
|
}
|
|
138649
139555
|
try {
|
|
138650
|
-
return (0,
|
|
139556
|
+
return (0, import_node_fs6.realpathSync)(currentPath) === (0, import_node_fs6.realpathSync)(entrypointPath);
|
|
138651
139557
|
} catch {
|
|
138652
139558
|
return import_node_path3.default.resolve(currentPath) === import_node_path3.default.resolve(entrypointPath);
|
|
138653
139559
|
}
|
|
@@ -138668,7 +139574,8 @@ if (isEntrypoint(currentModulePath, entrypoint)) {
|
|
|
138668
139574
|
normalizeCliFlag,
|
|
138669
139575
|
parseCliArgs,
|
|
138670
139576
|
runCli,
|
|
138671
|
-
toDotenv
|
|
139577
|
+
toDotenv,
|
|
139578
|
+
writeOptionalFileAtomic
|
|
138672
139579
|
});
|
|
138673
139580
|
/*! Bundled license information:
|
|
138674
139581
|
|