// Hook: AfterSend // Send a Microsoft Teams webhook notification when a job fails. // // Replace the WebhookUrl constant with your actual Incoming Webhook URL. // Successful runs are silent. Ideal for on-call alerting without a paid // PagerDuty seat. using System.Net.Http; using System.Text; if (JobResult.Success) { Logger.LogInformation($"Job '{JobName}' succeeded - no alert required."); return; } const string WebhookUrl = "https://outlook.office.com/webhook/YOUR_WEBHOOK_URL_HERE"; var errorSummary = JobResult.Errors.Any() ? string.Join("\n", JobResult.Errors.Take(5)) : "No error details available."; // Escape backslashes and quotes so the JSON payload stays valid var safeErrors = errorSummary.Replace(@"\", @"\\").Replace("\"", "\\\""); var payload = $$""" { "@type": "MessageCard", "@context": "https://schema.org/extensions", "summary": "ReportWORQ Job Failed", "themeColor": "FF0000", "title": "❌ ReportWORQ Job Failed: {{JobName}}", "text": "**Output:** {{OutputName}}\n\n**Errors:**\n```\n{{safeErrors}}\n```" } """; // NOTE: a .csx is compiled as a *script*, where `using` at the start of a statement // is parsed as a using DIRECTIVE. `using var http = ...;` therefore does not compile. // Use the using STATEMENT form instead. using (var http = new HttpClient()) { var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await http.PostAsync(WebhookUrl, content); Logger.LogInformation($"Teams alert sent. HTTP status: {response.StatusCode}"); }