/// <summary> /// Add the default branch protections to the provided branch in the specified repository /// </summary> /// <param name="repositoryName">New repository created that needs branch protections</param> public async Task AddBranchProtections(string repositoryName) { // The webhook payload does not seem to have the correct Default Branch name, its defaulted to master // Also the repository doesn't seem to report the correct default branch consistently either var repo = await client.Repository.Get(Organization, repositoryName); if (Configuration["DefaultBranch"] != repo.DefaultBranch) { Console.WriteLine("Specified default did not match the repo"); } if (await AwaitDefaultBranch(repositoryName, Configuration["DefaultBranch"])) { // Adding Branch protections // Required PR Reviews: Dismiss stale reviews and requiring at least 1 required approver // Enforce Admins to follow branch policy as well var requiredPullRequestReviews = new BranchProtectionRequiredReviewsUpdate(true, false, 1); var branchProtections = new BranchProtectionSettingsUpdate(null, requiredPullRequestReviews, null, true); var result = await client.Repository.Branch.UpdateBranchProtection(Organization, repositoryName, repo.DefaultBranch, branchProtections); // Create and close an issue in this repository denoting the actions we've taken await CreateIssue(repositoryName); } else { Console.WriteLine("Default branch not detected"); } }
public async Task UpdatesReviewEnforcementWithRepositoryId() { var repoId = _userRepoContext.RepositoryId; var update = new BranchProtectionRequiredReviewsUpdate(false, true); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); }
public async Task UpdatesReviewEnforcement() { var repoOwner = _userRepoContext.RepositoryOwner; var repoName = _userRepoContext.RepositoryName; var update = new BranchProtectionRequiredReviewsUpdate(false, true, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.True(requiredReviews.RequireCodeOwnerReviews); Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); }
public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryId() { var repoId = _orgRepoContext.RepositoryContext.RepositoryId; var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(true), false, false); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Empty(requiredReviews.DismissalRestrictions.Teams); Assert.Empty(requiredReviews.DismissalRestrictions.Users); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); }
public async Task UpdatesReviewEnforcementForOrgRepo() { var repoOwner = _orgRepoContext.RepositoryContext.RepositoryOwner; var repoName = _orgRepoContext.RepositoryContext.RepositoryName; var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false); var requiredReviews = await _client.UpdateReviewEnforcement(repoOwner, repoName, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); }
public async Task UpdatesReviewEnforcementForOrgRepoWithRepositoryId() { var repoId = _orgRepoContext.RepositoryContext.RepositoryId; var update = new BranchProtectionRequiredReviewsUpdate( new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(false), false, false, 2); var requiredReviews = await _client.UpdateReviewEnforcement(repoId, "master", update); Assert.Null(requiredReviews.DismissalRestrictions); Assert.False(requiredReviews.DismissStaleReviews); Assert.False(requiredReviews.RequireCodeOwnerReviews); Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount); }
/// <summary> /// /// </summary> /// <param name="orgNm">Organization Name</param> /// <param name="id">Repository ID</param> private async void ExecuteProtection(Dictionary <string, object> result) { // get repository name string orgNm = (JObject.FromObject(result["organization"]).ToObject <Dictionary <string, object> >())["login"].ToString(); // get repository ID long id = long.Parse((JObject.FromObject(result["repository"]).ToObject <Dictionary <string, object> >())["id"].ToString()); // Login Credentials cre = new Credentials(_setting.Value.Email, _setting.Value.Pwd); GitHubClient ghc = new GitHubClient(new ProductHeaderValue(orgNm)); ghc.Credentials = cre; // Check for branches amount var repoBranches = await ghc.Repository.Branch.GetAll(id); if (repoBranches.Count > 0) // Check if there is at least a branch { // get the master branch var master = repoBranches.Where(br => br.Name.Equals("master")).FirstOrDefault(); if (!master.Protected) { // set protection BranchProtectionRequiredReviewsUpdate bprru = new BranchProtectionRequiredReviewsUpdate(true, true, 1); BranchProtectionSettingsUpdate Setting = new BranchProtectionSettingsUpdate(bprru); await ghc.Repository.Branch.UpdateBranchProtection(id, "master", Setting); // mentioning oneself var ic = ghc.Issue; var newIssue = new NewIssue("Master Branch Protection Validation") { Body = "Hi @" + _setting.Value.MentionAccount + " , Please check if the master branch protection is valid!" }; var issue = await ic.Create(id, newIssue); } } }
internal async Task UpdateBranches() { Console.WriteLine("Enter a repository name to update a single repository or * for all repositories"); var response = Console.ReadLine(); Log.Debug("Getting repositories for organisation {Organisation}", _organisationName); var branches = new List <(long repositoryId, string repositoryName, string branchName)>(); Console.WriteLine("Getting branches..."); if (response != "*") { Console.WriteLine("Continuing with single repository"); Log.Debug("Updating single repository {RepositoryName}", response); var repo = await _client.Repository.Get(_organisationName, response); await FetchBranchesInRepository(repo.Id, repo.Name); } else { Console.WriteLine("Continuing with all repositories"); Log.Debug("Updating all repositories, fetching repositories"); var repositories = await _client.Repository.GetAllForOrg(_organisationName); foreach (var repository in repositories) { await FetchBranchesInRepository(repository.Id, repository.Name); } } Console.WriteLine("Enter a comma separated list of branches to update or * for all branches in a given repository"); var branchUpdateResponse = Console.ReadLine(); var branchesToUpdate = new List <string>(); if (!string.IsNullOrWhiteSpace(response)) { branchesToUpdate = branchUpdateResponse.Split(',').ToList(); Log.Debug("Updating {NumberOfBranches} branches: {IgnoredRepositories}", branchesToUpdate.Count, branchesToUpdate); } else { Log.Debug("Updating all branches in the target repositories"); } Console.WriteLine("Configure global settings"); Console.WriteLine("Respond Y or yes to enable, N or no to disable and just enter to leave a setting as is on the target repository"); Console.WriteLine("Default: leave setting as is"); var isStrict = AskYesNoOrDefaultResponse("Require strict PR reviews (branch must be up to date with merge target)"); var enableStaleReviews = AskYesNoOrDefaultResponse("Enable reset approval on stale branch (reset approvals on PRs on every new change)"); var enableCodeOwners = AskYesNoOrDefaultResponse("Enable require code owner review (code owners must review PRs)"); var enforceAdmins = AskYesNoOrDefaultResponse("Enable admin enforcement (enforce some rules on administrators of the repository)"); Console.WriteLine("Other settings, these DO NOT require Y (yes) or N (no)"); var numberOfReviewsRequired = AskIntResponse("Specify number of reviews required for a PR before it can be merged"); const string DELETE_ALL_TEAMS_COMMAND = "DELETE_ALL_TEAMS"; var teamsToAdd = AskListResponse($"Enter a comma separated list of teams to set to the protection levels, enter {DELETE_ALL_TEAMS_COMMAND} to remove all current teams, press enter to leave empty and existing teams"); if (teamsToAdd.Count > 1 && teamsToAdd.Any(x => x.Equals(DELETE_ALL_TEAMS_COMMAND, StringComparison.CurrentCultureIgnoreCase))) { throw new InvalidOperationException("Cannot delete all teams when there is more than one team specified, to override teams provide just the list of teams that are desired"); } var teamsToSetAsBranchProtectors = new List <string>(); if (teamsToAdd.Any(x => !x.Equals(DELETE_ALL_TEAMS_COMMAND, StringComparison.CurrentCultureIgnoreCase))) { teamsToSetAsBranchProtectors.AddRange(teamsToAdd); } Console.WriteLine("Processing updates to branches..."); Log.Debug( $"Updating branches with require strict reviews: {isStrict}, " + $"reset approval: {enableStaleReviews}, " + $"code owners: {enableCodeOwners}, " + $"enforce on admins: {enforceAdmins}, " + $"number of reviews: {numberOfReviewsRequired}, " + $"teams: {string.Join(", ", teamsToSetAsBranchProtectors)}"); foreach (var(branchRepositoryId, branchRepositoryName, branchName) in branches) { if (branchesToUpdate.Any() && !branchesToUpdate.Any(x => x.Equals(branchName, StringComparison.CurrentCultureIgnoreCase))) { Log.Debug("Ignoring branch {BranchName} in repository {RepositoryId}", branchName, branchRepositoryId); continue; } Log.Debug("Processing update for branch {BranchName} in repository {RepositoryId}", branchName, branchRepositoryId); var currentProtection = new BranchProtectionSettings(new BranchProtectionRequiredStatusChecks(false, new List <string>()), new BranchProtectionPushRestrictions(new List <Team>(), new List <User>()), new BranchProtectionRequiredReviews(), new EnforceAdmins(false)); try { currentProtection = await _client.Repository.Branch.GetBranchProtection(branchRepositoryId, branchName); } catch (Exception) { // There may not be protection on the branch } var statusChecks = new BranchProtectionRequiredStatusChecksUpdate(isStrict ?? currentProtection.RequiredStatusChecks.Strict, currentProtection.RequiredStatusChecks.Contexts); var pullRequestRequirements = new BranchProtectionRequiredReviewsUpdate( enableStaleReviews ?? currentProtection.RequiredPullRequestReviews.DismissStaleReviews, enableCodeOwners ?? currentProtection.RequiredPullRequestReviews.RequireCodeOwnerReviews, numberOfReviewsRequired ?? currentProtection.RequiredPullRequestReviews.RequiredApprovingReviewCount); BranchProtectionPushRestrictionsUpdate pushRestrictions = null; if (teamsToSetAsBranchProtectors.Any()) { pushRestrictions = new BranchProtectionPushRestrictionsUpdate(new BranchProtectionTeamCollection(teamsToSetAsBranchProtectors)); } var enforceBranchProtectionOnAdmins = enforceAdmins ?? currentProtection.EnforceAdmins.Enabled; await _client.Repository.Branch.UpdateBranchProtection(branchRepositoryId, branchName, new BranchProtectionSettingsUpdate(statusChecks, pullRequestRequirements, pushRestrictions, enforceBranchProtectionOnAdmins)); Log.Debug("Processed update for branch {BranchName} in repository {RepositoryId}", branchName, branchRepositoryId); Console.WriteLine($"Processed {branchRepositoryName}/{branchName}"); } Console.WriteLine("Finished processing branches!"); async Task FetchBranchesInRepository(long repositoryId, string repositoryName) { var branchesInRepository = await _client.Repository.Branch.GetAll(repositoryId); branches.AddRange(branchesInRepository.Select(x => (repositoryId, repositoryName, x.Name))); } }