@postman-cse/onboarding-repo-sync 2.1.6 → 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action.cjs +281 -47
- package/dist/cli.cjs +281 -47
- package/dist/index.cjs +281 -47
- package/package.json +1 -1
package/dist/action.cjs
CHANGED
|
@@ -125114,12 +125114,14 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125114
125114
|
prod: {
|
|
125115
125115
|
apiBaseUrl: "https://api.getpostman.com",
|
|
125116
125116
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125117
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125117
125118
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125118
125119
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125119
125120
|
},
|
|
125120
125121
|
beta: {
|
|
125121
125122
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
125122
125123
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125124
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125123
125125
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125124
125126
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125125
125127
|
}
|
|
@@ -126893,7 +126895,85 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126893
126895
|
throw advised ?? httpErr;
|
|
126894
126896
|
}
|
|
126895
126897
|
}
|
|
126896
|
-
|
|
126898
|
+
/**
|
|
126899
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
126900
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
126901
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
126902
|
+
*
|
|
126903
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
126904
|
+
* - 200 + data null -> free
|
|
126905
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
126906
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
126907
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
126908
|
+
*/
|
|
126909
|
+
async findWorkspaceForRepo(repoUrl, path9 = "/") {
|
|
126910
|
+
const fsPath = path9 && path9.trim() ? path9.trim() : "/";
|
|
126911
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126912
|
+
const payload = {
|
|
126913
|
+
service: "workspaces",
|
|
126914
|
+
method: "GET",
|
|
126915
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
126916
|
+
};
|
|
126917
|
+
try {
|
|
126918
|
+
const response = await this.fetchImpl(url, {
|
|
126919
|
+
method: "POST",
|
|
126920
|
+
headers: this.bifrostHeaders(),
|
|
126921
|
+
body: JSON.stringify(payload)
|
|
126922
|
+
});
|
|
126923
|
+
let parsed = {};
|
|
126924
|
+
try {
|
|
126925
|
+
parsed = await response.json();
|
|
126926
|
+
} catch {
|
|
126927
|
+
return {
|
|
126928
|
+
state: "unknown",
|
|
126929
|
+
reason: `filesystem lookup returned non-JSON body (HTTP ${response.status})`
|
|
126930
|
+
};
|
|
126931
|
+
}
|
|
126932
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
126933
|
+
if (errorMetaWorkspaceId) {
|
|
126934
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
126935
|
+
}
|
|
126936
|
+
if (response.ok) {
|
|
126937
|
+
if (parsed?.data == null) {
|
|
126938
|
+
return { state: "free" };
|
|
126939
|
+
}
|
|
126940
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
126941
|
+
if (!id) {
|
|
126942
|
+
return {
|
|
126943
|
+
state: "unknown",
|
|
126944
|
+
reason: "filesystem lookup returned 200 without a workspace id"
|
|
126945
|
+
};
|
|
126946
|
+
}
|
|
126947
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
126948
|
+
return {
|
|
126949
|
+
state: "linked-visible",
|
|
126950
|
+
workspace: name ? { id, name } : { id }
|
|
126951
|
+
};
|
|
126952
|
+
}
|
|
126953
|
+
if (response.status === 403) {
|
|
126954
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
126955
|
+
JSON.stringify(parsed)
|
|
126956
|
+
);
|
|
126957
|
+
if (workspaceId) {
|
|
126958
|
+
return { state: "linked-invisible", workspaceId };
|
|
126959
|
+
}
|
|
126960
|
+
return {
|
|
126961
|
+
state: "unknown",
|
|
126962
|
+
reason: "filesystem lookup returned 403 without error.meta.workspaceId"
|
|
126963
|
+
};
|
|
126964
|
+
}
|
|
126965
|
+
return {
|
|
126966
|
+
state: "unknown",
|
|
126967
|
+
reason: `filesystem lookup returned HTTP ${response.status}`
|
|
126968
|
+
};
|
|
126969
|
+
} catch (error2) {
|
|
126970
|
+
return {
|
|
126971
|
+
state: "unknown",
|
|
126972
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
126973
|
+
};
|
|
126974
|
+
}
|
|
126975
|
+
}
|
|
126976
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
126897
126977
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126898
126978
|
const payload = {
|
|
126899
126979
|
service: "workspaces",
|
|
@@ -126920,6 +127000,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126920
127000
|
if (isDuplicate) {
|
|
126921
127001
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126922
127002
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
127003
|
+
if (options?.preflightWasFree) {
|
|
127004
|
+
throw new Error(
|
|
127005
|
+
`REPOSITORY_LINK_CONFLICT_UNRESOLVED: Preflight found no active owner, but link creation reported workspace ${existingWorkspaceId}. Stop and contact Postman support; do not alter the repository URL.`
|
|
127006
|
+
);
|
|
127007
|
+
}
|
|
126923
127008
|
throw new Error(
|
|
126924
127009
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126925
127010
|
);
|
|
@@ -127587,6 +127672,14 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127587
127672
|
createFlights.set(key, { fingerprint, promise: pending });
|
|
127588
127673
|
return pending;
|
|
127589
127674
|
}
|
|
127675
|
+
/**
|
|
127676
|
+
* Reconcile an ambiguous create. Returns the adopted match, `undefined`
|
|
127677
|
+
* when every discovery read succeeded and found nothing (the create is
|
|
127678
|
+
* conclusively absent, so a fallback resend cannot duplicate), or `null`
|
|
127679
|
+
* when the outcome is inconclusive (non-ambiguous error, or a discovery
|
|
127680
|
+
* read itself failed — in that case a resend could duplicate a committed
|
|
127681
|
+
* twin and must not fire).
|
|
127682
|
+
*/
|
|
127590
127683
|
async discoverAfterAmbiguousCreate(discover, error2) {
|
|
127591
127684
|
if (!this.isAmbiguousCreateOutcome(error2)) {
|
|
127592
127685
|
return null;
|
|
@@ -127595,12 +127688,31 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127595
127688
|
if (attempt > 0) {
|
|
127596
127689
|
await this.sleep(this.reconcileDelayMs);
|
|
127597
127690
|
}
|
|
127598
|
-
|
|
127691
|
+
let found;
|
|
127692
|
+
try {
|
|
127693
|
+
found = await discover();
|
|
127694
|
+
} catch {
|
|
127695
|
+
return null;
|
|
127696
|
+
}
|
|
127599
127697
|
if (found) {
|
|
127600
127698
|
return found;
|
|
127601
127699
|
}
|
|
127602
127700
|
}
|
|
127603
|
-
return
|
|
127701
|
+
return void 0;
|
|
127702
|
+
}
|
|
127703
|
+
/**
|
|
127704
|
+
* After an ambiguous create failed AND discovery proved the asset absent,
|
|
127705
|
+
* re-attempt the create once with the cold `/_api` fallback enabled: the
|
|
127706
|
+
* reconcile above guarantees no committed twin, so the resend cannot
|
|
127707
|
+
* duplicate. Returns null when the resend also fails (caller rethrows the
|
|
127708
|
+
* original error).
|
|
127709
|
+
*/
|
|
127710
|
+
async resendAbsentCreate(operation) {
|
|
127711
|
+
try {
|
|
127712
|
+
return await operation();
|
|
127713
|
+
} catch {
|
|
127714
|
+
return null;
|
|
127715
|
+
}
|
|
127604
127716
|
}
|
|
127605
127717
|
publicEnvironmentUid(data, bareId) {
|
|
127606
127718
|
const owner = String(data?.owner ?? "").trim();
|
|
@@ -127648,17 +127760,18 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127648
127760
|
name: envName,
|
|
127649
127761
|
values: normalizedValues
|
|
127650
127762
|
};
|
|
127763
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127764
|
+
{
|
|
127765
|
+
service: "sync",
|
|
127766
|
+
method: "post",
|
|
127767
|
+
path: `/environment/import?workspace=${ws}`,
|
|
127768
|
+
body,
|
|
127769
|
+
...fallback ? { fallback } : {}
|
|
127770
|
+
},
|
|
127771
|
+
{ retryTransient: false }
|
|
127772
|
+
);
|
|
127651
127773
|
try {
|
|
127652
|
-
const
|
|
127653
|
-
{
|
|
127654
|
-
service: "sync",
|
|
127655
|
-
method: "post",
|
|
127656
|
-
path: `/environment/import?workspace=${ws}`,
|
|
127657
|
-
body
|
|
127658
|
-
},
|
|
127659
|
-
{ retryTransient: false }
|
|
127660
|
-
);
|
|
127661
|
-
const data = this.dataOf(response);
|
|
127774
|
+
const data = this.dataOf(await send2());
|
|
127662
127775
|
const bareId = this.idOf(data);
|
|
127663
127776
|
if (!bareId) {
|
|
127664
127777
|
throw new Error("Environment import did not return a UID");
|
|
@@ -127673,6 +127786,15 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127673
127786
|
await this.updateEnvironment(adopted, envName, values);
|
|
127674
127787
|
return adopted;
|
|
127675
127788
|
}
|
|
127789
|
+
if (adopted === void 0) {
|
|
127790
|
+
const retried = await this.resendAbsentCreate(async () => {
|
|
127791
|
+
const data = this.dataOf(await send2("auto"));
|
|
127792
|
+
const bareId = this.idOf(data);
|
|
127793
|
+
if (!bareId) throw new Error("Environment import did not return a UID");
|
|
127794
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
127795
|
+
});
|
|
127796
|
+
if (retried) return retried;
|
|
127797
|
+
}
|
|
127676
127798
|
throw error2;
|
|
127677
127799
|
}
|
|
127678
127800
|
});
|
|
@@ -127804,19 +127926,20 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127804
127926
|
private: false,
|
|
127805
127927
|
...environment ? { environment } : {}
|
|
127806
127928
|
};
|
|
127807
|
-
|
|
127808
|
-
|
|
127809
|
-
|
|
127810
|
-
|
|
127811
|
-
|
|
127812
|
-
|
|
127813
|
-
|
|
127814
|
-
|
|
127815
|
-
|
|
127816
|
-
|
|
127817
|
-
|
|
127818
|
-
|
|
127819
|
-
|
|
127929
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127930
|
+
{
|
|
127931
|
+
service: "mock",
|
|
127932
|
+
method: "post",
|
|
127933
|
+
path: `/mocks?workspace=${ws}`,
|
|
127934
|
+
body,
|
|
127935
|
+
...fallback ? { fallback } : {}
|
|
127936
|
+
},
|
|
127937
|
+
// Unsafe create: never blind re-POST. An ESOCKETTIMEDOUT after accept
|
|
127938
|
+
// may still have created the mock; reconcile via discovery below and
|
|
127939
|
+
// let the orchestrator retry the whole create-or-adopt cycle.
|
|
127940
|
+
{ retryTransient: false }
|
|
127941
|
+
);
|
|
127942
|
+
const parseMock = (response) => {
|
|
127820
127943
|
const record = this.dataOf(response);
|
|
127821
127944
|
const uid = this.idOf(record);
|
|
127822
127945
|
if (!uid) {
|
|
@@ -127826,6 +127949,9 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127826
127949
|
uid,
|
|
127827
127950
|
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
127828
127951
|
};
|
|
127952
|
+
};
|
|
127953
|
+
try {
|
|
127954
|
+
return parseMock(await send2());
|
|
127829
127955
|
} catch (error2) {
|
|
127830
127956
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127831
127957
|
() => this.findMockByCollection(collection, environment, mockName),
|
|
@@ -127834,6 +127960,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127834
127960
|
if (adopted) {
|
|
127835
127961
|
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
127836
127962
|
}
|
|
127963
|
+
if (adopted === void 0) {
|
|
127964
|
+
const retried = await this.resendAbsentCreate(async () => parseMock(await send2("auto")));
|
|
127965
|
+
if (retried) return retried;
|
|
127966
|
+
}
|
|
127837
127967
|
throw error2;
|
|
127838
127968
|
}
|
|
127839
127969
|
});
|
|
@@ -127940,21 +128070,25 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127940
128070
|
distribution: null,
|
|
127941
128071
|
...environment ? { environment } : {}
|
|
127942
128072
|
};
|
|
127943
|
-
|
|
127944
|
-
|
|
127945
|
-
|
|
127946
|
-
|
|
127947
|
-
|
|
127948
|
-
|
|
127949
|
-
|
|
127950
|
-
|
|
127951
|
-
|
|
127952
|
-
|
|
128073
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
128074
|
+
{
|
|
128075
|
+
service: "monitors",
|
|
128076
|
+
method: "post",
|
|
128077
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
128078
|
+
body,
|
|
128079
|
+
...fallback ? { fallback } : {}
|
|
128080
|
+
},
|
|
128081
|
+
{ retryTransient: false }
|
|
128082
|
+
);
|
|
128083
|
+
const parseMonitor = (response) => {
|
|
127953
128084
|
const uid = this.idOf(this.dataOf(response));
|
|
127954
128085
|
if (!uid) {
|
|
127955
128086
|
throw new Error("Monitor create did not return a UID");
|
|
127956
128087
|
}
|
|
127957
128088
|
return uid;
|
|
128089
|
+
};
|
|
128090
|
+
try {
|
|
128091
|
+
return parseMonitor(await send2());
|
|
127958
128092
|
} catch (error2) {
|
|
127959
128093
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127960
128094
|
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
@@ -127963,6 +128097,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127963
128097
|
if (adopted?.uid) {
|
|
127964
128098
|
return adopted.uid;
|
|
127965
128099
|
}
|
|
128100
|
+
if (adopted === void 0) {
|
|
128101
|
+
const retried = await this.resendAbsentCreate(async () => parseMonitor(await send2("auto")));
|
|
128102
|
+
if (retried) return retried;
|
|
128103
|
+
}
|
|
127966
128104
|
throw error2;
|
|
127967
128105
|
}
|
|
127968
128106
|
});
|
|
@@ -128191,6 +128329,7 @@ var AccessTokenGatewayClient = class {
|
|
|
128191
128329
|
fetchImpl;
|
|
128192
128330
|
secretMasker;
|
|
128193
128331
|
maxRetries;
|
|
128332
|
+
fallbackBaseUrl;
|
|
128194
128333
|
retryBaseDelayMs;
|
|
128195
128334
|
sleepImpl;
|
|
128196
128335
|
constructor(options) {
|
|
@@ -128203,6 +128342,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128203
128342
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
128204
128343
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
128205
128344
|
this.maxRetries = options.maxRetries ?? 3;
|
|
128345
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
128346
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
128206
128347
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
128207
128348
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
128208
128349
|
}
|
|
@@ -128221,8 +128362,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128221
128362
|
}
|
|
128222
128363
|
return headers;
|
|
128223
128364
|
}
|
|
128224
|
-
async send(request) {
|
|
128225
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
128365
|
+
async send(request, baseUrl) {
|
|
128366
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
128226
128367
|
return this.fetchImpl(url, {
|
|
128227
128368
|
method: "POST",
|
|
128228
128369
|
headers: this.buildHeaders(request.headers),
|
|
@@ -128235,6 +128376,43 @@ var AccessTokenGatewayClient = class {
|
|
|
128235
128376
|
})
|
|
128236
128377
|
});
|
|
128237
128378
|
}
|
|
128379
|
+
/**
|
|
128380
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
128381
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
128382
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
128383
|
+
* with `retryTransient: false` still reconcile first — the fallback attempt
|
|
128384
|
+
* here is the resend, so it is only used for requests whose mutation is
|
|
128385
|
+
* known idempotent or already reconciled by the caller's adopt-on-ambiguous
|
|
128386
|
+
* loop.
|
|
128387
|
+
*/
|
|
128388
|
+
async tryFallback(request) {
|
|
128389
|
+
if (!this.fallbackBaseUrl) return null;
|
|
128390
|
+
try {
|
|
128391
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
128392
|
+
} catch {
|
|
128393
|
+
return null;
|
|
128394
|
+
}
|
|
128395
|
+
}
|
|
128396
|
+
/**
|
|
128397
|
+
* Run the fallback attempt and classify its response the same way the
|
|
128398
|
+
* primary path would. Returns the success response, or null when the
|
|
128399
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
128400
|
+
* Non-transient fallback failures (4xx) surface as their own HttpError since
|
|
128401
|
+
* they are the freshest authoritative answer.
|
|
128402
|
+
*/
|
|
128403
|
+
fallbackEligible(request, retryTransient) {
|
|
128404
|
+
if (!this.fallbackBaseUrl) return false;
|
|
128405
|
+
return retryTransient || request.fallback === "auto";
|
|
128406
|
+
}
|
|
128407
|
+
async attemptFallback(request, retryTransient) {
|
|
128408
|
+
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
128409
|
+
const response = await this.tryFallback(request);
|
|
128410
|
+
if (!response) return null;
|
|
128411
|
+
if (response.ok) return response;
|
|
128412
|
+
const body = await response.text().catch(() => "");
|
|
128413
|
+
if (isRetryableSafeReadResponse(response.status)) return null;
|
|
128414
|
+
throw this.toHttpError(request, response, body);
|
|
128415
|
+
}
|
|
128238
128416
|
/**
|
|
128239
128417
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
128240
128418
|
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
@@ -128257,6 +128435,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128257
128435
|
await this.sleepImpl(delay);
|
|
128258
128436
|
continue;
|
|
128259
128437
|
}
|
|
128438
|
+
const fallbackResponse2 = await this.attemptFallback(request, retryTransient);
|
|
128439
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
128260
128440
|
throw error2;
|
|
128261
128441
|
}
|
|
128262
128442
|
if (response.ok) {
|
|
@@ -128278,6 +128458,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128278
128458
|
await this.sleepImpl(delay);
|
|
128279
128459
|
continue;
|
|
128280
128460
|
}
|
|
128461
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
128462
|
+
if (fallbackResponse) return fallbackResponse;
|
|
128281
128463
|
throw this.toHttpError(request, response, body);
|
|
128282
128464
|
}
|
|
128283
128465
|
}
|
|
@@ -128904,6 +129086,7 @@ function resolveInputs(env = process.env) {
|
|
|
128904
129086
|
postmanStack,
|
|
128905
129087
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
128906
129088
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129089
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
128907
129090
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
128908
129091
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
128909
129092
|
};
|
|
@@ -129748,6 +129931,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129748
129931
|
}
|
|
129749
129932
|
}
|
|
129750
129933
|
}
|
|
129934
|
+
let skipRepositoryLinkPost = false;
|
|
129935
|
+
let repositoryLinkPreflightWasFree = false;
|
|
129936
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
129937
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
129938
|
+
inputs.repoUrl,
|
|
129939
|
+
"/"
|
|
129940
|
+
);
|
|
129941
|
+
if (probe.state === "linked-visible") {
|
|
129942
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
129943
|
+
skipRepositoryLinkPost = true;
|
|
129944
|
+
dependencies.core.info(
|
|
129945
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
129946
|
+
);
|
|
129947
|
+
} else {
|
|
129948
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
129949
|
+
throw new Error(
|
|
129950
|
+
`REPOSITORY_LINK_CONFLICT_VISIBLE: Repository ${inputs.repoUrl} at path / is already linked to workspace ${probe.workspace.id} ("${ownerName}"). No Postman assets were changed. Reuse that workspace or disconnect it in Workspace Settings, then rerun.`
|
|
129951
|
+
);
|
|
129952
|
+
}
|
|
129953
|
+
} else if (probe.state === "linked-invisible") {
|
|
129954
|
+
let message = `REPOSITORY_LINK_CONFLICT_INVISIBLE: Repository ${inputs.repoUrl} at path / is linked to workspace ${probe.workspaceId}, but these credentials cannot view it. No Postman assets were changed. Ask its owner or a team admin to disconnect it.`;
|
|
129955
|
+
if (inputs.orgMode) {
|
|
129956
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
129957
|
+
}
|
|
129958
|
+
throw new Error(message);
|
|
129959
|
+
} else if (probe.state === "free") {
|
|
129960
|
+
repositoryLinkPreflightWasFree = true;
|
|
129961
|
+
} else {
|
|
129962
|
+
dependencies.core.warning(
|
|
129963
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
129964
|
+
);
|
|
129965
|
+
}
|
|
129966
|
+
}
|
|
129751
129967
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129752
129968
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129753
129969
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -129880,18 +130096,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129880
130096
|
}
|
|
129881
130097
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
129882
130098
|
try {
|
|
129883
|
-
|
|
129884
|
-
|
|
129885
|
-
|
|
129886
|
-
|
|
129887
|
-
|
|
129888
|
-
|
|
129889
|
-
|
|
129890
|
-
|
|
130099
|
+
if (skipRepositoryLinkPost) {
|
|
130100
|
+
outputs["workspace-link-status"] = "success";
|
|
130101
|
+
dependencies.core.info(
|
|
130102
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
130103
|
+
);
|
|
130104
|
+
} else {
|
|
130105
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
130106
|
+
inputs.workspaceId,
|
|
130107
|
+
inputs.repoUrl,
|
|
130108
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
130109
|
+
);
|
|
130110
|
+
outputs["workspace-link-status"] = "success";
|
|
130111
|
+
dependencies.core.info(
|
|
130112
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
130113
|
+
);
|
|
130114
|
+
}
|
|
129891
130115
|
} catch (error2) {
|
|
129892
130116
|
outputs["workspace-link-status"] = "failed";
|
|
129893
|
-
const
|
|
130117
|
+
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
130118
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
130119
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
130120
|
+
);
|
|
130121
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
129894
130122
|
if (branchDecision.tier === "canonical") {
|
|
130123
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130124
|
+
throw error2;
|
|
130125
|
+
}
|
|
129895
130126
|
throw new Error(message, { cause: error2 });
|
|
129896
130127
|
}
|
|
129897
130128
|
dependencies.core.warning(message);
|
|
@@ -130045,6 +130276,8 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130045
130276
|
const gateway = new AccessTokenGatewayClient({
|
|
130046
130277
|
tokenProvider,
|
|
130047
130278
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130279
|
+
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
130280
|
+
// surface verbatim, not be re-fired against the /_api alias.
|
|
130048
130281
|
secretMasker: masker
|
|
130049
130282
|
});
|
|
130050
130283
|
const squads = await gateway.getSquads(teamId);
|
|
@@ -130100,6 +130333,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130100
130333
|
const gateway = new AccessTokenGatewayClient({
|
|
130101
130334
|
tokenProvider,
|
|
130102
130335
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130336
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
130103
130337
|
teamId: resolved.teamId,
|
|
130104
130338
|
orgMode: inputs.orgMode,
|
|
130105
130339
|
secretMasker: masker
|