-
Notifications
You must be signed in to change notification settings - Fork 240
Alternative for PR search #11821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Alternative for PR search #11821
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
308385d
testing
3104daf
pr number or branch name
be28377
PR numbers
926f583
changed cli description
94f3d7e
changes
71c789e
updated names
36993c4
Merge remote-tracking branch 'origin/main' into explore2025-issue11778
21f471d
Update tools/azsdk-cli/Azure.Sdk.Tools.Cli/Tools/EngSys/CodeownersToo…
shirelmr 9ecb39f
Update tools/azsdk-cli/Azure.Sdk.Tools.Cli/Tools/EngSys/CodeownersToo…
shirelmr f393fc6
Merge branch 'origin/main' into explore2025-issue11778
2c99b30
added push to forks
fba84f4
pr search by number
f9cade0
Merge remote-tracking branch 'origin/main' into explore2025-issue11778
da31545
solved errors
08fc9ac
handle different cases
cbadb7c
added checking for push permissions
c98d002
implemented new method in mockservice
b3d524e
Update tools/azsdk-cli/Azure.Sdk.Tools.Cli/Services/GitHubService.cs
shirelmr d078ab8
changes
94ef9fc
changedhardcoded things
bd6e702
changes
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,7 +41,7 @@ public class CodeownersTools : MCPTool | |
| private readonly Option<string[]> serviceOwnersOption = new(["--service-owners"], "The service owners (space-separated)") { IsRequired = false }; | ||
| private readonly Option<string[]> sourceOwnersOption = new(["--source-owners"], "The source owners (space-separated)") { IsRequired = false }; | ||
| private readonly Option<bool> isAddingOption = new(["--is-adding"], "Whether to add (true) or remove (false) owners") { IsRequired = false }; | ||
| private readonly Option<string> workingBranchOption = new(["--branch"], "Branch to make edits to, only if provided.") { IsRequired = false }; | ||
| private readonly Option<int> prNumberOption = new(["--pr-number"], "PR number.") { IsRequired = false }; | ||
|
|
||
| public CodeownersTools( | ||
| IGitHubService githubService, | ||
|
|
@@ -74,13 +74,14 @@ public override Command GetCommand() | |
| serviceOwnersOption, | ||
| sourceOwnersOption, | ||
| isAddingOption, | ||
| workingBranchOption, | ||
| prNumberOption, | ||
| }, | ||
| new Command(validateCodeownersEntryCommandName, "Validate codeowners for an existing service entry") | ||
| { | ||
| repoOption, | ||
| serviceLabelOption, | ||
| pathOptionOptional | ||
| pathOptionOptional, | ||
| prNumberOption, | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -106,7 +107,7 @@ public override async Task HandleCommand(InvocationContext ctx, CancellationToke | |
| var serviceOwnersValue = commandParser.GetValueForOption(serviceOwnersOption); | ||
| var sourceOwnersValue = commandParser.GetValueForOption(sourceOwnersOption); | ||
| var isAddingValue = commandParser.GetValueForOption(isAddingOption); | ||
| var workingBranchValue = commandParser.GetValueForOption(workingBranchOption); | ||
| var prNumberValue = commandParser.GetValueForOption(prNumberOption); | ||
|
|
||
| var addResult = await UpdateCodeowners( | ||
| repoValue ?? "", | ||
|
|
@@ -116,7 +117,7 @@ public override async Task HandleCommand(InvocationContext ctx, CancellationToke | |
| serviceOwnersValue?.ToList() ?? new List<string>(), | ||
| sourceOwnersValue?.ToList() ?? new List<string>(), | ||
| isAddingValue, | ||
| workingBranchValue ?? ""); | ||
| prNumberValue); | ||
| ctx.ExitCode = ExitCode; | ||
| output.Output(addResult); | ||
| return; | ||
|
|
@@ -126,11 +127,13 @@ public override async Task HandleCommand(InvocationContext ctx, CancellationToke | |
| var validateRepo = commandParser.GetValueForOption(repoOption); | ||
| var validateServiceLabel = commandParser.GetValueForOption(serviceLabelOption); | ||
| var validateRepoPath = commandParser.GetValueForOption(pathOptionOptional); | ||
| var prNumberValue = commandParser.GetValueForOption(prNumberOption); | ||
|
|
||
| var validateResult = await ValidateCodeownersEntryForService( | ||
| validateRepo ?? "", | ||
| validateServiceLabel, | ||
| validateRepoPath); | ||
| validateRepoPath, | ||
| prNumberValue); | ||
| ctx.ExitCode = ExitCode; | ||
| output.Output(validateResult); | ||
| return; | ||
|
|
@@ -152,7 +155,7 @@ public async Task<string> UpdateCodeowners( | |
| List<string> serviceOwners = null, | ||
| List<string> sourceOwners = null, | ||
| bool isAdding = false, | ||
| string workingBranch = "") | ||
| int prNumber = 0) | ||
| { | ||
| try | ||
| { | ||
|
|
@@ -162,29 +165,28 @@ public async Task<string> UpdateCodeowners( | |
| throw new Exception($"Service label: {serviceLabel} and Path: {path} are both invalid. At least one must be valid"); | ||
| } | ||
|
|
||
| if (workingBranch.Equals("main", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| throw new Exception($"Cannot make changes on branch: {workingBranch}"); | ||
| } | ||
| else if (string.IsNullOrEmpty(workingBranch)) | ||
| { | ||
| var codeownersPullRequests = (await githubService.SearchPullRequestsByTitleAsync(Constants.AZURE_OWNER_PATH, repo, "[CODEOWNERS]")) | ||
| ?? new List<PullRequest?>().AsReadOnly(); | ||
| string workingBranch = ""; | ||
| string repoOwner = ""; | ||
|
|
||
| foreach (var codeownersPullRequest in codeownersPullRequests) | ||
| // Resolve PR number to actual branch name if provided. | ||
| if (prNumber > 0) | ||
| { | ||
| var pr = await githubService.GetPullRequestAsync(Constants.AZURE_OWNER_PATH, repo, prNumber); | ||
| if (pr == null) | ||
| { | ||
| if (codeownersPullRequest != null && | ||
| ((!string.IsNullOrEmpty(serviceLabel) && codeownersPullRequest.Title.Contains(serviceLabel, StringComparison.OrdinalIgnoreCase)) || | ||
| (!string.IsNullOrEmpty(path) && codeownersPullRequest.Title.Contains(path, StringComparison.OrdinalIgnoreCase)))) | ||
| { | ||
| workingBranch = codeownersPullRequest.Head.Ref; | ||
| break; | ||
| } | ||
| throw new Exception($"Pull request #{prNumber} could not be found or retrieved from repository '{repo}'."); | ||
| } | ||
| workingBranch = pr.Head.Ref; | ||
| repoOwner = pr.Head.Repository.Owner.Login; | ||
| } | ||
|
|
||
| if (string.IsNullOrEmpty(repoOwner)) | ||
| { | ||
| repoOwner = Constants.AZURE_OWNER_PATH; | ||
| } | ||
|
shirelmr marked this conversation as resolved.
|
||
|
|
||
| // Get codeowners file contents. | ||
| var codeownersFileContent = await githubService.GetContentsSingleAsync(Constants.AZURE_OWNER_PATH, repo, Constants.AZURE_CODEOWNERS_PATH, workingBranch); | ||
| var codeownersFileContent = await githubService.GetContentsSingleAsync(repoOwner, repo, Constants.AZURE_CODEOWNERS_PATH, workingBranch); | ||
|
|
||
| if (codeownersFileContent == null) | ||
| { | ||
|
|
@@ -233,7 +235,8 @@ public async Task<string> UpdateCodeowners( | |
| $"Update codeowners entry for {identifier}", // Description for commit message, PR title, and description | ||
| "update-codeowners-entry", // Branch prefix for the action | ||
| identifier, // Identifier for the PR | ||
| workingBranch); | ||
| workingBranch, | ||
| repoOwner); | ||
|
|
||
| return string.Join("\n", resultMessages.Concat(new[] { codeownersValidationResultMessage })); | ||
| } | ||
|
|
@@ -251,13 +254,22 @@ private async Task<List<string>> CreateCodeownersPR( | |
| string description, // used for commit message, PR title, and PR description | ||
| string branchPrefix, | ||
| string identifier, | ||
| string workingBranch) | ||
| string workingBranch, | ||
| string repoOwner) | ||
| { | ||
| List<string> resultMessages = new(); | ||
| var branchName = ""; | ||
| var hasPushPermissions = await githubService.HasPushPermission(repoOwner, repo); | ||
|
|
||
| if (!hasPushPermissions) | ||
| { | ||
| resultMessages.Add($"GitHub token does not have permission to push to {repoOwner} repository, opening a new PR on a branch in the main repo"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure I understand this message. The user can't create a PR so the tool is going to create it for them? |
||
| repoOwner = Constants.AZURE_OWNER_PATH; | ||
| workingBranch = ""; | ||
| } | ||
|
|
||
| // Check if we have a working branch from SDK generation | ||
| if (!string.IsNullOrEmpty(workingBranch) && await githubService.IsExistingBranchAsync(Constants.AZURE_OWNER_PATH, repo, workingBranch)) | ||
| if (!string.IsNullOrEmpty(workingBranch) && await githubService.IsExistingBranchAsync(repoOwner, repo, workingBranch)) | ||
| { | ||
| branchName = workingBranch; | ||
| resultMessages.Add($"Using existing branch: {branchName}"); | ||
|
|
@@ -271,7 +283,7 @@ private async Task<List<string>> CreateCodeownersPR( | |
| } | ||
|
|
||
| // After branchName is set | ||
| var codeownersFileContent = await githubService.GetContentsSingleAsync(Constants.AZURE_OWNER_PATH, repo, Constants.AZURE_CODEOWNERS_PATH, branchName); | ||
| var codeownersFileContent = await githubService.GetContentsSingleAsync(repoOwner, repo, Constants.AZURE_CODEOWNERS_PATH, branchName); | ||
|
|
||
| if (codeownersFileContent == null) | ||
| { | ||
|
|
@@ -281,7 +293,7 @@ private async Task<List<string>> CreateCodeownersPR( | |
| var codeownersSha = codeownersFileContent.Sha; | ||
|
|
||
| // Use codeownersSha in UpdateFileAsync | ||
| await githubService.UpdateFileAsync(Constants.AZURE_OWNER_PATH, repo, Constants.AZURE_CODEOWNERS_PATH, description, modifiedContent, codeownersSha, branchName); | ||
| await githubService.UpdateFileAsync(repoOwner, repo, Constants.AZURE_CODEOWNERS_PATH, description, modifiedContent, codeownersSha, branchName); | ||
|
|
||
| var prInfoList = await githubService.CreatePullRequestAsync(repo, Constants.AZURE_OWNER_PATH, "main", branchName, "[CODEOWNERS] " + description, description); | ||
| if (prInfoList != null) | ||
|
|
@@ -298,7 +310,7 @@ private async Task<List<string>> CreateCodeownersPR( | |
| } | ||
|
|
||
| [McpServerTool(Name = "azsdk_engsys_validate_codeowners_entry_for_service"), Description("Validates codeowners in a specific repository for a given service or repo path.")] | ||
| public async Task<ServiceCodeownersResult> ValidateCodeownersEntryForService(string repoName, string? serviceLabel = null, string? path = null) | ||
| public async Task<ServiceCodeownersResult> ValidateCodeownersEntryForService(string repoName, string? serviceLabel = null, string? path = null, int prNumber = 0) | ||
| { | ||
| ServiceCodeownersResult response = new() { }; | ||
|
|
||
|
|
@@ -316,17 +328,19 @@ public async Task<ServiceCodeownersResult> ValidateCodeownersEntryForService(str | |
| throw new Exception("Must provide a service label or a repository path."); | ||
| } | ||
|
|
||
| var workingBranch = ""; | ||
| var codeownersPullRequests = await githubService.SearchPullRequestsByTitleAsync(Constants.AZURE_OWNER_PATH, repoName, "[CODEOWNERS]"); | ||
| string workingBranch = ""; | ||
| string repoOwner = Constants.AZURE_OWNER_PATH; | ||
|
|
||
| foreach (var codeownersPullRequest in codeownersPullRequests) | ||
| if (prNumber > 0) | ||
| { | ||
| if (codeownersPullRequest != null && | ||
| ((!string.IsNullOrEmpty(serviceLabel) && codeownersPullRequest.Title.Contains(serviceLabel, StringComparison.OrdinalIgnoreCase)) || | ||
| (!string.IsNullOrEmpty(path) && codeownersPullRequest.Title.Contains(path, StringComparison.OrdinalIgnoreCase)))) | ||
| var pr = await githubService.GetPullRequestAsync(Constants.AZURE_OWNER_PATH, repoName, prNumber); | ||
|
shirelmr marked this conversation as resolved.
|
||
| if (pr == null) | ||
| { | ||
| workingBranch = codeownersPullRequest.Head.Ref; | ||
| response.Message += $"Pull request #{prNumber} not found in repository '{repoName}'."; | ||
| return response; | ||
| } | ||
| workingBranch = pr.Head.Ref; | ||
| repoOwner = pr.Head.Repository.Owner.Login; | ||
| } | ||
|
|
||
| if (workingBranch.Equals("main", StringComparison.OrdinalIgnoreCase)) | ||
|
|
@@ -337,10 +351,10 @@ public async Task<ServiceCodeownersResult> ValidateCodeownersEntryForService(str | |
| CodeownersEntry? matchingEntry; | ||
| try | ||
| { | ||
| var contents = await githubService.GetContentsSingleAsync("Azure", "azure-sdk-for-net", ".github/CODEOWNERS", workingBranch); | ||
| var contents = await githubService.GetContentsSingleAsync(repoOwner, repoName, ".github/CODEOWNERS", workingBranch); | ||
| if (contents == null) | ||
| { | ||
| throw new Exception("Could not retrieve upstream CODEOWNERS (azure-sdk-for-net) for the requested branch."); | ||
| throw new Exception($"Could not retrieve upstream CODEOWNERS ({repoName}) for the requested branch."); | ||
| } | ||
| var codeownersContent = contents.Content; | ||
| var codeownersSha = contents.Sha; | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.