public override async Task Action(Repository repo) { try { BranchProtectionRequiredStatusChecks statusChecks; BranchProtectionRequiredStatusChecksUpdate statusChecksUpdate; if (cachedStatusContexts.TryGetValue(repo.Name, out statusChecks)) { statusChecksUpdate = new BranchProtectionRequiredStatusChecksUpdate(false, statusChecks.Contexts); } else { statusChecksUpdate = new BranchProtectionRequiredStatusChecksUpdate(false, EmptyContexts); } l($"[MODIFING] Setting branch protections on {repo.Name} to unstrict and with contexts {string.Join(",", statusChecksUpdate.Contexts)} ", 1); await Client.Repository.Branch.UpdateBranchProtection( repo.Owner.Login, repo.Name, repo.DefaultBranch, new BranchProtectionSettingsUpdate( statusChecksUpdate, new BranchProtectionRequiredReviewsUpdate(false, false, reviewers), false ) ); } catch (Octokit.NotFoundException) { l($"[WARN] could not set anything on {repo.Name} because {repo.DefaultBranch} does not exist.", 1); } }
public async Task UpdatesRequiredStatusChecksWithRepositoryId() { var repoId = _userRepoContext.RepositoryId; var update = new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "new" }); var requiredStatusChecks = await _client.UpdateRequiredStatusChecks(repoId, "master", update); Assert.NotNull(requiredStatusChecks); Assert.NotNull(requiredStatusChecks.Contexts); Assert.True(requiredStatusChecks.Contexts.Contains("new")); Assert.True(requiredStatusChecks.Strict); Assert.Equal(1, requiredStatusChecks.Contexts.Count); }
public override async Task Action(Protection.RepoUpdate repo) { var settings = RepoSettingsFor(repo.Name); try { BranchProtectionRequiredStatusChecks statusChecks; BranchProtectionRequiredStatusChecksUpdate statusChecksUpdate; if (cachedStatusContexts.TryGetValue(repo.Name, out statusChecks)) { statusChecksUpdate = new BranchProtectionRequiredStatusChecksUpdate(false, statusChecks.Contexts); } else { statusChecksUpdate = new BranchProtectionRequiredStatusChecksUpdate(false, EmptyContexts); } l($"[MODIFING] Setting branch protections on {repo.Name} to unstrict, require code owners reviews and with contexts {string.Join(",", statusChecksUpdate.Contexts)} ", 1); await Client.Repository.Branch.UpdateBranchProtection( Config.Github.Org , repo.Name , repo.DefaultBranch , new BranchProtectionSettingsUpdate( statusChecksUpdate, new BranchProtectionRequiredReviewsUpdate( settings.DismissStaleReviews , settings.RequireCodeOwnerReviews , settings.Reviewers ) , false ) ); } catch (Octokit.NotFoundException) { l($"[WARN] could not set anything on {repo.Name} because {repo.DefaultBranch} does not exist.", 1); } }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="repositoryId">The Id of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public IObservable <BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(long repositoryId, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return(_client.UpdateRequiredStatusChecks(repositoryId, branch, update).ToObservable()); }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="owner">The owner of the repository</param> /// <param name="name">The name of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public IObservable <BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(string owner, string name, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return(_client.UpdateRequiredStatusChecks(owner, name, branch, update).ToObservable()); }
public async Task EnsuresNonNullArguments() { var client = new ObservableRepositoryBranchesClient(Substitute.For<IGitHubClient>()); var update = new BranchProtectionRequiredStatusChecksUpdate(true, true, new[] { "test" }); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks(null, "repo", "branch", update)); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks("owner", null, "branch", update)); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks("owner", "repo", null, update)); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks("owner", "repo", "branch", null)); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks(1, null, update)); Assert.Throws<ArgumentNullException>(() => client.UpdateRequiredStatusChecks(1, "branch", null)); Assert.Throws<ArgumentException>(() => client.UpdateRequiredStatusChecks("", "repo", "branch", update)); Assert.Throws<ArgumentException>(() => client.UpdateRequiredStatusChecks("owner", "", "branch", update)); Assert.Throws<ArgumentException>(() => client.UpdateRequiredStatusChecks("owner", "repo", "", update)); Assert.Throws<ArgumentException>(() => client.UpdateRequiredStatusChecks(1, "", update)); }
public void RequestsTheCorrectUrlWithRepositoryId() { var gitHubClient = Substitute.For<IGitHubClient>(); var client = new ObservableRepositoryBranchesClient(gitHubClient); var update = new BranchProtectionRequiredStatusChecksUpdate(true, true, new[] { "test" }); client.UpdateRequiredStatusChecks(1, "branch", update); gitHubClient.Repository.Branch.Received() .UpdateRequiredStatusChecks(1, "branch", update); }
public async Task UpdatesRequiredStatusChecksWithRepositoryId() { var repoId = _userRepoContext.RepositoryId; var update = new BranchProtectionRequiredStatusChecksUpdate(true, true, new[] { "new" }); var requiredStatusChecks = await _client.UpdateRequiredStatusChecks(repoId, "master", update); Assert.NotNull(requiredStatusChecks); Assert.NotNull(requiredStatusChecks.Contexts); Assert.True(requiredStatusChecks.Contexts.Contains("new")); Assert.True(requiredStatusChecks.IncludeAdmins); Assert.True(requiredStatusChecks.Strict); Assert.Equal(1, requiredStatusChecks.Contexts.Count); }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="repositoryId">The Id of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public IObservable<BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(long repositoryId, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return _client.UpdateRequiredStatusChecks(repositoryId, branch, update).ToObservable(); }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="owner">The owner of the repository</param> /// <param name="name">The name of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public IObservable<BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(string owner, string name, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return _client.UpdateRequiredStatusChecks(owner, name, branch, update).ToObservable(); }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="repositoryId">The Id of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public Task<BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(long repositoryId, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return ApiConnection.Patch<BranchProtectionRequiredStatusChecks>(ApiUrls.RepoRequiredStatusChecks(repositoryId, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); }
/// <summary> /// Replace required status checks for the specified branch /// </summary> /// <remarks> /// See the <a href="https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch">API documentation</a> for more details /// </remarks> /// <param name="owner">The owner of the repository</param> /// <param name="name">The name of the repository</param> /// <param name="branch">The name of the branch</param> /// <param name="update">Required status checks</param> public Task<BranchProtectionRequiredStatusChecks> UpdateRequiredStatusChecks(string owner, string name, string branch, BranchProtectionRequiredStatusChecksUpdate update) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); Ensure.ArgumentNotNull(update, "update"); return ApiConnection.Patch<BranchProtectionRequiredStatusChecks>(ApiUrls.RepoRequiredStatusChecks(owner, name, branch), update, AcceptHeaders.ProtectedBranchesApiPreview); }
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))); } }
public void RequestsTheCorrectUrlWithRepositoryId() { var connection = Substitute.For<IApiConnection>(); var client = new RepositoryBranchesClient(connection); var update = new BranchProtectionRequiredStatusChecksUpdate(true, true, new[] { "test" }); const string previewAcceptsHeader = "application/vnd.github.loki-preview+json"; client.UpdateRequiredStatusChecks(1, "branch", update); connection.Received() .Patch<BranchProtectionRequiredStatusChecks>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/branches/branch/protection/required_status_checks"), Arg.Any<BranchProtectionRequiredStatusChecksUpdate>(), previewAcceptsHeader); }