@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/index.cjs
CHANGED
|
@@ -125134,12 +125134,14 @@ var POSTMAN_ENDPOINT_PROFILES = {
|
|
|
125134
125134
|
prod: {
|
|
125135
125135
|
apiBaseUrl: "https://api.getpostman.com",
|
|
125136
125136
|
bifrostBaseUrl: "https://bifrost-premium-https-v4.gw.postman.com",
|
|
125137
|
+
fallbackBaseUrl: "https://go.postman.co/_api",
|
|
125137
125138
|
cliInstallUrl: "https://dl-cli.pstmn.io/install/unix.sh",
|
|
125138
125139
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125139
125140
|
},
|
|
125140
125141
|
beta: {
|
|
125141
125142
|
apiBaseUrl: "https://api.getpostman-beta.com",
|
|
125142
125143
|
bifrostBaseUrl: "https://bifrost-https-v4.gw.postman-beta.com",
|
|
125144
|
+
fallbackBaseUrl: "https://go.postman-beta.co/_api",
|
|
125143
125145
|
cliInstallUrl: "https://dl-cli.pstmn-beta.io/install/unix.sh",
|
|
125144
125146
|
iapubBaseUrl: "https://iapub.postman.co"
|
|
125145
125147
|
}
|
|
@@ -126913,7 +126915,85 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126913
126915
|
throw advised ?? httpErr;
|
|
126914
126916
|
}
|
|
126915
126917
|
}
|
|
126916
|
-
|
|
126918
|
+
/**
|
|
126919
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
126920
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
126921
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
126922
|
+
*
|
|
126923
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
126924
|
+
* - 200 + data null -> free
|
|
126925
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
126926
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
126927
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
126928
|
+
*/
|
|
126929
|
+
async findWorkspaceForRepo(repoUrl, path9 = "/") {
|
|
126930
|
+
const fsPath = path9 && path9.trim() ? path9.trim() : "/";
|
|
126931
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126932
|
+
const payload = {
|
|
126933
|
+
service: "workspaces",
|
|
126934
|
+
method: "GET",
|
|
126935
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
126936
|
+
};
|
|
126937
|
+
try {
|
|
126938
|
+
const response = await this.fetchImpl(url, {
|
|
126939
|
+
method: "POST",
|
|
126940
|
+
headers: this.bifrostHeaders(),
|
|
126941
|
+
body: JSON.stringify(payload)
|
|
126942
|
+
});
|
|
126943
|
+
let parsed = {};
|
|
126944
|
+
try {
|
|
126945
|
+
parsed = await response.json();
|
|
126946
|
+
} catch {
|
|
126947
|
+
return {
|
|
126948
|
+
state: "unknown",
|
|
126949
|
+
reason: `filesystem lookup returned non-JSON body (HTTP ${response.status})`
|
|
126950
|
+
};
|
|
126951
|
+
}
|
|
126952
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
126953
|
+
if (errorMetaWorkspaceId) {
|
|
126954
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
126955
|
+
}
|
|
126956
|
+
if (response.ok) {
|
|
126957
|
+
if (parsed?.data == null) {
|
|
126958
|
+
return { state: "free" };
|
|
126959
|
+
}
|
|
126960
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
126961
|
+
if (!id) {
|
|
126962
|
+
return {
|
|
126963
|
+
state: "unknown",
|
|
126964
|
+
reason: "filesystem lookup returned 200 without a workspace id"
|
|
126965
|
+
};
|
|
126966
|
+
}
|
|
126967
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
126968
|
+
return {
|
|
126969
|
+
state: "linked-visible",
|
|
126970
|
+
workspace: name ? { id, name } : { id }
|
|
126971
|
+
};
|
|
126972
|
+
}
|
|
126973
|
+
if (response.status === 403) {
|
|
126974
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
126975
|
+
JSON.stringify(parsed)
|
|
126976
|
+
);
|
|
126977
|
+
if (workspaceId) {
|
|
126978
|
+
return { state: "linked-invisible", workspaceId };
|
|
126979
|
+
}
|
|
126980
|
+
return {
|
|
126981
|
+
state: "unknown",
|
|
126982
|
+
reason: "filesystem lookup returned 403 without error.meta.workspaceId"
|
|
126983
|
+
};
|
|
126984
|
+
}
|
|
126985
|
+
return {
|
|
126986
|
+
state: "unknown",
|
|
126987
|
+
reason: `filesystem lookup returned HTTP ${response.status}`
|
|
126988
|
+
};
|
|
126989
|
+
} catch (error2) {
|
|
126990
|
+
return {
|
|
126991
|
+
state: "unknown",
|
|
126992
|
+
reason: error2 instanceof Error ? error2.message : String(error2)
|
|
126993
|
+
};
|
|
126994
|
+
}
|
|
126995
|
+
}
|
|
126996
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
126917
126997
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126918
126998
|
const payload = {
|
|
126919
126999
|
service: "workspaces",
|
|
@@ -126940,6 +127020,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126940
127020
|
if (isDuplicate) {
|
|
126941
127021
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126942
127022
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
127023
|
+
if (options?.preflightWasFree) {
|
|
127024
|
+
throw new Error(
|
|
127025
|
+
`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.`
|
|
127026
|
+
);
|
|
127027
|
+
}
|
|
126943
127028
|
throw new Error(
|
|
126944
127029
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126945
127030
|
);
|
|
@@ -127607,6 +127692,14 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127607
127692
|
createFlights.set(key, { fingerprint, promise: pending });
|
|
127608
127693
|
return pending;
|
|
127609
127694
|
}
|
|
127695
|
+
/**
|
|
127696
|
+
* Reconcile an ambiguous create. Returns the adopted match, `undefined`
|
|
127697
|
+
* when every discovery read succeeded and found nothing (the create is
|
|
127698
|
+
* conclusively absent, so a fallback resend cannot duplicate), or `null`
|
|
127699
|
+
* when the outcome is inconclusive (non-ambiguous error, or a discovery
|
|
127700
|
+
* read itself failed — in that case a resend could duplicate a committed
|
|
127701
|
+
* twin and must not fire).
|
|
127702
|
+
*/
|
|
127610
127703
|
async discoverAfterAmbiguousCreate(discover, error2) {
|
|
127611
127704
|
if (!this.isAmbiguousCreateOutcome(error2)) {
|
|
127612
127705
|
return null;
|
|
@@ -127615,12 +127708,31 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127615
127708
|
if (attempt > 0) {
|
|
127616
127709
|
await this.sleep(this.reconcileDelayMs);
|
|
127617
127710
|
}
|
|
127618
|
-
|
|
127711
|
+
let found;
|
|
127712
|
+
try {
|
|
127713
|
+
found = await discover();
|
|
127714
|
+
} catch {
|
|
127715
|
+
return null;
|
|
127716
|
+
}
|
|
127619
127717
|
if (found) {
|
|
127620
127718
|
return found;
|
|
127621
127719
|
}
|
|
127622
127720
|
}
|
|
127623
|
-
return
|
|
127721
|
+
return void 0;
|
|
127722
|
+
}
|
|
127723
|
+
/**
|
|
127724
|
+
* After an ambiguous create failed AND discovery proved the asset absent,
|
|
127725
|
+
* re-attempt the create once with the cold `/_api` fallback enabled: the
|
|
127726
|
+
* reconcile above guarantees no committed twin, so the resend cannot
|
|
127727
|
+
* duplicate. Returns null when the resend also fails (caller rethrows the
|
|
127728
|
+
* original error).
|
|
127729
|
+
*/
|
|
127730
|
+
async resendAbsentCreate(operation) {
|
|
127731
|
+
try {
|
|
127732
|
+
return await operation();
|
|
127733
|
+
} catch {
|
|
127734
|
+
return null;
|
|
127735
|
+
}
|
|
127624
127736
|
}
|
|
127625
127737
|
publicEnvironmentUid(data, bareId) {
|
|
127626
127738
|
const owner = String(data?.owner ?? "").trim();
|
|
@@ -127668,17 +127780,18 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127668
127780
|
name: envName,
|
|
127669
127781
|
values: normalizedValues
|
|
127670
127782
|
};
|
|
127783
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127784
|
+
{
|
|
127785
|
+
service: "sync",
|
|
127786
|
+
method: "post",
|
|
127787
|
+
path: `/environment/import?workspace=${ws}`,
|
|
127788
|
+
body,
|
|
127789
|
+
...fallback ? { fallback } : {}
|
|
127790
|
+
},
|
|
127791
|
+
{ retryTransient: false }
|
|
127792
|
+
);
|
|
127671
127793
|
try {
|
|
127672
|
-
const
|
|
127673
|
-
{
|
|
127674
|
-
service: "sync",
|
|
127675
|
-
method: "post",
|
|
127676
|
-
path: `/environment/import?workspace=${ws}`,
|
|
127677
|
-
body
|
|
127678
|
-
},
|
|
127679
|
-
{ retryTransient: false }
|
|
127680
|
-
);
|
|
127681
|
-
const data = this.dataOf(response);
|
|
127794
|
+
const data = this.dataOf(await send2());
|
|
127682
127795
|
const bareId = this.idOf(data);
|
|
127683
127796
|
if (!bareId) {
|
|
127684
127797
|
throw new Error("Environment import did not return a UID");
|
|
@@ -127693,6 +127806,15 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127693
127806
|
await this.updateEnvironment(adopted, envName, values);
|
|
127694
127807
|
return adopted;
|
|
127695
127808
|
}
|
|
127809
|
+
if (adopted === void 0) {
|
|
127810
|
+
const retried = await this.resendAbsentCreate(async () => {
|
|
127811
|
+
const data = this.dataOf(await send2("auto"));
|
|
127812
|
+
const bareId = this.idOf(data);
|
|
127813
|
+
if (!bareId) throw new Error("Environment import did not return a UID");
|
|
127814
|
+
return this.publicEnvironmentUid(data, bareId);
|
|
127815
|
+
});
|
|
127816
|
+
if (retried) return retried;
|
|
127817
|
+
}
|
|
127696
127818
|
throw error2;
|
|
127697
127819
|
}
|
|
127698
127820
|
});
|
|
@@ -127824,19 +127946,20 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127824
127946
|
private: false,
|
|
127825
127947
|
...environment ? { environment } : {}
|
|
127826
127948
|
};
|
|
127827
|
-
|
|
127828
|
-
|
|
127829
|
-
|
|
127830
|
-
|
|
127831
|
-
|
|
127832
|
-
|
|
127833
|
-
|
|
127834
|
-
|
|
127835
|
-
|
|
127836
|
-
|
|
127837
|
-
|
|
127838
|
-
|
|
127839
|
-
|
|
127949
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
127950
|
+
{
|
|
127951
|
+
service: "mock",
|
|
127952
|
+
method: "post",
|
|
127953
|
+
path: `/mocks?workspace=${ws}`,
|
|
127954
|
+
body,
|
|
127955
|
+
...fallback ? { fallback } : {}
|
|
127956
|
+
},
|
|
127957
|
+
// Unsafe create: never blind re-POST. An ESOCKETTIMEDOUT after accept
|
|
127958
|
+
// may still have created the mock; reconcile via discovery below and
|
|
127959
|
+
// let the orchestrator retry the whole create-or-adopt cycle.
|
|
127960
|
+
{ retryTransient: false }
|
|
127961
|
+
);
|
|
127962
|
+
const parseMock = (response) => {
|
|
127840
127963
|
const record = this.dataOf(response);
|
|
127841
127964
|
const uid = this.idOf(record);
|
|
127842
127965
|
if (!uid) {
|
|
@@ -127846,6 +127969,9 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127846
127969
|
uid,
|
|
127847
127970
|
url: String(record?.url ?? record?.mockUrl ?? "").trim()
|
|
127848
127971
|
};
|
|
127972
|
+
};
|
|
127973
|
+
try {
|
|
127974
|
+
return parseMock(await send2());
|
|
127849
127975
|
} catch (error2) {
|
|
127850
127976
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127851
127977
|
() => this.findMockByCollection(collection, environment, mockName),
|
|
@@ -127854,6 +127980,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127854
127980
|
if (adopted) {
|
|
127855
127981
|
return { uid: adopted.uid, url: adopted.mockUrl };
|
|
127856
127982
|
}
|
|
127983
|
+
if (adopted === void 0) {
|
|
127984
|
+
const retried = await this.resendAbsentCreate(async () => parseMock(await send2("auto")));
|
|
127985
|
+
if (retried) return retried;
|
|
127986
|
+
}
|
|
127857
127987
|
throw error2;
|
|
127858
127988
|
}
|
|
127859
127989
|
});
|
|
@@ -127960,21 +128090,25 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127960
128090
|
distribution: null,
|
|
127961
128091
|
...environment ? { environment } : {}
|
|
127962
128092
|
};
|
|
127963
|
-
|
|
127964
|
-
|
|
127965
|
-
|
|
127966
|
-
|
|
127967
|
-
|
|
127968
|
-
|
|
127969
|
-
|
|
127970
|
-
|
|
127971
|
-
|
|
127972
|
-
|
|
128093
|
+
const send2 = (fallback) => this.gateway.requestJson(
|
|
128094
|
+
{
|
|
128095
|
+
service: "monitors",
|
|
128096
|
+
method: "post",
|
|
128097
|
+
path: `/jobTemplates?workspace=${ws}`,
|
|
128098
|
+
body,
|
|
128099
|
+
...fallback ? { fallback } : {}
|
|
128100
|
+
},
|
|
128101
|
+
{ retryTransient: false }
|
|
128102
|
+
);
|
|
128103
|
+
const parseMonitor = (response) => {
|
|
127973
128104
|
const uid = this.idOf(this.dataOf(response));
|
|
127974
128105
|
if (!uid) {
|
|
127975
128106
|
throw new Error("Monitor create did not return a UID");
|
|
127976
128107
|
}
|
|
127977
128108
|
return uid;
|
|
128109
|
+
};
|
|
128110
|
+
try {
|
|
128111
|
+
return parseMonitor(await send2());
|
|
127978
128112
|
} catch (error2) {
|
|
127979
128113
|
const adopted = await this.discoverAfterAmbiguousCreate(
|
|
127980
128114
|
() => this.findMonitorByCollection(collection, environment, monitorName),
|
|
@@ -127983,6 +128117,10 @@ var PostmanGatewayAssetsClient = class {
|
|
|
127983
128117
|
if (adopted?.uid) {
|
|
127984
128118
|
return adopted.uid;
|
|
127985
128119
|
}
|
|
128120
|
+
if (adopted === void 0) {
|
|
128121
|
+
const retried = await this.resendAbsentCreate(async () => parseMonitor(await send2("auto")));
|
|
128122
|
+
if (retried) return retried;
|
|
128123
|
+
}
|
|
127986
128124
|
throw error2;
|
|
127987
128125
|
}
|
|
127988
128126
|
});
|
|
@@ -128211,6 +128349,7 @@ var AccessTokenGatewayClient = class {
|
|
|
128211
128349
|
fetchImpl;
|
|
128212
128350
|
secretMasker;
|
|
128213
128351
|
maxRetries;
|
|
128352
|
+
fallbackBaseUrl;
|
|
128214
128353
|
retryBaseDelayMs;
|
|
128215
128354
|
sleepImpl;
|
|
128216
128355
|
constructor(options) {
|
|
@@ -128223,6 +128362,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128223
128362
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
128224
128363
|
this.secretMasker = options.secretMasker ?? createSecretMasker([this.tokenProvider.current()]);
|
|
128225
128364
|
this.maxRetries = options.maxRetries ?? 3;
|
|
128365
|
+
const fallbackEnv = typeof process !== "undefined" ? process.env?.POSTMAN_ITEM_CREATE_FALLBACK : void 0;
|
|
128366
|
+
this.fallbackBaseUrl = fallbackEnv === "off" ? void 0 : options.fallbackBaseUrl?.replace(/\/+$/, "");
|
|
128226
128367
|
this.retryBaseDelayMs = options.retryBaseDelayMs ?? 400;
|
|
128227
128368
|
this.sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
128228
128369
|
}
|
|
@@ -128241,8 +128382,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128241
128382
|
}
|
|
128242
128383
|
return headers;
|
|
128243
128384
|
}
|
|
128244
|
-
async send(request) {
|
|
128245
|
-
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
128385
|
+
async send(request, baseUrl) {
|
|
128386
|
+
const url = `${baseUrl ?? this.bifrostBaseUrl}/ws/proxy`;
|
|
128246
128387
|
return this.fetchImpl(url, {
|
|
128247
128388
|
method: "POST",
|
|
128248
128389
|
headers: this.buildHeaders(request.headers),
|
|
@@ -128255,6 +128396,43 @@ var AccessTokenGatewayClient = class {
|
|
|
128255
128396
|
})
|
|
128256
128397
|
});
|
|
128257
128398
|
}
|
|
128399
|
+
/**
|
|
128400
|
+
* One cold, serial attempt against the fallback base URL after the primary
|
|
128401
|
+
* budget is exhausted on a transient failure. Never hedged in parallel with
|
|
128402
|
+
* the primary; only fires when the request would otherwise throw. Callers
|
|
128403
|
+
* with `retryTransient: false` still reconcile first — the fallback attempt
|
|
128404
|
+
* here is the resend, so it is only used for requests whose mutation is
|
|
128405
|
+
* known idempotent or already reconciled by the caller's adopt-on-ambiguous
|
|
128406
|
+
* loop.
|
|
128407
|
+
*/
|
|
128408
|
+
async tryFallback(request) {
|
|
128409
|
+
if (!this.fallbackBaseUrl) return null;
|
|
128410
|
+
try {
|
|
128411
|
+
return await this.send(request, this.fallbackBaseUrl);
|
|
128412
|
+
} catch {
|
|
128413
|
+
return null;
|
|
128414
|
+
}
|
|
128415
|
+
}
|
|
128416
|
+
/**
|
|
128417
|
+
* Run the fallback attempt and classify its response the same way the
|
|
128418
|
+
* primary path would. Returns the success response, or null when the
|
|
128419
|
+
* fallback also failed transiently (caller then throws the original error).
|
|
128420
|
+
* Non-transient fallback failures (4xx) surface as their own HttpError since
|
|
128421
|
+
* they are the freshest authoritative answer.
|
|
128422
|
+
*/
|
|
128423
|
+
fallbackEligible(request, retryTransient) {
|
|
128424
|
+
if (!this.fallbackBaseUrl) return false;
|
|
128425
|
+
return retryTransient || request.fallback === "auto";
|
|
128426
|
+
}
|
|
128427
|
+
async attemptFallback(request, retryTransient) {
|
|
128428
|
+
if (!this.fallbackEligible(request, retryTransient)) return null;
|
|
128429
|
+
const response = await this.tryFallback(request);
|
|
128430
|
+
if (!response) return null;
|
|
128431
|
+
if (response.ok) return response;
|
|
128432
|
+
const body = await response.text().catch(() => "");
|
|
128433
|
+
if (isRetryableSafeReadResponse(response.status)) return null;
|
|
128434
|
+
throw this.toHttpError(request, response, body);
|
|
128435
|
+
}
|
|
128258
128436
|
/**
|
|
128259
128437
|
* Send a gateway request, refreshing the token once on an auth failure and
|
|
128260
128438
|
* optionally retrying transient downstream failures (5xx / Bifrost read
|
|
@@ -128277,6 +128455,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128277
128455
|
await this.sleepImpl(delay);
|
|
128278
128456
|
continue;
|
|
128279
128457
|
}
|
|
128458
|
+
const fallbackResponse2 = await this.attemptFallback(request, retryTransient);
|
|
128459
|
+
if (fallbackResponse2) return fallbackResponse2;
|
|
128280
128460
|
throw error2;
|
|
128281
128461
|
}
|
|
128282
128462
|
if (response.ok) {
|
|
@@ -128298,6 +128478,8 @@ var AccessTokenGatewayClient = class {
|
|
|
128298
128478
|
await this.sleepImpl(delay);
|
|
128299
128479
|
continue;
|
|
128300
128480
|
}
|
|
128481
|
+
const fallbackResponse = await this.attemptFallback(request, retryTransient);
|
|
128482
|
+
if (fallbackResponse) return fallbackResponse;
|
|
128301
128483
|
throw this.toHttpError(request, response, body);
|
|
128302
128484
|
}
|
|
128303
128485
|
}
|
|
@@ -128924,6 +129106,7 @@ function resolveInputs(env = process.env) {
|
|
|
128924
129106
|
postmanStack,
|
|
128925
129107
|
postmanApiBase: endpointProfile.apiBaseUrl,
|
|
128926
129108
|
postmanBifrostBase: endpointProfile.bifrostBaseUrl,
|
|
129109
|
+
postmanFallbackBase: endpointProfile.fallbackBaseUrl,
|
|
128927
129110
|
postmanCliInstallUrl: endpointProfile.cliInstallUrl,
|
|
128928
129111
|
postmanIapubBase: endpointProfile.iapubBaseUrl
|
|
128929
129112
|
};
|
|
@@ -129768,6 +129951,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129768
129951
|
}
|
|
129769
129952
|
}
|
|
129770
129953
|
}
|
|
129954
|
+
let skipRepositoryLinkPost = false;
|
|
129955
|
+
let repositoryLinkPreflightWasFree = false;
|
|
129956
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
129957
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
129958
|
+
inputs.repoUrl,
|
|
129959
|
+
"/"
|
|
129960
|
+
);
|
|
129961
|
+
if (probe.state === "linked-visible") {
|
|
129962
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
129963
|
+
skipRepositoryLinkPost = true;
|
|
129964
|
+
dependencies.core.info(
|
|
129965
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
129966
|
+
);
|
|
129967
|
+
} else {
|
|
129968
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
129969
|
+
throw new Error(
|
|
129970
|
+
`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.`
|
|
129971
|
+
);
|
|
129972
|
+
}
|
|
129973
|
+
} else if (probe.state === "linked-invisible") {
|
|
129974
|
+
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.`;
|
|
129975
|
+
if (inputs.orgMode) {
|
|
129976
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
129977
|
+
}
|
|
129978
|
+
throw new Error(message);
|
|
129979
|
+
} else if (probe.state === "free") {
|
|
129980
|
+
repositoryLinkPreflightWasFree = true;
|
|
129981
|
+
} else {
|
|
129982
|
+
dependencies.core.warning(
|
|
129983
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
129984
|
+
);
|
|
129985
|
+
}
|
|
129986
|
+
}
|
|
129771
129987
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129772
129988
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129773
129989
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -129900,18 +130116,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129900
130116
|
}
|
|
129901
130117
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
129902
130118
|
try {
|
|
129903
|
-
|
|
129904
|
-
|
|
129905
|
-
|
|
129906
|
-
|
|
129907
|
-
|
|
129908
|
-
|
|
129909
|
-
|
|
129910
|
-
|
|
130119
|
+
if (skipRepositoryLinkPost) {
|
|
130120
|
+
outputs["workspace-link-status"] = "success";
|
|
130121
|
+
dependencies.core.info(
|
|
130122
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
130123
|
+
);
|
|
130124
|
+
} else {
|
|
130125
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
130126
|
+
inputs.workspaceId,
|
|
130127
|
+
inputs.repoUrl,
|
|
130128
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
130129
|
+
);
|
|
130130
|
+
outputs["workspace-link-status"] = "success";
|
|
130131
|
+
dependencies.core.info(
|
|
130132
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
130133
|
+
);
|
|
130134
|
+
}
|
|
129911
130135
|
} catch (error2) {
|
|
129912
130136
|
outputs["workspace-link-status"] = "failed";
|
|
129913
|
-
const
|
|
130137
|
+
const rawMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
130138
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
130139
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
130140
|
+
);
|
|
130141
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
129914
130142
|
if (branchDecision.tier === "canonical") {
|
|
130143
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130144
|
+
throw error2;
|
|
130145
|
+
}
|
|
129915
130146
|
throw new Error(message, { cause: error2 });
|
|
129916
130147
|
}
|
|
129917
130148
|
dependencies.core.warning(message);
|
|
@@ -130065,6 +130296,8 @@ async function resolvePostmanApiKeyAndTeamId(inputs, actionCore, actionExec, mas
|
|
|
130065
130296
|
const gateway = new AccessTokenGatewayClient({
|
|
130066
130297
|
tokenProvider,
|
|
130067
130298
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130299
|
+
// No fallback on the org-mode probe: the expected non-org 400 must
|
|
130300
|
+
// surface verbatim, not be re-fired against the /_api alias.
|
|
130068
130301
|
secretMasker: masker
|
|
130069
130302
|
});
|
|
130070
130303
|
const squads = await gateway.getSquads(teamId);
|
|
@@ -130120,6 +130353,7 @@ function createRepoSyncDependencies(inputs, resolved, factories, options = {}) {
|
|
|
130120
130353
|
const gateway = new AccessTokenGatewayClient({
|
|
130121
130354
|
tokenProvider,
|
|
130122
130355
|
bifrostBaseUrl: inputs.postmanBifrostBase,
|
|
130356
|
+
fallbackBaseUrl: inputs.postmanFallbackBase,
|
|
130123
130357
|
teamId: resolved.teamId,
|
|
130124
130358
|
orgMode: inputs.orgMode,
|
|
130125
130359
|
secretMasker: masker
|