Skip to content

fix(templates): silence inbound WARN + guard blank auto-replies (EVO-1720)#150

Merged
dpaes merged 1 commit into
developfrom
danilocarneiro/evo-1720-follow-up-611-achados-do-review-da-evo-1235-wire-call-sites
Jun 15, 2026
Merged

fix(templates): silence inbound WARN + guard blank auto-replies (EVO-1720)#150
dpaes merged 1 commit into
developfrom
danilocarneiro/evo-1720-follow-up-611-achados-do-review-da-evo-1235-wire-call-sites

Conversation

@daniloleonecarneiro

@daniloleonecarneiro daniloleonecarneiro commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Non-blocking follow-up (6.11) to the EVO-1235 [6.6] wire-call-sites review. Three findings raised; two fixed, one documented.

  • 🟡 [Medium] False-positive "deprecated inline content" WARN on INBOUND. Public::Api::V1::Inboxes::MessagesController#create included TemplateConsumerLogging and fired warn_legacy_inline_content whenever content was present. But an inbound message (from the contact) always carries content and has no template alternative — there is nothing to migrate. The WARN fired on every inbound message, spamming the very signal meant to identify legacy outbound consumers. Removed the include + the call (and its coexistence comment). The outbound_messages_controller (the legitimate WARN site) and the TemplateConsumerLogging concern are untouched; permitted_params/message_params are preserved.

  • 🟢 [Low] Blank auto-reply edge. Greeting/Out-of-Office fire when *_message_template_id is present. If the referenced template has a required: true variable outside {first_name, name, email}, render_with_variables raises ArgumentError; TemplateContent#template_content_for rescues it and falls back to the inline column. Message has no content presence validation, so a blank inline column produced a blank :template message. perform now resolves the content once (via a *_content helper, so the guard adds no extra SendResolver lookup) and return if content.blank? — skip silently. Skipping the blank :template message keeps HookExecutionService#first_message_from_contact? accurate, so a later valid greeting can still fire.

  • 🟢 [Low / Documented] Dormant message_template_id accept-paths in agent-bot/macro/automation are intentionally untouched — no producer feeds the id yet (expected until a UI does).

No migration, no schema change.

Test plan

  • POSTGRES_PORT=5433 ... bundle exec rspec spec/services/message_templates/template/greeting_spec.rb spec/services/message_templates/template/out_of_office_spec.rb spec/requests/public/api/v1/inboxes/messages_controller_spec.rb spec/requests/public/api/v1/inboxes/outbound_messages_controller_spec.rb14 examples, 0 failures.
  • Inbound spec inverted: the existing example asserted the WARN fired; it now asserts the incoming message persists (incoming, with the posted content) and the deprecated WARN is not emitted (allow → have_received so unrelated warns don't interfere).
  • New service specs build a global MessageTemplate with a surviving required variable ({{order_id}} in content + explicit required: true, since extract_variables_from_content strips vars absent from content) and assert render_with_variables actually raises before relying on the guard (no vacuous test). Cover: blank-skip, render-raise→inline fallback, and no-template→inline. Created fallback message is message_type: :template, content_type: 'text'.
  • RuboCop: clean on all 6 touched files.

Notes

Summary by Sourcery

Silence deprecated inline-content warnings for inbound messages and prevent sending blank auto-reply template messages for greeting and out-of-office flows.

Bug Fixes:

  • Stop emitting deprecated inline-content WARN logs for inbound inbox messages that always carry content and have no template alternative.
  • Avoid creating blank greeting auto-reply messages when both the referenced template and inline fallback yield empty content.
  • Avoid creating blank out-of-office auto-reply messages when both the referenced template and inline fallback yield empty content.

Tests:

  • Update inbound messages controller request spec to assert message creation without deprecated inline-content warnings.
  • Add service specs for greeting and out-of-office template services covering blank-skipped replies, template render failures falling back to inline content, and no-template inline scenarios.

…1720)

