Skip to content

Added dormant tables for welcome email automations#27183

Merged
EvanHahn merged 4 commits intomainfrom
NY-1188-part-1
Apr 7, 2026
Merged

Added dormant tables for welcome email automations#27183
EvanHahn merged 4 commits intomainfrom
NY-1188-part-1

Conversation

@EvanHahn
Copy link
Copy Markdown
Contributor

@EvanHahn EvanHahn commented Apr 6, 2026

towards https://linear.app/ghost/issue/NY-1188

This change should have no user impact. It adds welcome_email_automations and welcome_email_automated_emails tables.

These are split up from the existing automated_emails table with two additions in welcome_email_automated_emails:

  • delay_days
  • next_welcome_email_automated_email_id

You may wish to review a diff between automated_emails and the new tables:

diff --git a/j.js b/j.js
index dded3c3..68070f4 100644
--- a/j.js
+++ b/j.js
@@ -1,8 +1,16 @@
-automated_emails: {
+welcome_email_automations: {
     id: {type: 'string', maxlength: 24, nullable: false, primary: true},
     status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'inactive', validations: {isIn: [['active', 'inactive']]}},
     name: {type: 'string', maxlength: 191, nullable: false, unique: true},
     slug: {type: 'string', maxlength: 191, nullable: false, unique: true},
+    created_at: {type: 'dateTime', nullable: false},
+    updated_at: {type: 'dateTime', nullable: true}
+},
+welcome_email_automated_emails: {
+    id: {type: 'string', maxlength: 24, nullable: false, primary: true},
+    welcome_email_automation_id: {type: 'string', maxlength: 24, nullable: false, references: 'welcome_email_automations.id', constraintName: 'weae_automation_id_foreign', cascadeDelete: true},
+    next_welcome_email_automated_email_id: {type: 'string', maxlength: 24, nullable: true, references: 'welcome_email_automated_emails.id', constraintName: 'weae_next_email_id_foreign', cascadeDelete: false},
+    delay_days: {type: 'integer', nullable: false},
     subject: {type: 'string', maxlength: 300, nullable: false},
     lexical: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
     sender_name: {type: 'string', maxlength: 191, nullable: true},
@@ -10,9 +18,5 @@ automated_emails: {
     sender_reply_to: {type: 'string', maxlength: 191, nullable: true, validations: {isEmail: true}},
     email_design_setting_id: {type: 'string', maxlength: 24, nullable: false, references: 'email_design_settings.id'},
     created_at: {type: 'dateTime', nullable: false},
-    updated_at: {type: 'dateTime', nullable: true},
-    '@@INDEXES@@': [
-        ['slug'],
-        ['status']
-    ]
+    updated_at: {type: 'dateTime', nullable: true}
 },

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c6a78cc1-3498-49f3-bfcb-6e71aa43b03d

📥 Commits

Reviewing files that changed from the base of the PR and between e534b85 and d42068d.

📒 Files selected for processing (3)
  • ghost/core/core/server/data/migrations/versions/6.27/2026-04-06-14-27-21-add-welcome-email-automation-tables.js
  • ghost/core/core/server/data/schema/schema.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js
✅ Files skipped from review due to trivial changes (2)
  • ghost/core/test/unit/server/data/schema/integrity.test.js
  • ghost/core/core/server/data/migrations/versions/6.27/2026-04-06-14-27-21-add-welcome-email-automation-tables.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • ghost/core/core/server/data/schema/schema.js

Walkthrough

Two new database tables, welcome_email_automations and welcome_email_automated_emails, have been introduced with a migration that creates them and defines foreign key relationships and cascade behavior. The schema declares welcome_email_automations with status and naming fields, and welcome_email_automated_emails with scheduling, content, sender details, a reference to an email design setting, and an optional self-referential link. The new tables were added to the backup/allowlist, tests expecting exported tables were updated, and the schema integrity hash was updated.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding two dormant database tables for welcome email automations.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of adding the new tables, their relationship to existing tables, and providing a helpful schema comparison.
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
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch NY-1188-part-1

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.

@github-actions github-actions bot added the migration [pull request] Includes migration for review label Apr 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

It looks like this PR contains a migration 👀
Here's the checklist for reviewing migrations:

General requirements

  • ⚠️ Tested performance on staging database servers, as performance on local machines is not comparable to a production environment
  • Satisfies idempotency requirement (both up() and down())
  • Does not reference models
  • Filename is in the correct format (and correctly ordered)
  • Targets the next minor version
  • All code paths have appropriate log messages
  • Uses the correct utils
  • Contains a minimal changeset
  • Does not mix DDL/DML operations
  • Tested in MySQL and SQLite

Schema changes

  • Both schema change and related migration have been implemented
  • For index changes: has been performance tested for large tables
  • For new tables/columns: fields use the appropriate predefined field lengths
  • For new tables/columns: field names follow the appropriate conventions
  • Does not drop a non-alpha table outside of a major version

Data changes

  • Mass updates/inserts are batched appropriately
  • Does not loop over large tables/datasets
  • Defends against missing or invalid data
  • For settings updates: follows the appropriate guidelines

EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183

We just added two new tables: `welcome_email_automations` and
`welcome_email_automated_emails`. This adds dormant models for those,
which are based on the existing `AutomatedEmail` model.

**You may wish to review a diff of these with their associated
`AutomatedEmail` counterpart, which will make these changes look much
smaller.** For example, I ran these commands as part of self-review:

```sh
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automation}.js
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automated-email}.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automation}.test.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automated-email}.test.js
```
EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
towards https://linear.app/ghost/issue/NY-1188

This change should have no user impact. It adds
`welcome_email_automations` and `welcome_email_automated_emails` tables.

These are split up from the existing `automated_emails` table with two
additions in `welcome_email_automated_emails`:

- `delay_days`
- `next_welcome_email_automated_email_id`

You may wish to review a diff between `automated_emails` and the new
tables:

```diff
diff --git a/j.js b/j.js
index dded3c3..68070f4 100644
--- a/j.js
+++ b/j.js
@@ -1,8 +1,16 @@
-automated_emails: {
+welcome_email_automations: {
     id: {type: 'string', maxlength: 24, nullable: false, primary: true},
     status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'inactive', validations: {isIn: [['active', 'inactive']]}},
     name: {type: 'string', maxlength: 191, nullable: false, unique: true},
     slug: {type: 'string', maxlength: 191, nullable: false, unique: true},
+    created_at: {type: 'dateTime', nullable: false},
+    updated_at: {type: 'dateTime', nullable: true}
+},
+welcome_email_automated_emails: {
+    id: {type: 'string', maxlength: 24, nullable: false, primary: true},
+    welcome_email_automation_id: {type: 'string', maxlength: 24, nullable: false, references: 'welcome_email_automations.id', constraintName: 'weae_automation_id_foreign', cascadeDelete: true},
+    next_welcome_email_automated_email_id: {type: 'string', maxlength: 24, nullable: true, references: 'welcome_email_automated_emails.id', constraintName: 'weae_next_email_id_foreign', cascadeDelete: false},
+    delay_days: {type: 'integer', nullable: false},
     subject: {type: 'string', maxlength: 300, nullable: false},
     lexical: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
     sender_name: {type: 'string', maxlength: 191, nullable: true},
@@ -10,9 +18,5 @@ automated_emails: {
     sender_reply_to: {type: 'string', maxlength: 191, nullable: true, validations: {isEmail: true}},
     email_design_setting_id: {type: 'string', maxlength: 24, nullable: false, references: 'email_design_settings.id'},
     created_at: {type: 'dateTime', nullable: false},
-    updated_at: {type: 'dateTime', nullable: true},
-    '@@indexes@@': [
-        ['slug'],
-        ['status']
-    ]
+    updated_at: {type: 'dateTime', nullable: true}
 },
```
EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183

We just added two new tables: `welcome_email_automations` and
`welcome_email_automated_emails`. This adds dormant models for those,
which are based on the existing `AutomatedEmail` model.

**You may wish to review a diff of these with their associated
`AutomatedEmail` counterpart, which will make these changes look much
smaller.** For example, I ran these commands as part of self-review:

```sh
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automation}.js
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automated-email}.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automation}.test.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automated-email}.test.js
```
EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
EvanHahn added a commit that referenced this pull request Apr 6, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
@EvanHahn EvanHahn marked this pull request as ready for review April 6, 2026 19:45
@EvanHahn EvanHahn requested a review from cmraible April 6, 2026 19:47
Copy link
Copy Markdown
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.

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 `@ghost/core/core/server/data/schema/schema.js`:
- Line 1182: The delay_days integer field currently allows negatives; update the
schema and migration so delay_days enforces non-negative values: in schema.js
(the delay_days field) add a validation constraint (e.g., "minimum: 0") to the
field definition; mirror the same constraint in the migration
2026-04-06-14-27-21-add-welcome-email-automation-tables.js by making the column
non-negative (use .unsigned() for integer columns where supported or add an
explicit CHECK constraint like "delay_days >= 0" in the table definition) so
both fresh installs and upgrades enforce delay_days >= 0.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8ff1a4ea-3149-4baa-b711-81f6ed9278f0

📥 Commits

Reviewing files that changed from the base of the PR and between e7481e9 and e534b85.

📒 Files selected for processing (5)
  • ghost/core/core/server/data/exporter/table-lists.js
  • ghost/core/core/server/data/migrations/versions/6.27/2026-04-06-14-27-21-add-welcome-email-automation-tables.js
  • ghost/core/core/server/data/schema/schema.js
  • ghost/core/test/integration/exporter/exporter.test.js
  • ghost/core/test/unit/server/data/schema/integrity.test.js

Copy link
Copy Markdown
Collaborator

@cmraible cmraible left a comment

Choose a reason for hiding this comment

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

Looks good! Main suggestion is to use the existing addTable() migration util for consistency, and I think CodeRabbit's suggestion re: delay_days is valid as well, though not blocking from my perspective.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 7, 2026

@EvanHahn EvanHahn requested a review from cmraible April 7, 2026 15:16
Copy link
Copy Markdown
Collaborator

@cmraible cmraible left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for addressing the feedback!

@EvanHahn EvanHahn merged commit 6922d27 into main Apr 7, 2026
39 checks passed
@EvanHahn EvanHahn deleted the NY-1188-part-1 branch April 7, 2026 17:27
EvanHahn added a commit that referenced this pull request Apr 7, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183

We just added two new tables: `welcome_email_automations` and
`welcome_email_automated_emails`. This adds dormant models for those,
which are based on the existing `AutomatedEmail` model.

**You may wish to review a diff of these with their associated
`AutomatedEmail` counterpart, which will make these changes look much
smaller.** For example, I ran these commands as part of self-review:

```sh
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automation}.js
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automated-email}.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automation}.test.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automated-email}.test.js
```
EvanHahn added a commit that referenced this pull request Apr 7, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183

We just added two new tables: `welcome_email_automations` and
`welcome_email_automated_emails`. This adds dormant models for those,
which are based on the existing `AutomatedEmail` model.

**You may wish to review a diff of these with their associated
`AutomatedEmail` counterpart, which will make these changes look much
smaller.** For example, I ran these commands as part of self-review:

```sh
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automation}.js
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automated-email}.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automation}.test.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automated-email}.test.js
```
EvanHahn added a commit that referenced this pull request Apr 7, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
9larsons pushed a commit that referenced this pull request Apr 7, 2026
towards https://linear.app/ghost/issue/NY-1188

This change should have no user impact. It adds
`welcome_email_automations` and `welcome_email_automated_emails` tables.

These are split up from the existing `automated_emails` table with two
additions in `welcome_email_automated_emails`:

- `delay_days`
- `next_welcome_email_automated_email_id`

You may wish to review a diff between `automated_emails` and the new
tables:

```diff
diff --git a/j.js b/j.js
index dded3c3..68070f4 100644
--- a/j.js
+++ b/j.js
@@ -1,8 +1,16 @@
-automated_emails: {
+welcome_email_automations: {
     id: {type: 'string', maxlength: 24, nullable: false, primary: true},
     status: {type: 'string', maxlength: 50, nullable: false, defaultTo: 'inactive', validations: {isIn: [['active', 'inactive']]}},
     name: {type: 'string', maxlength: 191, nullable: false, unique: true},
     slug: {type: 'string', maxlength: 191, nullable: false, unique: true},
+    created_at: {type: 'dateTime', nullable: false},
+    updated_at: {type: 'dateTime', nullable: true}
+},
+welcome_email_automated_emails: {
+    id: {type: 'string', maxlength: 24, nullable: false, primary: true},
+    welcome_email_automation_id: {type: 'string', maxlength: 24, nullable: false, references: 'welcome_email_automations.id', constraintName: 'weae_automation_id_foreign', cascadeDelete: true},
+    next_welcome_email_automated_email_id: {type: 'string', maxlength: 24, nullable: true, references: 'welcome_email_automated_emails.id', constraintName: 'weae_next_email_id_foreign', cascadeDelete: false},
+    delay_days: {type: 'integer', nullable: false},
     subject: {type: 'string', maxlength: 300, nullable: false},
     lexical: {type: 'text', maxlength: 1000000000, fieldtype: 'long', nullable: true},
     sender_name: {type: 'string', maxlength: 191, nullable: true},
@@ -10,9 +18,5 @@ automated_emails: {
     sender_reply_to: {type: 'string', maxlength: 191, nullable: true, validations: {isEmail: true}},
     email_design_setting_id: {type: 'string', maxlength: 24, nullable: false, references: 'email_design_settings.id'},
     created_at: {type: 'dateTime', nullable: false},
-    updated_at: {type: 'dateTime', nullable: true},
-    '@@indexes@@': [
-        ['slug'],
-        ['status']
-    ]
+    updated_at: {type: 'dateTime', nullable: true}
 },
```
9larsons pushed a commit that referenced this pull request Apr 7, 2026
towards https://linear.app/ghost/issue/NY-1188
ref #27183

We just added two new tables: `welcome_email_automations` and
`welcome_email_automated_emails`. This adds dormant models for those,
which are based on the existing `AutomatedEmail` model.

**You may wish to review a diff of these with their associated
`AutomatedEmail` counterpart, which will make these changes look much
smaller.** For example, I ran these commands as part of self-review:

```sh
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automation}.js
vimdiff ghost/core/core/server/models/{automated-email,welcome-email-automated-email}.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automation}.test.js
vimdiff ghost/core/test/unit/server/models/{automated-email,welcome-email-automated-email}.test.js
```
EvanHahn added a commit that referenced this pull request Apr 8, 2026
…es (#27185)

towards https://linear.app/ghost/issue/NY-1188
ref #27183
ref #27184

Previous patches added new dormant tables and models. This change
actually uses them.

More specifically, this does a database migration to move
`automated_emails` to `welcome_email_automations` and
`welcome_email_automated_emails`. Then, it updates all relevant code to
use those new tables.

The old model is deleted, but the tables are not. (That's forthcoming.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

migration [pull request] Includes migration for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants