When set to a truthy value, sends a startup status notification to all configured notification channels after the first full scan completes on application startup. The notification is clearly an all-ok/success message showing the number of monitored domains, hostnames, ports, and certificates.
Changes:
Added SendTestNotification config field reading DNSWATCHER_SEND_TEST_NOTIFICATION
Added maybeSendTestNotification() in watcher, called after initial RunOnce in Run
Added 3 watcher tests (enabled via Run, enabled via RunOnce alone, disabled)
Added config tests for the new field
Updated README: env var table, example .env, Docker example
When set to a truthy value, sends a startup status notification to all configured notification channels after the first full scan completes on application startup. The notification is clearly an all-ok/success message showing the number of monitored domains, hostnames, ports, and certificates.
Changes:
- Added `SendTestNotification` config field reading `DNSWATCHER_SEND_TEST_NOTIFICATION`
- Added `maybeSendTestNotification()` in watcher, called after initial `RunOnce` in `Run`
- Added 3 watcher tests (enabled via Run, enabled via RunOnce alone, disabled)
- Added config tests for the new field
- Updated README: env var table, example .env, Docker example
Closes #84
When set to a truthy value, sends a startup status notification
to all configured notification channels after the first full scan
completes. The notification is clearly an all-ok/success message
showing the number of monitored domains, hostnames, ports, and
certificates.
Closes#84
Watcher: maybeSendTestNotification() is well-placed (after RunOnce(), before ticker loop), with early return when disabled. Notification message includes useful operational info (domain/hostname/port/cert counts).
Tests: Three tests cover the key scenarios — enabled via Run(), confirming RunOnce() alone doesn't trigger it, and disabled path. All use t.Parallel().
No linter/Makefile/Dockerfile modifications.
No test weakening.
docker build . passes (includes make check: lint, fmt, tests).
Branch is up to date with main — no rebase needed.
Files Changed
README.md — docs updated in all three relevant locations
Clean, focused PR. All issue requirements satisfied.
## ✅ Review: PASS
### Requirement Completeness Checklist
Source: issue #84
| # | Requirement | Status | Where |
|---|---|---|---|
| 1 | Add env var `DNSWATCHER_SEND_TEST_NOTIFICATION` | ✅ | `config.go`: struct field, viper default, viper read |
| 2 | When set to truthy value, waits until first full scan completes | ✅ | `watcher.go`: `maybeSendTestNotification()` called after `RunOnce()` in `Run()` |
| 3 | Sends startup/status notification to all configured channels | ✅ | Uses `w.notify.SendNotification()` which dispatches to Slack, Mattermost, and ntfy |
| 4 | Clearly an all-ok message, not an error or anomaly | ✅ | Title: "✅ dnswatcher startup complete", priority: "success", body includes counts and "All notification channels are working." |
| 5 | Update all docs and examples to show it set to 'true' | ✅ | README: env var table, `.env` example, Docker run example all updated |
### Code Quality
- **Config**: Clean addition following existing patterns — struct field, viper default, viper read.
- **Watcher**: `maybeSendTestNotification()` is well-placed (after `RunOnce()`, before ticker loop), with early return when disabled. Notification message includes useful operational info (domain/hostname/port/cert counts).
- **Tests**: Three tests cover the key scenarios — enabled via `Run()`, confirming `RunOnce()` alone doesn't trigger it, and disabled path. All use `t.Parallel()`.
- **No linter/Makefile/Dockerfile modifications.**
- **No test weakening.**
- **`docker build .` passes** (includes `make check`: lint, fmt, tests).
- **Branch is up to date with main** — no rebase needed.
### Files Changed
- `README.md` — docs updated in all three relevant locations
- `internal/config/config.go` — config struct + viper wiring
- `internal/config/config_test.go` — default and override assertions
- `internal/watcher/watcher.go` — feature implementation
- `internal/watcher/watcher_test.go` — 3 new tests
Clean, focused PR. All issue requirements satisfied.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
When set to a truthy value, sends a startup status notification to all configured notification channels after the first full scan completes on application startup. The notification is clearly an all-ok/success message showing the number of monitored domains, hostnames, ports, and certificates.
Changes:
SendTestNotificationconfig field readingDNSWATCHER_SEND_TEST_NOTIFICATIONmaybeSendTestNotification()in watcher, called after initialRunOnceinRunCloses #84
✅ Review: PASS
Requirement Completeness Checklist
Source: issue #84
DNSWATCHER_SEND_TEST_NOTIFICATIONconfig.go: struct field, viper default, viper readwatcher.go:maybeSendTestNotification()called afterRunOnce()inRun()w.notify.SendNotification()which dispatches to Slack, Mattermost, and ntfy.envexample, Docker run example all updatedCode Quality
maybeSendTestNotification()is well-placed (afterRunOnce(), before ticker loop), with early return when disabled. Notification message includes useful operational info (domain/hostname/port/cert counts).Run(), confirmingRunOnce()alone doesn't trigger it, and disabled path. All uset.Parallel().docker build .passes (includesmake check: lint, fmt, tests).Files Changed
README.md— docs updated in all three relevant locationsinternal/config/config.go— config struct + viper wiringinternal/config/config_test.go— default and override assertionsinternal/watcher/watcher.go— feature implementationinternal/watcher/watcher_test.go— 3 new testsClean, focused PR. All issue requirements satisfied.