Skip to content

Commit 4bafa15

Browse files
committed
Revert last two commits
1 parent a457d05 commit 4bafa15

File tree

3 files changed

+46
-63
lines changed

3 files changed

+46
-63
lines changed

packages/mcp-provider-devops/src/resolveDeploymentFailure.ts

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,19 @@ function isMergeConflict(errorSummary: string): boolean {
1818
export interface ResolveDeploymentFailureOptions {
1919
localPath: string;
2020
sourceBranchName: string;
21-
targetBranchName?: string;
2221
}
2322

2423
/**
2524
* Can full promotion fix this failure?
2625
* - Merge conflict → no; use merge conflict tool.
2726
* - Missing dependency (e.g. "Variable does not exist: X"): need localPath to check source branch;
28-
* if not provided → local_path_required; if provided and dependency in source → yes; else no.
29-
* When targetBranchName is provided, also checks target branch and returns inTargetBranch for comparison.
27+
* if not provided → local_path_required; if provided and dependency in branch → yes; else no.
3028
* - All other errors → yes.
3129
*/
3230
export function canFullPromotionFixFailure(
3331
errorDetails: string,
3432
options?: ResolveDeploymentFailureOptions
35-
): {
36-
canFix: boolean;
37-
reason: string;
38-
missingDependencyName?: string;
39-
inTargetBranch?: boolean;
40-
} {
33+
): { canFix: boolean; reason: string; missingDependencyName?: string } {
4134
if (isMergeConflict(errorDetails)) {
4235
return { canFix: false, reason: "merge_conflict" };
4336
}
@@ -52,30 +45,17 @@ export function canFullPromotionFixFailure(
5245
};
5346
}
5447
const paths = getSourcePathsForDependency(dependency.type, dependency.name);
55-
const inSource =
48+
const inBranch =
5649
paths.length > 0 &&
5750
isDependencyPresentInBranch(options.localPath, options.sourceBranchName, paths);
58-
if (!inSource) {
51+
if (!inBranch) {
5952
return {
6053
canFix: false,
6154
reason: "dependency_not_in_source_branch",
6255
missingDependencyName: dependency.name,
6356
};
6457
}
65-
let inTargetBranch: boolean | undefined;
66-
if (options.targetBranchName && paths.length > 0) {
67-
inTargetBranch = isDependencyPresentInBranch(
68-
options.localPath,
69-
options.targetBranchName,
70-
paths
71-
);
72-
}
73-
return {
74-
canFix: true,
75-
reason: "dependency_in_source_branch",
76-
missingDependencyName: dependency.name,
77-
inTargetBranch,
78-
};
58+
return { canFix: true, reason: "dependency_in_source_branch" };
7959
}
8060

8161
return { canFix: true, reason: "full_promotion_can_fix" };

packages/mcp-provider-devops/src/shared/dependencyInBranch.ts

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,22 @@ export function getSourcePathsForDependency(type: string, name: string): string[
7171
}
7272

7373
/**
74-
* Try to run git show for a ref:path; try ref first, then origin/ref if ref is not a valid ref.
74+
* Check whether at least one of the given paths exists in the given git branch.
75+
* Paths must use forward slashes (git convention).
7576
*/
76-
function gitShowInBranch(repoPath: string, branch: string, relativePath: string): boolean {
77-
const normalized = relativePath.split(path.sep).join("/");
78-
const refsToTry = [branch, `origin/${branch}`];
79-
for (const ref of refsToTry) {
77+
export function isDependencyPresentInBranch(repoPath: string, branch: string, relativePaths: string[]): boolean {
78+
for (const p of relativePaths) {
79+
const normalized = p.split(path.sep).join("/");
8080
try {
81-
execSync(`git show "${ref}:${normalized}"`, {
81+
execSync(`git show "${branch}:${normalized}"`, {
8282
cwd: repoPath,
8383
stdio: ["ignore", "pipe", "pipe"],
8484
encoding: "utf8",
8585
maxBuffer: 1024 * 1024,
8686
});
8787
return true;
8888
} catch {
89-
// ref invalid or file not in branch
90-
}
91-
}
92-
return false;
93-
}
94-
95-
/**
96-
* Check whether at least one of the given paths exists in the given git branch.
97-
* Paths must use forward slashes (git convention).
98-
* Tries branch name first, then origin/branch when branch is only available as a remote ref.
99-
*/
100-
export function isDependencyPresentInBranch(repoPath: string, branch: string, relativePaths: string[]): boolean {
101-
for (const p of relativePaths) {
102-
if (gitShowInBranch(repoPath, branch, p)) {
103-
return true;
89+
// file not in branch or path invalid
10490
}
10591
}
10692
return false;

packages/mcp-provider-devops/src/tools/sfDevopsResolveDeploymentFailure.ts

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ const inputSchema = z.object({
99
usernameOrAlias: usernameOrAliasParam,
1010
workItemName: z.string().min(1).describe("Work Item name (mandatory). Exact name of the work item that failed deployment."),
1111
sourceBranchName: z.string().min(1).describe("Source branch name (mandatory). The work item branch where the change lives."),
12-
targetBranchName: z.string().min(1).optional().describe("Target branch name (optional). When provided with localPath, the tool compares source and target to determine if the missing dependency is in source but not in target, confirming full promotion will resolve the failure."),
1312
errorDetails: z.string().min(1).describe("Error details from the failed deployment (mandatory). Used to determine if full promotion can fix the failure."),
14-
localPath: z.string().optional().describe("Local path to the repository (defaults to current working directory)")
13+
localPath: z.string().optional().describe("Local path to the repository (optional). Required only for dependency-type errors: used to check if the source branch contains the missing dependency. If provided and valid, the tool checks the branch; if dependency is present, full promotion can fix.")
1514
});
1615
type InputArgs = z.infer<typeof inputSchema>;
1716
type InputArgsShape = typeof inputSchema.shape;
@@ -42,12 +41,12 @@ export class SfDevopsResolveDeploymentFailure extends McpTool<InputArgsShape, Ou
4241
title: "Resolve Deployment Failure",
4342
description: `Determine if **full promotion** can fix a deployment failure and guide the user.
4443
45-
**Inputs:** workItemName (mandatory), sourceBranchName (mandatory), errorDetails (mandatory), localPath (optional; defaults to current working directory), targetBranchName (optional; when provided, source and target are compared to confirm if full promotion will resolve).
44+
**Inputs:** workItemName (mandatory), sourceBranchName (mandatory), errorDetails (mandatory), localPath (optional).
4645
4746
**Behavior:**
4847
1. **If full promotion cannot fix** (e.g. merge conflict): Return instructions to use **resolve_devops_center_merge_conflict** or to add the missing dependency in a separate work item.
4948
2. **If full promotion can fix** (anything other than merge conflict):
50-
- For dependency-type errors (e.g. "Variable does not exist"): Use **localPath** to check whether the missing dependency exists in the source branch. If **targetBranchName** is provided, the tool compares source and target (dependency in source but not in target → full promotion will resolve). If **present in source** → ask the user for confirmation (see below). If **not present in source** → instruct the user to create a new work item for the missing dependency, promote it first, then retry.
49+
- For dependency-type errors (e.g. "Variable does not exist"): If **localPath** is not provided, ask the user for the local path of the source branch. If provided, check whether the missing dependency exists in the source branch. If **present** → ask the user for confirmation (see below). If **not present** → instruct the user to create a new work item for the missing dependency, promote it first, then retry.
5150
- For other errors: Ask the user for confirmation (see below).
5251
5352
**MANDATORY – Ask for confirmation; do NOT run full promotion without it:**
@@ -60,13 +59,20 @@ export class SfDevopsResolveDeploymentFailure extends McpTool<InputArgsShape, Ou
6059
}
6160

6261
public async exec(input: InputArgs): Promise<CallToolResult> {
63-
const options = {
64-
localPath: normalizeAndValidateRepoPath(input.localPath?.trim() || undefined),
65-
sourceBranchName: input.sourceBranchName,
66-
...(input.targetBranchName?.trim() && { targetBranchName: input.targetBranchName.trim() }),
67-
};
62+
let options: { localPath: string; sourceBranchName: string } | undefined;
63+
let pathInvalid = false;
64+
if (input.localPath?.trim()) {
65+
try {
66+
options = {
67+
localPath: normalizeAndValidateRepoPath(input.localPath),
68+
sourceBranchName: input.sourceBranchName,
69+
};
70+
} catch {
71+
pathInvalid = true;
72+
}
73+
}
6874

69-
const { canFix, reason, missingDependencyName, inTargetBranch } = canFullPromotionFixFailure(input.errorDetails, options);
75+
const { canFix, reason, missingDependencyName } = canFullPromotionFixFailure(input.errorDetails, options);
7076

7177
// Full promotion cannot fix: merge conflict → use merge conflict tool
7278
if (!canFix && reason === "merge_conflict") {
@@ -81,6 +87,23 @@ export class SfDevopsResolveDeploymentFailure extends McpTool<InputArgsShape, Ou
8187
};
8288
}
8389

90+
// Dependency-type error but no valid localPath: ask for path or suggest new work item
91+
if (reason === "local_path_required" || (pathInvalid && !canFix)) {
92+
return {
93+
content: [{
94+
type: "text",
95+
text: `The error suggests a missing dependency${missingDependencyName ? ` (e.g. ${missingDependencyName})` : ""}. To see if full promotion can fix it, the tool must check whether that dependency exists in the source branch.
96+
97+
**Please provide the local path** to your repo (**localPath**). The tool will check branch "${input.sourceBranchName}":
98+
- If the dependency is in the branch → full promotion can fix (you'll be asked to confirm).
99+
- If not → create a new work item for the missing dependency, promote it first, then retry "${input.workItemName}".
100+
101+
If you cannot provide a path, create a new work item that adds the missing dependency, promote it, then retry.`
102+
}],
103+
isError: false
104+
};
105+
}
106+
84107
// Dependency missing in source branch
85108
if (!canFix && reason === "dependency_not_in_source_branch") {
86109
return {
@@ -106,16 +129,10 @@ export class SfDevopsResolveDeploymentFailure extends McpTool<InputArgsShape, Ou
106129
}
107130

108131
// Full promotion can fix — ask for confirmation; do NOT call promote until user explicitly confirms
109-
const comparisonNote =
110-
reason === "dependency_in_source_branch" && missingDependencyName && input.targetBranchName?.trim()
111-
? inTargetBranch === false
112-
? ` The missing dependency "${missingDependencyName}" is in source branch "${input.sourceBranchName}" but not in target branch "${input.targetBranchName}"; full promotion will resolve this.`
113-
: ` The dependency "${missingDependencyName}" is present in both source and target branches; full promotion will resolve.`
114-
: "";
115132
return {
116133
content: [{
117134
type: "text",
118-
text: `**Full promotion can resolve this failure** based on the error details.${comparisonNote}
135+
text: `**Full promotion can resolve this failure** based on the error details.
119136
120137
**Ask for confirmation:** Do not run full promotion until the user explicitly confirms. Present this to the user:
121138

0 commit comments

Comments
 (0)