Пример #1
0
        /// <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);
            }
Пример #3
0
            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);
            }
Пример #6
0
            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);
            }
Пример #7
0
        /// <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);
                }
            }
        }
Пример #8
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)));
            }
        }