fix(worker): populate email-webhook payloadDetails content for v2 workflows fixes NV-8153#11743
fix(worker): populate email-webhook payloadDetails content for v2 workflows fixes NV-8153#11743scopsy wants to merge 2 commits into
Conversation
…kflows fixes NV-8153 Co-authored-by: Dima Grossman <dima@grossman.io>
✅ Deploy preview added
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@cursoragent let's introduce an e2e test to verify our fix |
| payload.subject = subject; | ||
| payload.content = command.bridgeData | ||
| ? (bridgeOutputs as EmailOutput)?.body || html || '' | ||
| : (content ?? html ?? step.template.content); |
There was a problem hiding this comment.
Let's only do that for v2 workflows where bridge output is present to ensure backwards compatability for v0 templates @cursoragent
There was a problem hiding this comment.
@cursoragent Let's only do that for v2 workflows where bridge output is present to ensure backwards compatability for v0 templates
There was a problem hiding this comment.
Scoping is updated per review: payloadDetails.content is only rewritten when bridge output is present (v2 workflows). Legacy v0 email-webhook payloads are unchanged.
if (integration.providerId === EmailProviderIdEnum.EmailWebhook) {
if (command.bridgeData) {
payload.content = (bridgeOutputs as EmailOutput)?.body || html || '';
}
mailData.payloadDetails = payload;
}What changed
- Removed the legacy fallback
(content ?? html ?? step.template.content)and the unconditionalpayload.subject = subjectupdate. - For v0 templates,
payloadDetailsstill carries the original template subject/content (with the existing in-place editor compilation behavior). - For v2 bridge workflows,
payloadDetails.contentis set from the rendered bridge email body.
Tests added in send-message-email.usecase.spec.ts:
- v2 bridge workflow →
payloadDetails.contentis populated with rendered HTML - v0 legacy workflow →
payloadDetails.contentandsubjectstay as template values
Both worker specs pass. Changes are pushed to PR #11743.
…kflows fixes NV-8153 Co-authored-by: Dima Grossman <dima@grossman.io>


Summary
Fixes empty
contentin email-webhookpayloadDetailswhen sending emails from new dashboard (v2) workflows, while preserving legacy v0 payload behavior.Problem
New dashboard workflows store email body in control values and render it via the bridge/framework path. The message template's
contentfield is intentionally empty (''), butSendMessageEmailwas passing that raw template value intopayloadDetails.contentfor the email-webhook provider.The old dashboard populated
contentbecause template compilation mutated the in-memory blocks array referenced bypayload.content. Bridge-based v2 workflows skip that compilation path, leavingcontentas an empty string whilesubjectand rendered HTML were correct.Solution
For email-webhook integrations, populate
payloadDetails.contentonly when bridge output is present (v2 workflows):Legacy v0 workflows without bridge output keep the existing
payloadDetailssubject/content contract unchanged.Test plan
payloadDetails.contentwith rendered HTMLpayloadDetails.contentandsubjectpayloadDetails.contentcontains rendered HTMLLinear Issue: NV-8153
Greptile Summary
This PR fixes an empty
payloadDetails.contentfield in email-webhook integrations when emails are sent through v2 (new-dashboard) workflows. The root cause was that v2 workflows store the rendered body in bridge outputs and skip template compilation, leavingpayload.contentas the raw (empty) template string.send-message-email.usecase.ts: Adds a guard inside theEmailWebhookbranch — whencommand.bridgeDatais present the handler overwritespayload.contentwithbridgeOutputs.body(falling back to the compiledhtmlvariable and then''), before assigningpayloadtomailData.payloadDetails. V0 workflows withoutbridgeDataare unaffected.send-message-email.usecase.spec.ts: New spec file with two focused test cases: one verifying that a v2 workflow setspayloadDetails.contentto the rendered bridge body, and one verifying that a v0 workflow preserves the raw template string and subject unchanged.Confidence Score: 5/5
Safe to merge — the change is narrowly scoped to the EmailWebhook integration path and only activates when bridge data is present, leaving all other send paths untouched.
The fix is minimal and well-contained: four lines inside a doubly-guarded block (EmailWebhook provider AND bridgeData present). The fallback chain mirrors the identical pattern already used on line 356 for mailData.html. Unit tests cover both the v2 and v0 paths, and the constructor argument count in the test matches the 13-parameter signature exactly.
No files require special attention.
Important Files Changed
payloadDetails.contentfrom bridge outputs (orhtml) whencommand.bridgeDatais present, fixing empty content for v2 email-webhook workflows while leaving the v0 path untouched.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[SendMessageEmail.execute] --> B{command.bridgeData?} B -- Yes v2 workflow --> C[Skip compileEmailTemplateUsecase] B -- No v0 workflow --> D[compileEmailTemplateUsecase.execute] C --> E[Build payload with empty content] D --> E E --> F[Build mailData] F --> G{EmailWebhook?} G -- No --> H[sendMessage] G -- Yes --> I{command.bridgeData?} I -- Yes v2 --> J[payload.content = bridgeOutputs.body or html or ''] I -- No v0 --> K[payload.content stays as raw template string] J --> L[mailData.payloadDetails = payload] K --> L L --> H%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[SendMessageEmail.execute] --> B{command.bridgeData?} B -- Yes v2 workflow --> C[Skip compileEmailTemplateUsecase] B -- No v0 workflow --> D[compileEmailTemplateUsecase.execute] C --> E[Build payload with empty content] D --> E E --> F[Build mailData] F --> G{EmailWebhook?} G -- No --> H[sendMessage] G -- Yes --> I{command.bridgeData?} I -- Yes v2 --> J[payload.content = bridgeOutputs.body or html or ''] I -- No v0 --> K[payload.content stays as raw template string] J --> L[mailData.payloadDetails = payload] K --> L L --> HComments Outside Diff (1)
General comment
Template subject {{name}},<p>Template legacy {{name}}</p>), while head rewrites them to the final compiled subject/content (Final legacy compiled subject for Grace,<p>Compiled legacy HTML for Grace</p>). This is a user-visible provider request payloadDetails contract change for legacy email-webhook integrations.apps/worker/src/app/workflow/usecases/send-message/send-message-email.usecase.tsunconditionally assignspayload.subject = subjectand, whencommand.bridgeDatais absent, assignspayload.content = (content ?? html ?? step.template.content). That code path also runs for legacy/v1 email-webhook sends, not just bridge/v2 sends.payloadobject for non-bridge sends. If compiled subject/content is intentionally desired for legacy too, update the contract/request because the executed behavior is not unchanged.Reviews (2): Last reviewed commit: "fix(worker): scope email-webhook payload..." | Re-trigger Greptile