public async Task TriggerMatchingTests(string registered, int expected) { var notification = new WebHookNotification { TriggerId = "something.interesting.happened" }; var context = new InMemoryContext(); context.Add(new WebHook { IsPaused = false, Filters = new List <WebHookFilter> { new WebHookFilter { TriggerId = registered } } }); context.SaveChanges(); var protector = new Mock <ISecretProtector>(); protector.Setup(p => p.Unprotect(It.IsAny <string>())).Returns("http://www.example.org"); var store = new WebHookStore <InMemoryContext>(context, protector.Object); var result = await store.GetApplicableWebHooksAsync(notification); Assert.Equal(expected, result.Count); }
public async Task NormalScenarioAsync(object payload) { var logger = new Mock <ILogger <DefaultWebHookSender> >(); var signature = "FIXED_SIGNATURE"; var signatureService = new Mock <ISignatureService>(); signatureService.Setup(s => s.GetSignature(It.IsAny <string>(), It.IsAny <string>())).Returns(signature); var webHook = new WebHook { Callback = "http://www.example.com" }; var notif = new WebHookNotification { TriggerId = "noun.verb", Payload = payload }; var callbackHasBeenCalled = false; var httpClient = HttpClientMocker.Callback(async m => { callbackHasBeenCalled = true; Assert.Equal(HttpMethod.Post, m.Method); Assert.Equal(new Uri(webHook.Callback), m.RequestUri); var content = JsonConvert.DeserializeObject <Dictionary <string, object> >(await m.Content.ReadAsStringAsync()); var headers = m.Headers.Select(kvp => kvp.Key).ToHashSet(); Assert.Contains(DefaultWebHookSender.TimestampKey, headers); Assert.Contains(DefaultWebHookSender.UniqueIdKey, headers); if (notif.Payload != null) { Assert.NotEqual(default, content["notificationId"]);
public async Task GetAllTests() { var services = _fixture.Provider; var context = services.GetRequiredService <TestContext1>(); await SeedAsync(context); var store = services.GetRequiredService <WebHookStore <TestContext1> >(); var payload = new WebHookNotification { TriggerId = "noun.verb", Payload = new Dictionary <string, object> { ["property"] = 2, ["otherProperty"] = "value", ["thirdProperty"] = "nope" } }; var webHooks = await store.GetApplicableWebHooksAsync(payload); Assert.Equal(4, webHooks.Count); Assert.All(webHooks, t => { Assert.NotEqual(Guid.Empty, t.Id); Assert.False(t.IsPaused); }); AssertHaveBeenPrepared(webHooks); }
public async Task GetAllTests() { var services = _fixture.Provider; var context = services.GetRequiredService <TestContext1>(); await SeedAsync(context); var store = services.GetRequiredService <WebHookStore <TestContext1> >(); var payload = new WebHookNotification { TriggerId = "noun.verb", Payload = new Payload { Property = 2, OtherProperty = "value", ThirdProperty = "nope" } }; var webHooks = await store.GetApplicableWebHooksAsync(payload); Assert.All(webHooks, t => { Assert.NotEqual(Guid.Empty, t.Id); Assert.False(t.IsPaused); Assert.True(t.Filters != null && t.Filters.Count != 0); Assert.Contains("noun.verb", t.Filters.Select(f => f.Trigger)); }); AssertHaveBeenPrepared(webHooks); Assert.Equal(2, webHooks.Count); }
public Task SendMessageAsync(string organizationId, string projectId, string url, SlackMessage message) { if (String.IsNullOrEmpty(organizationId)) { throw new ArgumentNullException(nameof(organizationId)); } if (String.IsNullOrEmpty(projectId)) { throw new ArgumentNullException(nameof(projectId)); } if (String.IsNullOrEmpty(url)) { throw new ArgumentNullException(nameof(url)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } var notification = new WebHookNotification { OrganizationId = organizationId, ProjectId = projectId, Url = url, Type = WebHookType.Slack, Data = message }; return(_webHookNotificationQueue.EnqueueAsync(notification)); }
public async Task FullIntegrationMassTransitTests() { var expectedWebHooksCount = 10; var counter = new HttpClientMocker.CounterHandler(); var services = new ServiceCollection(); var store = new Mock <IWebHookStore>(); store.Setup(s => s.GetApplicableWebHooksAsync(It.IsAny <IWebHookNotification>(), It.IsAny <CancellationToken>())).ReturnsAsync(() => { return(Enumerable.Range(0, expectedWebHooksCount).Select(i => new WebHook { Callback = new Uri("http://www.example.org") }).ToList()); }); services.AddSingleton(store.Object); var protector = new Mock <ISignatureService>(); protector.Setup(p => p.GetSignature(It.IsAny <string>(), It.IsAny <string>())).Returns("secret"); services.AddSingleton(protector.Object); services.AddHarpoon(c => c.UseAllMassTransitDefaults(a => a.AddHttpMessageHandler(() => counter))); services.AddMassTransit(p => Bus.Factory.CreateUsingRabbitMq(cfg => { var host = cfg.Host(new Uri("rabbitmq://localhost:5672"), hostConfigurator => { hostConfigurator.Username("guest"); hostConfigurator.Password("guest"); }); cfg.ConfigureNotificationsConsumer(p, "NotificationsFullTestsQueue"); cfg.ConfigureWebHookWorkItemsConsumer(p, "WebHookWorkItemsFullTestsQueue"); }), x => x.UseAllMassTransitDefaults()); var provider = services.BuildServiceProvider(); var token = new CancellationTokenSource(); var hosts = provider.GetRequiredService <IEnumerable <IHostedService> >(); foreach (var host in hosts) { await host.StartAsync(token.Token); } var notif = new WebHookNotification { TriggerId = "noun.verb" }; await provider.GetRequiredService <IWebHookService>().NotifyAsync(notif); await Task.Delay(10000); Assert.Equal(expectedWebHooksCount, counter.Counter); token.Cancel(); }
public override async Task ProcessAsync(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } // notifications are disabled or stack is hidden. if (ctx.Stack.DisableNotifications || ctx.Stack.IsHidden) { return; } if (ShouldQueueNotification(ctx)) { await _notificationQueue.EnqueueAsync(new EventNotificationWorkItem { EventId = ctx.Event.Id, IsNew = ctx.IsNew, IsRegression = ctx.IsRegression, TotalOccurrences = ctx.Stack.TotalOccurrences }).AnyContext(); } var webHooks = await _webHookRepository.GetByOrganizationIdOrProjectIdAsync(ctx.Event.OrganizationId, ctx.Event.ProjectId).AnyContext(); foreach (var hook in webHooks.Documents) { if (!ShouldCallWebHook(hook, ctx)) { continue; } var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); var notification = new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, WebHookId = hook.Id, Url = hook.Url, Type = WebHookType.General, Data = await _webHookDataPluginManager.CreateFromEventAsync(context).AnyContext() }; await _webHookNotificationQueue.EnqueueAsync(notification).AnyContext(); using (_logger.BeginScope(new Dictionary <string, object> { { "Web Hook Notification", notification } })) _logger.LogTrace("Web hook queued: project={project} url={Url}", ctx.Event.ProjectId, hook.Url); } }
public async Task TriggerMatchingTests() { var notification = new WebHookNotification { TriggerId = "something.interesting.happened" }; var context = new InMemoryContext(); context.Add(new WebHook { IsPaused = false, Filters = new List <WebHookFilter> { new WebHookFilter { Trigger = "something.interesting.happened" } } }); context.Add(new WebHook { IsPaused = true, Filters = new List <WebHookFilter> { new WebHookFilter { Trigger = "something.interesting.happened" } } }); context.SaveChanges(); var secret = "http://www.example.org"; var protector = new Mock <ISecretProtector>(); protector.Setup(p => p.Unprotect(It.IsAny <string>())).Returns(secret); var matcher = new Mock <IWebHookMatcher>(); matcher.Setup(m => m.Matches(It.IsAny <IWebHook>(), It.IsAny <IWebHookNotification>())).Returns(true); var store = new WebHookStore <InMemoryContext>(context, protector.Object, matcher.Object); var result = await store.GetApplicableWebHooksAsync(notification); Assert.Equal(1, result.Count); var webhook = result[0]; Assert.False(webhook.IsPaused); Assert.Equal(secret, webhook.Secret); Assert.Equal(new Uri(secret), webhook.Callback); }
public async Task NormalScenarioAsync(Dictionary <string, object> payload) { var logger = new Mock <ILogger <DefaultWebHookSender> >(); var signature = "FIXED_SIGNATURE"; var signatureService = new Mock <ISignatureService>(); signatureService.Setup(s => s.GetSignature(It.IsAny <string>(), It.IsAny <string>())).Returns(signature); var webHook = new WebHook { Callback = new Uri("http://www.example.com") }; var notif = new WebHookNotification { TriggerId = "noun.verb", Payload = payload }; var callbackHasBeenCalled = false; var httpClient = HttpClientMocker.Callback(async m => { callbackHasBeenCalled = true; Assert.Equal(HttpMethod.Post, m.Method); Assert.Equal(webHook.Callback, m.RequestUri); var content = JsonConvert.DeserializeObject <Dictionary <string, string> >(await m.Content.ReadAsStringAsync()); Assert.NotNull(content); Assert.Contains(DefaultWebHookSender.TriggerKey, content.Keys); Assert.Equal(notif.TriggerId, content[DefaultWebHookSender.TriggerKey]); Assert.Contains(DefaultWebHookSender.TimestampKey, content.Keys); Assert.Contains(DefaultWebHookSender.UniqueIdKey, content.Keys); if (notif.Payload != null) { foreach (var kvp in notif.Payload) { Assert.Contains(kvp.Key, content.Keys); Assert.Equal(kvp.Value, content[kvp.Key]); } } Assert.Contains(DefaultWebHookSender.SignatureHeader, m.Headers.Select(kvp => kvp.Key)); Assert.Equal(signature, m.Headers.GetValues(DefaultWebHookSender.SignatureHeader).First()); }); var service = new CounterDefaultWebHookSender(httpClient, signatureService.Object, logger.Object); await service.SendAsync(new WebHookWorkItem(notif, webHook), CancellationToken.None); Assert.True(callbackHasBeenCalled); Assert.Equal(1, service.Successes); }
protected async override Task <JobResult> RunInternalAsync(CancellationToken token) { Log.Trace().Message("Web hook job starting").Write(); QueueEntry <WebHookNotification> queueEntry = null; try { queueEntry = _queue.Dequeue(); } catch (Exception ex) { if (!(ex is TimeoutException)) { Log.Error().Exception(ex).Message("An error occurred while trying to dequeue the next WebHookNotification: {0}", ex.Message).Write(); return(JobResult.FromException(ex)); } } if (queueEntry == null) { return(JobResult.Success); } Log.Trace().Message("Processing WebHookNotification '{0}'.", queueEntry.Id).Write(); WebHookNotification body = queueEntry.Value; Log.Trace().Project(body.ProjectId).Message("Process web hook call: project={0} url={1}", body.ProjectId, body.Url).Write(); var client = new HttpClient(); try { var result = client.PostAsJson(body.Url, body.Data.ToJson(Formatting.Indented)); if (result.StatusCode == HttpStatusCode.Gone) { _webHookRepository.RemoveByUrl(body.Url); Log.Warn().Project(body.ProjectId).Message("Deleting web hook: org={0} project={1} url={2}", body.OrganizationId, body.ProjectId, body.Url).Write(); } queueEntry.Complete(); Log.Info().Project(body.ProjectId).Message("Web hook POST complete: status={0} org={1} project={2} url={3}", result.StatusCode, body.OrganizationId, body.ProjectId, body.Url).Write(); } catch (Exception ex) { queueEntry.Abandon(); return(JobResult.FromException(ex)); } return(JobResult.Success); }
public async Task ErrorScenarioAsync() { var logger = new Mock <ILogger <DefaultWebHookSender> >(); var signature = new Mock <ISignatureService>(); var webHook = new WebHook { Callback = new Uri("http://www.example.com") }; var notif = new WebHookNotification { TriggerId = "noun.verb" }; var httpClient = HttpClientMocker.AlwaysFail(new Exception()); var service = new CounterDefaultWebHookSender(httpClient, signature.Object, logger.Object); await service.SendAsync(new WebHookWorkItem(notif, webHook), CancellationToken.None); Assert.Equal(1, service.Failures); }
public async Task NotFoundScenarioAsync(System.Net.HttpStatusCode code) { var logger = new Mock <ILogger <DefaultWebHookSender> >(); var signature = new Mock <ISignatureService>(); var webHook = new WebHook { Callback = new Uri("http://www.example.com") }; var notif = new WebHookNotification { TriggerId = "noun.verb" }; var httpClient = HttpClientMocker.Static(code, ""); var service = new CounterDefaultWebHookSender(httpClient, signature.Object, logger.Object); await service.SendAsync(new WebHookWorkItem(notif, webHook), CancellationToken.None); Assert.Equal(1, service.NotFounds); }
public async Task NotifyFailure(string livenessName, string content) { foreach (var webHook in _settings.Webhooks) { if (webHook.Uri == null || !Uri.TryCreate(webHook.Uri, UriKind.Absolute, out Uri webHookUri)) { _logger.LogWarning($"The web hook notification uri is not stablished or is not an absolute Uri ({webHook.Name}). Set the webhook uri value on BeatPulse setttings."); continue; } using (var httpClient = new HttpClient()) { var targetWebHook = new WebHookNotification() { Name = webHook.Name, Uri = webHook.Uri, Payload = webHook.Payload }; targetWebHook.Payload = targetWebHook.Payload .Replace(BeatPulseUIKeys.LIVENESS_BOOKMARK, livenessName) .Replace(BeatPulseUIKeys.FAILURE_BOOKMARK, content); var payload = new StringContent(targetWebHook.Payload, Encoding.UTF8, BeatPulseUIKeys.DEFAULT_RESPONSE_CONTENT_TYPE); try { var response = await httpClient.PostAsync(webHookUri, payload); if (!response.IsSuccessStatusCode) { _logger.LogError($"The failure notification is not executed successfully for {webHook.Name} webhook. The error code is {response.StatusCode}."); } } catch (Exception exception) { _logger.LogError($"The failure notification for {webHook.Name} is not executed successfully.", exception); } } } }
public override async Task ProcessAsync(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } if (ShouldQueueNotification(ctx)) { await _notificationQueue.EnqueueAsync(new EventNotificationWorkItem { EventId = ctx.Event.Id, IsNew = ctx.IsNew, IsCritical = ctx.Event.IsCritical(), IsRegression = ctx.IsRegression, TotalOccurrences = ctx.Stack.TotalOccurrences, ProjectName = ctx.Project.Name }).AnyContext(); } foreach (WebHook hook in (await _webHookRepository.GetByOrganizationIdOrProjectIdAsync(ctx.Event.OrganizationId, ctx.Event.ProjectId).AnyContext()).Documents) { if (!ShouldCallWebHook(hook, ctx)) { continue; } var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); var notification = new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, WebHookId = hook.Id, Url = hook.Url, Data = await _webHookDataPluginManager.CreateFromEventAsync(context).AnyContext() }; await _webHookNotificationQueue.EnqueueAsync(notification).AnyContext(); _logger.Trace().Project(ctx.Event.ProjectId).Message("Web hook queued: project={0} url={1}", ctx.Event.ProjectId, hook.Url).Property("Web Hook Notification", notification).Write(); } }
public async Task NotFoundScenarioAsync(System.Net.HttpStatusCode code) { var logger = new Mock <ILogger <EFWebHookSender <TestContext1> > >(); var signature = new Mock <ISignatureService>(); var context = _fixture.Provider.GetRequiredService <TestContext1>(); var webHook = AddWebHook(context, Guid.NewGuid(), "myPrincipalxxx", "noun.verb", false, null); webHook.Callback = new Uri("http://example.org"); await context.SaveChangesAsync(); var notif = new WebHookNotification { TriggerId = "noun.verb" }; var httpClient = HttpClientMocker.Static(code, ""); var service = new EFWebHookSender <TestContext1>(httpClient, signature.Object, logger.Object, context); await service.SendAsync(new WebHookWorkItem(notif, webHook), CancellationToken.None); Assert.True((await context.WebHooks.FirstAsync(w => w.Id == webHook.Id)).IsPaused); }
public static string FirePushNotification([ActivityTrigger] WebHookNotification notification, TraceWriter log) { log.Info($"TODO: All regions are sync'd - add whatever onward notification you want here! Repository: {notification.Target.Repository}, Tag: {notification.Target.Tag}, Id: {notification.Request.Id}"); return($"All regions are sync'd!"); }
public void MatchesTests(List <WebHookFilter> filters, WebHookNotification notif, bool result) { Assert.Equal(result, new DefaultWebHookMatcher().Matches(new WebHook { Filters = filters }, notif)); }
public static string FireTimeoutNotification([ActivityTrigger] WebHookNotification notification, TraceWriter log) { log.Info($"TODO: Timed out waiting for replication - add whatever onward notification you want here! Repository: {notification.Target.Repository}, Tag: {notification.Target.Tag}, Id: {notification.Request.Id}"); return($"Timed out"); }