예제 #1
0
        public async Task <IRemote> GetRemoteAsync(string repoUrl, ILogger logger)
        {
            using (_operations.BeginOperation($"Getting remote for repo {repoUrl}."))
            {
                // Normalize the url with the AzDO client prior to attempting to
                // get a token. When we do coherency updates we build a repo graph and
                // may end up traversing links to classic azdo uris.
                string normalizedUrl     = AzureDevOpsClient.NormalizeUrl(repoUrl);
                Uri    normalizedRepoUri = new Uri(normalizedUrl);
                // Look up the setting for where the repo root should be held.  Default to empty,
                // which will use the temp directory.
                string temporaryRepositoryRoot = _configuration.GetValue <string>("DarcTemporaryRepoRoot", null);
                if (string.IsNullOrEmpty(temporaryRepositoryRoot))
                {
                    temporaryRepositoryRoot = _tempFiles.GetFilePath("repos");
                }
                IGitRepo gitClient;

                long installationId = await _context.GetInstallationId(normalizedUrl);

                var gitExe = await ExponentialRetry.RetryAsync(
                    async() => await _localGit.GetPathToLocalGitAsync(),
                    ex => logger.LogError(ex, $"Failed to install git to local temporary directory."),
                    ex => true);

                switch (normalizedRepoUri.Host)
                {
                case "github.com":
                    if (installationId == default)
                    {
                        throw new GithubApplicationInstallationException($"No installation is avaliable for repository '{normalizedUrl}'");
                    }

                    gitClient = new GitHubClient(gitExe, await _gitHubTokenProvider.GetTokenForInstallationAsync(installationId),
                                                 logger, temporaryRepositoryRoot, _cache.Cache);
                    break;

                case "dev.azure.com":
                    gitClient = new AzureDevOpsClient(gitExe, await _azureDevOpsTokenProvider.GetTokenForRepository(normalizedUrl),
                                                      logger, temporaryRepositoryRoot);
                    break;

                default:
                    throw new NotImplementedException($"Unknown repo url type {normalizedUrl}");
                }
                ;

                return(new Remote(gitClient, new MaestroBarClient(_context), logger));
            }
        }
예제 #2
0
        /// <summary>
        /// Github authentication.
        /// </summary>
        /// <param name="issueRepo">Repository where gitHub issue is created.</param>
        /// <returns>Authenticated GithubClient</returns>
        private async Task <GitHubClient> AuthenticateGitHubClient(string issueRepo)
        {
            IGitHubTokenProvider gitHubTokenProvider = _context.GetService <IGitHubTokenProvider>();
            long installationId = await _context.GetInstallationId(issueRepo);

            string gitHubToken = await gitHubTokenProvider.GetTokenForInstallationAsync(installationId);

            _logger.LogInformation($"GitHub token acquired for '{issueRepo}'");
            string version = Assembly.GetExecutingAssembly()
                             .GetCustomAttribute <AssemblyInformationalVersionAttribute>()
                             .InformationalVersion;
            ProductHeaderValue product = new ProductHeaderValue("Maestro", version);

            return(new GitHubClient(product)
            {
                Credentials = new Credentials(gitHubToken),
            });
        }
        private async Task CreateGitHubIssueAsync(int buildId, int releaseId, string releaseName)
        {
            Logger.LogInformation($"Something failed in release definition {releaseId} triggered by build {buildId}");

            Build  build = Context.Builds.Where(b => b.Id == buildId).First();
            string whereToCreateIssue = "https://github.com/dotnet/arcade";
            string fyiHandles = "@JohnTortugo, @riarenas";
            string gitHubToken = null, azureDevOpsToken = null;
            string repo = build.GitHubRepository ?? build.AzureDevOpsRepository;

            using (Logger.BeginScope($"Opening GitHub issue for release definition {releaseId} " +
                                     $"triggered by build {buildId} from repo '{repo}'."))
            {
                try
                {
                    // We get the token of the repo which triggered the release so we can get the author.
                    if (!string.IsNullOrEmpty(build.GitHubRepository))
                    {
                        IGitHubTokenProvider gitHubTokenProvider = Context.GetService <IGitHubTokenProvider>();
                        long installationId = await Context.GetInstallationId(build.GitHubRepository);

                        gitHubToken = await gitHubTokenProvider.GetTokenForInstallationAsync(installationId);

                        Logger.LogInformation($"GitHub token acquired for '{build.GitHubRepository}'!");
                    }

                    if (!string.IsNullOrEmpty(build.AzureDevOpsRepository))
                    {
                        IAzureDevOpsTokenProvider azdoTokenProvider = Context.GetService <IAzureDevOpsTokenProvider>();
                        azureDevOpsToken = await azdoTokenProvider.GetTokenForAccount(build.AzureDevOpsAccount);

                        Logger.LogInformation($"AzureDevOPs token acquired for '{build.AzureDevOpsRepository}'!");
                    }

                    IssueManager issueManager = new IssueManager(gitHubToken, azureDevOpsToken);

                    string title       = $"Release '{releaseName}' with id {releaseId} failed";
                    string description = $"Something failed while running an async release pipeline for build " +
                                         $"[{build.AzureDevOpsBuildNumber}](https://dnceng.visualstudio.com/internal/_build/results?buildId={build.AzureDevOpsBuildId})." +
                                         $"{Environment.NewLine} {Environment.NewLine}" +
                                         $"Please click [here](https://dnceng.visualstudio.com/internal/_releaseProgress?_a=release-pipeline-progress&releaseId={releaseId}) to check the error logs." +
                                         $" {Environment.NewLine} {Environment.NewLine}" +
                                         $"/FYI: {fyiHandles}";

                    if (build.GitHubRepository != whereToCreateIssue)
                    {
                        // We get the token of the Arcade installation since there's where the actual issue will be
                        // created. We cannot reuse the previously acquired token since its generated for a
                        // different repo.
                        IGitHubTokenProvider gitHubTokenProvider = Context.GetService <IGitHubTokenProvider>();
                        long installationId = await Context.GetInstallationId(whereToCreateIssue);

                        gitHubToken = await gitHubTokenProvider.GetTokenForInstallationAsync(installationId);

                        Logger.LogInformation($"GitHub token acquired for '{whereToCreateIssue}'!");

                        issueManager = new IssueManager(gitHubToken, azureDevOpsToken);
                    }

                    int issueId = await issueManager.CreateNewIssueAsync(whereToCreateIssue, title, description);

                    Logger.LogInformation($"Issue {issueId} was created in '{whereToCreateIssue}'");
                }
                catch (Exception exc)
                {
                    Logger.LogError(exc, $"Something failed while attempting to create an issue based on repo '{repo}' " +
                                    $"and commit {build.Commit}.");
                }
            }
        }