Skip to content

Conversation

@nscuro
Copy link
Member

@nscuro nscuro commented Mar 26, 2025

Description

Builds upon @MM-msr's PR #3925 in the following ways:

  • Adds validator for cron expressions so syntax mistakes can be caught sooner.
  • Removes ScheduledNotificationRule model, associated persistence methods, and REST endpoints. Add the fields and capabilities required to support scheduled notifications to the existing NotificationRule model instead. This avoids a ton of redundant code.
  • Removes ScheduledNotificationTaskManager in favour of the existing eventing system. An event is emitted every minute to check for due scheduled notifications. To keep track of when a notification was last sent, and when it's next due, we simply use dedicated fields in the NotificationRule model.
  • Removes SendScheduledNotificationTask and leverages the existing NotificationRouter instead. Again avoiding a lot of redundant code.
  • Improves efficiency slightly by avoiding redundant queries as much as possible while assembling notification subjects. The assembly is still relatively inefficient because it loads too much data into memory. Ideally we would convert all of this to SQL in v5.
  • Enforces scheduled notifications to be limited to a set of projects. Emitting them for the entire portfolio is likely to cause OOM scenarios.
  • Introduce dedicated NotificationGroups for scheduled notifications, and integrate them into existing templates. There are no longer separate NotificationPublishers for scheduled notifications. Instead, templates may be updated to support them.
  • Unfortunately I had to remove the template for HTML emails. It was not possible to integrate into the existing text-based email template due to how MIME-types are handled. Ideally we would have a separate publisher and template for HTML-formatted emails, but I ran out of time to create such a template that covers all (or at least most) notification groups. For the time being, users can simply create their own publisher and template.

Addressed Issue

Supersedes #3925
Closes #322

Additional Details

Frontend PR: DependencyTrack/frontend#1210

Checklist

  • I have read and understand the contributing guidelines
  • This PR fixes a defect, and I have provided tests to verify that the fix is effective
  • This PR implements an enhancement, and I have provided tests to verify that it works as intended
  • This PR introduces changes to the database model, and I have added corresponding update logic
  • This PR introduces new or alters existing behavior, and I have updated the documentation accordingly

@nscuro nscuro added the enhancement New feature or request label Mar 26, 2025
@nscuro nscuro added this to the 4.13 milestone Mar 26, 2025
@nscuro nscuro force-pushed the msr-322-suggestions branch 19 times, most recently from 4af866e to 9891a28 Compare March 30, 2025 22:46
@codacy-production
Copy link

codacy-production bot commented Mar 30, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.25% (target: -1.00%) 89.77% (target: 70.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (db5d1bb) 23313 18728 80.33%
Head commit (c9e952b) 23968 (+655) 19314 (+586) 80.58% (+0.25%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#4783) 704 632 89.77%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@nscuro nscuro changed the title WIP: Scheduled notification changes Add support for scheduled summary notifications Mar 31, 2025
@nscuro nscuro force-pushed the msr-322-suggestions branch 4 times, most recently from db5b388 to 8adfdb9 Compare April 1, 2025 19:08
@nscuro nscuro marked this pull request as ready for review April 1, 2025 19:48
@rkg-mm
Copy link
Contributor

rkg-mm commented Apr 1, 2025

@nscuro Thank you very much, we will check this asap.
Some questions:

  1. Did you also update the frontend already?
  2. We had html mails working, whats the difference now which makes it no longer possible in your approach? Adding own publishers isn't easy without modifying the source code, or is it possible to plug them in without rebuilding the project, ideally using the official containers?

@nscuro nscuro force-pushed the msr-322-suggestions branch 3 times, most recently from 7468f09 to aaa9826 Compare April 1, 2025 20:55
@nscuro
Copy link
Member Author

nscuro commented Apr 1, 2025

@rkg-mm Did you also update the frontend already?

Yes, see here: DependencyTrack/frontend#1210

We had html mails working, whats the difference now which makes it no longer possible in your approach?

Basically, the default email publisher uses the MIME type text/plain. If you send an HTML email with this MIME type, mail clients are likely to not render the HTML. So it wasn't feasible to simply add the HTML to the existing email template.

In order to change the MIME type, you need a new publisher. This is what your original PR did. The downside is that that publisher and its associated template only catered to the new scheduled notification, but not any other notification type.

In your PR, you worked around this by differentiating between publishers for scheduled, and those for "normal" notifications. But this was really just a workaround, and it was really only necessary for email due to the MIME type conflict. On a technical level there is nothing that would prevent a normal publisher to be used for scheduled notifications, other than that its template would need updating.

So I had two options at this point:

  1. Keep the additional email publisher for HTML, and extend the template such that it also caters to other notification types.
  2. Simply extend the existing plaintext email publisher for the new summary types.

For time reasons, I went with (2). Reasoning being that at least the core functionality would be out sooner, and those wishing to use HTML could simply provide a custom template (see below).

We can of course still include the partial HTML email template per default, but my fear is that it'd be too confusing if it only supports a very small subset of notifications.

If you can think of other options I'm open to that of course.

Adding own publishers isn't easy without modifying the source code, or is it possible to plug them in without rebuilding the project, ideally using the official containers?

You can just clone the default email publisher via the UI, and provide a custom template: https://docs.dependencytrack.org/integrations/notifications/#creation-of-publisher

@rkg-mm
Copy link
Contributor

rkg-mm commented Apr 2, 2025

If you can think of other options I'm open to that of course.

Why not just change the mime type of the existing publisher? Shouldn't matter if you send HTML or non-html via HTML mime type. Would also open the existing templates up for using html if someone wants to

@nscuro
Copy link
Member Author

nscuro commented Apr 2, 2025

Why not just change the mime type of the existing publisher?

Mostly because I am unsure about the consequences, tbh. It's really hard to tell if this switch could break things for people who may currently rely on it being plain text.

You likely have more experience than me when it comes to mail clients. Possible I am overthinking this. If you think it's a safe thing to do, we can simply add your original HTML template code to the email.peb file and update the publisher's MIME type.

@rbt-mm
Copy link
Contributor

rbt-mm commented Apr 2, 2025

@nscuro Thank you very much for helping us to implement this feature.

From a first look, everything looks good and fulfills the needs which we had when creating the original PR.
Creating a new publisher and using text/html also seems to work just as well as before when using an adjusted HTML template which I created for testing these changes. So I don't think that it is necessary to generally switch the default publisher from text/plain to text/html. I could also provide our newly adjusted HTML template in some way once I'm done with testing.

The only issue which I am currently experiencing, is that scheduled mail notifications only seem to work via the Perform Test button but not during the normal dispatch once the cron job is run.

Everytime the scheduled email should be dispatched, the following two exceptions occur and no mail is sent:

Exceptions
2025-04-02 16:33:24,292 WARN [ScheduledNotificationDispatchTask] Failed to dispatch notification for group NEW_VULNERABILITIES_SUMMARY [notificationRuleUuid=80e1843a-a590-48dd-8aa2-bb78baf735da, notificationRuleName=Scheduled Email HTML]
java.util.ConcurrentModificationException: null
        at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
        at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getActiveChildProjectIds(ScheduledNotificationDispatchTask.java:365)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getActiveChildProjectIds(ScheduledNotificationDispatchTask.java:366)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getApplicableProjectIds(ScheduledNotificationDispatchTask.java:345)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.createNewVulnerabilitiesNotification(ScheduledNotificationDispatchTask.java:160)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.processRule(ScheduledNotificationDispatchTask.java:118)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.inform(ScheduledNotificationDispatchTask.java:99)
        at alpine.event.framework.BaseEventService.lambda$publish$0(BaseEventService.java:110)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
2025-04-02 16:33:24,293 WARN [ScheduledNotificationDispatchTask] Failed to dispatch notification for group NEW_POLICY_VIOLATIONS_SUMMARY [notificationRuleUuid=80e1843a-a590-48dd-8aa2-bb78baf735da, notificationRuleName=Scheduled Email HTML]
java.util.ConcurrentModificationException: null
        at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
        at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getActiveChildProjectIds(ScheduledNotificationDispatchTask.java:365)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getActiveChildProjectIds(ScheduledNotificationDispatchTask.java:366)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.getApplicableProjectIds(ScheduledNotificationDispatchTask.java:345)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.createNewPolicyViolationsNotification(ScheduledNotificationDispatchTask.java:251)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.processRule(ScheduledNotificationDispatchTask.java:119)
        at org.dependencytrack.tasks.ScheduledNotificationDispatchTask.inform(ScheduledNotificationDispatchTask.java:99)
        at alpine.event.framework.BaseEventService.lambda$publish$0(BaseEventService.java:110)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)

Those exception always occur, regardless whether using the original Email template or the newly created HTML template. Maybe you've got any idea why this could be happening?

@nscuro
Copy link
Member Author

nscuro commented Apr 2, 2025

Everytime the scheduled email should be dispatched, the following two exceptions occur and no mail is sent: [...]

Yep, good catch. Here I am adding to a list while iterating over it:

https://github.com/nscuro/dependency-track/blob/c9e952b20fe6252afb2d9367f1e59af8f3062208/src/main/java/org/dependencytrack/tasks/ScheduledNotificationDispatchTask.java#L365-L367

Fixing. Edit: Fixed.

@nscuro
Copy link
Member Author

nscuro commented Apr 2, 2025

@rbt-mm Should be fixed now, please have another go when you find the time.

I could also provide our newly adjusted HTML template in some way once I'm done with testing.

On that topic. what are your thoughts on my previous question:

If you think it's a safe thing to do, we can simply add your original HTML template code to the email.peb file and update the publisher's MIME type.

I def. see the value in having summaries such as these in HTML format, I'm just not too fond of shipping partial templates. So wondering how to best progress on this.

@codacy-production
Copy link

codacy-production bot commented Apr 2, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.25% (target: -1.00%) 89.80% (target: 70.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (db5d1bb) 23313 18728 80.33%
Head commit (eabd376) 23970 (+657) 19316 (+588) 80.58% (+0.25%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#4783) 706 634 89.80%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@rbt-mm
Copy link
Contributor

rbt-mm commented Apr 2, 2025

@rbt-mm Should be fixed now, please have another go when you find the time.

Thanks for the quick fix, the mails are now correctly dispatched! Stuff like limiting to projects/teams and not publishing mails when there is no new information also seems to work fine. So the changes look good to me 👍

I def. see the value in having summaries such as these in HTML format, I'm just not too fond of shipping partial templates. So wondering how to best progress on this.

I also think its better to have such summaries in an easy to digest format like HTML, but I wouldn't add it to the current email.peb and change the MIME type of the publisher, because I'm also not sure if changing to text/html could potentially break stuff for the current users.

Maybe providing this HTML summary template (and potentially other useful templates from the community which might be contributed in the future?) in a designated documentation/wiki page could be a solution for this?

@nscuro
Copy link
Member Author

nscuro commented Apr 2, 2025

Maybe providing this HTML summary template (and potentially other useful templates from the community which might be contributed in the future?) in a designated documentation/wiki page could be a solution for this?

Like the idea. We could introduce a contrib directory to the repo where we keep these. Once templates mature enough we can introduce them as defaults to the core application.

Can I ask one last favour? What are your thoughts on the text-based templates in this PR? Any more info you'd like to see there?

@rbt-mm
Copy link
Contributor

rbt-mm commented Apr 3, 2025

I think the text-based templates look good and contain all the necessary information 👍
Two things which I think could be helpful when adjusted:

  • In the Project Summary & Vulnerability/Violation Details adding an empty newline between separate entries could improve readability
  • Not sure if it is possible, but mentioning the number of findings directly in the notification title like New Policy Violations Summary (208 violations in 4 components) - same for vulnerability summaries of course- could also help receivers to quickly identify how important/urgent a message is and it also helps when differentiating different notifications because they won't all have the same title anymore

@nscuro
Copy link
Member Author

nscuro commented Apr 3, 2025

In the Project Summary & Vulnerability/Violation Details adding an empty newline between separate entries could improve readability

Great feedback, thanks. Will add this.

Not sure if it is possible, but mentioning the number of findings directly in the notification title [...]

Unfortunately it's not, currently. Email is kind of unique in that the title of the message is specified separate from the main body. We'd need separate templating to enable this. But agree on that it'd be good to have.

Co-authored-by: Max Schiller <msr@mm-software.com>
Co-authored-by: Marlon Gäthje <mge@mm-software.com>
Co-authored-by: Richard Bickert <rbt@mm-software.com>
Signed-off-by: nscuro <nscuro@protonmail.com>
@nscuro nscuro force-pushed the msr-322-suggestions branch from 60251e3 to eabd376 Compare April 3, 2025 19:41
@nscuro nscuro merged commit 1f9cfe7 into DependencyTrack:master Apr 3, 2025
11 checks passed
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 4, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Portfolio Notification: Support for "Summary" Group

3 participants