@postman-cse/onboarding-repo-sync 2.1.7 → 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 +141 -10
- package/dist/cli.cjs +141 -10
- package/dist/index.cjs +141 -10
- package/package.json +1 -1
package/dist/action.cjs
CHANGED
|
@@ -126895,7 +126895,85 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126895
126895
|
throw advised ?? httpErr;
|
|
126896
126896
|
}
|
|
126897
126897
|
}
|
|
126898
|
-
|
|
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) {
|
|
126899
126977
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126900
126978
|
const payload = {
|
|
126901
126979
|
service: "workspaces",
|
|
@@ -126922,6 +127000,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126922
127000
|
if (isDuplicate) {
|
|
126923
127001
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126924
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
|
+
}
|
|
126925
127008
|
throw new Error(
|
|
126926
127009
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126927
127010
|
);
|
|
@@ -129848,6 +129931,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129848
129931
|
}
|
|
129849
129932
|
}
|
|
129850
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
|
+
}
|
|
129851
129967
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129852
129968
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129853
129969
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -129980,18 +130096,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129980
130096
|
}
|
|
129981
130097
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
129982
130098
|
try {
|
|
129983
|
-
|
|
129984
|
-
|
|
129985
|
-
|
|
129986
|
-
|
|
129987
|
-
|
|
129988
|
-
|
|
129989
|
-
|
|
129990
|
-
|
|
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
|
+
}
|
|
129991
130115
|
} catch (error2) {
|
|
129992
130116
|
outputs["workspace-link-status"] = "failed";
|
|
129993
|
-
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}`;
|
|
129994
130122
|
if (branchDecision.tier === "canonical") {
|
|
130123
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130124
|
+
throw error2;
|
|
130125
|
+
}
|
|
129995
130126
|
throw new Error(message, { cause: error2 });
|
|
129996
130127
|
}
|
|
129997
130128
|
dependencies.core.warning(message);
|
package/dist/cli.cjs
CHANGED
|
@@ -124998,7 +124998,85 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
124998
124998
|
throw advised ?? httpErr;
|
|
124999
124999
|
}
|
|
125000
125000
|
}
|
|
125001
|
-
|
|
125001
|
+
/**
|
|
125002
|
+
* Probe who (if anyone) already owns the global `(repo, path)` filesystem
|
|
125003
|
+
* link. Non-fatal: unexpected statuses / network errors yield `unknown` so
|
|
125004
|
+
* callers can proceed and rely on reactive POST conflict handling.
|
|
125005
|
+
*
|
|
125006
|
+
* Bifrost states (FileSystemController.fetchWorkspaceForFileSystem):
|
|
125007
|
+
* - 200 + data null -> free
|
|
125008
|
+
* - 200 + data -> linked-visible (workspace payload)
|
|
125009
|
+
* - 403 + error.meta.workspaceId -> linked-invisible
|
|
125010
|
+
* - 200 + error.meta.workspaceId -> linked-invisible (proxy envelope)
|
|
125011
|
+
*/
|
|
125012
|
+
async findWorkspaceForRepo(repoUrl, path5 = "/") {
|
|
125013
|
+
const fsPath = path5 && path5.trim() ? path5.trim() : "/";
|
|
125014
|
+
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
125015
|
+
const payload = {
|
|
125016
|
+
service: "workspaces",
|
|
125017
|
+
method: "GET",
|
|
125018
|
+
path: `/workspaces/filesystem?repo=${encodeURIComponent(repoUrl)}&path=${encodeURIComponent(fsPath)}`
|
|
125019
|
+
};
|
|
125020
|
+
try {
|
|
125021
|
+
const response = await this.fetchImpl(url, {
|
|
125022
|
+
method: "POST",
|
|
125023
|
+
headers: this.bifrostHeaders(),
|
|
125024
|
+
body: JSON.stringify(payload)
|
|
125025
|
+
});
|
|
125026
|
+
let parsed = {};
|
|
125027
|
+
try {
|
|
125028
|
+
parsed = await response.json();
|
|
125029
|
+
} catch {
|
|
125030
|
+
return {
|
|
125031
|
+
state: "unknown",
|
|
125032
|
+
reason: `filesystem lookup returned non-JSON body (HTTP ${response.status})`
|
|
125033
|
+
};
|
|
125034
|
+
}
|
|
125035
|
+
const errorMetaWorkspaceId = typeof parsed?.error?.meta?.workspaceId === "string" && parsed.error.meta.workspaceId.trim() ? parsed.error.meta.workspaceId.trim() : void 0;
|
|
125036
|
+
if (errorMetaWorkspaceId) {
|
|
125037
|
+
return { state: "linked-invisible", workspaceId: errorMetaWorkspaceId };
|
|
125038
|
+
}
|
|
125039
|
+
if (response.ok) {
|
|
125040
|
+
if (parsed?.data == null) {
|
|
125041
|
+
return { state: "free" };
|
|
125042
|
+
}
|
|
125043
|
+
const id = typeof parsed.data.id === "string" ? parsed.data.id.trim() : "";
|
|
125044
|
+
if (!id) {
|
|
125045
|
+
return {
|
|
125046
|
+
state: "unknown",
|
|
125047
|
+
reason: "filesystem lookup returned 200 without a workspace id"
|
|
125048
|
+
};
|
|
125049
|
+
}
|
|
125050
|
+
const name = typeof parsed.data.name === "string" && parsed.data.name.trim() ? parsed.data.name.trim() : void 0;
|
|
125051
|
+
return {
|
|
125052
|
+
state: "linked-visible",
|
|
125053
|
+
workspace: name ? { id, name } : { id }
|
|
125054
|
+
};
|
|
125055
|
+
}
|
|
125056
|
+
if (response.status === 403) {
|
|
125057
|
+
const workspaceId = extractDuplicateWorkspaceId(
|
|
125058
|
+
JSON.stringify(parsed)
|
|
125059
|
+
);
|
|
125060
|
+
if (workspaceId) {
|
|
125061
|
+
return { state: "linked-invisible", workspaceId };
|
|
125062
|
+
}
|
|
125063
|
+
return {
|
|
125064
|
+
state: "unknown",
|
|
125065
|
+
reason: "filesystem lookup returned 403 without error.meta.workspaceId"
|
|
125066
|
+
};
|
|
125067
|
+
}
|
|
125068
|
+
return {
|
|
125069
|
+
state: "unknown",
|
|
125070
|
+
reason: `filesystem lookup returned HTTP ${response.status}`
|
|
125071
|
+
};
|
|
125072
|
+
} catch (error) {
|
|
125073
|
+
return {
|
|
125074
|
+
state: "unknown",
|
|
125075
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
125076
|
+
};
|
|
125077
|
+
}
|
|
125078
|
+
}
|
|
125079
|
+
async connectWorkspaceToRepository(workspaceId, repoUrl, options) {
|
|
125002
125080
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
125003
125081
|
const payload = {
|
|
125004
125082
|
service: "workspaces",
|
|
@@ -125025,6 +125103,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
125025
125103
|
if (isDuplicate) {
|
|
125026
125104
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
125027
125105
|
if (existingWorkspaceId && existingWorkspaceId !== workspaceId) {
|
|
125106
|
+
if (options?.preflightWasFree) {
|
|
125107
|
+
throw new Error(
|
|
125108
|
+
`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.`
|
|
125109
|
+
);
|
|
125110
|
+
}
|
|
125028
125111
|
throw new Error(
|
|
125029
125112
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
125030
125113
|
);
|
|
@@ -127758,6 +127841,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127758
127841
|
}
|
|
127759
127842
|
}
|
|
127760
127843
|
}
|
|
127844
|
+
let skipRepositoryLinkPost = false;
|
|
127845
|
+
let repositoryLinkPreflightWasFree = false;
|
|
127846
|
+
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration?.findWorkspaceForRepo) {
|
|
127847
|
+
const probe = await dependencies.internalIntegration.findWorkspaceForRepo(
|
|
127848
|
+
inputs.repoUrl,
|
|
127849
|
+
"/"
|
|
127850
|
+
);
|
|
127851
|
+
if (probe.state === "linked-visible") {
|
|
127852
|
+
if (probe.workspace.id === inputs.workspaceId) {
|
|
127853
|
+
skipRepositoryLinkPost = true;
|
|
127854
|
+
dependencies.core.info(
|
|
127855
|
+
`REPOSITORY_LINK_ALREADY_TARGET: Repository ${inputs.repoUrl} at path / is already linked to target workspace ${inputs.workspaceId}; continuing.`
|
|
127856
|
+
);
|
|
127857
|
+
} else {
|
|
127858
|
+
const ownerName = probe.workspace.name?.trim() || "unknown";
|
|
127859
|
+
throw new Error(
|
|
127860
|
+
`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.`
|
|
127861
|
+
);
|
|
127862
|
+
}
|
|
127863
|
+
} else if (probe.state === "linked-invisible") {
|
|
127864
|
+
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.`;
|
|
127865
|
+
if (inputs.orgMode) {
|
|
127866
|
+
message += " Verify workspace-team-id; if the owner is in another sub-team, ask that sub-team's admin to disconnect it.";
|
|
127867
|
+
}
|
|
127868
|
+
throw new Error(message);
|
|
127869
|
+
} else if (probe.state === "free") {
|
|
127870
|
+
repositoryLinkPreflightWasFree = true;
|
|
127871
|
+
} else {
|
|
127872
|
+
dependencies.core.warning(
|
|
127873
|
+
`REPOSITORY_LINK_PREFLIGHT_UNKNOWN: Unable to determine the existing repository link (${probe.reason}); continuing and relying on link creation conflict handling.`
|
|
127874
|
+
);
|
|
127875
|
+
}
|
|
127876
|
+
}
|
|
127761
127877
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
127762
127878
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
127763
127879
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -127890,18 +128006,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
127890
128006
|
}
|
|
127891
128007
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
127892
128008
|
try {
|
|
127893
|
-
|
|
127894
|
-
|
|
127895
|
-
|
|
127896
|
-
|
|
127897
|
-
|
|
127898
|
-
|
|
127899
|
-
|
|
127900
|
-
|
|
128009
|
+
if (skipRepositoryLinkPost) {
|
|
128010
|
+
outputs["workspace-link-status"] = "success";
|
|
128011
|
+
dependencies.core.info(
|
|
128012
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl} (preflight already-target; link POST skipped)`
|
|
128013
|
+
);
|
|
128014
|
+
} else {
|
|
128015
|
+
await dependencies.internalIntegration.connectWorkspaceToRepository(
|
|
128016
|
+
inputs.workspaceId,
|
|
128017
|
+
inputs.repoUrl,
|
|
128018
|
+
repositoryLinkPreflightWasFree ? { preflightWasFree: true } : void 0
|
|
128019
|
+
);
|
|
128020
|
+
outputs["workspace-link-status"] = "success";
|
|
128021
|
+
dependencies.core.info(
|
|
128022
|
+
`workspace-link-status=success workspace-id=${inputs.workspaceId} repo=${inputs.repoUrl}`
|
|
128023
|
+
);
|
|
128024
|
+
}
|
|
127901
128025
|
} catch (error) {
|
|
127902
128026
|
outputs["workspace-link-status"] = "failed";
|
|
127903
|
-
const
|
|
128027
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
128028
|
+
const isUnresolvedContract = rawMessage.startsWith(
|
|
128029
|
+
"REPOSITORY_LINK_CONFLICT_UNRESOLVED:"
|
|
128030
|
+
);
|
|
128031
|
+
const message = isUnresolvedContract ? rawMessage : `Workspace link failed: ${rawMessage}`;
|
|
127904
128032
|
if (branchDecision.tier === "canonical") {
|
|
128033
|
+
if (isUnresolvedContract && error instanceof Error) {
|
|
128034
|
+
throw error;
|
|
128035
|
+
}
|
|
127905
128036
|
throw new Error(message, { cause: error });
|
|
127906
128037
|
}
|
|
127907
128038
|
dependencies.core.warning(message);
|
package/dist/index.cjs
CHANGED
|
@@ -126915,7 +126915,85 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126915
126915
|
throw advised ?? httpErr;
|
|
126916
126916
|
}
|
|
126917
126917
|
}
|
|
126918
|
-
|
|
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) {
|
|
126919
126997
|
const url = `${this.bifrostBaseUrl}/ws/proxy`;
|
|
126920
126998
|
const payload = {
|
|
126921
126999
|
service: "workspaces",
|
|
@@ -126942,6 +127020,11 @@ var BifrostInternalIntegrationAdapter = class {
|
|
|
126942
127020
|
if (isDuplicate) {
|
|
126943
127021
|
const existingWorkspaceId = extractDuplicateWorkspaceId(body);
|
|
126944
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
|
+
}
|
|
126945
127028
|
throw new Error(
|
|
126946
127029
|
await this.describeWorkspaceLinkConflict(existingWorkspaceId, workspaceId, repoUrl)
|
|
126947
127030
|
);
|
|
@@ -129868,6 +129951,39 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
129868
129951
|
}
|
|
129869
129952
|
}
|
|
129870
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
|
+
}
|
|
129871
129987
|
const branchAssetMarker = buildBranchAssetMarker(branchDecision, inputs);
|
|
129872
129988
|
const envUids = await upsertEnvironments(inputs, dependencies, resourcesState, branchAssetMarker);
|
|
129873
129989
|
outputs["environment-uids-json"] = JSON.stringify(envUids);
|
|
@@ -130000,18 +130116,33 @@ async function runRepoSyncInner(inputs, dependencies) {
|
|
|
130000
130116
|
}
|
|
130001
130117
|
if (inputs.workspaceLinkEnabled && inputs.workspaceId && inputs.repoUrl && dependencies.internalIntegration) {
|
|
130002
130118
|
try {
|
|
130003
|
-
|
|
130004
|
-
|
|
130005
|
-
|
|
130006
|
-
|
|
130007
|
-
|
|
130008
|
-
|
|
130009
|
-
|
|
130010
|
-
|
|
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
|
+
}
|
|
130011
130135
|
} catch (error2) {
|
|
130012
130136
|
outputs["workspace-link-status"] = "failed";
|
|
130013
|
-
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}`;
|
|
130014
130142
|
if (branchDecision.tier === "canonical") {
|
|
130143
|
+
if (isUnresolvedContract && error2 instanceof Error) {
|
|
130144
|
+
throw error2;
|
|
130145
|
+
}
|
|
130015
130146
|
throw new Error(message, { cause: error2 });
|
|
130016
130147
|
}
|
|
130017
130148
|
dependencies.core.warning(message);
|