feat(referral): template the real email#2147
Conversation
WalkthroughThis change adds Askama (workspace dependency) and converts the referral_invitation crate to use Askama templates. InviteToMacro now derives Askama Template and includes a template path; URL construction logic was added to produce environment-aware referral links (/app/signup with referral_code). The email rendering uses the template output. New tests validate URL generation, email formatting, rate-limit helpers, and serde roundtrips. The invite HTML template now uses the generated referral URL. Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
rust/cloud-storage/referral_invitation/templates/invite.html (1)
124-124: 🧹 Nitpick | 🔵 TrivialStatic "User" placeholder may need dynamic replacement.
Lines 124 and 142 display "User has invited you..." but this appears to be a static placeholder. Consider whether the inviter's name should be templated here for personalization (e.g.,
{{ inviter_name }}).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@rust/cloud-storage/referral_invitation/templates/invite.html` at line 124, The static text "User has invited you to Macro" in the invite.html template should be replaced with a templated inviter name to personalize the message; update the template to use a variable like {{ inviter_name }} (or the project's existing context key) in both occurrences, ensure the rendering code that calls the invite.html template (the function or controller responsible for creating referral invitations) supplies inviter_name in the template context, and add a fallback (e.g., "Someone") if inviter_name is missing to avoid blank output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rust/cloud-storage/Cargo.toml`:
- Line 136: Update the askama dependency from "0.14" to the newer version (e.g.,
"0.15.5") in Cargo.toml by changing the askama = "0.14" line to askama =
"0.15.5"; after updating run cargo update and cargo check/cargo build (and cargo
test) to catch any breakages, and address any API changes in code that
references Askama types/macros (search for usages of askama::Template,
#[derive(Template)], and related template macros) and adjust imports or template
attributes as needed.
In `@rust/cloud-storage/referral_invitation/src/lib.rs`:
- Line 67: Replace the terse expect message on the self.render() call with a
more descriptive context that names the Askama template/struct and the enclosing
function so failures are easier to debug; locate the expression setting body:
self.render().expect("This cant fail, it is tested") and update the expect text
to mention the template type (e.g., the invitation template) and the
function/operation that attempted the render so the panic message clearly
identifies what failed.
In `@rust/cloud-storage/referral_invitation/src/test.rs`:
- Around line 16-28: The test get_url_all_environments currently checks path and
query but not that host differs by Environment; update the test to assert
expected host values for each Environment (Environment::Production,
Environment::Develop, Environment::Local) when calling get_url(&code) for
ReferralCode("CODE"), e.g. check url.host_str() or url.as_str() contains the
expected host for each variant alongside the existing assertions so the test
verifies environment-specific hosts in get_url.
- Around line 30-36: The test format_email_does_not_panic currently only checks
that subject and body are non-empty; update it to also assert that the rendered
email body contains the referral link so template regressions are caught. Locate
the test using make_invite() and invite.format_email(), then add an assertion
that email.body contains the invite's referral URL (or the specific field on the
Invite struct, e.g., invite.url or invite.referral_code formatted into the
expected URL) so the test will fail if the link is omitted from the template.
---
Outside diff comments:
In `@rust/cloud-storage/referral_invitation/templates/invite.html`:
- Line 124: The static text "User has invited you to Macro" in the invite.html
template should be replaced with a templated inviter name to personalize the
message; update the template to use a variable like {{ inviter_name }} (or the
project's existing context key) in both occurrences, ensure the rendering code
that calls the invite.html template (the function or controller responsible for
creating referral invitations) supplies inviter_name in the template context,
and add a fallback (e.g., "Someone") if inviter_name is missing to avoid blank
output.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2d2213fd-0a92-4c5b-a239-81c10368ad93
⛔ Files ignored due to path filters (1)
rust/cloud-storage/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
rust/cloud-storage/Cargo.tomlrust/cloud-storage/email_formatting/Cargo.tomlrust/cloud-storage/referral_invitation/Cargo.tomlrust/cloud-storage/referral_invitation/src/lib.rsrust/cloud-storage/referral_invitation/src/test.rsrust/cloud-storage/referral_invitation/templates/invite.html
|
|
||
| [workspace.dependencies] | ||
| anyhow = "1.0.93" | ||
| askama = "0.14" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🌐 Web query:
askama crate latest version 2025
💡 Result:
In 2025, the latest askama crate release was v0.15.0, published on December 22, 2025. [1]
Earlier in 2025, v0.14.0 was released on April 23, 2025. [2]
(For reference, as of March 24, 2026, docs.rs shows the latest askama version as 0.15.5.) [3]
Sources:
[1] [GitHub releases: askama-rs/askama (v0.15.0, Dec 22)] (github.com)
[2] [GitHub releases: askama-rs/askama (v0.14.0, Apr 23)] (github.com)
[3] [docs.rs: askama 0.15.5] (docs.rs)
Citations:
- 1: https://github.com/askama-rs/askama/releases
- 2: https://github.com/askama-rs/askama/releases?utm_source=openai
- 3: https://docs.rs/crate/askama/latest/features
Consider updating askama to the latest version.
Askama v0.14.0 is valid (released April 23, 2025), but as of March 2026, the latest version is 0.15.5. Consider updating to benefit from recent improvements and security patches.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rust/cloud-storage/Cargo.toml` at line 136, Update the askama dependency from
"0.14" to the newer version (e.g., "0.15.5") in Cargo.toml by changing the
askama = "0.14" line to askama = "0.15.5"; after updating run cargo update and
cargo check/cargo build (and cargo test) to catch any breakages, and address any
API changes in code that references Askama types/macros (search for usages of
askama::Template, #[derive(Template)], and related template macros) and adjust
imports or template attributes as needed.
6846da2 to
1f67a7a
Compare
1f67a7a to
33cc78c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rust/cloud-storage/referral_invitation/src/lib.rs`:
- Around line 48-61: The get_url function is private but your tests need to call
it directly; make it test-accessible by changing its visibility to pub(crate)
(i.e., pub(crate) fn get_url(env: Environment, code: &ReferralCode) -> Url) so
tests in the crate can import and exercise it, leaving the function body and
types (Environment, ReferralCode, Url) unchanged; update any references that
rely on the old private visibility if necessary.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f4cefcdc-096a-4c1b-bb03-f9e186c4ee10
⛔ Files ignored due to path filters (1)
rust/cloud-storage/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
rust/cloud-storage/Cargo.tomlrust/cloud-storage/email_formatting/Cargo.tomlrust/cloud-storage/referral_invitation/Cargo.tomlrust/cloud-storage/referral_invitation/src/lib.rsrust/cloud-storage/referral_invitation/src/test.rsrust/cloud-storage/referral_invitation/templates/invite.html
| fn get_url(env: Environment, code: &ReferralCode) -> Url { | ||
| let host = match env { | ||
| Environment::Production => "https://macro.com", | ||
| Environment::Develop => "https://dev.macro.com", | ||
| Environment::Local => "http://localhost:3000", | ||
| }; | ||
| let mut url = Url::parse(host).expect("all the inputs are static, valid values"); | ||
| url.set_path("/app/signup"); | ||
| url.query_pairs_mut() | ||
| .clear() | ||
| .append_pair("referral_code", &code.0) | ||
| .finish(); | ||
| url | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider making get_url testable.
The get_url function is private but is directly called in tests. See the related comment on test.rs regarding the use super::* import not bringing private items into scope.
If you want to keep this function tested directly, consider making it pub(crate):
Suggested change
-fn get_url(env: Environment, code: &ReferralCode) -> Url {
+pub(crate) fn get_url(env: Environment, code: &ReferralCode) -> Url {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn get_url(env: Environment, code: &ReferralCode) -> Url { | |
| let host = match env { | |
| Environment::Production => "https://macro.com", | |
| Environment::Develop => "https://dev.macro.com", | |
| Environment::Local => "http://localhost:3000", | |
| }; | |
| let mut url = Url::parse(host).expect("all the inputs are static, valid values"); | |
| url.set_path("/app/signup"); | |
| url.query_pairs_mut() | |
| .clear() | |
| .append_pair("referral_code", &code.0) | |
| .finish(); | |
| url | |
| } | |
| pub(crate) fn get_url(env: Environment, code: &ReferralCode) -> Url { | |
| let host = match env { | |
| Environment::Production => "https://macro.com", | |
| Environment::Develop => "https://dev.macro.com", | |
| Environment::Local => "http://localhost:3000", | |
| }; | |
| let mut url = Url::parse(host).expect("all the inputs are static, valid values"); | |
| url.set_path("/app/signup"); | |
| url.query_pairs_mut() | |
| .clear() | |
| .append_pair("referral_code", &code.0) | |
| .finish(); | |
| url | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@rust/cloud-storage/referral_invitation/src/lib.rs` around lines 48 - 61, The
get_url function is private but your tests need to call it directly; make it
test-accessible by changing its visibility to pub(crate) (i.e., pub(crate) fn
get_url(env: Environment, code: &ReferralCode) -> Url) so tests in the crate can
import and exercise it, leaving the function body and types (Environment,
ReferralCode, Url) unchanged; update any references that rely on the old private
visibility if necessary.
Replace the placeholder with the real email template