Show a slack target's retry setting in the target list (closes #395)
check / check (push) Successful in 3m12s

The target list showed only the masked webhook URL for a slack
target, though its edit page saves a retry setting and delivery
honours it. It now shows the same retry fields, with the same
labels and wording, as an http target.

Model: opus-5-5
This commit is contained in:
2026-10-02 21:02:00 +00:00
parent da75950e91
commit d0fe433d31
2 changed files with 38 additions and 13 deletions
+8 -7
View File
@@ -97,7 +97,7 @@ func targetConfigFields(
) []ConfigField { ) []ConfigField {
switch t.Type { switch t.Type {
case database.TargetTypeSlack: case database.TargetTypeSlack:
return slackConfigFields(t.Config) return slackConfigFields(t)
case database.TargetTypeHTTP: case database.TargetTypeHTTP:
return httpConfigFields(t) return httpConfigFields(t)
case database.TargetTypeDatabase: case database.TargetTypeDatabase:
@@ -119,18 +119,19 @@ func unavailableConfigFields() []ConfigField {
}} }}
} }
// slackConfigFields describes a Slack target. Only the masked // slackConfigFields describes a Slack target: its masked
// webhook URL is shown; the full URL is the credential. // webhook URL and its retry settings. Only the masked URL is
func slackConfigFields(configJSON string) []ConfigField { // shown; the full URL is the credential.
cfg, err := parseSlackConfig(configJSON) func slackConfigFields(t *database.Target) []ConfigField {
cfg, err := parseSlackConfig(t.Config)
if err != nil { if err != nil {
return unavailableConfigFields() return unavailableConfigFields()
} }
return []ConfigField{{ return append([]ConfigField{{
Label: "Webhook URL", Label: "Webhook URL",
Value: cfg.MaskedWebhookURL(), Value: cfg.MaskedWebhookURL(),
}} }}, retryFields(t)...)
} }
// httpConfigFields describes an HTTP target: its destination // httpConfigFields describes an HTTP target: its destination
+30 -6
View File
@@ -32,6 +32,7 @@ const (
viewMaskedOrigin = viewExampleOrigin + "/..." viewMaskedOrigin = viewExampleOrigin + "/..."
viewUnavailable = "(unavailable)" viewUnavailable = "(unavailable)"
viewExpiryNever = "never" viewExpiryNever = "never"
viewMaxRetries = "Max Retries"
) )
func TestMaskedWebhookURL(t *testing.T) { func TestMaskedWebhookURL(t *testing.T) {
@@ -157,9 +158,7 @@ func TestNewTargetViews_DeletedTarget(t *testing.T) {
t, slackTargetName+" (deleted)", view.DisplayName(), t, slackTargetName+" (deleted)", view.DisplayName(),
) )
assert.Equal( assert.Equal(
t, t, viewFor(t, slackTarget()).Config, view.Config,
map[string]string{"Webhook URL": slackMaskedURL},
fieldMap(view.Config),
) )
} }
@@ -189,7 +188,32 @@ func TestNewTargetViews_Slack(t *testing.T) {
assert.Equal( assert.Equal(
t, t,
map[string]string{"Webhook URL": slackMaskedURL}, map[string]string{
"Webhook URL": slackMaskedURL,
viewMaxRetries: "0 (fire-and-forget)",
},
fieldMap(view.Config),
)
}
// TestNewTargetViews_SlackRetries proves a Slack target shows
// its retry settings the same way an HTTP target does.
func TestNewTargetViews_SlackRetries(t *testing.T) {
t.Parallel()
target := slackTarget()
target.MaxRetries = 2
target.MaxQueueSize = 100
view := viewFor(t, target)
assert.Equal(
t,
map[string]string{
"Webhook URL": slackMaskedURL,
viewMaxRetries: "2",
"Max Queue Size": "100",
},
fieldMap(view.Config), fieldMap(view.Config),
) )
} }
@@ -214,7 +238,7 @@ func TestNewTargetViews_HTTP(t *testing.T) {
"Destination URL": viewMaskedOrigin, "Destination URL": viewMaskedOrigin,
"Timeout": "30s", "Timeout": "30s",
"Headers": "1 configured", "Headers": "1 configured",
"Max Retries": "5", viewMaxRetries: "5",
"Max Queue Size": "100", "Max Queue Size": "100",
}, },
fields, fields,
@@ -238,7 +262,7 @@ func TestNewTargetViews_HTTPFireAndForget(t *testing.T) {
t, t,
map[string]string{ map[string]string{
"Destination URL": viewMaskedOrigin, "Destination URL": viewMaskedOrigin,
"Max Retries": "0 (fire-and-forget)", viewMaxRetries: "0 (fire-and-forget)",
}, },
fieldMap(view.Config), fieldMap(view.Config),
) )