Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): Move backend config to a separate package (no-changelog) #9325

Merged
merged 24 commits into from
Jul 5, 2024

Conversation

netroy
Copy link
Member

@netroy netroy commented May 7, 2024

This PR moves the config related code into a separate @n8n/config package so that we can use the config on all backend packages (like core and nodes-base) without creating a circular dependency with cli.
This PR also changes the config object to be

  1. an injectable class, that can be used with regular DI code
  2. type-safe without the need for the complicated inference code in packages/cli/node_modules/@types/convict/index.d.ts
  3. annotated with JSDocs on every config property, which adds helpful tooltips in our editors
    image

Every sub-section in the config is also now separately injectable, which we can use to create config objects specific to certain sections of the codebase, instead of using this one global config everywhere.

Ticket

ENG-126 & ENG-126

Review / Merge checklist

  • PR title and summary are descriptive
  • Docs updated or follow-up ticket created.
  • Tests included

@n8n-assistant n8n-assistant bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels May 7, 2024
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/.eslintrc.js Outdated Show resolved Hide resolved
packages/@n8n/config/src/decorators.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/index.ts Outdated Show resolved Hide resolved
@netroy netroy marked this pull request as ready for review July 2, 2024 14:03
@netroy netroy requested a review from a team as a code owner July 2, 2024 14:03
Copy link
Contributor

@ivov ivov left a comment

Choose a reason for hiding this comment

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

Submitting for now but not finished

TODOs:

  • Manually test envs → pass
  • Manually test N8N_CONFIG_FILESfail pass
  • Manually test _FILE → pass
  • Look closer at new decorators
  • Look closer at mailer changes

packages/@n8n/config/package.json Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/credentials.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/credentials.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/database.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/email.ts Outdated Show resolved Hide resolved
packages/@n8n/config/src/configs/email.ts Outdated Show resolved Hide resolved

