Skip to content

Removed welcomeEmails feature flag checks in the members repository#26454

Merged
cmraible merged 6 commits intomainfrom
chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo
Feb 23, 2026
Merged

Removed welcomeEmails feature flag checks in the members repository#26454
cmraible merged 6 commits intomainfrom
chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo

Conversation

@cmraible
Copy link
Collaborator

@cmraible cmraible commented Feb 17, 2026

ref https://linear.app/ghost/issue/NY-971/post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-admin
closes https://linear.app/ghost/issue/NY-965/post-ga-cleanup-remove-labsservice-from-memberrepository

There should be no behavioral changes in this commit, since the welcomeEmails flag has already been promoted to GA.

Now that welcome emails are in GA, we want to remove the flag completely. This commit removes any conditional behavior in Ghost/core's Member Repository that depends on the welcomeEmails flag.

Note: this also removes the labsService dependency from the MembersRepository entirely.

I've manually tested the following:

  • Free welcome email disabled, free signup does not receive welcome email
  • Free welcome email enabled, free signup does receive welcome email
  • Paid welcome email disabled, paid signup does not receive welcome email
  • Paid welcome email enabled, paid signup does receive welcome email

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Removed labsService from MembersAPI and MemberRepository constructor parameters and deleted internal _labsService usage. Welcome-email gating no longer depends on the welcomeEmails labs flag; free vs paid welcome-email decisions now rely on member source, Stripe signup state, and AutomatedEmail configuration. Outbox enqueue and StartOutboxProcessingEvent paths for free welcome emails are preserved but no longer conditioned on labsService. Tests and mocks referencing labsService were removed or updated accordingly.

Possibly related PRs

Suggested labels

ok to merge for me

Suggested reviewers

  • troyciesco
  • 9larsons
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary change: removing welcomeEmails feature flag checks from the members repository, which is the main objective.
Description check ✅ Passed The description is well-related to the changeset, clearly explaining the removal of the welcomeEmails flag and labsService dependency, with references to related issues and manual testing confirmation.
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 unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cmraible cmraible marked this pull request as ready for review February 17, 2026 23:53
Copy link
Contributor

@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.

🧹 Nitpick comments (1)
ghost/core/core/server/services/members/members-api/repositories/member-repository.js (1)

359-403: Unnecessary transaction wrapper when free welcome email is inactive.

When source === 'member' but isFreeWelcomeEmailActive is false, runMemberCreation is still wrapped in this._Member.transaction() (line 398) even though there's nothing to do atomically — the outbox write is skipped. Pre-GA, the labs flag naturally bypassed this and fell through to the simple this._Member.add(...) path. Now every member-source signup incurs a transaction wrapper and an extra AutomatedEmail.findOne read even on instances with no active welcome email.

Consider short-circuiting to the simple path when the outbox write won't happen:

♻️ Optional refactor
-        if (WELCOME_EMAIL_SOURCES.includes(source)) {
-            const freeWelcomeEmail = this._AutomatedEmail ? await this._AutomatedEmail.findOne({slug: MEMBER_WELCOME_EMAIL_SLUGS.free}) : null;
-            const isFreeWelcomeEmailActive = freeWelcomeEmail && freeWelcomeEmail.get('lexical') && freeWelcomeEmail.get('status') === 'active';
-            const isFreeSignup = !stripeCustomer;
-
-            const runMemberCreation = async (transacting) => {
+        const isFreeSignup = !stripeCustomer;
+        const freeWelcomeEmail = WELCOME_EMAIL_SOURCES.includes(source) && this._AutomatedEmail
+            ? await this._AutomatedEmail.findOne({slug: MEMBER_WELCOME_EMAIL_SLUGS.free})
+            : null;
+        const isFreeWelcomeEmailActive = freeWelcomeEmail && freeWelcomeEmail.get('lexical') && freeWelcomeEmail.get('status') === 'active';
+
+        if (WELCOME_EMAIL_SOURCES.includes(source) && isFreeWelcomeEmailActive && isFreeSignup) {
+            const runMemberCreation = async (transacting) => {

This way the AutomatedEmail query and transaction wrapper are only incurred when a welcome email will actually be sent. The else branch (lines 404-410) handles all other cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ghost/core/core/server/services/members/members-api/repositories/member-repository.js`
around lines 359 - 403, The code always queries AutomatedEmail and wraps
runMemberCreation in this._Member.transaction even when no outbox write will
occur; to fix, short-circuit: move the AutomatedEmail.findOne and computation of
isFreeWelcomeEmailActive behind a guard so you only compute them when
WELCOME_EMAIL_SOURCES.includes(source) AND you may send the outbox (i.e., only
when isFreeSignup can be true), and then only create/run runMemberCreation
inside this._Member.transaction when isFreeWelcomeEmailActive && isFreeSignup is
true; otherwise call this._Member.add(...) directly (avoid
this._Member.transaction and avoid the AutomatedEmail.findOne read) and skip
dispatching StartOutboxProcessingEvent. Use the existing symbols:
WELCOME_EMAIL_SOURCES, isFreeSignup, isFreeWelcomeEmailActive,
runMemberCreation, this._Member.transaction, this._Member.add,
AutomatedEmail.findOne, and StartOutboxProcessingEvent.create to locate and
change the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@ghost/core/core/server/services/members/members-api/repositories/member-repository.js`:
- Around line 359-403: The code always queries AutomatedEmail and wraps
runMemberCreation in this._Member.transaction even when no outbox write will
occur; to fix, short-circuit: move the AutomatedEmail.findOne and computation of
isFreeWelcomeEmailActive behind a guard so you only compute them when
WELCOME_EMAIL_SOURCES.includes(source) AND you may send the outbox (i.e., only
when isFreeSignup can be true), and then only create/run runMemberCreation
inside this._Member.transaction when isFreeWelcomeEmailActive && isFreeSignup is
true; otherwise call this._Member.add(...) directly (avoid
this._Member.transaction and avoid the AutomatedEmail.findOne read) and skip
dispatching StartOutboxProcessingEvent. Use the existing symbols:
WELCOME_EMAIL_SOURCES, isFreeSignup, isFreeWelcomeEmailActive,
runMemberCreation, this._Member.transaction, this._Member.add,
AutomatedEmail.findOne, and StartOutboxProcessingEvent.create to locate and
change the logic.

@cmraible cmraible marked this pull request as draft February 18, 2026 00:43
@cmraible cmraible marked this pull request as draft February 18, 2026 00:43
@cmraible
Copy link
Collaborator Author

The rabbit makes a good point here. Planning to address the comment before merging this one.

@cmraible cmraible force-pushed the chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo branch from eaa59ec to 99c9fb7 Compare February 19, 2026 00:13
@cmraible cmraible marked this pull request as ready for review February 19, 2026 00:13
Copy link
Contributor

@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.

🧹 Nitpick comments (1)
ghost/core/core/server/services/members/members-api/repositories/member-repository.js (1)

359-368: && isFreeSignup in the branch condition is redundant

isFreeWelcomeEmailActive can only ever be true if shouldCheckFreeWelcomeEmail was true, and that already requires isFreeSignup === true (line 360). The second && isFreeSignup at line 368 is therefore dead-code as written today.

♻️ Suggested simplification
-        if (isFreeWelcomeEmailActive && isFreeSignup) {
+        if (isFreeWelcomeEmailActive) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ghost/core/core/server/services/members/members-api/repositories/member-repository.js`
around lines 359 - 368, The final if condition redundantly checks isFreeSignup
because isFreeWelcomeEmailActive can only be set when
shouldCheckFreeWelcomeEmail (which already requires isFreeSignup) is true;
remove the extra "&& isFreeSignup" from the if that checks
isFreeWelcomeEmailActive so it becomes simply "if (isFreeWelcomeEmailActive)".
Keep the existing logic that sets isFreeWelcomeEmailActive via
this._AutomatedEmail.findOne({slug: MEMBER_WELCOME_EMAIL_SLUGS.free}) and its
status/lexical checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@ghost/core/core/server/services/members/members-api/repositories/member-repository.js`:
- Around line 359-368: The final if condition redundantly checks isFreeSignup
because isFreeWelcomeEmailActive can only be set when
shouldCheckFreeWelcomeEmail (which already requires isFreeSignup) is true;
remove the extra "&& isFreeSignup" from the if that checks
isFreeWelcomeEmailActive so it becomes simply "if (isFreeWelcomeEmailActive)".
Keep the existing logic that sets isFreeWelcomeEmailActive via
this._AutomatedEmail.findOne({slug: MEMBER_WELCOME_EMAIL_SLUGS.free}) and its
status/lexical checks.

@cmraible
Copy link
Collaborator Author

isFreeWelcomeEmailActive can only ever be true if shouldCheckFreeWelcomeEmail was true, and that already requires isFreeSignup === true (line 360). The second && isFreeSignup at line 368 is therefore dead-code as written today.

Coderabbit's nit pick here is technically true, but I think I prefer to keep the isFreeSignup condition here just to be super explicit. Happy to be swayed otherwise though.

@cmraible cmraible requested a review from troyciesco February 19, 2026 20:10
}

if (isFreeWelcomeEmailActive && isFreeSignup) {
const runMemberCreation = async (transacting) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This got a bit hairier than I expected for just removing a flag, but I'm pretty sure this is correct. Very open to suggestions/simplification

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah this file is always tricky. I think this is fine though, to me the logic is clear and easy to follow even if we could technically do it in fewer lines.

@cmraible
Copy link
Collaborator Author

This should be the last one before removing the flag itself 😄

@cmraible cmraible force-pushed the chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo branch from 2584233 to 44c2bf1 Compare February 19, 2026 23:58
@cmraible
Copy link
Collaborator Author

Sorry for the commits after requesting a review - I noticed there was some mocking still hanging around in the integration tests, then I rebased so I can stack the lab removal itself on top of this.

}

if (isFreeWelcomeEmailActive && isFreeSignup) {
const runMemberCreation = async (transacting) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

yeah this file is always tricky. I think this is fine though, to me the logic is clear and easy to follow even if we could technically do it in fewer lines.

@cmraible cmraible merged commit 519483f into main Feb 23, 2026
33 checks passed
@cmraible cmraible deleted the chris-ny-971-post-ga-cleanup-remove-the-welcomeemails-labs-flag-from-member-repo branch February 23, 2026 17:40
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