Add live smoke testing for email providers#21
Conversation
- Document live verification status in the provider catalog - Add env example, verification manifest, and smoke test runner
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR introduces a
Confidence Score: 4/5Safe to merge after fixing the hardcoded personal email fallback in live-smoke.ts and .env.live.example. The smoke runner is well-structured — it checks env vars before attempting sends, exits non-zero on failures, and the dry-run path is safe. The one real concern is that the default packages/email-sdk/src/live-smoke.ts (line 33) and packages/email-sdk/.env.live.example (line 4) — both contain the hardcoded personal email address that acts as the live-send recipient fallback. Important Files Changed
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant CLI as live-smoke.ts
participant Env as process.env / flags
participant Adapter as EmailAdapter
participant Provider as Email Provider API
Dev->>CLI: bun run live:smoke [--send] [--adapter X] [--from addr]
CLI->>Env: resolve `to`, `from`, credentials per adapter
alt missing env vars
CLI-->>Dev: "results[].skipped = true (no send)"
else dry-run (no --send)
CLI-->>Dev: "results[].sent = false"
else --send mode
CLI->>Adapter: provider.create()
CLI->>Adapter: "createEmailClient({ adapters })"
Adapter->>Provider: HTTP send request
Provider-->>Adapter: response / error
Adapter-->>CLI: EmailProviderResponse
CLI-->>Dev: JSON summary (redacted response)
end
CLI->>Dev: process.exit(1) if any non-skipped failure
Reviews (1): Last reviewed commit: "Add live smoke testing for email provide..." | Re-trigger Greptile |
| const flags = parseFlags(Bun.argv.slice(2)); | ||
| const sendLive = truthyFlag("send"); | ||
| const selectedAdapters = selectedAdapterNames(); | ||
| const to = stringFlag("to") ?? process.env.LIVE_EMAIL_TO ?? "leodoesdev@gmail.com"; |
There was a problem hiding this comment.
Hardcoded personal email as the default recipient
Any contributor who runs bun run live:smoke -- --send without exporting LIVE_EMAIL_TO will silently deliver live test emails to a personal Gmail address. The same address is also pre-filled in .env.live.example (line 4), so copy-paste usage inherits it. The fallback should require an explicit value — throw if neither --to nor LIVE_EMAIL_TO is set — rather than quietly routing real email to someone's inbox. Confidence: 5/5
| text: [ | ||
| "Email SDK live smoke test.", | ||
| `Adapter: ${adapter}`, | ||
| `Timestamp: ${new Date().toISOString()}`, | ||
| ].join("\n"), | ||
| html: [ | ||
| "<p>Email SDK live smoke test.</p>", | ||
| `<p><strong>Adapter:</strong> ${escapeHtml(adapter)}</p>`, | ||
| `<p><strong>Timestamp:</strong> ${escapeHtml(new Date().toISOString())}</p>`, | ||
| ].join(""), |
There was a problem hiding this comment.
new Date() is called separately for the text and html bodies, so the two timestamps can diverge by a millisecond or more on a slow machine. Capture it once and share the value. Confidence: 3/5
| text: [ | |
| "Email SDK live smoke test.", | |
| `Adapter: ${adapter}`, | |
| `Timestamp: ${new Date().toISOString()}`, | |
| ].join("\n"), | |
| html: [ | |
| "<p>Email SDK live smoke test.</p>", | |
| `<p><strong>Adapter:</strong> ${escapeHtml(adapter)}</p>`, | |
| `<p><strong>Timestamp:</strong> ${escapeHtml(new Date().toISOString())}</p>`, | |
| ].join(""), | |
| text: [ | |
| "Email SDK live smoke test.", | |
| `Adapter: ${adapter}`, | |
| `Timestamp: ${new Date().toISOString()}`, | |
| ].join("\n"), | |
| html: (() => { | |
| const ts = escapeHtml(new Date().toISOString()); | |
| return [ | |
| "<p>Email SDK live smoke test.</p>", | |
| `<p><strong>Adapter:</strong> ${escapeHtml(adapter)}</p>`, | |
| `<p><strong>Timestamp:</strong> ${ts}</p>`, | |
| ].join(""); | |
| })(), |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| if (status === "verified") { | ||
| return ( | ||
| <span | ||
| className={`mt-3 inline-flex w-fit rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-700 dark:text-emerald-300 ${className ?? ""}`} | ||
| > | ||
| Live verified | ||
| </span> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <span | ||
| className={`mt-3 inline-flex w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-800 dark:text-amber-300 ${className ?? ""}`} | ||
| > | ||
| Untested live | ||
| </span> | ||
| ); |
There was a problem hiding this comment.
The
VerificationPill component concatenates className via a template string (${className ?? ""}). If className is undefined the span gets a trailing space in its class attribute. The rest of the codebase likely uses a cn() / clsx() utility — prefer that pattern to avoid potential whitespace issues. Confidence: 2/5
| if (status === "verified") { | |
| return ( | |
| <span | |
| className={`mt-3 inline-flex w-fit rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-700 dark:text-emerald-300 ${className ?? ""}`} | |
| > | |
| Live verified | |
| </span> | |
| ); | |
| } | |
| return ( | |
| <span | |
| className={`mt-3 inline-flex w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-800 dark:text-amber-300 ${className ?? ""}`} | |
| > | |
| Untested live | |
| </span> | |
| ); | |
| if (status === "verified") { | |
| return ( | |
| <span | |
| className={[ | |
| "mt-3 inline-flex w-fit rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-700 dark:text-emerald-300", | |
| className, | |
| ] | |
| .filter(Boolean) | |
| .join(" ")} | |
| > | |
| Live verified | |
| </span> | |
| ); | |
| } | |
| return ( | |
| <span | |
| className={[ | |
| "mt-3 inline-flex w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-800 dark:text-amber-300", | |
| className, | |
| ] | |
| .filter(Boolean) | |
| .join(" ")} | |
| > | |
| Untested live | |
| </span> | |
| ); |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
live:smokescript andsrc/live-smoke.tsCLI to validate provider configuration and optionally send live test emails.live-verification.json.Testing
--sendis passed.