feat(notif): add digest mode to batch notifications into a single message per scan run - #1813
Open
slmingol wants to merge 11 commits into
Open
feat(notif): add digest mode to batch notifications into a single message per scan run#1813slmingol wants to merge 11 commits into
slmingol wants to merge 11 commits into
Conversation
…sage Adds a `digest` boolean to the notif config. When enabled, per-image Send calls are suppressed during a scan run; a single SendBatch call fires after all workers complete, sending one message per notifier. Slack implements BatchHandler for a true summary message (one attachment per update, @channel header with counts). All other notifiers fall back to deferred individual sends at end-of-run via the SendBatch loop. Also fixes a pre-existing data race: NotifEntries.Add was called concurrently from the worker pool without a mutex. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Routes image publish to ghcr.io/slmingol/diun instead of upstream. Removes DockerHub login/push/inspect (no secrets in fork). Adds feat/** to push triggers so feature branches build images. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r-image attachments
… counters Global CountNew/CountUpdate include entries filtered by notifyOn/firstCheck rules that never get PendingNotify() set — causing header count to exceed the actual bullet list length. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Strip registry prefix and sha256 digest from image names, trim diun__ hostname prefix, and remove <!channel> mention from batch summary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each bullet now shows the image build date and first 8 hex chars of its sha256 digest for quick identification. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mode=max provenance and sbom push in-toto attestation manifests that older Nexus proxy versions cannot serve, causing pull failures on hosts with newer Docker versions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a HubLink is available, render the image as a Slack hyperlink with a short name (last two path segments + tag) hiding the full URL. Falls back to backtick code formatting when no HubLink exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds a
digestboolean field to theNotifconfig that, when enabled, buffers all image update notifications from a single scan run and fires them as one batched message instead of one message per image.This is useful when monitoring many containers across multiple hosts -- without digest mode, a single scan can flood a Slack channel (or other notifier) with dozens of individual messages.
How it works
pendingNotifyflag is set on eachNotifEntrythat passes all notification filters injob.go, instead of immediately callingSendwg.Wait()inapp.go),SendBatchis called once with the fullNotifEntriessetBatchHandlerinterface (SendBatch(*model.NotifEntries) error)BatchHandlerfall back to individualSendcalls for each pending entry, so existing notifiers work without changesChanges
Model / core
internal/model/notif.go— addsDigest booltoNotif; addspendingNotifyfield withMarkPendingNotify()/PendingNotify()accessors toNotifEntry; adds mutex-safeAdd()toNotifEntriesinternal/notif/notifier/notifier.go— adds optionalBatchHandlerinterfaceinternal/notif/client.go— addsIsDigest()andSendBatch()internal/app/job.go— marks entry pending instead of sending immediately when digest mode is oninternal/app/app.go— callsSendBatchafterwg.Wait()when digest mode is onSlack notifier
internal/notif/slack/client.go— implementsBatchHandler.SendBatchwith a compact bullet-list summary (registry-stripped image names, HubLink hyperlinks where available, build date, short sha256 digest, clean hostname)Config
Or via environment variable:
Example output (Slack)
Notes
BatchHandlerin this PR; other notifiers fall back to individual sends automaticallyNotifEntries.mumutex guards concurrent worker writes; the pointer receiver onSendBatchavoids copying it🤖 Generated with Claude Code