private async Task HandleChanges( bool allowDeletion, PolicyHttpClient policyClient, Guid projectId, GitRepository repository, List <GitBranchStats> branches, IEnumerable <BranchPolicies> relevantPolicies, IEnumerable <PolicyConfiguration> serverPolicy, IEnumerable <PolicyType> types) { var handledServerPolicies = new List <int>(); var resultList = new List <Task>(); foreach (var currentPolicy in relevantPolicies) { // Ignore exact branches not found on the repository if (string.IsNullOrEmpty(currentPolicy.Branch) || currentPolicy.Branch.Contains("*") || branches.Any(x => x.Name == currentPolicy.Branch)) { this.HandleBranchChanges(policyClient, projectId, repository, serverPolicy, types, handledServerPolicies, currentPolicy, resultList); } else { this.Logger.Debug($"Policy branch ignored, because branch does not exist on the current repository. (Repository: {repository.Name}, Branch: {currentPolicy.Branch})"); } } this.RemoveNoMatchServerPolicies(allowDeletion, policyClient, projectId, serverPolicy, handledServerPolicies); await Task.WhenAll(resultList).ConfigureAwait(false); }
public GitClient(Uri baseUrl, VssCredentials credentials) { var vssConnection = new VssConnection(baseUrl, credentials); this.client = vssConnection.GetClient <GitHttpClient>(); this.policyClient = new PolicyHttpClient(baseUrl, credentials); }
/// <summary> /// Creates a policy in Azure DevOps. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="types">Types</param> /// <param name="projectId">Team project id</param> /// <param name="repository">Git repository</param> /// <param name="currentPolicy">Branch policy</param> /// <param name="policy">Policy</param> /// <returns>Task</returns> protected abstract Task CreatePolicy( PolicyHttpClient policyClient, IEnumerable <PolicyType> types, Guid projectId, GitRepository repository, BranchPolicies currentPolicy, Policy policy);
/// <summary> /// Logs the change. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="types">Types</param> /// <param name="projectId">Team project id</param> /// <param name="repository">Git repository</param> /// <param name="currentPolicy">Branch policy</param> /// <param name="policy">Policy</param> /// <returns>Task</returns> #pragma warning disable 1998 protected override async Task CreatePolicy( PolicyHttpClient policyClient, IEnumerable <PolicyType> types, Guid projectId, GitRepository repository, BranchPolicies currentPolicy, Policy policy) { this.Logger.Info($"Policy not found in Azure DevOps, would be created. (Repository: {repository.Name}, Branch: {currentPolicy.Branch}, Type: {policy.TypeString})"); this.Logger.Debug($"Settings is: {policy.PrepareSettingsWithScopeAndSubType(repository.Id, policy)}"); }
private void HandleBranchChanges( PolicyHttpClient policyClient, Guid projectId, GitRepository repository, IEnumerable <PolicyConfiguration> serverPolicies, IEnumerable <PolicyType> types, List <int> handledServerPolicies, BranchPolicies currentPolicy, List <Task> resultList) { foreach (var policy in currentPolicy.Policies) { bool hasMatch = false; policy.PreparePolicyType(types); if (policy.PolicyType == null) { this.Logger.Warn($"Type not found. (Branch: {currentPolicy.Branch}, Type: {policy.Type})"); } if (serverPolicies != null) { foreach (var serverPolicy in serverPolicies) { if (policy.PolicyType.Id == serverPolicy.Type.Id && serverPolicy.DoesSubTypeMatch(policy) && ((serverPolicy.GetBranch() == null) || // Repository specific (serverPolicy.GetBranch() == policy.Branch && serverPolicy.GetMatchKind() == policy.MatchKind))) { hasMatch = true; handledServerPolicies.Add(serverPolicy.Id); if (policy.PolicyEquals(serverPolicy)) { this.Logger.Info($"Policy is up to date. (Repository: {repository.Name}, Branch: {currentPolicy.Branch}, Type: {policy.TypeString})"); } else { resultList.Add(this.UpdatePolicy(policyClient, types, projectId, repository, currentPolicy, policy, serverPolicy)); } break; } } } if (!hasMatch) { resultList.Add(this.CreatePolicy(policyClient, types, projectId, repository, currentPolicy, policy)); } } }
/// <summary> /// Creates a policy in Azure DevOps. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="types">Types</param> /// <param name="projectId">Team project id</param> /// <param name="repository">Git repository</param> /// <param name="currentPolicy">Branch policy</param> /// <param name="policy">Policy</param> /// <returns>Task</returns> protected override async Task CreatePolicy( PolicyHttpClient policyClient, IEnumerable <PolicyType> types, Guid projectId, GitRepository repository, BranchPolicies currentPolicy, Policy policy) { var policyConfiguration = this.GetPolicyConfiguration(types, repository, policy); var result = await policyClient.CreatePolicyConfigurationAsync(policyConfiguration, projectId).ConfigureAwait(false); this.Logger.Debug(this.Serializer.Serialize(result)); this.Logger.Info($"Policy created. (Repository: {repository.Name}, Branch: {currentPolicy.Branch}, Type: {policy.TypeString})"); }
private void RemoveNoMatchServerPolicies(bool allowDeletion, PolicyHttpClient policyClient, Guid projectId, IEnumerable <PolicyConfiguration> serverPolicy, List <int> handledServerPolicies) { if (serverPolicy != null) { var removeables = serverPolicy.Where(x => handledServerPolicies.All(htp => x.Id != htp)); foreach (var removeable in removeables) { if (!allowDeletion) { this.Logger.Info($"Existing policy not defined. Skipping removal due to allowDeletion Flag. (Repository: {removeable.GetRepositoryId()}, Branch: {removeable.GetBranch()}, Type: {removeable.Type.DisplayName})"); continue; } this.DeletePolicy(policyClient, projectId, removeable); } } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); services.AddDbContext <SaludsaContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddHealthChecks() .AddCheck("MyDatabase", new SqlConnectionHealthCheck(Configuration.GetConnectionString("DefaultConnection"))); services.AddTransient <TimingHandler>(); services.Replace(ServiceDescriptor.Singleton <IHttpMessageHandlerBuilderFilter, CustomLoggingFilter>()); services.AddHttpClient <IPaisServicio, PaisServicio>(x => x.BaseAddress = new Uri("https://restcountries.eu/")) .AddHttpMessageHandler <TimingHandler>() .SetHandlerLifetime(TimeSpan.FromSeconds(10)) .AddPolicyHandler(PolicyHttpClient.GetRetryPolicy()) .AddPolicyHandler(PolicyHttpClient.GetCircuitBreakerPolicy()); }
/// <summary> /// Deletes a policy in Azure DevOps. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="projectId">Team project id</param> /// <param name="policy">Policy</param> protected override async void DeletePolicy(PolicyHttpClient policyClient, Guid projectId, PolicyConfiguration policy) { await policyClient.DeletePolicyConfigurationAsync(projectId, policy.Id).ConfigureAwait(false); this.Logger.Info($"Policy removed. (Repository: {policy.GetRepositoryId()}, Branch: {policy.GetBranch()}, Type: {policy.Type.DisplayName})"); }
public async Task Check(string projectId, string repoId, int pullRequestId, Dictionary <string, string> args = null) { try { const string evaluationConfigurationType = "Build"; string artifactId(string projectId, int pullRequestId) => $"vstfs:///CodeReview/CodeReviewId/{projectId}/{pullRequestId}"; string buildUrl = $"{_config.URL}/{_config.Collection}/{projectId}/_build"; string statusName = (args != null) && args.TryGetValue("name", out string name) ? name : "CheckCodeCoverage"; _logger.LogInformation($"[{nameof(Check)}] BEGIN {{pullRequestId:{pullRequestId}}}"); GitHttpClient gitClient = _connection.GetClient <GitHttpClient>(); PolicyHttpClient policyClient = _connection.GetClient <PolicyHttpClient>(); // получить политики для ПР var evaluations = await policyClient.GetPolicyEvaluationsAsync(projectId, artifactId(projectId, pullRequestId)); _logger.LogInformation($"[{nameof(Check)}] GetPolicyEvaluationsAsync(project:{projectId}, artifactId:{artifactId(projectId, pullRequestId)}) success: {{evaluations count:{evaluations.Count}}}"); var policy = evaluations.FirstOrDefault(x => x.Configuration.Settings.TryGetValue("statusName", out JToken name) && name.ToString().Equals(statusName, StringComparison.OrdinalIgnoreCase)); // Если у полученного PullRequest не найдена политика для правила с заданным именем, то не создаем статуса. if (policy == null) { _logger.LogInformation($"[{nameof(Check)}] SKIPPED. Pullrequest({pullRequestId}) has no this policy"); return; } var evaluation = evaluations.FirstOrDefault(x => x.Configuration.Type.DisplayName.Equals(evaluationConfigurationType, StringComparison.OrdinalIgnoreCase)); _logger.LogInformation($"[{nameof(Check)}] build evaluation: {JsonConvert.SerializeObject(evaluation)}"); var resState = GitStatusState.NotApplicable; string description; string targetUrl; switch (evaluation?.Status) { case PolicyEvaluationStatus.Running: case PolicyEvaluationStatus.Queued: case PolicyEvaluationStatus.Rejected: { var buildId = evaluation.Context?.Value <int>("buildId"); resState = GitStatusState.NotSet; description = "Ожидаение успешной сборки"; targetUrl = buildId != null ? $"{buildUrl}/results?buildId={buildId}&view=results" : null; break; } case PolicyEvaluationStatus.Approved: { var buildId = evaluation.Context.Value <int>("buildId"); var cover = await GetCodeCoverageForBuild(projectId, buildId); int quality = 0; if (args != null && args.TryGetValue("quality", out string qualityStr) && (cover != null)) { if (!int.TryParse(qualityStr, out quality)) { _logger.LogWarning(message: $"[{nameof(Check)}] param \"Quality\"({qualityStr}) is not parse to int"); } resState = (quality <= cover) ? GitStatusState.Succeeded : GitStatusState.Error; } else { resState = GitStatusState.Succeeded; } description = cover != null ? $"CodeCoverage = {cover:F2}%" : "CodeCoverage = (не определен)"; targetUrl = $"{buildUrl}/results?buildId={buildId}&view=results"; break; } case PolicyEvaluationStatus.NotApplicable: default: resState = GitStatusState.Succeeded; description = "CodeCoverage = (Build not used)"; targetUrl = null; break; } // New status var status = new GitPullRequestStatus() { State = resState, Description = description, TargetUrl = targetUrl, Context = new GitStatusContext() { Name = statusName, Genre = "PullRequestCheckService" } }; _logger.LogInformation($"[{nameof(Check)}] created new status: " + $"{{pullRequestId:{pullRequestId}," + $"status:{{" + $"state:{status.State}," + $"description:{status.Description},context:{{name:{status.Context.Name},genre:{status.Context.Genre}}}" + $"}}" + $"}}"); // set PR status var prStatus = await gitClient.CreatePullRequestStatusAsync(status, repoId, pullRequestId); _logger.LogInformation($"[{nameof(Check)}] CreatePullRequestStatusAsync(status:{status}, repositoryId:{repoId}, pullRequestId:{pullRequestId}) success: {JsonConvert.SerializeObject(prStatus)}"); } catch (Exception e) { _logger.LogError($"Check FAILED: {e.ToString()}"); } finally { _logger.LogInformation($"[{nameof(Check)}] COMPLETED"); } }
/// <summary> /// Deletes a policy in Azure DevOps. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="projectId">Team project id</param> /// <param name="policy">Policy</param> protected abstract void DeletePolicy(PolicyHttpClient policyClient, Guid projectId, PolicyConfiguration policy);
#pragma warning restore 1998 /// <summary> /// Logs the change. /// </summary> /// <param name="policyClient">Policy client</param> /// <param name="projectId">Team project id</param> /// <param name="policy">Policy</param> protected override void DeletePolicy(PolicyHttpClient policyClient, Guid projectId, PolicyConfiguration policy) { this.Logger.Info($"Policy not in the definition, would be removed from Azure DevOps. (Repository: {policy.GetRepositoryId()}, Branch: {policy.GetBranch()}, Type: {policy.Type.DisplayName})"); }