@Config
export class TemplateConfig {
/** Overrides default HTML template for inviting new people (use full path) */
Copy link
Contributor

Choose a reason for hiding this comment

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

Not clear what full path means exactly. Maybe an example? Same below.


@Config
export class EmailConfig {
/** How to send emails */
Copy link
Contributor

Choose a reason for hiding this comment

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

Whether to send emails?

Copy link
Member Author

Choose a reason for hiding this comment

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

almost all the comments here are literally copy-pasted from what we have in schema.ts. We should definitely improve all these docs, but I don't think we need to block this PR on these docs.
It might make sense to get the docs team involved once the new package has all the config variables in it.

@netroy
Copy link
Member Author

netroy commented Jul 4, 2024

Addressed most of the comments. But overall, I don't think this PR should be fixing the existing docs for these config variables. We need a more involved overhaul of these docs, collaborating with the docs team.

Regarding the mailer changes, those could be a separate PR. Please let me know if you prefer it that way 🙏🏽

@netroy netroy requested a review from ivov July 4, 2024 15:12
@ivov
Copy link
Contributor

ivov commented Jul 4, 2024

Tested export N8N_CONFIG_FILES=$N8N_CONFIG_FILES_DIR/local-postgres.json where the file is as below, and I'm seeing the following error. This does not fail on master.

{
  "database": {
    "type": "postgresdb",
    "postgresdb": {
      "database": "n8n",
      "host": "localhost",
      "port": "5432",
      "schema": "public",
      "user": "postgres",
      "password": "some-password"
    }
  }
}

And seeing this:

n.st

> n8n-monorepo@1.49.0 start /Users/ivov/Development/n8n
> run-script-os


> n8n-monorepo@1.49.0 start:default
> cd packages/cli/bin && ./n8n

User settings loaded from: /Users/ivov/.n8n/config
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
Loading config overwrites [ '/Users/ivov/.n8n/config-files/local-postgres.json' ]
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (BaseCommand)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(Use `node --trace-warnings ...` to show where the warning was created)
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (audit)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (execute)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (executeBatch)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (start)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (webhook)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (worker)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (db:revert)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (export:credentials)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (export:workflow)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (import:credentials)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (import:workflow)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (license:clear)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (license:info)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (list:workflow)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (ldap:reset)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (mfa:disable)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (update:workflow)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
(node:89674) Warning: Error
module: @oclif/core@4.0.7
task: findCommand (user-management:reset)
plugin: n8n
root: /Users/ivov/Development/n8n/packages/cli
message: configuration param 'database.type' not declared in the schema
configuration param 'database.postgresdb.database' not declared in the schema
configuration param 'database.postgresdb.host' not declared in the schema
configuration param 'database.postgresdb.port' not declared in the schema
configuration param 'database.postgresdb.schema' not declared in the schema
configuration param 'database.postgresdb.user' not declared in the schema
configuration param 'database.postgresdb.password' not declared in the schema
See more details with DEBUG=*
 ›   Error: command start not found
 ELIFECYCLE  Command failed with exit code 2.

@netroy
Copy link
Member Author

netroy commented Jul 4, 2024

The plan was to add support for N8N_CONFIG_FILES in the new config package in a new PR, but for now I've fixed the existing support. Created a new sub-issue ENG-132 to add support in the new package, were we can write tests more easily.

Copy link
Contributor

@ivov ivov left a comment

Choose a reason for hiding this comment

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

🚀

const classMetadata = globalMetadata.get(ConfigClass);
if (!classMetadata) {
// eslint-disable-next-line n8n-local-rules/no-plain-errors
throw new Error('Invalid config class: ' + ConfigClass.name);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we enable n8n-local-rules/no-plain-errors for this package? In this case it makes no difference as failing here breaks the build and is not reportable, but for future proofing any other errors we may need to throw in this package. Maybe the rule should be live at the top lint config file and be disabled on a case-by-case basis.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'd like to see if we can make the type-checker somehow catch these kind of errors, to prevent stuff like this even reaching runtime.

ignoreTLS: !config.getEnv('userManagement.emails.smtp.startTLS'),
};
constructor(
globalConfig: GlobalConfig,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
globalConfig: GlobalConfig,
readonly globalConfig: GlobalConfig,

Copy link
Member Author

Choose a reason for hiding this comment

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

will update in the next PR

globalConfig: GlobalConfig,
private readonly logger: Logger,
) {
const smtpConfig = globalConfig.userManagement.emails.smtp;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can a consumer of globalConfig mutate it by accident? If so should we prevent this?

Copy link
Member Author

Choose a reason for hiding this comment

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

right now, unfortunately yes. The plan is to switch to read-only proxies for the config eventually so that we can

  1. prevent writes
  2. block any callers from outside our packages from reading any config

Created ENG-134 for that.


constructor(
private readonly userRepository: UserRepository,
globalConfig: GlobalConfig,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
globalConfig: GlobalConfig,
readonly globalConfig: GlobalConfig,

config.getEnv('userManagement.emails.mode') === 'smtp' &&
config.getEnv('userManagement.emails.smtp.host') !== '';
const emailsConfig = globalConfig.userManagement.emails;
this.isEmailSetUp = emailsConfig.mode === 'smtp' && emailsConfig.smtp.host !== '';
Copy link
Contributor

Choose a reason for hiding this comment

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

We could consider 'getters' for the new config.

Copy link
Member Author

Choose a reason for hiding this comment

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

That is also a part of the plan, to have more utility methods/getters on the config classes.

if (loggingOption) {
const optionsString = config.getEnv('database.logging.options').replace(/\s+/g, '');

const optionsString = loggingConfig.options.replace(/\s+/g, '');
Copy link
Contributor

Choose a reason for hiding this comment

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

Also in future we could have config doing its own validation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. not only validation, but also transformation. so that JSON values could be auto-parsed, and we don't need to manually parse them, like we do for credentials.overwrite.data, and a few other properties.

Copy link

cypress bot commented Jul 5, 2024

3 flaky tests on run #5797 ↗︎

0 399 0 0 Flakiness 3

Details:

🌳 🖥️ browsers:node18.12.0-chrome107 🤖 netroy 🗃️ e2e/*
Project: n8n Commit: a7652b80dd
Status: Passed Duration: 05:05 💡
Started: Jul 5, 2024 8:23 AM Ended: Jul 5, 2024 8:28 AM
Flakiness  5-ndv.cy.ts • 2 flaky tests

View Output Video

Test Artifacts
NDV > should not retrieve remote options when required params throw errors Screenshots Video
NDV > Stop listening for trigger event from NDV Screenshots Video
Flakiness  10-undo-redo.cy.ts • 1 flaky test

View Output Video

Test Artifacts
Undo/Redo > should undo/redo adding nodes Test Replay Screenshots Video

Review all test suite changes for PR #9325 ↗︎

Copy link
Contributor

github-actions bot commented Jul 5, 2024

✅ All Cypress E2E specs passed

@netroy netroy changed the title refactor(core): Move backend config to a separate package refactor(core): Move backend config to a separate package (no-changelog) Jul 5, 2024
@netroy netroy merged commit c7d4b47 into master Jul 5, 2024
51 checks passed
@netroy netroy deleted the config-package branch July 5, 2024 09:43
@janober
Copy link
Member

janober commented Jul 10, 2024

Got released with n8n@1.50.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team Released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants