Ejemplo n.º 1
0
        /// <summary>
        /// Create notification groups for failures in scheduled builds
        /// </summary>
        /// <param name="organization">Azure DevOps Organization</param>
        /// <param name="project">Name of the DevOps project</param>
        /// <param name="pathPrefix">Path prefix to include pipelines (e.g. "\net")</param>
        /// <param name="tokenVariableName">Environment variable token name (e.g. "SYSTEM_ACCESSTOKEN")</param>
        /// <param name="selectionStrategy">Pipeline selection strategy</param>
        /// <param name="dryRun">Prints changes but does not alter any objects</param>
        /// <returns></returns>
        static async Task Main(
            string organization,
            string project,
            string pathPrefix,
            string tokenVariableName,
            PipelineSelectionStrategy selectionStrategy = PipelineSelectionStrategy.Scheduled,
            bool dryRun = false)
        {
            var devOpsToken      = Environment.GetEnvironmentVariable(tokenVariableName);
            var devOpsCreds      = new VssBasicCredential("nobody", devOpsToken);
            var devOpsConnection = new VssConnection(new Uri($"https://dev.azure.com/{organization}/"), devOpsCreds);

#pragma warning disable CS0618 // Type or member is obsolete
            var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.AddConsole(config => { config.IncludeScopes = true; });
            });
#pragma warning restore CS0618 // Type or member is obsolete
            var devOpsServiceLogger            = loggerFactory.CreateLogger <AzureDevOpsService>();
            var notificationConfiguratorLogger = loggerFactory.CreateLogger <NotificationConfigurator>();

            var devOpsService = new AzureDevOpsService(devOpsConnection, devOpsServiceLogger);

            var configurator = new NotificationConfigurator(devOpsService, notificationConfiguratorLogger);
            await configurator.ConfigureNotifications(
                project,
                pathPrefix,
                persistChanges : !dryRun,
                strategy : selectionStrategy);
        }
Ejemplo n.º 2
0
Archivo: Lazy.cs Proyecto: silvath/lazy
 public void CreatePullRequest()
 {
     if (this.Solution == null)
     {
         return;
     }
     if (this.WorkItem == null)
     {
         MessageBox.ErrorQuery(50, 7, "VSTS", "You must select a work item first", "Ok");
         return;
     }
     if (!EnsureHasNoChanges())
     {
         return;
     }
     WindowManager.ShowLog();
     GitService.CheckoutBranch(this.Solution, this.WorkItem.TaskID);
     GitService.Pull(this.Solution);
     GitService.Push(this.Solution);
     GitService.UpdateStatus(this.Solution, true);
     if (!EnsureHasNoChanges())
     {
         WindowManager.CloseLog();
         return;
     }
     GitService.Push(this.Solution);
     foreach (RepositoryVO repository in this.Solution.Repositories)
     {
         if ((!repository.Selected))
         {
             continue;
         }
         if (!GitService.HasCommits(repository, this.WorkItem, this.BranchBase))
         {
             continue;
         }
         bool isPullRequestAlreadyCreated  = false;
         List <PullRequestVO> pullRequests = AzureDevOpsService.ListPullRequests(repository.Path);
         foreach (PullRequestVO pullRequest in pullRequests)
         {
             if (isPullRequestAlreadyCreated = ((pullRequest.Repository == repository.Name) && (pullRequest.Title.StartsWith(this.WorkItem.TaskID))))
             {
                 break;
             }
         }
         if (isPullRequestAlreadyCreated)
         {
             continue;
         }
         //Create PR
         AzureDevOpsService.CreatePullRequest(repository, this.WorkItem);
     }
     GitService.UpdateStatus(this.Solution, true);
     WindowManager.CloseLog();
     this.RefreshUI();
 }
