Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
        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);
            }
        }
Ejemplo n.º 4
0
        /// <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());
        }
Ejemplo n.º 5
0
        /// <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);
        }
Ejemplo n.º 13
0
        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);
            }