Ejemplo n.º 1
0
    private static async Task MakeGithubPr(
        GithubMergeTool.GithubMergeTool gh,
        string repoOwner,
        string repoName,
        string srcBranch,
        string destBranch,
        bool addAutoMergeLabel,
        bool isAutomatedRun)
    {
        Console.WriteLine($"Merging {repoName} from {srcBranch} to {destBranch}");

        var(prCreated, error) = await gh.CreateMergePr(repoOwner, repoName, srcBranch, destBranch, addAutoMergeLabel, isAutomatedRun);

        if (prCreated)
        {
            Console.WriteLine("PR created successfully");
        }
        else if (error == null)
        {
            Console.WriteLine("PR creation skipped. PR already exists or all commits are present in base branch");
        }
        else
        {
            Console.WriteLine($"##vso[task.logissue type=error]Error creating PR. GH response code: {error.StatusCode}");
            Console.WriteLine($"##vso[task.logissue type=error]{await error.Content.ReadAsStringAsync()}");
        }
    }
Ejemplo n.º 2
0
    // Returns 'true' if all PRs were created/updated successfully.
    private static async Task <bool> RunAsync(XDocument config, bool isAutomatedRun, bool isDryRun, string githubToken)
    {
        // Since this is run on AzDO as an automated cron pipeline, times are in UTC.
        // See https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops&tabs=yaml#scheduled-triggers
        var runDateTime = DateTime.UtcNow;

        var allSuccess = true;
        var gh         = new GithubMergeTool.GithubMergeTool("*****@*****.**", githubToken, isDryRun);

        foreach (var repo in config.Root.Elements("repo"))
        {
            var owner       = repo.Attribute("owner").Value;
            var mergeOwners = repo.Attribute("mergeOwners")?.Value.Split(',').ToList() ?? new List <string>();
            var name        = repo.Attribute("name").Value;

            // We don't try to update existing PR unless asked.
            var updateExistingPr = bool.Parse(repo.Attribute("updateExistingPr")?.Value ?? "false");

            foreach (var merge in repo.Elements("merge"))
            {
                var fromBranch = merge.Attribute("from").Value;
                var toBranch   = merge.Attribute("to").Value;

                if (!ShouldRunMerge(merge, isAutomatedRun, runDateTime))
                {
                    continue;
                }

                var prOwners          = merge.Attribute("owners")?.Value.Split(',').ToList() ?? mergeOwners;
                var addAutoMergeLabel = bool.Parse(merge.Attribute("addAutoMergeLabel")?.Value ?? "true");
                try
                {
                    var(success, shouldContinue) = await MakeGithubPr(gh, owner, name, prOwners, fromBranch, toBranch,
                                                                      updateExistingPr, addAutoMergeLabel, isAutomatedRun, isDryRun, githubToken);

                    allSuccess = allSuccess && success;
                    if (!shouldContinue)
                    {
                        return(false);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("##vso[task.logissue type=error]Error creating merge PR.", ex);
                }
                finally
                {
                    // Delay in order to avoid triggering GitHub rate limiting
                    await Task.Delay(4000);
                }
            }
        }

        return(allSuccess);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Make requests to github to merge a source branch into a destination branch.
    /// </summary>
    private static async Task <(bool success, bool shouldContinue)> MakeGithubPr(
        GithubMergeTool.GithubMergeTool gh,
        string repoOwner,
        string repoName,
        List <string> prOwners,
        string srcBranch,
        string destBranch,
        bool updateExistingPr,
        bool addAutoMergeLabel,
        bool isAutomatedRun,
        bool isDryRun,
        string githubToken)
    {
        Console.WriteLine($"Merging {repoName} from {srcBranch} to {destBranch}");

        var(prCreated, error) = await gh.CreateMergePr(repoOwner, repoName, prOwners, srcBranch, destBranch, updateExistingPr, addAutoMergeLabel, isAutomatedRun);

        if (prCreated)
        {
            Console.WriteLine("PR created successfully");
        }
        else if (error == null)
        {
            Console.WriteLine("PR creation skipped. PR already exists or all commits are present in base branch");
        }
        else
        {
            var errorStatus = error.StatusCode;
            var isWarning   = errorStatus == HttpStatusCode.UnprocessableEntity || errorStatus == HttpStatusCode.NotFound;
            var issueType   = isWarning ? "warning" : "error";
            Console.WriteLine($"##vso[task.logissue type={issueType}]Error creating PR. GH response code: {error.StatusCode}");
            Console.WriteLine($"##vso[task.logissue type={issueType}]{await error.Content.ReadAsStringAsync()}");

            // Github rate limits are much lower for unauthenticated users.  We will definitely hit a rate limit
            // If we hit it during a dryrun, just bail out.
            if (isDryRun && string.IsNullOrWhiteSpace(githubToken))
            {
                if (TryGetRemainingRateLimit(error.Headers, out var remainingRateLimit) && remainingRateLimit == 0)
                {
                    Console.WriteLine($"##vso[task.logissue type=error]Hit GitHub rate limit in dryrun with no auth token.  Bailing out.");
                    return(success : false, shouldContinue : false);
                }
            }


            return(success : isWarning, shouldContinue : true);
        }

        return(success : true, shouldContinue : true);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Make requests to github to merge a source branch into a destination branch.
    /// </summary>
    /// <returns>true if we encounter a recoverable error, false if unrecoverable.</returns>
    private static async Task <bool> MakeGithubPr(
        GithubMergeTool.GithubMergeTool gh,
        string repoOwner,
        string repoName,
        string srcBranch,
        string destBranch,
        bool addAutoMergeLabel,
        bool isAutomatedRun,
        bool isDryRun,
        string githubToken)
    {
        Console.WriteLine($"Merging {repoName} from {srcBranch} to {destBranch}");

        var(prCreated, error) = await gh.CreateMergePr(repoOwner, repoName, srcBranch, destBranch, addAutoMergeLabel, isAutomatedRun);

        if (prCreated)
        {
            Console.WriteLine("PR created successfully");
        }
        else if (error == null)
        {
            Console.WriteLine("PR creation skipped. PR already exists or all commits are present in base branch");
        }
        else
        {
            Console.WriteLine($"##vso[task.logissue type=error]Error creating PR. GH response code: {error.StatusCode}");
            Console.WriteLine($"##vso[task.logissue type=error]{await error.Content.ReadAsStringAsync()}");

            // Github rate limits are much lower for unauthenticated users.  We will definitely hit a rate limit
            // If we hit it during a dryrun, just bail out.
            if (isDryRun && string.IsNullOrWhiteSpace(githubToken))
            {
                if (TryGetRemainingRateLimit(error.Headers, out var remainingRateLimit) && remainingRateLimit == 0)
                {
                    Console.WriteLine($"##vso[task.logissue type=error]Hit GitHub rate limit in dryrun with no auth token.  Bailing out.");
                    return(false);
                }
            }
        }

        return(true);
    }
Ejemplo n.º 5
0
    private static async Task RunAsync(XDocument config, bool isAutomatedRun, bool isDryRun, string githubToken)
    {
        var gh = new GithubMergeTool.GithubMergeTool("*****@*****.**", githubToken, isDryRun);

        foreach (var repo in config.Root.Elements("repo"))
        {
            var owner = repo.Attribute("owner").Value;
            var name  = repo.Attribute("name").Value;
            foreach (var merge in repo.Elements("merge"))
            {
                var fromBranch = merge.Attribute("from").Value;
                var toBranch   = merge.Attribute("to").Value;

                var frequency = merge.Attribute("frequency")?.Value;
                if (isAutomatedRun && frequency == "weekly" && DateTime.Now.DayOfWeek != DayOfWeek.Sunday)
                {
                    continue;
                }

                var addAutoMergeLabel = bool.Parse(merge.Attribute("addAutoMergeLabel")?.Value ?? "true");
                try
                {
                    bool shouldContinue = await MakeGithubPr(gh, owner, name, fromBranch, toBranch, addAutoMergeLabel,
                                                             isAutomatedRun, isDryRun, githubToken);

                    if (!shouldContinue)
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("##vso[task.logissue type=error]Error creating merge PR.", ex);
                }
                finally
                {
                    // Delay in order to avoid triggering GitHub rate limiting
                    await Task.Delay(4000);
                }
            }
        }
    }