Ejemplo n.º 3
0
Archivo: Lazy.cs Proyecto: silvath/lazy
        public void AddReviewerToPullRequest()
        {
            if (this.Solution == null)
            {
                return;
            }
            if (this.WorkItem == null)
            {
                MessageBox.ErrorQuery(50, 7, "VSTS", "You must select a work item first", "Ok");
                return;
            }
            string reviewerEmail = "*****@*****.**";

            reviewerEmail = WindowManager.ShowDialogText("Choose the Reviewer", "E-mail:", reviewerEmail);
            if (string.IsNullOrEmpty(reviewerEmail))
            {
                return;
            }
            WindowManager.ShowLog();
            foreach (RepositoryVO repository in this.Solution.Repositories)
            {
                if ((!repository.Selected))
                {
                    continue;
                }
                List <PullRequestVO> pullRequests        = AzureDevOpsService.ListPullRequests(repository.Path);
                PullRequestVO        pullRequestWorkItem = null;
                foreach (PullRequestVO pullRequest in pullRequests)
                {
                    if (((pullRequest.Repository != repository.Name) || (!pullRequest.Title.StartsWith(this.WorkItem.TaskID))))
                    {
                        continue;
                    }
                    pullRequestWorkItem = pullRequest;
                    break;
                }
                if (pullRequestWorkItem == null)
                {
                    continue;
                }
                List <string> reviewers = AzureDevOpsService.ListPullRequestReviewers(repository, pullRequestWorkItem);
                if (reviewers.Contains(reviewerEmail))
                {
                    continue;
                }
                AzureDevOpsService.AddPullRequestReviewer(repository, pullRequestWorkItem, reviewerEmail);
            }
            WindowManager.CloseLog();
            this.RefreshUI();
        }
        public async Task <RocketChatUserDto[]> GetUsersAsync(Uri azureDevOpsBaseUri, Guid[] identityIds)
        {
            var identities = await AzureDevOpsService.GetAndIterateIdentitiesAsync(
                azureDevOpsBaseUri,
                identityIds
                );

            var mails = identities
                        .Select(x => x.Properties.GetOrDefault(AzureDevOpsRocketChatConsts.Identity.MailPropertyName)?.ToString())
                        .Where(x => !x.IsNullOrWhiteSpace())
                        .ToArray();

            return(await RocketChatClient.GetUsersByEmailAsync(new GetRocketChatUsersByEmailInputDto
            {
                Emails = mails
            }));
        }
        public override async Task OnWillAppear(StreamDeckEventPayload args)
        {
            this.azureDevOpsService = new AzureDevOpsService(async(message) =>
            {
                // This is only used for debugging. No-op in release builds.
#if DEBUG
                await Manager.LogMessageAsync(args.context, message);
#else
                await Task.CompletedTask;
#endif
            });
            await base.OnWillAppear(args);

            timer          = new Timer(5 * 60 * 1000);
            timer.Elapsed += async(sender, e) =>
            {
                await Manager.ShowOkAsync(args.context);
                await FetchLatestInfo(args);
            };
            timer.Start();

            await FetchLatestInfo(args);
        }
