Skip to content

Comments

Changed member welcome email job to run based on config#30

Open
tomerqodo wants to merge 6 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_changed_member_welcome_email_job_to_run_based_on_config_pr246from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_changed_member_welcome_email_job_to_run_based_on_config_pr246
Open

Changed member welcome email job to run based on config#30
tomerqodo wants to merge 6 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_changed_member_welcome_email_job_to_run_based_on_config_pr246from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_changed_member_welcome_email_job_to_run_based_on_config_pr246

Conversation

@tomerqodo
Copy link

@tomerqodo tomerqodo commented Jan 21, 2026

Benchmark PR from qodo-benchmark#246

Summary by CodeRabbit

  • Refactor
    • Updated member welcome email system to use configuration-based controls instead of experimental feature flags for improved stability and reliability.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Walkthrough

Feature-flag based member welcome email control is replaced with config-driven toggling using memberWelcomeEmailTestInbox. Job scheduling logic is refactored to check if already scheduled before proceeding. Production and test code are updated to use config utilities instead of labs feature flags.

Changes

Cohort / File(s) Summary
Job Scheduling
ghost/core/core/server/services/member-welcome-emails/jobs/index.js
Replaced feature flag source from labs.isSet('welcomeEmails') to config.get('memberWelcomeEmailTestInbox'). Inverted scheduling guard logic to proceed when already scheduled. Added job name parameter and state tracking via hasScheduled.processOutbox.
Member Repository
ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js
Replaced strict feature flag check with config-driven toggle. Welcome email path now enabled based on config value truthiness or source type. Variable declaration updated to align with new conditional flow.
Integration Tests
ghost/core/test/integration/services/member-welcome-emails.test.js
Migrated from labs.isSet stubs to configUtils for test inbox configuration. Removed sinon dependency; tests now use concrete inbox values (empty string or valid email) to control behavior.
Unit Tests
ghost/core/test/unit/server/services/members/members-api/repositories/MemberRepository.test.js
Replaced labsService stubs with config.get('memberWelcomeEmailTestInbox') stubs. Updated test cases to reflect config-driven gating logic while preserving payload structure and outbox creation behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Welcome emails leap from labs to configs bright,
No more flags to juggle, just settings set right!
The scheduler hops in rhythm, jobs dance on queue,
A simpler path for rabbits—and your users too! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: transitioning the member welcome email job from feature flag-based control to configuration-driven execution across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ghost/core/core/server/services/member-welcome-emails/jobs/index.js (1)

11-23: Fix inverted scheduling guard (job never schedules).

With hasScheduled.processOutbox initially false, the job never schedules; if it were ever set true, repeated calls would reschedule. Also, NODE_ENV can be undefined. Suggest restoring the original guard and using optional chaining.