Non-blocking follow-up (6.11) to the EVO-1235 [6.6] wire-call-sites review.

- #1 [Medium] The inbound public endpoint
  Public::Api::V1::Inboxes::MessagesController#create included
  TemplateConsumerLogging and fired the "deprecated inline content" WARN on
  every message. Inbound messages always carry content and have no template
  alternative, so the WARN was pure spam polluting the signal meant to flag
  legacy OUTBOUND consumers. Removed the include + call; outbound (the
  legitimate WARN site) and the concern are unchanged.

- #3 [Low] Greeting/Out-of-Office could deliver a blank auto-reply: when a
  referenced template raises ArgumentError (required var outside
  first_name/name/email), TemplateContent falls back to the inline column,
  and Message has no content-presence validation, so a blank :template
  message persisted. perform now resolves content once and returns early when
  it is blank (skip silently). Skipping the blank :template message keeps
  HookExecutionService#first_message_from_contact? accurate, so a later valid
  greeting can still fire.

- #2 [Low] Dormant message_template_id accept-paths in bot/macro/automation
  are intentionally untouched (no producer feeds the id yet).

Specs: inbound request spec inverted to assert no deprecated WARN (+ asserts
the incoming message persists); new greeting/out_of_office service specs cover
the blank-skip, render-raise-to-inline fallback, and no-template-to-inline
paths, asserting the template render actually raises before relying on the
guard. 14 examples, 0 failures; RuboCop clean.
@sourcery-ai

sourcery-ai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refines template-based auto-reply behavior to avoid blank messages and removes deprecated inline-content logging from inbound messages, while adding focused service and request specs to cover the new behavior and guardrails.

Sequence diagram for guarded greeting/OOO auto-reply generation

sequenceDiagram
  participant Conversation
  participant GreetingService as MessageTemplates_Template_Greeting
  participant OutOfOfficeService as MessageTemplates_Template_OutOfOffice
  participant Inbox
  participant Message as Conversation_messages

  Conversation->>GreetingService: perform
  GreetingService->>Inbox: greeting_content
  Inbox-->>GreetingService: template_content_for(...) || greeting_message
  alt [content.blank?]
    GreetingService-->>Conversation: return (no message created)
  else [content present]
    GreetingService->>Message: create!(inbox_id, message_type: :template, content)
  end

  Conversation->>OutOfOfficeService: perform
  OutOfOfficeService->>Inbox: out_of_office_content
  Inbox-->>OutOfOfficeService: template_content_for(...) || out_of_office_message
  alt [content.blank?]
    OutOfOfficeService-->>Conversation: return (no message created)
  else [content present]
    OutOfOfficeService->>Message: create!(inbox_id, message_type: :template, content)
  end
Loading

File-Level Changes

Change Details Files
Guard greeting and out-of-office auto-replies from sending when no resolved content is available, while keeping template resolution behavior and message shape the same.
  • Refactor greeting auto-reply perform to resolve content once via a new helper and early-return when content is blank.
  • Refactor out-of-office auto-reply perform similarly with a dedicated content helper and blank-content guard.
  • Inline the message creation parameters in both services to always create :template messages with inbox_id and resolved content inside a transaction.
  • Document via comments that content is resolved once to avoid extra SendResolver lookups and that blank auto-replies are intentionally skipped.
app/services/message_templates/template/greeting.rb
app/services/message_templates/template/out_of_office.rb
Stop treating inbound messages with inline content as deprecated inline template consumers and assert the new behavior in request specs.
  • Remove inclusion of TemplateConsumerLogging from the inbound messages controller and delete the warn_legacy_inline_content call in create.
  • Keep permitted_params/message_params behavior unchanged while still building and saving messages with attachments.
  • Update the inbound messages controller request spec to expect message creation, verify message_type/content, and assert that the deprecated inline-content WARN is not emitted.
  • Use an allow/expect-not-to-have-received pattern on Rails.logger.warn so unrelated warnings do not interfere with the assertion.
