From 3d7f48a2631782ee8a2ca08870d60dbffc86a23b Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Wed, 16 Feb 2022 20:01:43 +0100 Subject: [PATCH 01/21] fix: npm run docs on Windows (#3973) --- site/scripts/docs.mjs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site/scripts/docs.mjs b/site/scripts/docs.mjs index f60cd35945c..927adb3e66d 100644 --- a/site/scripts/docs.mjs +++ b/site/scripts/docs.mjs @@ -1,6 +1,6 @@ // @ts-check import { basename, join } from 'path' -import { env } from 'process' +import { env, platform } from 'process' import { fileURLToPath } from 'url' import markdownMagic from 'markdown-magic' @@ -9,7 +9,11 @@ import stripAnsi from 'strip-ansi' import { generateCommandData } from './generate-command-data.mjs' const rootDir = fileURLToPath(new URL('../..', import.meta.url)) -const markdownFiles = [join(rootDir, 'README.md'), join(rootDir, 'docs/**/**.md')] +const isWindows = platform === 'win32' +const markdownFiles = [ + isWindows ? join(rootDir, 'README.md').replace(/\\/g, '/') : join(rootDir, 'README.md'), + isWindows ? join(rootDir, 'docs/**/**.md').replace(/\\/g, '/') : join(rootDir, 'docs/**/**.md'), +] env.DOCS_GEN = 'TRUE' From 8b6c5467576958095d1231993ce8620a942a756a Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 12:44:49 +0100 Subject: [PATCH 02/21] feat: env_priority in netlify.toml (#4272) --- src/commands/dev/dev-exec.js | 4 ++-- src/commands/dev/dev.js | 3 +-- src/commands/dev/types.d.ts | 3 ++- src/commands/functions/functions-create.js | 16 ++++++++++++++-- src/commands/functions/functions-serve.js | 2 +- src/utils/dev.js | 4 ++-- src/utils/dot-env.js | 9 +++++---- src/utils/init/utils.js | 1 + 8 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/commands/dev/dev-exec.js b/src/commands/dev/dev-exec.js index 95e2196fcd0..86454f73f85 100644 --- a/src/commands/dev/dev-exec.js +++ b/src/commands/dev/dev-exec.js @@ -8,8 +8,8 @@ const { injectEnvVariables } = require('../../utils') * @param {import('../base-command').BaseCommand} command */ const devExec = async (cmd, options, command) => { - const { cachedConfig, site } = command.netlify - await injectEnvVariables({ env: cachedConfig.env, site }) + const { cachedConfig, config, site } = command.netlify + await injectEnvVariables({ devConfig: { ...config.dev }, env: cachedConfig.env, site }) await execa(cmd, command.args.slice(1), { stdio: 'inherit', diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index 0011733ed31..f0485476afc 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -325,8 +325,7 @@ const dev = async (options, command) => { '--trafficMesh and -t are deprecated and will be removed in the near future. Please use --edgeHandlers or -e instead.', ) } - - await injectEnvVariables({ env: command.netlify.cachedConfig.env, site }) + await injectEnvVariables({ devConfig, env: command.netlify.cachedConfig.env, site }) const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({ // inherited from base command --offline diff --git a/src/commands/dev/types.d.ts b/src/commands/dev/types.d.ts index 99c1a06bbf2..b392ed9c375 100644 --- a/src/commands/dev/types.d.ts +++ b/src/commands/dev/types.d.ts @@ -17,5 +17,6 @@ export type DevConfig = { https?: { keyFile: string certFile: string - } + }, + envPriority?:string[] } diff --git a/src/commands/functions/functions-create.js b/src/commands/functions/functions-create.js index 1d8fec0c54f..f38b5cc610c 100644 --- a/src/commands/functions/functions-create.js +++ b/src/commands/functions/functions-create.js @@ -477,8 +477,14 @@ const createFunctionAddon = async function ({ addonName, addons, api, siteData, * @param {(command: import('../base-command').BaseCommand) => any} config.onComplete */ const handleOnComplete = async ({ command, onComplete }) => { + const { config } = command.netlify + if (onComplete) { - await injectEnvVariables({ env: command.netlify.cachedConfig.env, site: command.netlify.site }) + await injectEnvVariables({ + devConfig: { ...config.dev }, + env: command.netlify.cachedConfig.env, + site: command.netlify.site, + }) await onComplete.call(command) } } @@ -491,6 +497,8 @@ const handleOnComplete = async ({ command, onComplete }) => { * @param {string} config.fnPath */ const handleAddonDidInstall = async ({ addonCreated, addonDidInstall, command, fnPath }) => { + const { config } = command.netlify + if (!addonCreated || !addonDidInstall) { return } @@ -508,7 +516,11 @@ const handleAddonDidInstall = async ({ addonCreated, addonDidInstall, command, f return } - await injectEnvVariables({ env: command.netlify.cachedConfig.env, site: command.netlify.site }) + await injectEnvVariables({ + devConfig: { ...config.dev }, + env: command.netlify.cachedConfig.env, + site: command.netlify.site, + }) addonDidInstall(fnPath) } diff --git a/src/commands/functions/functions-serve.js b/src/commands/functions/functions-serve.js index dd1f9037e27..8dc434ca71e 100644 --- a/src/commands/functions/functions-serve.js +++ b/src/commands/functions/functions-serve.js @@ -17,7 +17,7 @@ const functionsServe = async (options, command) => { const functionsDir = getFunctionsDir({ options, config }, join('netlify', 'functions')) - await injectEnvVariables({ env: command.netlify.cachedConfig.env, site }) + await injectEnvVariables({ devConfig: { ...config.dev }, env: command.netlify.cachedConfig.env, site }) const { capabilities, siteUrl, timeouts } = await getSiteInformation({ offline: options.offline, diff --git a/src/utils/dev.js b/src/utils/dev.js index 0457ff21fe5..ecc2cb9a13a 100644 --- a/src/utils/dev.js +++ b/src/utils/dev.js @@ -139,9 +139,9 @@ const getEnvSourceName = (source) => { // Takes a set of environment variables in the format provided by @netlify/config, augments it with variables from both // dot-env files and the process itself, and injects into `process.env`. -const injectEnvVariables = async ({ env, site }) => { +const injectEnvVariables = async ({ devConfig, env, site }) => { const environment = new Map(Object.entries(env)) - const dotEnvFiles = await loadDotEnvFiles({ projectDir: site.root }) + const dotEnvFiles = await loadDotEnvFiles({ envPriority: devConfig.envPriority, projectDir: site.root }) dotEnvFiles.forEach(({ env: fileEnv, file }) => { Object.keys(fileEnv).forEach((key) => { diff --git a/src/utils/dot-env.js b/src/utils/dot-env.js index 90d5d1645d1..7a0270afbc0 100644 --- a/src/utils/dot-env.js +++ b/src/utils/dot-env.js @@ -8,8 +8,8 @@ const { isFileAsync } = require('../lib/fs') const { warn } = require('./command-helpers') -const loadDotEnvFiles = async function ({ projectDir }) { - const response = await tryLoadDotEnvFiles({ projectDir }) +const loadDotEnvFiles = async function ({ envPriority, projectDir }) { + const response = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envPriority }) const filesWithWarning = response.filter((el) => el.warning) filesWithWarning.forEach((el) => { @@ -19,8 +19,9 @@ const loadDotEnvFiles = async function ({ projectDir }) { return response.filter((el) => el.file && el.env) } -const tryLoadDotEnvFiles = async ({ projectDir }) => { - const dotenvFiles = ['.env', '.env.development'] +const defaultEnvPriority = ['.env', '.env.development', '.env.local', '.env.development.local'] + +const tryLoadDotEnvFiles = async ({ projectDir, dotenvFiles = defaultEnvPriority }) => { const results = await Promise.all( dotenvFiles.map(async (file) => { const filepath = path.resolve(projectDir, file) diff --git a/src/utils/init/utils.js b/src/utils/init/utils.js index 4f7aa39fe76..e9a6f2ec99c 100644 --- a/src/utils/init/utils.js +++ b/src/utils/init/utils.js @@ -198,6 +198,7 @@ const getNetlifyToml = ({ # command = "yarn start" # Command to start your dev server # port = 3000 # Port that the dev server will be listening on # publish = "dist" # Folder with the static content for _redirect file + # env_priority = [ ".env", ".env.local", ".env.development", ".env.development.local" ] ## more info on configuring this file: https://www.netlify.com/docs/netlify-toml-reference/ ` From c8d207b526ff4327a7ce8c87b75f75d0f9a95e20 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 13:24:47 +0100 Subject: [PATCH 03/21] feat: dev --env flag (#4272) --- src/commands/dev/dev.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index f0485476afc..67d0a9bfaa6 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -325,6 +325,9 @@ const dev = async (options, command) => { '--trafficMesh and -t are deprecated and will be removed in the near future. Please use --edgeHandlers or -e instead.', ) } + if (options.env) { + devConfig.envPriority = options.env.split(' ') + } await injectEnvVariables({ devConfig, env: command.netlify.cachedConfig.env, site }) const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({ @@ -462,6 +465,7 @@ const createDevCommand = (program) => { .option('-o ,--offline', 'disables any features that require network access') .option('-l, --live', 'start a public live session', false) .option('--functionsPort ', 'port of functions server', (value) => Number.parseInt(value)) + .option('-e, --env ', 'set the env files priority', false) .addOption( new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') .argParser((value) => Number.parseInt(value)) From 672903d7e2d79fc836f822d1f2cb26463d6a62be Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 15:31:02 +0100 Subject: [PATCH 04/21] chore: rollback docs --- docs/commands/dev.md | 1 + site/scripts/docs.mjs | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/commands/dev.md b/docs/commands/dev.md index cf912651434..86f66e27eec 100644 --- a/docs/commands/dev.md +++ b/docs/commands/dev.md @@ -19,6 +19,7 @@ netlify dev - `command` (*string*) - command to run - `dir` (*string*) - dir with static files +- `env` (*string*) - set the env files priority - `framework` (*string*) - framework to use. Defaults to #auto which automatically detects a framework - `functions` (*string*) - specify a functions folder to serve - `functionsPort` (*string*) - port of functions server diff --git a/site/scripts/docs.mjs b/site/scripts/docs.mjs index 927adb3e66d..f60cd35945c 100644 --- a/site/scripts/docs.mjs +++ b/site/scripts/docs.mjs @@ -1,6 +1,6 @@ // @ts-check import { basename, join } from 'path' -import { env, platform } from 'process' +import { env } from 'process' import { fileURLToPath } from 'url' import markdownMagic from 'markdown-magic' @@ -9,11 +9,7 @@ import stripAnsi from 'strip-ansi' import { generateCommandData } from './generate-command-data.mjs' const rootDir = fileURLToPath(new URL('../..', import.meta.url)) -const isWindows = platform === 'win32' -const markdownFiles = [ - isWindows ? join(rootDir, 'README.md').replace(/\\/g, '/') : join(rootDir, 'README.md'), - isWindows ? join(rootDir, 'docs/**/**.md').replace(/\\/g, '/') : join(rootDir, 'docs/**/**.md'), -] +const markdownFiles = [join(rootDir, 'README.md'), join(rootDir, 'docs/**/**.md')] env.DOCS_GEN = 'TRUE' From db6ca39966b171816dc023c4ac9611f00a03cead Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 16:00:49 +0100 Subject: [PATCH 05/21] refactor: envPriority-> envFiles --- src/commands/dev/dev.js | 2 +- src/commands/dev/types.d.ts | 2 +- src/utils/dev.js | 2 +- src/utils/dot-env.js | 8 ++++---- src/utils/init/utils.js | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index 67d0a9bfaa6..5de6994aaf6 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -326,7 +326,7 @@ const dev = async (options, command) => { ) } if (options.env) { - devConfig.envPriority = options.env.split(' ') + devConfig.envFiles = options.env.split(' ') } await injectEnvVariables({ devConfig, env: command.netlify.cachedConfig.env, site }) diff --git a/src/commands/dev/types.d.ts b/src/commands/dev/types.d.ts index b392ed9c375..d6b83fab302 100644 --- a/src/commands/dev/types.d.ts +++ b/src/commands/dev/types.d.ts @@ -18,5 +18,5 @@ export type DevConfig = { keyFile: string certFile: string }, - envPriority?:string[] + envFiles?:string[] } diff --git a/src/utils/dev.js b/src/utils/dev.js index ecc2cb9a13a..dac2bd09ee1 100644 --- a/src/utils/dev.js +++ b/src/utils/dev.js @@ -141,7 +141,7 @@ const getEnvSourceName = (source) => { // dot-env files and the process itself, and injects into `process.env`. const injectEnvVariables = async ({ devConfig, env, site }) => { const environment = new Map(Object.entries(env)) - const dotEnvFiles = await loadDotEnvFiles({ envPriority: devConfig.envPriority, projectDir: site.root }) + const dotEnvFiles = await loadDotEnvFiles({ envFiles: devConfig.envFiles, projectDir: site.root }) dotEnvFiles.forEach(({ env: fileEnv, file }) => { Object.keys(fileEnv).forEach((key) => { diff --git a/src/utils/dot-env.js b/src/utils/dot-env.js index 7a0270afbc0..6dd0ef4c721 100644 --- a/src/utils/dot-env.js +++ b/src/utils/dot-env.js @@ -8,8 +8,8 @@ const { isFileAsync } = require('../lib/fs') const { warn } = require('./command-helpers') -const loadDotEnvFiles = async function ({ envPriority, projectDir }) { - const response = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envPriority }) +const loadDotEnvFiles = async function ({ envFiles, projectDir }) { + const response = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envFiles }) const filesWithWarning = response.filter((el) => el.warning) filesWithWarning.forEach((el) => { @@ -19,9 +19,9 @@ const loadDotEnvFiles = async function ({ envPriority, projectDir }) { return response.filter((el) => el.file && el.env) } -const defaultEnvPriority = ['.env', '.env.development', '.env.local', '.env.development.local'] +const defaultEnvFiles = ['.env', '.env.development'] -const tryLoadDotEnvFiles = async ({ projectDir, dotenvFiles = defaultEnvPriority }) => { +const tryLoadDotEnvFiles = async ({ projectDir, dotenvFiles = defaultEnvFiles }) => { const results = await Promise.all( dotenvFiles.map(async (file) => { const filepath = path.resolve(projectDir, file) diff --git a/src/utils/init/utils.js b/src/utils/init/utils.js index e9a6f2ec99c..4f7aa39fe76 100644 --- a/src/utils/init/utils.js +++ b/src/utils/init/utils.js @@ -198,7 +198,6 @@ const getNetlifyToml = ({ # command = "yarn start" # Command to start your dev server # port = 3000 # Port that the dev server will be listening on # publish = "dist" # Folder with the static content for _redirect file - # env_priority = [ ".env", ".env.local", ".env.development", ".env.development.local" ] ## more info on configuring this file: https://www.netlify.com/docs/netlify-toml-reference/ ` From 5dd6dc63ee6f96b1739e8a9b441bea43245667dd Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 16:28:26 +0100 Subject: [PATCH 06/21] chore: comma separated list for env option --- src/commands/dev/dev.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index 5de6994aaf6..6897b5c937a 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -326,7 +326,7 @@ const dev = async (options, command) => { ) } if (options.env) { - devConfig.envFiles = options.env.split(' ') + devConfig.envFiles = options.env } await injectEnvVariables({ devConfig, env: command.netlify.cachedConfig.env, site }) @@ -465,7 +465,7 @@ const createDevCommand = (program) => { .option('-o ,--offline', 'disables any features that require network access') .option('-l, --live', 'start a public live session', false) .option('--functionsPort ', 'port of functions server', (value) => Number.parseInt(value)) - .option('-e, --env ', 'set the env files priority', false) + .option('-e, --env ', 'set the env files priority', (value) =>value.split(',')) .addOption( new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') .argParser((value) => Number.parseInt(value)) From 316e367521c099cf62b5dc7332ed095545c5adb3 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Thu, 17 Feb 2022 16:34:09 +0100 Subject: [PATCH 07/21] chore: comma separated list for env option --- src/commands/dev/dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index 6897b5c937a..d78e8f6a6dd 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -465,7 +465,7 @@ const createDevCommand = (program) => { .option('-o ,--offline', 'disables any features that require network access') .option('-l, --live', 'start a public live session', false) .option('--functionsPort ', 'port of functions server', (value) => Number.parseInt(value)) - .option('-e, --env ', 'set the env files priority', (value) =>value.split(',')) + .option('-e, --env ', 'set the env files priority', (value) => value.split(',')) .addOption( new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') .argParser((value) => Number.parseInt(value)) From 361123399fc2b00503154aad2cca302247a62364 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 15:30:25 +0100 Subject: [PATCH 08/21] chore: env flag removal --- site/scripts/docs.mjs | 8 +++++--- src/commands/dev/dev.js | 5 +---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/site/scripts/docs.mjs b/site/scripts/docs.mjs index f60cd35945c..2296489f14d 100644 --- a/site/scripts/docs.mjs +++ b/site/scripts/docs.mjs @@ -1,15 +1,17 @@ // @ts-check -import { basename, join } from 'path' +import { basename } from 'path' import { env } from 'process' import { fileURLToPath } from 'url' import markdownMagic from 'markdown-magic' import stripAnsi from 'strip-ansi' +import { normalizeBackslash } from '../../src/lib/path.js' + import { generateCommandData } from './generate-command-data.mjs' -const rootDir = fileURLToPath(new URL('../..', import.meta.url)) -const markdownFiles = [join(rootDir, 'README.md'), join(rootDir, 'docs/**/**.md')] +const rootDir = normalizeBackslash(fileURLToPath(new URL('../..', import.meta.url))) +const markdownFiles = [`${rootDir}/README.md`, `${rootDir}/docs/**/**.md`] env.DOCS_GEN = 'TRUE' diff --git a/src/commands/dev/dev.js b/src/commands/dev/dev.js index d78e8f6a6dd..bb6f06c7715 100644 --- a/src/commands/dev/dev.js +++ b/src/commands/dev/dev.js @@ -325,9 +325,7 @@ const dev = async (options, command) => { '--trafficMesh and -t are deprecated and will be removed in the near future. Please use --edgeHandlers or -e instead.', ) } - if (options.env) { - devConfig.envFiles = options.env - } + await injectEnvVariables({ devConfig, env: command.netlify.cachedConfig.env, site }) const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({ @@ -465,7 +463,6 @@ const createDevCommand = (program) => { .option('-o ,--offline', 'disables any features that require network access') .option('-l, --live', 'start a public live session', false) .option('--functionsPort ', 'port of functions server', (value) => Number.parseInt(value)) - .option('-e, --env ', 'set the env files priority', (value) => value.split(',')) .addOption( new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') .argParser((value) => Number.parseInt(value)) From ea28bb29aa915cb1d0ba0f2b1bb0a6d0177fca18 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 15:32:33 +0100 Subject: [PATCH 09/21] chore: env flag removal --- docs/commands/dev.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/commands/dev.md b/docs/commands/dev.md index 86f66e27eec..cf912651434 100644 --- a/docs/commands/dev.md +++ b/docs/commands/dev.md @@ -19,7 +19,6 @@ netlify dev - `command` (*string*) - command to run - `dir` (*string*) - dir with static files -- `env` (*string*) - set the env files priority - `framework` (*string*) - framework to use. Defaults to #auto which automatically detects a framework - `functions` (*string*) - specify a functions folder to serve - `functionsPort` (*string*) - port of functions server From 152b49f971cbfe02f17025816f628d1ad1f94909 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 16:22:36 +0100 Subject: [PATCH 10/21] chore: env files test and docs --- docs/netlify-dev.md | 1 + tests/integration/300.command.dev.test.js | 25 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index 2d0448466c5..41502397a9b 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -141,6 +141,7 @@ Netlify Dev will attempt to detect the site generator or build command that you targetPort = 3000 # # The port for your application server, framework or site generator port = 8888 # The port that the netlify dev will be accessible on publish = "dist" # If you use a _redirect file, provide the path to your static content folder + env_files = [ ".env", ".env.development" ] # The env files to use in priority order ``` Or you if your project is being detected incorrectly or positive by multiple diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 7ed8ae86f7c..11755ef41c6 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -258,5 +258,30 @@ testMatrix.forEach(({ args }) => { }) }) }) + test(testName('should pass .env vars to function', args), async (t) => { + await withSiteBuilder('site-with-env-files', async (builder) => { + builder + .withNetlifyToml({ config: { env: { envFiles: ['.env.development', '.env'] } } }) + .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) + .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) + .withFunction({ + path: 'env.js', + handler: async () => ({ + statusCode: 200, + body: `${process.env.TEST}`, + metadata: { builder_function: true }, + }), + }) + + await builder.buildAsync() + + await withDevServer({ cwd: builder.directory, args }, async (server) => { + const response = await got(`${server.url}/.netlify/functions/env`).text() + t.is(response, 'FROM_ENV_FILE') + const builderResponse = await got(`${server.url}/.netlify/builders/env`).text() + t.is(builderResponse, 'FROM_ENV_FILE') + }) + }) + }) }) /* eslint-enable require-await */ From c86384a3858c86dd584298dd8a5fdafafcc42043 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 16:46:21 +0100 Subject: [PATCH 11/21] chore: env_files test --- tests/integration/300.command.dev.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 11755ef41c6..ed189359e1f 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -261,7 +261,7 @@ testMatrix.forEach(({ args }) => { test(testName('should pass .env vars to function', args), async (t) => { await withSiteBuilder('site-with-env-files', async (builder) => { builder - .withNetlifyToml({ config: { env: { envFiles: ['.env.development', '.env'] } } }) + .withNetlifyToml({ config: { env: { env_files: ['.env.development', '.env'] } } }) .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) .withFunction({ From 876a6185100978e0ed754931db03011c900c28ed Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 17:48:38 +0100 Subject: [PATCH 12/21] chore: env_files test --- tests/integration/300.command.dev.test.js | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index ed189359e1f..60ff717b023 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -283,5 +283,29 @@ testMatrix.forEach(({ args }) => { }) }) }) + test(testName('should pass .env vars to function', args), async (t) => { + await withSiteBuilder('site-with-build-environment', async (builder) => { + builder + .withNetlifyToml({ + config: { env: { env_files: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, + }) + .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) + .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) + .withFunction({ + path: 'env.js', + handler: async () => ({ + statusCode: 200, + body: `${process.env.TEST}`, + metadata: { builder_function: true }, + }), + }) + + await builder.buildAsync() + + await withDevServer({ cwd: builder.directory, args }, async (server) => { + t.true(server.output.includes('Ignored .env file')) + }) + }) + }) }) /* eslint-enable require-await */ From 132c6e62b8bfe4716f9f783355cfae69df7e22fb Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 18:27:01 +0100 Subject: [PATCH 13/21] chore: env_files test title --- tests/integration/300.command.dev.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 60ff717b023..49b8cce7a63 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -283,7 +283,7 @@ testMatrix.forEach(({ args }) => { }) }) }) - test(testName('should pass .env vars to function', args), async (t) => { + test(testName('should use .env vars instead of .env.development vars', args), async (t) => { await withSiteBuilder('site-with-build-environment', async (builder) => { builder .withNetlifyToml({ From 27f1825c21e8d1355126c77b74fc17d559f2a715 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 21:14:36 +0100 Subject: [PATCH 14/21] chore: env_files test fix --- docs/netlify-dev.md | 2 +- tests/integration/300.command.dev.test.js | 27 +---------------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index 41502397a9b..c03b35e38e5 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -141,7 +141,7 @@ Netlify Dev will attempt to detect the site generator or build command that you targetPort = 3000 # # The port for your application server, framework or site generator port = 8888 # The port that the netlify dev will be accessible on publish = "dist" # If you use a _redirect file, provide the path to your static content folder - env_files = [ ".env", ".env.development" ] # The env files to use in priority order + envFiles = [ ".env", ".env.development" ] # The env files to use in priority order ``` Or you if your project is being detected incorrectly or positive by multiple diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 60ff717b023..20d19e2c06e 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -258,33 +258,8 @@ testMatrix.forEach(({ args }) => { }) }) }) - test(testName('should pass .env vars to function', args), async (t) => { + test(testName('should use .env vars instead of .env.development vars', args), async (t) => { await withSiteBuilder('site-with-env-files', async (builder) => { - builder - .withNetlifyToml({ config: { env: { env_files: ['.env.development', '.env'] } } }) - .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) - .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) - .withFunction({ - path: 'env.js', - handler: async () => ({ - statusCode: 200, - body: `${process.env.TEST}`, - metadata: { builder_function: true }, - }), - }) - - await builder.buildAsync() - - await withDevServer({ cwd: builder.directory, args }, async (server) => { - const response = await got(`${server.url}/.netlify/functions/env`).text() - t.is(response, 'FROM_ENV_FILE') - const builderResponse = await got(`${server.url}/.netlify/builders/env`).text() - t.is(builderResponse, 'FROM_ENV_FILE') - }) - }) - }) - test(testName('should pass .env vars to function', args), async (t) => { - await withSiteBuilder('site-with-build-environment', async (builder) => { builder .withNetlifyToml({ config: { env: { env_files: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, From ce2f68fc34450e72b72bf2fdb67e344b86600ab7 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 21:31:15 +0100 Subject: [PATCH 15/21] refactor: env_files -> envFiles --- tests/integration/300.command.dev.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 20d19e2c06e..25d5cda97ce 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -262,7 +262,7 @@ testMatrix.forEach(({ args }) => { await withSiteBuilder('site-with-env-files', async (builder) => { builder .withNetlifyToml({ - config: { env: { env_files: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, + config: { env: { envFiles: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, }) .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) From e84972216ab911c4047b966ecb3a041f43118548 Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Fri, 18 Feb 2022 22:15:11 +0100 Subject: [PATCH 16/21] chore: env_files in dev block --- docs/netlify-dev.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index c03b35e38e5..68eb83227d6 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -122,6 +122,7 @@ Netlify Dev is meant to work with zero config for the majority of users, by usin jwtRolePath = "app_metadata.authorization.roles" # Object path we should look for role values for JWT based redirects autoLaunch = true # a Boolean value that determines if Netlify Dev launches the local server address in your browser # to start an https server instead of an http one, configure a certificate and key files + envFiles = [ ".env", ".env.development" ] # The env files to use in priority order [dev.https] certFile = "cert.pem" # path to the certificate file keyFile = "key.pem" # path to the private key file From 3c295d805d10121d502ad6ca09e07c55d75c60bb Mon Sep 17 00:00:00 2001 From: Erez Rokah Date: Mon, 21 Feb 2022 20:34:53 +0200 Subject: [PATCH 17/21] fix(docs): move `envFiles` to the general section --- docs/netlify-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index c03b35e38e5..ce831f9f7fd 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -121,6 +121,7 @@ Netlify Dev is meant to work with zero config for the majority of users, by usin jwtSecret = "secret" # The secret used to verify tokens for JWT based redirects jwtRolePath = "app_metadata.authorization.roles" # Object path we should look for role values for JWT based redirects autoLaunch = true # a Boolean value that determines if Netlify Dev launches the local server address in your browser + envFiles = [".env", ".env.development"] # The env files to use, ordered by priority # to start an https server instead of an http one, configure a certificate and key files [dev.https] certFile = "cert.pem" # path to the certificate file @@ -141,7 +142,6 @@ Netlify Dev will attempt to detect the site generator or build command that you targetPort = 3000 # # The port for your application server, framework or site generator port = 8888 # The port that the netlify dev will be accessible on publish = "dist" # If you use a _redirect file, provide the path to your static content folder - envFiles = [ ".env", ".env.development" ] # The env files to use in priority order ``` Or you if your project is being detected incorrectly or positive by multiple From a239de2e0c3f6b3a86d08ad04d7b37cec2b939e9 Mon Sep 17 00:00:00 2001 From: Erez Rokah Date: Mon, 21 Feb 2022 20:42:07 +0200 Subject: [PATCH 18/21] chore: use `dev` block in test --- tests/integration/300.command.dev.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 25d5cda97ce..05460211fbd 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -262,7 +262,7 @@ testMatrix.forEach(({ args }) => { await withSiteBuilder('site-with-env-files', async (builder) => { builder .withNetlifyToml({ - config: { env: { envFiles: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, + config: { dev: { envFiles: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, }) .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) From 070ffb3fc62f96e18515837b2ccdc08d7ed61bfc Mon Sep 17 00:00:00 2001 From: Ibrahima Date: Mon, 21 Feb 2022 20:20:02 +0100 Subject: [PATCH 19/21] fix: env_files test --- tests/integration/300.command.dev.test.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 05460211fbd..726b00652fb 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -266,19 +266,11 @@ testMatrix.forEach(({ args }) => { }) .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) - .withFunction({ - path: 'env.js', - handler: async () => ({ - statusCode: 200, - body: `${process.env.TEST}`, - metadata: { builder_function: true }, - }), - }) await builder.buildAsync() await withDevServer({ cwd: builder.directory, args }, async (server) => { - t.true(server.output.includes('Ignored .env file')) + t.true(server.output.includes('Ignored .env.development file')) }) }) }) From 97380fa949a914ca7382e9821c8e723d48354b49 Mon Sep 17 00:00:00 2001 From: erezrokah Date: Tue, 22 Feb 2022 14:20:33 +0100 Subject: [PATCH 20/21] fix: apply config envFiles from left (highest) to right (lowest) --- docs/netlify-dev.md | 2 +- src/utils/dot-env.js | 6 ++++-- tests/integration/300.command.dev.test.js | 26 +++++++++++++++++++---- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index e1c8dfc9550..16f55dd4c2c 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -121,7 +121,7 @@ Netlify Dev is meant to work with zero config for the majority of users, by usin jwtSecret = "secret" # The secret used to verify tokens for JWT based redirects jwtRolePath = "app_metadata.authorization.roles" # Object path we should look for role values for JWT based redirects autoLaunch = true # a Boolean value that determines if Netlify Dev launches the local server address in your browser - envFiles = [".env", ".env.development"] # The env files to use, ordered by priority + envFiles = [".env.development", ".env"] # The env files to use, ordered by priority (left - highest, right - lowest) # to start an https server instead of an http one, configure a certificate and key files envFiles = [ ".env", ".env.development" ] # The env files to use in priority order [dev.https] diff --git a/src/utils/dot-env.js b/src/utils/dot-env.js index 6dd0ef4c721..ee5efc8f064 100644 --- a/src/utils/dot-env.js +++ b/src/utils/dot-env.js @@ -19,7 +19,8 @@ const loadDotEnvFiles = async function ({ envFiles, projectDir }) { return response.filter((el) => el.file && el.env) } -const defaultEnvFiles = ['.env', '.env.development'] +// in the user configuration, the order is highest to lowest +const defaultEnvFiles = ['.env.development', '.env'] const tryLoadDotEnvFiles = async ({ projectDir, dotenvFiles = defaultEnvFiles }) => { const results = await Promise.all( @@ -41,7 +42,8 @@ const tryLoadDotEnvFiles = async ({ projectDir, dotenvFiles = defaultEnvFiles }) }), ) - return results.filter(Boolean) + // we return in order of lowest to highest priority + return results.filter(Boolean).reverse() } module.exports = { loadDotEnvFiles, tryLoadDotEnvFiles } diff --git a/tests/integration/300.command.dev.test.js b/tests/integration/300.command.dev.test.js index 726b00652fb..d9179cc608b 100644 --- a/tests/integration/300.command.dev.test.js +++ b/tests/integration/300.command.dev.test.js @@ -258,19 +258,37 @@ testMatrix.forEach(({ args }) => { }) }) }) - test(testName('should use .env vars instead of .env.development vars', args), async (t) => { + + test(testName('should inject env vars based on [dev].envFiles file order', args), async (t) => { await withSiteBuilder('site-with-env-files', async (builder) => { builder .withNetlifyToml({ - config: { dev: { envFiles: ['.env.development', '.env'] }, functions: { directory: 'functions' } }, + config: { + dev: { envFiles: ['.env.production', '.env.development', '.env'] }, + functions: { directory: 'functions' }, + }, + }) + .withEnvFile({ path: '.env.production', env: { TEST: 'FROM_PRODUCTION_FILE' } }) + .withEnvFile({ + path: '.env.development', + env: { TEST: 'FROM_DEVELOPMENT_FILE', TEST2: 'FROM_DEVELOPMENT_FILE' }, + }) + .withEnvFile({ path: '.env', env: { TEST: 'FROM_DEFAULT_FILE', TEST2: 'FROM_DEFAULT_FILE' } }) + .withFunction({ + path: 'env.js', + handler: async () => ({ + statusCode: 200, + body: `${process.env.TEST}__${process.env.TEST2}`, + }), }) - .withEnvFile({ path: '.env.development', env: { TEST: 'FROM_ENV_DEV_FILE' } }) - .withEnvFile({ path: '.env', env: { TEST: 'FROM_ENV_FILE' } }) await builder.buildAsync() await withDevServer({ cwd: builder.directory, args }, async (server) => { + const response = await got(`${server.url}/.netlify/functions/env`).text() + t.is(response, 'FROM_PRODUCTION_FILE__FROM_DEVELOPMENT_FILE') t.true(server.output.includes('Ignored .env.development file')) + t.true(server.output.includes('Ignored .env file')) }) }) }) From e9ca564645167188508c30dd54171e3f0d8c5df4 Mon Sep 17 00:00:00 2001 From: erezrokah Date: Tue, 22 Feb 2022 15:26:39 +0100 Subject: [PATCH 21/21] chore: remove redundant doc line --- docs/netlify-dev.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/netlify-dev.md b/docs/netlify-dev.md index 16f55dd4c2c..a57406f4d89 100644 --- a/docs/netlify-dev.md +++ b/docs/netlify-dev.md @@ -123,7 +123,6 @@ Netlify Dev is meant to work with zero config for the majority of users, by usin autoLaunch = true # a Boolean value that determines if Netlify Dev launches the local server address in your browser envFiles = [".env.development", ".env"] # The env files to use, ordered by priority (left - highest, right - lowest) # to start an https server instead of an http one, configure a certificate and key files - envFiles = [ ".env", ".env.development" ] # The env files to use in priority order [dev.https] certFile = "cert.pem" # path to the certificate file keyFile = "key.pem" # path to the private key file