🐛 Proposed fix
-        if (hasScheduled.processOutbox && !process.env.NODE_ENV.startsWith('test')) {
+        if (!hasScheduled.processOutbox && !process.env.NODE_ENV?.startsWith('test')) {
             jobsService.addJob({
                 at: '0 */5 * * * *',
                 job: path.resolve(__dirname, 'process-outbox.js'),
                 name: 'process-member-welcome-emails'
             });

             hasScheduled.processOutbox = true;
         }
🤖 Fix all issues with AI agents
In
`@ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js`:
- Around line 341-342: The conditional that decides whether to create
welcome-email outbox entries incorrectly uses an OR: `welcomeEmailConfig ||
WELCOME_EMAIL_SOURCES.includes(source)`, which allows member-sourced signups to
enqueue when config is unset; change it back to an AND gate so both must be
true. Update the check around the welcome-email outbox creation (referencing
welcomeEmailConfig, WELCOME_EMAIL_SOURCES and source in MemberRepository.js) to
`welcomeEmailConfig && WELCOME_EMAIL_SOURCES.includes(source)` so outbox entries
are only created when the config is present and the source is allowed.
- Line 340: Replace the function-scope declaration using `var member;` with a
block-scoped `let member;` to satisfy the ESLint `no-var` rule; update the
declaration inside MemberRepository (look for the `member` variable in
MemberRepository.js) so all usages remain unchanged but the declaration uses
`let` instead of `var`.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3238ee2 and 96cac63.

📒 Files selected for processing (4)
  • ghost/core/core/server/services/member-welcome-emails/jobs/index.js
  • ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js
  • ghost/core/test/integration/services/member-welcome-emails.test.js
  • ghost/core/test/unit/server/services/members/members-api/repositories/MemberRepository.test.js
🧰 Additional context used
🧬 Code graph analysis (3)
ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js (1)
ghost/core/core/server/services/member-welcome-emails/jobs/lib/send-member-welcome-email.js (2)
  • config (4-4)
  • require (3-3)
ghost/core/core/server/services/member-welcome-emails/jobs/index.js (1)
ghost/core/core/server/services/member-welcome-emails/jobs/lib/send-member-welcome-email.js (2)
  • config (4-4)
  • require (3-3)
ghost/core/test/unit/server/services/members/members-api/repositories/MemberRepository.test.js (2)
ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js (3)
  • config (11-11)
  • require (6-6)
  • require (8-8)
ghost/core/core/server/services/member-welcome-emails/jobs/lib/send-member-welcome-email.js (2)
  • config (4-4)
  • require (3-3)
🪛 ESLint
ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js

[error] 340-340: Unexpected var, use let or const instead.

(no-var)

🔇 Additional comments (2)
ghost/core/test/integration/services/member-welcome-emails.test.js (1)

6-25: Config-driven setup/teardown looks solid.

Using configUtils.set(...) per test and configUtils.restore() in afterEach keeps state isolated and matches the new config-based gating.

Also applies to: 29-30, 52-54, 68-69, 83-84, 98-99

ghost/core/test/unit/server/services/members/members-api/repositories/MemberRepository.test.js (1)

7-7: Config-based stubbing aligns with new behavior.

The config.get('memberWelcomeEmailTestInbox') stubs cleanly model enable/disable scenarios and stay isolated via sinon.restore().

Also applies to: 529-617

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

const memberAddOptions = {...(options || {}), withRelated};
let member;
if (this._labsService.isSet('welcomeEmails') && WELCOME_EMAIL_SOURCES.includes(source)) {
var member;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find the MemberRepository.js file
fd "MemberRepository.js" --type f

# Check if the file exists at the exact path mentioned
if [ -f "ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js" ]; then
  echo "=== File found at expected path ==="
  echo "=== Content around line 340 ==="
  sed -n '335,345p' "ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js" | cat -n
else
  echo "File not found at expected path, searching..."
fi

Repository: qodo-benchmark/Ghost-combined-coderabbit

Length of output: 887


🏁 Script executed:

#!/bin/bash

# Look for ESLint configuration files
echo "=== ESLint configuration files ==="
find . -maxdepth 3 -type f \( -name ".eslintrc*" -o -name "eslint.config.*" \) 2>/dev/null | head -20

# Check root .eslintrc files
if [ -f ".eslintrc.js" ]; then
  echo "=== .eslintrc.js content ==="
  cat ".eslintrc.js" | head -100
fi

if [ -f ".eslintrc.json" ]; then
  echo "=== .eslintrc.json content ==="
  cat ".eslintrc.json" | head -100
fi

if [ -f ".eslintrc.yml" ] || [ -f ".eslintrc.yaml" ]; then
  echo "=== .eslintrc.yml/.yaml content ==="
  cat ".eslintrc.yml" 2>/dev/null || cat ".eslintrc.yaml" 2>/dev/null | head -100
fi

Repository: qodo-benchmark/Ghost-combined-coderabbit

Length of output: 841


🏁 Script executed:

#!/bin/bash

# Check the ESLint configuration for ghost/core
echo "=== ./ghost/core/.eslintrc.js content ==="
cat "./ghost/core/.eslintrc.js"

Repository: qodo-benchmark/Ghost-combined-coderabbit

Length of output: 5722


🏁 Script executed:

#!/bin/bash

# Search for 'no-var' rule in the ESLint config
echo "=== Searching for no-var rule ==="
rg "no-var" --type js --type json

Repository: qodo-benchmark/Ghost-combined-coderabbit

Length of output: 168


Replace var with let to comply with ESLint's no-var rule.

The no-var rule is set to error level in the ghost/core ESLint configuration, which will cause CI to fail.

Proposed fix
-        var member;
+        let member;
📝 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.

Suggested change
var member;
let member;
🧰 Tools
🪛 ESLint

[error] 340-340: Unexpected var, use let or const instead.

(no-var)

🤖 Prompt for AI Agents
In
`@ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js`
at line 340, Replace the function-scope declaration using `var member;` with a
block-scoped `let member;` to satisfy the ESLint `no-var` rule; update the
declaration inside MemberRepository (look for the `member` variable in
MemberRepository.js) so all usages remain unchanged but the declaration uses
`let` instead of `var`.

Comment on lines +341 to +342
const welcomeEmailConfig = config.get('memberWelcomeEmailTestInbox');
if (welcomeEmailConfig || WELCOME_EMAIL_SOURCES.includes(source)) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Require config and allowed source to gate welcome-email outbox creation.

Using welcomeEmailConfig || WELCOME_EMAIL_SOURCES.includes(source) means member-sourced signups still enqueue outbox entries even when config is unset, which defeats the config-based disable and can leave pending outbox rows never processed. Line 342 should preserve the previous AND-gate behavior.

🐛 Proposed fix
-        if (welcomeEmailConfig || WELCOME_EMAIL_SOURCES.includes(source)) {
+        if (welcomeEmailConfig && WELCOME_EMAIL_SOURCES.includes(source)) {
📝 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.

Suggested change
const welcomeEmailConfig = config.get('memberWelcomeEmailTestInbox');
if (welcomeEmailConfig || WELCOME_EMAIL_SOURCES.includes(source)) {
const welcomeEmailConfig = config.get('memberWelcomeEmailTestInbox');
if (welcomeEmailConfig && WELCOME_EMAIL_SOURCES.includes(source)) {
🤖 Prompt for AI Agents
In
`@ghost/core/core/server/services/members/members-api/repositories/MemberRepository.js`
around lines 341 - 342, The conditional that decides whether to create
welcome-email outbox entries incorrectly uses an OR: `welcomeEmailConfig ||
WELCOME_EMAIL_SOURCES.includes(source)`, which allows member-sourced signups to
enqueue when config is unset; change it back to an AND gate so both must be
true. Update the check around the welcome-email outbox creation (referencing
welcomeEmailConfig, WELCOME_EMAIL_SOURCES and source in MemberRepository.js) to
`welcomeEmailConfig && WELCOME_EMAIL_SOURCES.includes(source)` so outbox entries
are only created when the config is present and the source is allowed.

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