private async Task <IMergePolicyRunner> CreateNew(MergePolicyRunnerFactoryContext context) { var policyConfiguration = await context.AzDoClient !.GetMergePoliciesAsync(context.Organization, context.RepositoryId); if (policyConfiguration.Value is null || policyConfiguration.Value.Count == 0) { return(NoopMergePolicyRunner.Instance); } var policies = new List <MergePolicy>(); foreach (var policyConfig in policyConfiguration.Value.OrderBy(n => n.CreateDate)) { var policyType = policyConfig.Strategy switch { ReleaseBranchCascadingPolicy.PolicyName => typeof(ReleaseBranchCascadingPolicy), SpecificSourceAndTargetPolicy.PolicyName => typeof(SpecificSourceAndTargetPolicy), _ => null }; if (policyType != null) { var policy = (MergePolicy)_serviceProvider.GetService(policyType); try { policy.Configure(policyConfig); } catch (Exception ex) { _logger.LogDebug(new EventId(1, "ConfigurationFailed"), ex, "Failed to configure {Policy} with {@Config}", policyType.Name, policyConfig); return(NoopMergePolicyRunner.Instance); } policies.Add(policy); } } return(new MergePolicyRunner( policies.ToArray(), _serviceProvider.GetService <ILogger <MergePolicyRunner> >() )); } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure( IApplicationBuilder app, IMergePolicyRunnerFactory runnerFactory, IAzureDevOpsClientFactory azDoClientFactory, ILogger <Startup> logger) { app.UseSerilogRequestLogging(); app.Use(ExceptionHandler); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", Home); endpoints.MapPost("/jwt", JwtRoute); endpoints.MapPost("/webhook", Webhook).RequireAuthorization(); endpoints.MapDelete("/policies", ClearPolicies); }); async Task Home(HttpContext context) { await context.Response.WriteAsync("Merge-a-Bot"); } async Task JwtRoute(HttpContext context) { using var sr = new StreamReader(context.Request.Body); var pat = await sr.ReadToEndAsync(); if (string.IsNullOrEmpty(pat)) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Body did not contain Personal Access Token"); return; } var claims = new List <Claim> { new Claim(JwtRegisteredClaimNames.Sub, pat), }; var token = new JwtSecurityToken( issuer: JwtIssuer, audience: null, claims: claims, expires: DateTime.UtcNow.Date.AddYears(1), signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSigningKey)), SecurityAlgorithms.HmacSha256) ); var tokenValue = new JwtSecurityTokenHandler().WriteToken(token); await context.Response.WriteAsync(tokenValue); } async Task Webhook(HttpContext context) { var request = context.Request; if (!HttpMethods.IsPost(request.Method)) { return; } if (request.ContentType == null || !request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) { return; } var payload = await WebhookDeserializer.DeserializeAsync(request.Body); var pat = context.User.FindFirstValue(ClaimTypes.NameIdentifier); if (payload != null) { var azDoClient = azDoClientFactory.Create(pat); var organization = payload.Resource.Repository.GetOrganization(); var baseUrl = payload.Resource.Repository.GetBaseUrl(); var factoryContext = new MergePolicyRunnerFactoryContext(azDoClient, payload.Resource.Repository.Id, organization, baseUrl); var runner = await runnerFactory.CreateAsync(factoryContext); await runner.RunAsync(azDoClient, payload); } } async Task ExceptionHandler(HttpContext context, Func <Task> next) { try { await next(); } catch (Exception ex) { logger.LogError(new EventId(1, "UnhandledError"), ex, "Unhandled error"); context.Response.StatusCode = 200; } } Task ClearPolicies(HttpContext context) { var org = context.Request.Query["organization"]; var repoId = context.Request.Query["repositoryId"]; if (string.IsNullOrEmpty(org) || string.IsNullOrEmpty(repoId)) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; return(Task.CompletedTask); } runnerFactory.Clear(new MergePolicyRunnerFactoryContext(repoId, org)); return(Task.CompletedTask); } }
public void Clear(MergePolicyRunnerFactoryContext context) { _cache.Remove(context, out _); }
public Task <IMergePolicyRunner> CreateAsync(MergePolicyRunnerFactoryContext context) { return(_cache.GetOrAdd(context, _valueFactory)); }
public Task <IMergePolicyRunner> CreateAsync(MergePolicyRunnerFactoryContext context) { return(_valueFactory(context)); // Caching by the context will not reflect changes that are done in DevOps for the Merge-Policies. //return _cache.GetOrAdd(context, _valueFactory); }