build: update golangci-lint to v2.12.2 with canonical config
All checks were successful
check / check (push) Successful in 1m12s

Replace the commit-pinned golangci-lint install refs in Dockerfile and
script/bootstrap with the v2.12.2 version pin, and replace .golangci.yml
with the canonical v2-schema config (lint settings now live under
linters.settings, so the lll/funlen/cyclop/dupl thresholds are actually
applied).

Fix all findings surfaced by the newly-applied config:

- goconst: introduce shared constants for repeated status, priority,
  and DNS fixture strings in watcher.go and the notify, state, and
  watcher tests
- dupl: consolidate duplicated ntfy/slack HTTP-error tests and
  SendNotification endpoint-error tests behind shared helpers
- lll: wrap long test table entries and comments; shorten one inline
  nolint justification
This commit is contained in:
2026-08-07 17:08:04 +00:00
parent b72c436fda
commit dea7e441b9
11 changed files with 329 additions and 293 deletions

View File

@@ -25,6 +25,20 @@ const (
colorDefault = "#6c757d"
)
// Priority strings used across multiple tests.
const (
prioError = "error"
prioWarning = "warning"
prioSuccess = "success"
prioInfo = "info"
prioUnknown = "unknown"
prioDefault = "default"
prioUrgent = "urgent"
)
// testHost is the hostname used in request construction tests.
const testHost = "example.com"
// errSimulated is a static error for transport failures.
var errSimulated = errors.New("simulated transport failure")
@@ -101,13 +115,13 @@ func TestNtfyPriority(t *testing.T) {
input string
want string
}{
{"error", "urgent"},
{"warning", "high"},
{"success", "default"},
{"info", "low"},
{"", "default"},
{"unknown", "default"},
{"critical", "default"},
{prioError, prioUrgent},
{prioWarning, "high"},
{prioSuccess, prioDefault},
{prioInfo, "low"},
{"", prioDefault},
{prioUnknown, prioDefault},
{"critical", prioDefault},
}
for _, tc := range cases {
@@ -134,12 +148,12 @@ func TestSlackColor(t *testing.T) {
input string
want string
}{
{"error", colorError},
{"warning", colorWarning},
{"success", colorSuccess},
{"info", colorInfo},
{prioError, colorError},
{prioWarning, colorWarning},
{prioSuccess, colorSuccess},
{prioInfo, colorInfo},
{"", colorDefault},
{"unknown", colorDefault},
{prioUnknown, colorDefault},
{"critical", colorDefault},
}
@@ -165,7 +179,7 @@ func TestNewRequest(t *testing.T) {
target := &url.URL{
Scheme: "https",
Host: "example.com",
Host: testHost,
Path: "/webhook",
}
body := bytes.NewBufferString("hello")
@@ -187,9 +201,9 @@ func TestNewRequest(t *testing.T) {
)
}
if req.Host != "example.com" {
if req.Host != testHost {
t.Errorf(
"Host = %q, want %q", req.Host, "example.com",
"Host = %q, want %q", req.Host, testHost,
)
}
@@ -217,7 +231,7 @@ func TestNewRequestPreservesContext(t *testing.T) {
ctxKey("k"),
"v",
)
target := &url.URL{Scheme: "https", Host: "example.com"}
target := &url.URL{Scheme: "https", Host: testHost}
req := notify.NewRequestForTest(
ctx, http.MethodGet, target, http.NoBody,
@@ -289,10 +303,10 @@ func TestSendNtfyHeaders(t *testing.T) {
)
}
if captured.priority != "urgent" {
if captured.priority != prioUrgent {
t.Errorf(
"Priority header = %q, want %q",
captured.priority, "urgent",
captured.priority, prioUrgent,
)
}
@@ -311,10 +325,10 @@ func TestSendNtfyAllPriorities(t *testing.T) {
input string
want string
}{
{"error", "urgent"},
{"warning", "high"},
{"success", "default"},
{"info", "low"},
{prioError, prioUrgent},
{prioWarning, "high"},
{prioSuccess, prioDefault},
{prioInfo, "low"},
}
for _, tc := range priorities {
@@ -356,56 +370,69 @@ func TestSendNtfyAllPriorities(t *testing.T) {
}
}
func TestSendNtfyClientError(t *testing.T) {
t.Parallel()
// assertSendStatusError verifies that send returns an error
// wrapping wantErr when the server responds with status.
func assertSendStatusError(
t *testing.T,
status int,
wantErr error,
send func(*notify.Service, *url.URL) error,
) {
t.Helper()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusForbidden)
w.WriteHeader(status)
}),
)
defer srv.Close()
svc := notify.NewTestService(srv.Client().Transport)
topicURL, _ := url.Parse(srv.URL)
target, _ := url.Parse(srv.URL)
err := svc.SendNtfy(
context.Background(), topicURL, "t", "m", "info",
)
err := send(svc, target)
if err == nil {
t.Fatal("expected error for 403 response")
t.Fatalf("expected error for %d response", status)
}
if !errors.Is(err, notify.ErrNtfyFailed) {
t.Errorf("error = %v, want ErrNtfyFailed", err)
if !errors.Is(err, wantErr) {
t.Errorf("error = %v, want %v", err, wantErr)
}
}
func sendNtfyInfo(
svc *notify.Service, target *url.URL,
) error {
return svc.SendNtfy(
context.Background(), target, "t", "m", prioInfo,
)
}
func sendSlackInfo(
svc *notify.Service, target *url.URL,
) error {
return svc.SendSlack(
context.Background(), target, "t", "m", prioInfo,
)
}
func TestSendNtfyClientError(t *testing.T) {
t.Parallel()
assertSendStatusError(
t, http.StatusForbidden,
notify.ErrNtfyFailed, sendNtfyInfo,
)
}
func TestSendNtfyServerError(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}),
assertSendStatusError(
t, http.StatusInternalServerError,
notify.ErrNtfyFailed, sendNtfyInfo,
)
defer srv.Close()
svc := notify.NewTestService(srv.Client().Transport)
topicURL, _ := url.Parse(srv.URL)
err := svc.SendNtfy(
context.Background(), topicURL, "t", "m", "info",
)
if err == nil {
t.Fatal("expected error for 500 response")
}
if !errors.Is(err, notify.ErrNtfyFailed) {
t.Errorf("error = %v, want ErrNtfyFailed", err)
}
}
func TestSendNtfySuccess(t *testing.T) {
@@ -550,11 +577,11 @@ func TestSendSlackAllColors(t *testing.T) {
priority string
want string
}{
{"error", colorError},
{"warning", colorWarning},
{"success", colorSuccess},
{"info", colorInfo},
{"unknown", colorDefault},
{prioError, colorError},
{prioWarning, colorWarning},
{prioSuccess, colorSuccess},
{prioInfo, colorInfo},
{prioUnknown, colorDefault},
}
for _, tc := range colors {
@@ -606,53 +633,19 @@ func TestSendSlackAllColors(t *testing.T) {
func TestSendSlackClientError(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}),
assertSendStatusError(
t, http.StatusBadRequest,
notify.ErrSlackFailed, sendSlackInfo,
)
defer srv.Close()
svc := notify.NewTestService(srv.Client().Transport)
webhookURL, _ := url.Parse(srv.URL)
err := svc.SendSlack(
context.Background(), webhookURL, "t", "m", "info",
)
if err == nil {
t.Fatal("expected error for 400 response")
}
if !errors.Is(err, notify.ErrSlackFailed) {
t.Errorf("error = %v, want ErrSlackFailed", err)
}
}
func TestSendSlackServerError(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusBadGateway)
}),
assertSendStatusError(
t, http.StatusBadGateway,
notify.ErrSlackFailed, sendSlackInfo,
)
defer srv.Close()
svc := notify.NewTestService(srv.Client().Transport)
webhookURL, _ := url.Parse(srv.URL)
err := svc.SendSlack(
context.Background(), webhookURL, "t", "m", "error",
)
if err == nil {
t.Fatal("expected error for 502 response")
}
if !errors.Is(err, notify.ErrSlackFailed) {
t.Errorf("error = %v, want ErrSlackFailed", err)
}
}
func TestSendSlackNetworkError(t *testing.T) {
@@ -977,74 +970,62 @@ func TestSendNotificationMattermostOnly(t *testing.T) {
}
}
func TestSendNotificationNtfyError(t *testing.T) {
t.Parallel()
// assertSendNotificationTolerates verifies SendNotification
// neither panics nor blocks when the endpoint configured by
// setURL responds with status.
func assertSendNotificationTolerates(
t *testing.T,
status int,
priority string,
setURL func(*notify.Service, *url.URL),
) {
t.Helper()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(status)
}),
)
defer srv.Close()
ntfyURL, _ := url.Parse(srv.URL)
target, _ := url.Parse(srv.URL)
svc := notify.NewTestService(http.DefaultTransport)
svc.SetNtfyURL(ntfyURL)
setURL(svc, target)
// Should not panic or block.
svc.SendNotification(
context.Background(), "t", "m", "error",
context.Background(), "t", "m", priority,
)
time.Sleep(100 * time.Millisecond)
}
func TestSendNotificationNtfyError(t *testing.T) {
t.Parallel()
assertSendNotificationTolerates(
t, http.StatusInternalServerError, prioError,
(*notify.Service).SetNtfyURL,
)
}
func TestSendNotificationSlackError(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusForbidden)
}),
assertSendNotificationTolerates(
t, http.StatusForbidden, prioError,
(*notify.Service).SetSlackWebhookURL,
)
defer srv.Close()
slackURL, _ := url.Parse(srv.URL)
svc := notify.NewTestService(http.DefaultTransport)
svc.SetSlackWebhookURL(slackURL)
svc.SendNotification(
context.Background(), "t", "m", "error",
)
time.Sleep(100 * time.Millisecond)
}
func TestSendNotificationMattermostError(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusBadGateway)
}),
assertSendNotificationTolerates(
t, http.StatusBadGateway, prioWarning,
(*notify.Service).SetMattermostWebhookURL,
)
defer srv.Close()
mmURL, _ := url.Parse(srv.URL)
svc := notify.NewTestService(http.DefaultTransport)
svc.SetMattermostWebhookURL(mmURL)
svc.SendNotification(
context.Background(), "t", "m", "warning",
)
time.Sleep(100 * time.Millisecond)
}
// ── SlackPayload JSON marshaling ──────────────────────────