app/controllers/public/api/v1/inboxes/messages_controller.rb
spec/requests/public/api/v1/inboxes/messages_controller_spec.rb
Add service-level specs for greeting and out-of-office template services covering blank content, template render failures, and inline fallbacks.
  • Create new specs that build a MessageTemplate with a required variable that will cause render_with_variables to raise, verifying the guard and fallback behavior are actually exercised.
  • Cover scenarios where greeting/out-of-office content is blank (skip creation), where template rendering raises and falls back to inline content, and where there is no template so inline content is used.
  • Ensure created fallback messages are of message_type :template with 'text' content_type to match expected shape.
  • Use plain ActiveRecord.create! instead of FactoryBot to align with existing test patterns in the repo.
spec/services/message_templates/template/greeting_spec.rb
spec/services/message_templates/template/out_of_office_spec.rb

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The greeting and out-of-office template services now share nearly identical *_content resolution, blank-guard, and messages.create! logic; consider extracting a small shared helper/module (e.g., a base template auto-reply service) to reduce duplication and keep future behavior changes (like new message attributes) in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The greeting and out-of-office template services now share nearly identical `*_content` resolution, blank-guard, and `messages.create!` logic; consider extracting a small shared helper/module (e.g., a base template auto-reply service) to reduce duplication and keep future behavior changes (like new message attributes) in one place.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dpaes dpaes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — EVO-1720 [6.11] follow-up · APPROVED ✅

Non-blocking follow-up to the EVO-1235 [6.6] wire-call-sites review. All three findings verified against the code; no blockers.

🟡 #1 [Medium] Inbound deprecated-content WARN — fixed. Public::Api::V1::Inboxes::MessagesController no longer includes TemplateConsumerLogging nor calls warn_legacy_inline_content. The legitimate site (OutboundMessagesController#outbound_content) and the concern itself are untouched, and no dangling reference to the removed methods remains in the inbound controller. The request spec is correctly inverted to assert the WARN does NOT fire and the incoming message still persists with message_type=incoming.

🟢 #3 [Low] Blank auto-reply — fixed (greeting + out-of-office). perform resolves content once and return if content.blank? before create!. Traced the raise path: a required variable missing from the auto-reply's {first_name,name,email} makes MessageTemplate#render_with_variables raise ArgumentError; TemplateContent#template_content_for rescues to nil; the inline column is the fallback; a blank inline column is now skipped. Skipping (rather than persisting) the blank :template message keeps HookExecutionService#first_message_from_contact? — which counts messages.template — accurate, so a later valid greeting can still fire. That regression is genuinely closed.

🟢 #2 [Low] Dormant accept-paths (bot/macro/automation) intentionally untouched — documented in the commit.

Spec quality: the "render actually raises" guard tests are genuine — extract_variables_from_content (before_save) strips variables absent from content, so keeping {{order_id}} in the content is required to preserve the explicit required:true; the specs do exactly that. Setup mirrors the existing request spec, and MessageTemplate.create! without language is valid (column default pt_BR).

Non-blocking notes:

  • This repo does not run RSpec in CI (Sourcery + contract only), so "14 examples, 0 failures" is self-reported — recommend a local bundle exec rspec spec/services/message_templates/template/ spec/requests/public/api/v1/inboxes/messages_controller_spec.rb before relying on it.
  • Minor test-symmetry gap: greeting_spec has the "later valid greeting fires" case (AC6); out_of_office_spec has no equivalent. Skip behavior is identical, so non-blocking.
  • Pre-existing (not introduced here): delegate :inbox, to: :message in greeting.rb/out_of_office.rb points to a non-existent message method (dead code) — worth removing while in the area.

Approving and merging. 🟢

@dpaes dpaes merged commit 4fd05e6 into develop Jun 15, 2026
2 checks passed
@dpaes dpaes deleted the danilocarneiro/evo-1720-follow-up-611-achados-do-review-da-evo-1235-wire-call-sites branch June 15, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants