Skip to content

Conversation

@nuno-agostinho
Copy link

@nuno-agostinho nuno-agostinho commented Nov 3, 2025

Motivation: Ensure best practices for environment variables by using uppercase naming and the GHOST_ prefix (to avoid collisions with generic variables like url), such as GHOST_MAIL_OPTIONS_HOST.

What: Add nconf configuration to load environmental variables prefixed with GHOST_. The prefix is stripped and the variable is converted to lower case. These environment variables take higher precedence than the previous lowercase ones like mail__options__host.

Why: This change was requested by the community (#21021) and aligns with recommended environment variable practices.

Testing

I haven't added an automated test. Two possible approaches:

  1. Modify some environment variables in the current E2E testing:

    Ghost/e2e/compose.yml

    Lines 27 to 31 in d3ee99c

    database__client: mysql2
    database__connection__host: mysql
    database__connection__user: root
    database__connection__password: root
    database__connection__database: ghost_testing
  2. Create a dedicated automated test. I don't think there is much benefit of going this route just to test env vars configuration.

Please tell me which approach (or alternatives) you recommend to test this. Thanks!

PR checklist

  • I've read and followed the Contributor Guide
  • I've explained my change
  • I've written an automated test to prove my change works

Note

Adds nconf handling for GHOST_-prefixed env vars (e.g., GHOST_MAIL_OPTIONS_HOST), stripping the prefix, lowercasing keys, and loading them before existing __-based vars.

  • Config loading (core/shared/config/loader.js):
    • Add nconf.env handler for GHOST_-prefixed environment variables.
      • Uses _ separator, strips GHOST_ prefix, lowercases keys, and parses values.
      • Loaded before existing nconf.env with __ separator to take precedence.

Written by Cursor Bugbot for commit 44b8694. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

A specialized environment variable loader was added to the Nconf configuration setup to selectively process environment variables prefixed with GHOST_. The loader filters keys that start with GHOST_, strips that prefix, converts the remainder to lowercase, and exposes the transformed key for Nconf to load; environment variables not matching the prefix are ignored. This loader is registered before the existing nconf.env({separator: '__', parseValues: true}) call, changing how environment variables are mapped into the configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Single-file change (ghost/core/core/shared/config/loader.js) but affects configuration parsing behavior and precedence.
  • Requires checking transformer logic for correct key normalization and collision handling with nconf.env.
  • Verify ordering relative to nconf.env({separator: '__', parseValues: true}) and ensure no unexpected shadowing of keys.
  • Ensure tests or runtime checks cover edge cases (mixed-case keys, dots/underscores, and parseValues interactions).

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add support for uppercase GHOST_ environment variables' directly and clearly summarizes the main change in the pull request. It accurately reflects the primary objective of adding nconf configuration to load environment variables prefixed with GHOST_, which is the core purpose of the changeset.
Description check ✅ Passed The pull request description is comprehensive and directly related to the changeset. It explains the motivation (best practices for environment variables), what was changed (nconf configuration for GHOST_ prefixed variables with prefix stripping and lowercasing), why the change was made (community request and alignment with recommended practices), and discusses testing considerations. The description aligns well with the actual code changes summarized.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e12a1cd and 44b8694.

📒 Files selected for processing (1)
  • ghost/core/core/shared/config/loader.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ghost/core/core/shared/config/loader.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cursor Bugbot

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.

cursor[bot]

This comment was marked as outdated.

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.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3ee99c and e12a1cd.

📒 Files selected for processing (1)
  • ghost/core/core/shared/config/loader.js (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: kevinansfield
Repo: TryGhost/Ghost PR: 25031
File: ghost/core/test/utils/fixtures/config/defaults.json:68-80
Timestamp: 2025-10-07T12:19:15.174Z
Learning: In Ghost's configuration system (ghost/core/core/shared/config/), environment-specific config files (e.g., config.development.json, config.production.json) automatically fall back to values defined in defaults.json. It's only necessary to specify changed overrides on a per-env basis. Missing keys in env configs are not an issue—they're intentional and will use the default values.
📚 Learning: 2025-10-07T12:19:15.174Z
Learnt from: kevinansfield
Repo: TryGhost/Ghost PR: 25031
File: ghost/core/test/utils/fixtures/config/defaults.json:68-80
Timestamp: 2025-10-07T12:19:15.174Z
Learning: In Ghost's configuration system (ghost/core/core/shared/config/), environment-specific config files (e.g., config.development.json, config.production.json) automatically fall back to values defined in defaults.json. It's only necessary to specify changed overrides on a per-env basis. Missing keys in env configs are not an issue—they're intentional and will use the default values.

Applied to files:

  • ghost/core/core/shared/config/loader.js
📚 Learning: 2025-10-30T17:13:26.190Z
Learnt from: sam-lord
Repo: TryGhost/Ghost PR: 25303
File: ghost/core/core/server/services/email-service/BatchSendingService.js:19-19
Timestamp: 2025-10-30T17:13:26.190Z
Learning: In ghost/core/core/server/services/email-service/BatchSendingService.js and similar files in the Ghost codebase, prefer using `{...options}` spread syntax without explicit guards like `...(options || {})` when spreading potentially undefined objects, as the maintainer prefers cleaner syntax over defensive patterns when the behavior is safe.

Applied to files:

  • ghost/core/core/shared/config/loader.js
🪛 ESLint
ghost/core/core/shared/config/loader.js

[error] 34-34: Expected { after 'if' condition.

(curly)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
obj.key = obj.key.replace(prefix, '').toLowerCase();
return obj;
}
});
Copy link

Choose a reason for hiding this comment

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

Bug: Exclude GHOST_ vars in repeated env parsing

The second nconf.env() call will process all environment variables including those with the GHOST_ prefix, causing duplicate processing. Variables like GHOST_MAIL_OPTIONS_HOST will be stored twice: once as mail:options:host (from the first nconf.env call at line 29-43) and once as GHOST_MAIL_OPTIONS_HOST (from this call). This creates redundant entries and potential conflicts. The second call should exclude GHOST_ prefixed variables by adding a transform function that returns false for keys matching /^GHOST_/.

Fix in Cursor Fix in Web

Copy link
Author

Choose a reason for hiding this comment

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

This is done to allow for backwards compatibility. However, tell me if you prefer to do as suggested here.

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.

1 participant