Ejemplo n.º 6
0
Archivo: Lazy.cs Proyecto: silvath/lazy
        public void ShowWorkItems()
        {
            if (this.Solution == null)
            {
                return;
            }
            if (!AzureDevOpsService.IsConfigurated())
            {
                MessageBox.ErrorQuery(50, 7, "VSTS", "You must configure VSTS client first", "Ok");
                return;
            }
            string            path                  = Directory.GetParent(this.Solution.Path).FullName;
            List <WorkItemVO> workItems             = AzureDevOpsService.ListWorkItems(path);
            Dictionary <WorkItemVO, string> objects = new Dictionary <WorkItemVO, string>();

            foreach (WorkItemVO workItem in workItems)
            {
                objects.Add(workItem, string.Format("{0} - {1}", workItem.Code, workItem.Name));
            }
            WorkItemVO workitemSelected = WindowManager.ShowDialogObjects <WorkItemVO>("WorkItems", objects);

            this.WorkItem = workitemSelected;
            this.RefreshUI();
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Synchronizes CODEOWNERS contacts to appropriate DevOps groups
        /// </summary>
        /// <param name="organization">Azure DevOps organization name</param>
        /// <param name="project">Azure DevOps project name</param>
        /// <param name="devOpsTokenVar">Personal Access Token environment variable name</param>
        /// <param name="aadAppIdVar">AAD App ID environment variable name (Kusto access)</param>
        /// <param name="aadAppSecretVar">AAD App Secret environment variable name (Kusto access)</param>
        /// <param name="aadTenantVar">AAD Tenant environment variable name (Kusto access)</param>
        /// <param name="kustoUrlVar">Kusto URL environment variable name</param>
        /// <param name="kustoDatabaseVar">Kusto DB environment variable name</param>
        /// <param name="kustoTableVar">Kusto Table environment variable name</param>
        /// <param name="pathPrefix">Azure DevOps path prefix (e.g. "\net")</param>
        /// <param name="dryRun">Do not persist changes</param>
        /// <returns></returns>
        public static async Task Main(
            string organization,
            string project,
            string devOpsTokenVar,
            string aadAppIdVar,
            string aadAppSecretVar,
            string aadTenantVar,
            string kustoUrlVar,
            string kustoDatabaseVar,
            string kustoTableVar,
            string pathPrefix = "",
            bool dryRun       = false
            )
        {
#pragma warning disable CS0618 // Type or member is obsolete
            using (var loggerFactory = LoggerFactory.Create(builder => {
                builder.AddConsole(config => { config.IncludeScopes = true; });
            }))
#pragma warning restore CS0618 // Type or member is obsolete
            {
                var devOpsService = AzureDevOpsService.CreateAzureDevOpsService(
                    Environment.GetEnvironmentVariable(devOpsTokenVar),
                    $"https://dev.azure.com/{organization}/",
                    loggerFactory.CreateLogger <AzureDevOpsService>()
                    );

                var gitHubServiceLogger = loggerFactory.CreateLogger <GitHubService>();
                var gitHubService       = new GitHubService(gitHubServiceLogger);

                var githubNameResolver = new GitHubNameResolver(
                    Environment.GetEnvironmentVariable(aadAppIdVar),
                    Environment.GetEnvironmentVariable(aadAppSecretVar),
                    Environment.GetEnvironmentVariable(aadTenantVar),
                    Environment.GetEnvironmentVariable(kustoUrlVar),
                    Environment.GetEnvironmentVariable(kustoDatabaseVar),
                    Environment.GetEnvironmentVariable(kustoTableVar),
                    loggerFactory.CreateLogger <GitHubNameResolver>()
                    );

                var logger = loggerFactory.CreateLogger <Program>();

                var pipelineGroupTasks = (await devOpsService.GetAllTeamsAsync(project))
                                         .Where(team =>
                                                YamlHelper.Deserialize <TeamMetadata>(team.Description, swallowExceptions: true)?.Purpose == TeamPurpose.SynchronizedNotificationTeam
                                                ).Select(async team =>
                {
                    var pipelineId = YamlHelper.Deserialize <TeamMetadata>(team.Description).PipelineId;
                    return(new
                    {
                        Pipeline = await devOpsService.GetPipelineAsync(project, pipelineId),
                        Team = team
                    });
                });

                var pipelineGroups = await Task.WhenAll(pipelineGroupTasks);

                var filteredGroups = pipelineGroups.Where(group => group.Pipeline != default && group.Pipeline.Path.StartsWith(pathPrefix));

                foreach (var group in filteredGroups)
                {
                    using (logger.BeginScope("Team Name = {0}", group.Team.Name))
                    {
                        if (group.Pipeline.Process.Type != PipelineYamlProcessType)
                        {
                            continue;
                        }

                        // Get contents of CODEOWNERS
                        logger.LogInformation("Fetching CODEOWNERS file");
                        var managementUrl     = new Uri(group.Pipeline.Repository.Properties["manageUrl"]);
                        var codeownersContent = await gitHubService.GetCodeownersFile(managementUrl);

                        if (codeownersContent == default)
                        {
                            logger.LogInformation("CODEOWNERS file not found, skipping sync");
                            continue;
                        }

                        var process = group.Pipeline.Process as YamlProcess;

                        // Find matching contacts for the YAML file's path
                        var parser     = new CodeOwnersParser(codeownersContent);
                        var matchPath  = PathWithoutFilename(process.YamlFilename);
                        var searchPath = $"/{matchPath}/";
                        logger.LogInformation("Searching CODEOWNERS for matching path Path = {0}", searchPath);
                        var contacts = parser.GetContactsForPath(searchPath);

                        logger.LogInformation("Matching Contacts Path = {0}, NumContacts = {1}", searchPath, contacts.Count);

                        // Get set of team members in the CODEOWNERS file
                        var contactResolutionTasks = contacts
                                                     .Where(contact => contact.StartsWith("@"))
                                                     .Select(contact => githubNameResolver.GetInternalUserPrincipal(contact.Substring(1)));
                        var codeownerPrincipals = await Task.WhenAll(contactResolutionTasks);

                        var codeownersDescriptorsTasks = codeownerPrincipals
                                                         .Where(userPrincipal => !string.IsNullOrEmpty(userPrincipal))
                                                         .Select(userPrincipal => devOpsService.GetDescriptorForPrincipal(userPrincipal));
                        var codeownersDescriptors = await Task.WhenAll(codeownersDescriptorsTasks);

                        var codeownersSet = new HashSet <string>(codeownersDescriptors);

                        // Get set of existing team members
                        var teamMembers = await devOpsService.GetMembersAsync(group.Team);

                        var teamContactTasks = teamMembers
                                               .Select(async member => await devOpsService.GetUserFromId(new Guid(member.Identity.Id)));
                        var teamContacts = await Task.WhenAll(teamContactTasks);

                        var teamDescriptors = teamContacts.Select(contact => contact.SubjectDescriptor.ToString());
                        var teamSet         = new HashSet <string>(teamDescriptors);

                        // Synchronize contacts
                        var contactsToRemove = teamSet.Except(codeownersSet);
                        var contactsToAdd    = codeownersSet.Except(teamSet);

                        var teamDescriptor = await devOpsService.GetDescriptorAsync(group.Team.Id);

                        foreach (var descriptor in contactsToRemove)
                        {
                            logger.LogInformation("Delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
                            if (!dryRun)
                            {
                                await devOpsService.RemoveMember(teamDescriptor, descriptor);
                            }
                        }

                        foreach (var descriptor in contactsToAdd)
                        {
                            logger.LogInformation("Add Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
                            if (!dryRun)
                            {
                                await devOpsService.AddToTeamAsync(teamDescriptor, descriptor);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Synchronizes CODEOWNERS contacts to appropriate DevOps groups
        /// </summary>
        /// <param name="organization">Azure DevOps organization name</param>
        /// <param name="project">Azure DevOps project name</param>
        /// <param name="devOpsTokenVar">Personal Access Token environment variable name</param>
        /// <param name="aadAppIdVar">AAD App ID environment variable name (OpensourceAPI access)</param>
        /// <param name="aadAppSecretVar">AAD App Secret environment variable name (OpensourceAPI access)</param>
        /// <param name="aadTenantVar">AAD Tenant environment variable name (OpensourceAPI access)</param>
        /// <param name="pathPrefix">Azure DevOps path prefix (e.g. "\net")</param>
        /// <param name="dryRun">Do not persist changes</param>
        /// <returns></returns>
        public static async Task Main(
            string organization,
            string project,
            string devOpsTokenVar,
            string aadAppIdVar,
            string aadAppSecretVar,
            string aadTenantVar,
            string pathPrefix = "",
            bool dryRun       = false
            )
        {
#pragma warning disable CS0618 // Type or member is obsolete
            using (var loggerFactory = LoggerFactory.Create(builder => {
                builder.AddConsole(config => { config.IncludeScopes = true; });
            }))
#pragma warning restore CS0618 // Type or member is obsolete
            {
                var devOpsService = AzureDevOpsService.CreateAzureDevOpsService(
                    Environment.GetEnvironmentVariable(devOpsTokenVar),
                    $"https://dev.azure.com/{organization}/",
                    loggerFactory.CreateLogger <AzureDevOpsService>()
                    );

                var gitHubServiceLogger = loggerFactory.CreateLogger <GitHubService>();
                var gitHubService       = new GitHubService(gitHubServiceLogger);
                var credential          = new ClientSecretCredential(
                    Environment.GetEnvironmentVariable(aadTenantVar),
                    Environment.GetEnvironmentVariable(aadAppIdVar),
                    Environment.GetEnvironmentVariable(aadAppSecretVar));
                var githubToAadResolver = new GitHubToAADConverter(
                    credential,
                    loggerFactory.CreateLogger <GitHubToAADConverter>()
                    );

                var logger    = loggerFactory.CreateLogger <Program>();
                var pipelines = (await devOpsService.GetPipelinesAsync(project)).ToDictionary(p => p.Id);

                var pipelineGroupTasks = (await devOpsService.GetAllTeamsAsync(project))
                                         .Where(team =>
                                                YamlHelper.Deserialize <TeamMetadata>(team.Description, swallowExceptions: true)?.Purpose == TeamPurpose.SynchronizedNotificationTeam
                                                ).Select(async team =>
                {
                    BuildDefinition pipeline;
                    var pipelineId = YamlHelper.Deserialize <TeamMetadata>(team.Description).PipelineId;

                    if (!pipelines.ContainsKey(pipelineId))
                    {
                        pipeline = await devOpsService.GetPipelineAsync(project, pipelineId);
                    }
                    else
                    {
                        pipeline = pipelines[pipelineId];
                    }

                    if (pipeline == default)
                    {
                        logger.LogWarning($"Could not find pipeline with id {pipelineId} referenced by team {team.Name}.");
                    }

                    return(new
                    {
                        Pipeline = pipeline,
                        Team = team
                    });
                });

                var pipelineGroups = await Task.WhenAll(pipelineGroupTasks);

                var filteredGroups = pipelineGroups.Where(group => group.Pipeline != default && group.Pipeline.Path.StartsWith(pathPrefix));

                foreach (var group in filteredGroups)
                {
                    using (logger.BeginScope("Team Name = {0}", group.Team.Name))
                    {
                        if (group.Pipeline.Process.Type != PipelineYamlProcessType)
                        {
                            continue;
                        }

                        // Get contents of CODEOWNERS
                        logger.LogInformation("Fetching CODEOWNERS file");
                        var managementUrl    = new Uri(group.Pipeline.Repository.Properties["manageUrl"]);
                        var codeOwnerEntries = await gitHubService.GetCodeownersFile(managementUrl);

                        if (codeOwnerEntries == default)
                        {
                            logger.LogInformation("CODEOWNERS file not found, skipping sync");
                            continue;
                        }

                        var process = group.Pipeline.Process as YamlProcess;

                        logger.LogInformation("Searching CODEOWNERS for matching path for {0}", process.YamlFilename);
                        var codeOwnerEntry = CodeOwnersFile.FindOwnersForClosestMatch(codeOwnerEntries, process.YamlFilename);
                        codeOwnerEntry.FilterOutNonUserAliases();

                        logger.LogInformation("Matching Contacts Path = {0}, NumContacts = {1}", process.YamlFilename, codeOwnerEntry.Owners.Count);

                        // Get set of team members in the CODEOWNERS file
                        var codeownerPrincipals = codeOwnerEntry.Owners
                                                  .Select(contact => githubToAadResolver.GetUserPrincipalNameFromGithub(contact));

                        var codeownersDescriptorsTasks = codeownerPrincipals
                                                         .Where(userPrincipal => !string.IsNullOrEmpty(userPrincipal))
                                                         .Select(userPrincipal => devOpsService.GetDescriptorForPrincipal(userPrincipal));
                        var codeownersDescriptors = await Task.WhenAll(codeownersDescriptorsTasks);

                        var codeownersSet = new HashSet <string>(codeownersDescriptors);

                        // Get set of existing team members
                        var teamMembers = await devOpsService.GetMembersAsync(group.Team);

                        var teamContactTasks = teamMembers
                                               .Select(async member => await devOpsService.GetUserFromId(new Guid(member.Identity.Id)));
                        var teamContacts = await Task.WhenAll(teamContactTasks);

                        var teamDescriptors = teamContacts.Select(contact => contact.SubjectDescriptor.ToString());
                        var teamSet         = new HashSet <string>(teamDescriptors);

                        // Synchronize contacts
                        var contactsToRemove = teamSet.Except(codeownersSet);
                        var contactsToAdd    = codeownersSet.Except(teamSet);

                        var teamDescriptor = await devOpsService.GetDescriptorAsync(group.Team.Id);

                        foreach (var descriptor in contactsToRemove)
                        {
                            logger.LogInformation("Delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
                            if (!dryRun)
                            {
                                await devOpsService.RemoveMember(teamDescriptor, descriptor);
                            }
                        }

                        foreach (var descriptor in contactsToAdd)
                        {
                            logger.LogInformation("Add Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
                            if (!dryRun)
                            {
                                await devOpsService.AddToTeamAsync(teamDescriptor, descriptor);
                            }
                        }
                    }
                }
            }
        }
 public NotificationConfigurator(AzureDevOpsService service, ILogger <NotificationConfigurator> logger)
 {
     this.service = service;
     this.logger  = logger;
 }
Ejemplo n.º 10
0
        static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder()
                          .SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                          .AddJsonFile("secrets.json", optional: false, reloadOnChange: true);

            IConfigurationRoot configuration = builder.Build();


            Console.WriteLine("Retrieving token from key vault...");
            var devOpsToken = configuration["AzureDevOpsInstallerToken"];

            var devOpsSettingSection = configuration.GetSection("DevOpsEnvironmentSettings");

            var organizationUri = GetSetting(devOpsSettingSection, "OrganizationUri");
            var projectName     = GetSetting(devOpsSettingSection, "ProjecName");
            var projectGuid     = GetSetting(devOpsSettingSection, "ProjectGuid");
            var username        = GetSetting(devOpsSettingSection, "Username");

            Console.WriteLine("Connecting Dev Ops organization...");
            var devOpsService = new AzureDevOpsService(organizationUri, username, devOpsToken, new Guid(projectGuid));

            Console.WriteLine("Retrieving build data...");
            var lastBuild = devOpsService.GetProjectBuilds()
                            .Result
                            .OrderByDescending(k => k.LastChangedDate)
                            .FirstOrDefault();

            Console.WriteLine("Downloading zip from artifactor...");

            if (File.Exists(FilePath))
            {
                File.Delete(FilePath);
            }
            CreateNewDirectory(ArtifactorExtractionFolder);
            //CreateNewDirectory(AssemblyCliExtractionFolder);

            Stream zipStream = devOpsService.GetArtifact(lastBuild.Id, ArtifactName).Result;

            using (FileStream zipFile = new FileStream(FilePath, FileMode.Append))
            {
                zipStream.CopyTo(zipFile);
            }


            Console.WriteLine("Unzipping artifactor...");
            ZipFile.ExtractToDirectory(FilePath, ArtifactorExtractionFolder);
            var assemblyCliZipFileName         = $@"{ArtifactorExtractionFolder}\Assembly\DDCli\{lastBuild.Id}.zip";
            var assemblyCliDynamicsZipFileName = $@"{ArtifactorExtractionFolder}\Assembly\DDCli.Dynamics\{lastBuild.Id}.zip";

            Console.WriteLine("Unzipping assemblies...");


            DeleteDirectory(AssemblyCliExtractionFolder);
            DeleteDirectory(AssemblyCliDynamicsExtractionFolder);

            ZipFile.ExtractToDirectory(assemblyCliZipFileName, AssemblyCliExtractionFolder);
            ZipFile.ExtractToDirectory(assemblyCliDynamicsZipFileName, AssemblyCliDynamicsExtractionFolder);
            Console.WriteLine("Installing files in folder...");
            if (Directory.Exists(InstallCliFolder))
            {
                Directory.Delete(InstallCliFolder, true);
            }
            if (Directory.Exists(InstallCliDynamicsFolder))
            {
                Directory.Delete(InstallCliDynamicsFolder, true);
            }
            Directory.Move(AssemblyCliExtractionFolder, InstallCliFolder);
            Directory.Move(AssemblyCliDynamicsExtractionFolder, InstallCliDynamicsFolder);
            Console.WriteLine("Installation complete");
        }