diff --git a/README.md b/README.md index 7db7fa1..bb5315b 100644 --- a/README.md +++ b/README.md @@ -611,8 +611,8 @@ fine — startup recovery rescans the database anyway). **Scope:** Circuit breakers only apply to **HTTP targets with `max_retries` > 0**. Fire-and-forget HTTP targets (`max_retries` == 0), -Slack targets, database targets (local operations), and log targets (stdout) do not use -circuit breakers. +Slack targets, database targets (local operations), and log +targets (stdout) do not use circuit breakers. When a circuit is open and a new delivery arrives, the engine marks the delivery as `retrying` and schedules a retry timer for after the diff --git a/internal/delivery/engine.go b/internal/delivery/engine.go index 1a03c5c..77fd8df 100644 --- a/internal/delivery/engine.go +++ b/internal/delivery/engine.go @@ -1080,11 +1080,11 @@ func (e *Engine) parseSlackConfig(configJSON string) (*SlackTargetConfig, error) func FormatSlackMessage(event *database.Event) string { var b strings.Builder - b.WriteString("**Webhook Event Received**\n") - b.WriteString(fmt.Sprintf("**Method:** `%s`\n", event.Method)) - b.WriteString(fmt.Sprintf("**Content-Type:** `%s`\n", event.ContentType)) - b.WriteString(fmt.Sprintf("**Timestamp:** `%s`\n", event.CreatedAt.UTC().Format(time.RFC3339))) - b.WriteString(fmt.Sprintf("**Body Size:** %d bytes\n", len(event.Body))) + b.WriteString("*Webhook Event Received*\n") + b.WriteString(fmt.Sprintf("*Method:* `%s`\n", event.Method)) + b.WriteString(fmt.Sprintf("*Content-Type:* `%s`\n", event.ContentType)) + b.WriteString(fmt.Sprintf("*Timestamp:* `%s`\n", event.CreatedAt.UTC().Format(time.RFC3339))) + b.WriteString(fmt.Sprintf("*Body Size:* %d bytes\n", len(event.Body))) if event.Body == "" { b.WriteString("\n_(empty body)_\n") @@ -1096,7 +1096,7 @@ func FormatSlackMessage(event *database.Event) string { if json.Unmarshal([]byte(event.Body), &parsed) == nil { var pretty bytes.Buffer if json.Indent(&pretty, parsed, "", " ") == nil { - b.WriteString("\n```json\n") + b.WriteString("\n```\n") prettyStr := pretty.String() // Truncate very large payloads to keep Slack messages reasonable const maxPayloadDisplay = 3500 diff --git a/internal/delivery/engine_test.go b/internal/delivery/engine_test.go index 96acd27..ddffd74 100644 --- a/internal/delivery/engine_test.go +++ b/internal/delivery/engine_test.go @@ -973,10 +973,11 @@ func TestFormatSlackMessage_JSONBody(t *testing.T) { msg := FormatSlackMessage(event) - assert.Contains(t, msg, "**Webhook Event Received**") + assert.Contains(t, msg, "*Webhook Event Received*") assert.Contains(t, msg, "`POST`") assert.Contains(t, msg, "`application/json`") - assert.Contains(t, msg, "```json") + assert.Contains(t, msg, "```") + assert.NotContains(t, msg, "```json") // Pretty-printed JSON should have indentation assert.Contains(t, msg, ` "action": "push"`) assert.Contains(t, msg, ` "repo": "test/repo"`) @@ -994,7 +995,7 @@ func TestFormatSlackMessage_NonJSONBody(t *testing.T) { msg := FormatSlackMessage(event) - assert.Contains(t, msg, "**Webhook Event Received**") + assert.Contains(t, msg, "*Webhook Event Received*") assert.Contains(t, msg, "```\nhello world plain text\n```") // Should NOT have ```json marker for non-JSON assert.NotContains(t, msg, "```json") @@ -1094,8 +1095,10 @@ func TestDeliverSlack_Success(t *testing.T) { // Verify the Slack payload contains the expected message var slackPayload map[string]string require.NoError(t, json.Unmarshal([]byte(receivedBody), &slackPayload)) - assert.Contains(t, slackPayload["text"], "**Webhook Event Received**") - assert.Contains(t, slackPayload["text"], "```json") + assert.Contains(t, slackPayload["text"], "*Webhook Event Received*") + assert.NotContains(t, slackPayload["text"], "**Webhook Event Received**") + assert.Contains(t, slackPayload["text"], "```") + assert.NotContains(t, slackPayload["text"], "```json") } func TestDeliverSlack_Failure(t *testing.T) { diff --git a/templates/source_detail.html b/templates/source_detail.html index ec4de52..5a62a4b 100644 --- a/templates/source_detail.html +++ b/templates/source_detail.html @@ -98,14 +98,14 @@
- +
- +

Slack or Mattermost incoming webhook URL. Payloads are pretty-printed in code blocks.