fix: resolve review issues for Slack target type
All checks were successful
check / check (push) Successful in 1m53s
All checks were successful
check / check (push) Successful in 1m53s
- Fix duplicate name="url" form fields by adding :disabled binding to each URL input so only the active target type's field submits - Fix message formatting to use Slack mrkdwn (*bold*) instead of Markdown (**bold**) and remove language hint from code blocks - Fix README line exceeding 80-column hard wrap
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -98,14 +98,14 @@
|
||||
</select>
|
||||
</div>
|
||||
<div x-show="targetType === 'http'">
|
||||
<input type="url" name="url" placeholder="https://example.com/webhook" class="input text-sm">
|
||||
<input type="url" name="url" placeholder="https://example.com/webhook" :disabled="targetType !== 'http'" class="input text-sm">
|
||||
</div>
|
||||
<div x-show="targetType === 'http'" class="flex gap-2 items-center">
|
||||
<label class="text-sm text-gray-700">Max retries (0 = fire-and-forget):</label>
|
||||
<input type="number" name="max_retries" value="0" min="0" max="20" class="input text-sm w-24">
|
||||
</div>
|
||||
<div x-show="targetType === 'slack'">
|
||||
<input type="url" name="url" placeholder="https://hooks.slack.com/services/..." class="input text-sm">
|
||||
<input type="url" name="url" placeholder="https://hooks.slack.com/services/..." :disabled="targetType !== 'slack'" class="input text-sm">
|
||||
<p class="text-xs text-gray-500 mt-1">Slack or Mattermost incoming webhook URL. Payloads are pretty-printed in code blocks.</p>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary text-sm">Add Target</button>
|
||||
|
||||
Reference in New Issue
Block a user