From 20f92ab558dd397934c6a30f00fc20e31197a038 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Fri, 8 Jan 2021 18:28:48 +0000 Subject: [PATCH 01/11] feat: initial work done to rely on new global config dir --- package-lock.json | 5 +++++ package.json | 1 + src/lib/settings.js | 13 ++++++++++--- src/utils/get-global-config.js | 32 ++++++++++++++++++++++++++++++++ src/utils/global-config.js | 17 ----------------- 5 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 src/utils/get-global-config.js delete mode 100644 src/utils/global-config.js diff --git a/package-lock.json b/package-lock.json index 6149f3b1865..3332dea28c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7781,6 +7781,11 @@ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true }, + "env-paths": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==" + }, "envinfo": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", diff --git a/package.json b/package.json index 03f3595e57f..8cedd05c765 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "del": "^5.1.0", "dot-prop": "^5.1.0", "dotenv": "^8.2.0", + "env-paths": "^2.2.0", "envinfo": "^7.3.1", "execa": "^5.0.0", "express": "^4.17.1", diff --git a/src/lib/settings.js b/src/lib/settings.js index 9ac03f4c16f..608b52cd45d 100644 --- a/src/lib/settings.js +++ b/src/lib/settings.js @@ -1,12 +1,19 @@ const os = require('os') const path = require('path') +const envPaths = require('env-paths') + +const OSBasedPaths = envPaths('netlify', { suffix: '' }) const NETLIFY_HOME = '.netlify' -const getHomeDirectory = () => path.join(os.homedir(), NETLIFY_HOME) +// Deprecated method to get netlify's home config - ~/.netlify/... +const getLegacyPathInHome = (paths) => { + const pathInHome = path.join(os.homedir(), NETLIFY_HOME, ...paths) + return pathInHome +} const getPathInHome = (paths) => { - const pathInHome = path.join(getHomeDirectory(), ...paths) + const pathInHome = path.join(OSBasedPaths.config, ...paths) return pathInHome } @@ -15,4 +22,4 @@ const getPathInProject = (paths) => { return pathInProject } -module.exports = { getPathInHome, getPathInProject } +module.exports = { getLegacyPathInHome, getPathInHome, getPathInProject } diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js new file mode 100644 index 00000000000..32c0c0c5bca --- /dev/null +++ b/src/utils/get-global-config.js @@ -0,0 +1,32 @@ +const Configstore = require('configstore') +const { v4: uuidv4 } = require('uuid') + +const { readFileAsync } = require('../lib/fs') +const { getPathInHome, getLegacyPathInHome } = require('../lib/settings') + +const globalConfigDefaults = { + /* disable stats from being sent to Netlify */ + telemetryDisabled: false, + /* cliId */ + cliId: uuidv4(), +} + +const globalConfigOptions = { + configPath: getPathInHome(['config.json']), +} + +const getGlobalConfig = async function ({ log }) { + // Legacy config file in home ~/.netlify/config.json + const legacyPath = getLegacyPathInHome(['config.json']) + let legacyConfig + try { + legacyConfig = await readFileAsync(legacyPath) + log(`Found existing legacy config in ${legacyPath}`) + } catch (_) { + // If file doesn't exist just move on + } + const defaults = { ...globalConfigDefaults, ...legacyConfig } + return new Configstore(null, defaults, globalConfigOptions) +} + +module.exports = getGlobalConfig diff --git a/src/utils/global-config.js b/src/utils/global-config.js deleted file mode 100644 index 7f10ff4b36d..00000000000 --- a/src/utils/global-config.js +++ /dev/null @@ -1,17 +0,0 @@ -const Configstore = require('configstore') -const { v4: uuidv4 } = require('uuid') - -const { getPathInHome } = require('../lib/settings') - -const globalConfigDefaults = { - /* disable stats from being sent to Netlify */ - telemetryDisabled: false, - /* cliId */ - cliId: uuidv4(), -} - -const globalConfigOptions = { - configPath: getPathInHome(['config.json']), -} - -module.exports = new Configstore(null, globalConfigDefaults, globalConfigOptions) From 89c8c11047f9b0f1f7c06f6798d3456ca60ebee9 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Tue, 12 Jan 2021 18:49:07 +0000 Subject: [PATCH 02/11] feat: add final functionality to the new global config spec --- src/commands/build/index.js | 3 +- src/commands/deploy.js | 3 +- src/commands/login.js | 2 +- src/commands/logout.js | 2 +- src/commands/status/index.js | 2 +- src/hooks/init.js | 3 +- src/lib/fs.js | 4 +++ src/utils/command.js | 15 +++++---- src/utils/get-global-config.js | 28 +++++++++------- src/utils/get-global-config.test.js | 50 +++++++++++++++++++++++++++++ src/utils/telemetry/index.js | 8 +++-- tests/command.deploy.test.js | 2 +- 12 files changed, 94 insertions(+), 28 deletions(-) create mode 100644 src/utils/get-global-config.test.js diff --git a/src/commands/build/index.js b/src/commands/build/index.js index 84f8fabf2b3..77cd5e27780 100644 --- a/src/commands/build/index.js +++ b/src/commands/build/index.js @@ -9,9 +9,10 @@ class BuildCommand extends Command { // Run Netlify Build async run() { // Retrieve Netlify Build options + const [token] = await this.getConfigToken() const options = await getBuildOptions({ context: this, - token: this.getConfigToken()[0], + token, flags: this.parse(BuildCommand).flags, }) this.checkOptions(options) diff --git a/src/commands/deploy.js b/src/commands/deploy.js index eb20197f04f..0beb0d10bb7 100644 --- a/src/commands/deploy.js +++ b/src/commands/deploy.js @@ -411,9 +411,10 @@ class DeployCommand extends Command { } if (flags.build) { + const [token] = await this.getConfigToken() const options = await getBuildOptions({ context: this, - token: this.getConfigToken()[0], + token, flags, }) const exitCode = await runBuild(options) diff --git a/src/commands/login.js b/src/commands/login.js index cd0d1c50a7c..8562f138bee 100644 --- a/src/commands/login.js +++ b/src/commands/login.js @@ -6,7 +6,7 @@ const Command = require('../utils/command') class LoginCommand extends Command { async run() { const { flags } = this.parse(LoginCommand) - const [accessToken, location] = this.getConfigToken() + const [accessToken, location] = await this.getConfigToken() if (accessToken && !flags.new) { this.log(`Already logged in ${msg(location)}`) this.log() diff --git a/src/commands/logout.js b/src/commands/logout.js index c40937505e4..7d0b7b977a7 100644 --- a/src/commands/logout.js +++ b/src/commands/logout.js @@ -3,7 +3,7 @@ const { track } = require('../utils/telemetry') class LogoutCommand extends Command { async run() { - const [accessToken, location] = this.getConfigToken() + const [accessToken, location] = await this.getConfigToken() if (!accessToken) { this.log(`Already logged out`) diff --git a/src/commands/status/index.js b/src/commands/status/index.js index 76d354bb364..96478acd47d 100644 --- a/src/commands/status/index.js +++ b/src/commands/status/index.js @@ -12,7 +12,7 @@ class StatusCommand extends Command { const { flags } = this.parse(StatusCommand) const current = globalConfig.get('userId') - const [accessToken] = this.getConfigToken() + const [accessToken] = await this.getConfigToken() if (!accessToken) { this.log(`Not logged in. Please log in to see site status.`) diff --git a/src/hooks/init.js b/src/hooks/init.js index 65e7c2584d5..38d6f9949a6 100644 --- a/src/hooks/init.js +++ b/src/hooks/init.js @@ -2,11 +2,12 @@ const process = require('process') const envinfo = require('envinfo') -const globalConfig = require('../utils/global-config') +const getGlobalConfig = require('../utils/get-global-config') const header = require('../utils/header') const { track } = require('../utils/telemetry') module.exports = async function initHooks(context) { + const globalConfig = await getGlobalConfig() // Enable/disable telemetry Global flags. TODO refactor where these fire if (context.id === '--telemetry-disable') { globalConfig.set('telemetryDisabled', true) diff --git a/src/lib/fs.js b/src/lib/fs.js index b6758767047..0fa7e3445b6 100644 --- a/src/lib/fs.js +++ b/src/lib/fs.js @@ -8,6 +8,8 @@ const pathType = require('path-type') const statAsync = promisify(fs.stat) const readFileAsync = promisify(fs.readFile) const writeFileAsync = promisify(fs.writeFile) +const rmFileAsync = promisify(fs.rm) +const copyFileAsync = promisify(fs.copyFile) const accessAsync = promisify(fs.access) const readFileAsyncCatchError = async (filepath) => { @@ -39,6 +41,8 @@ module.exports = { readFileAsync, readFileAsyncCatchError, writeFileAsync, + rmFileAsync, + copyFileAsync, fileExistsAsync, isFileAsync, mkdirRecursiveSync, diff --git a/src/utils/command.js b/src/utils/command.js index 9bf277daee7..df0b931590d 100644 --- a/src/utils/command.js +++ b/src/utils/command.js @@ -13,7 +13,7 @@ const { warnOnNetlifyDir } = require('../lib/deprecations') const { getAgent } = require('../lib/http-agent') const chalkInstance = require('./chalk') -const globalConfig = require('./global-config') +const getGlobalConfig = require('./get-global-config') const openBrowser = require('./open-browser') const StateConfig = require('./state-config') const { track, identify } = require('./telemetry') @@ -30,7 +30,7 @@ const isDefaultJson = () => argv._[0] === 'functions:invoke' || (argv._[0] === ' const isBuildCommand = () => argv._[0] === 'build' || (argv._[0] === 'deploy' && argv.build === true) -const getToken = (tokenFromFlag) => { +const getToken = async (tokenFromFlag) => { // 1. First honor command flag --auth if (tokenFromFlag) { return [tokenFromFlag, 'flag'] @@ -40,6 +40,7 @@ const getToken = (tokenFromFlag) => { return [NETLIFY_AUTH_TOKEN, 'env'] } // 3. If no env var use global user setting + const globalConfig = await getGlobalConfig() const userId = globalConfig.get('userId') const tokenFromConfig = globalConfig.get(`users.${userId}.auth.token`) if (tokenFromConfig) { @@ -55,7 +56,7 @@ class BaseCommand extends Command { // Grab netlify API token const authViaFlag = getAuthArg(argv) - const [token] = this.getConfigToken(authViaFlag) + const [token] = await this.getConfigToken(authViaFlag) // Get site id & build state const state = new StateConfig(cwd) @@ -78,6 +79,8 @@ class BaseCommand extends Command { apiOpts.pathPrefix = NETLIFY_API_URL === `${apiUrl.protocol}//${apiUrl.host}` ? '/api/v1' : apiUrl.pathname } + const globalConfig = await getGlobalConfig() + this.netlify = { // api methods api: new API(token || '', apiOpts), @@ -205,14 +208,14 @@ class BaseCommand extends Command { /** * Get user netlify API token * @param {string} - [tokenFromFlag] - value passed in by CLI flag - * @return {[string, string]} - tokenValue & location of resolved Netlify API token + * @return {Promise<[string, string]>} - Promise containing tokenValue & location of resolved Netlify API token */ getConfigToken(tokenFromFlag) { return getToken(tokenFromFlag) } - authenticate(tokenFromFlag) { - const [token] = this.getConfigToken(tokenFromFlag) + async authenticate(tokenFromFlag) { + const [token] = await this.getConfigToken(tokenFromFlag) if (token) { return token } diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index 32c0c0c5bca..4ec36f1c5a8 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -1,7 +1,7 @@ const Configstore = require('configstore') const { v4: uuidv4 } = require('uuid') -const { readFileAsync } = require('../lib/fs') +const { rmFileAsync, readFileAsync } = require('../lib/fs') const { getPathInHome, getLegacyPathInHome } = require('../lib/settings') const globalConfigDefaults = { @@ -11,22 +11,26 @@ const globalConfigDefaults = { cliId: uuidv4(), } -const globalConfigOptions = { - configPath: getPathInHome(['config.json']), -} - -const getGlobalConfig = async function ({ log }) { +const getGlobalConfig = async function () { + const configPath = getPathInHome(['config.json']) // Legacy config file in home ~/.netlify/config.json const legacyPath = getLegacyPathInHome(['config.json']) let legacyConfig + // Read legacy config if exists try { - legacyConfig = await readFileAsync(legacyPath) - log(`Found existing legacy config in ${legacyPath}`) - } catch (_) { - // If file doesn't exist just move on - } + legacyConfig = JSON.parse(await readFileAsync(legacyPath)) + } catch (_) {} + // Use legacy config as default values const defaults = { ...globalConfigDefaults, ...legacyConfig } - return new Configstore(null, defaults, globalConfigOptions) + const configStore = new Configstore(null, defaults, { configPath }) + + // If legacy config exsists we can now safely delete it + if (legacyConfig) { + try { + await rmFileAsync(legacyPath) + } catch (_) {} + } + return configStore } module.exports = getGlobalConfig diff --git a/src/utils/get-global-config.test.js b/src/utils/get-global-config.test.js new file mode 100644 index 00000000000..dfd72f7761f --- /dev/null +++ b/src/utils/get-global-config.test.js @@ -0,0 +1,50 @@ +const os = require('os') +const path = require('path') + +const test = require('ava') + +const { statAsync, writeFileAsync, copyFileAsync, rmFileAsync } = require('../lib/fs') +const { getPathInHome, getLegacyPathInHome } = require('../lib/settings') + +const getGlobalConfig = require('./get-global-config.js') + +const configPath = getPathInHome(['config.json']) +const legacyConfigPath = getLegacyPathInHome(['config.json']) +const tmpConfigBackupPath = path.join(os.tmpdir(), `netlify-config-backup-${Date.now()}`) + +test.before('backup current user config', async () => { + await copyFileAsync(configPath, tmpConfigBackupPath) +}) + +test.after.always('cleanup tmp directory and legacy config', async () => { + await copyFileAsync(tmpConfigBackupPath, configPath) + await rmFileAsync(tmpConfigBackupPath) + // Remove legacy config if exists + try { + await rmFileAsync(legacyConfigPath) + } catch (_) {} +}) + +test.serial('should use legacy config values as default if exists and delete it', async (t) => { + const legacyConfig = { someOldKey: 'someOldValue', overrideMe: 'oldValue' } + const newConfig = { overrideMe: 'newValue' } + await writeFileAsync(legacyConfigPath, JSON.stringify(legacyConfig)) + await writeFileAsync(configPath, JSON.stringify(newConfig)) + + const globalConfig = await getGlobalConfig() + t.is(globalConfig.get('someOldKey'), legacyConfig.someOldKey) + t.is(globalConfig.get('overrideMe'), newConfig.overrideMe) + await t.throwsAsync(statAsync(legacyConfigPath)) +}) + +test.serial('should not throw if legacy config is invalid JSON', async (t) => { + await writeFileAsync(legacyConfigPath, 'NotJson') + await t.notThrowsAsync(getGlobalConfig) +}) + +test.serial("should create config in netlify's config dir if none exist", async (t) => { + await rmFileAsync(configPath) + await rmFileAsync(legacyConfigPath) + await getGlobalConfig() + await t.notThrowsAsync(statAsync(configPath)) +}) diff --git a/src/utils/telemetry/index.js b/src/utils/telemetry/index.js index c2d5acd0226..8a2a627d7ce 100644 --- a/src/utils/telemetry/index.js +++ b/src/utils/telemetry/index.js @@ -4,7 +4,7 @@ const process = require('process') const ci = require('ci-info') -const globalConfig = require('../global-config') +const getGlobalConfig = require('../get-global-config') const isValidEventName = require('./validation') @@ -45,7 +45,7 @@ const eventConfig = { ], } -const track = function (eventName, payload) { +const track = async function (eventName, payload) { const properties = payload || {} if (IS_INSIDE_CI) { @@ -55,6 +55,7 @@ const track = function (eventName, payload) { return Promise.resolve() } + const globalConfig = await getGlobalConfig() // exit early if tracking disabled const TELEMETRY_DISABLED = globalConfig.get('telemetryDisabled') if (TELEMETRY_DISABLED && !properties.force) { @@ -103,7 +104,7 @@ const track = function (eventName, payload) { return send('track', defaultData) } -const identify = function (payload) { +const identify = async function (payload) { const data = payload || {} if (IS_INSIDE_CI) { @@ -113,6 +114,7 @@ const identify = function (payload) { return Promise.resolve() } + const globalConfig = await getGlobalConfig() // exit early if tracking disabled const TELEMETRY_DISABLED = globalConfig.get('telemetryDisabled') if (TELEMETRY_DISABLED && !data.force) { diff --git a/tests/command.deploy.test.js b/tests/command.deploy.test.js index 9e162b0f6bd..5c0cc456c1b 100644 --- a/tests/command.deploy.test.js +++ b/tests/command.deploy.test.js @@ -134,7 +134,7 @@ if (process.env.IS_FORK !== 'true') { // validate edge handlers // use this until we can use `netlify api` - const [apiToken] = getToken() + const [apiToken] = await getToken() const { content_length: contentLength, ...rest } = await got( `https://api.netlify.com/api/v1/deploys/${deploy.deploy_id}/edge_handlers`, { From d392c67872882695f51e7dae25e0a1d3ee7a0315 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Tue, 12 Jan 2021 19:03:59 +0000 Subject: [PATCH 03/11] chore: add comment to tests --- src/utils/get-global-config.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/get-global-config.test.js b/src/utils/get-global-config.test.js index dfd72f7761f..f29e6eb53fa 100644 --- a/src/utils/get-global-config.test.js +++ b/src/utils/get-global-config.test.js @@ -25,6 +25,8 @@ test.after.always('cleanup tmp directory and legacy config', async () => { } catch (_) {} }) +// Not running tests in parallel as we're messing with the same config files + test.serial('should use legacy config values as default if exists and delete it', async (t) => { const legacyConfig = { someOldKey: 'someOldValue', overrideMe: 'oldValue' } const newConfig = { overrideMe: 'newValue' } From aacac649df57ca112b62f801550df9e44f0204b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Wed, 13 Jan 2021 10:56:51 +0000 Subject: [PATCH 04/11] fix: typo in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Eduardo Bouças --- src/utils/get-global-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index 4ec36f1c5a8..d22c490ff51 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -24,7 +24,7 @@ const getGlobalConfig = async function () { const defaults = { ...globalConfigDefaults, ...legacyConfig } const configStore = new Configstore(null, defaults, { configPath }) - // If legacy config exsists we can now safely delete it + // If legacy config exists we can now safely delete it if (legacyConfig) { try { await rmFileAsync(legacyPath) From 2e4554ec97cffbb7be56903b5a6f954168520168 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 11:41:20 +0000 Subject: [PATCH 05/11] fix: don't fail tests if there's no config to backup --- src/utils/get-global-config.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/utils/get-global-config.test.js b/src/utils/get-global-config.test.js index f29e6eb53fa..627f67fbda1 100644 --- a/src/utils/get-global-config.test.js +++ b/src/utils/get-global-config.test.js @@ -12,15 +12,17 @@ const configPath = getPathInHome(['config.json']) const legacyConfigPath = getLegacyPathInHome(['config.json']) const tmpConfigBackupPath = path.join(os.tmpdir(), `netlify-config-backup-${Date.now()}`) -test.before('backup current user config', async () => { - await copyFileAsync(configPath, tmpConfigBackupPath) +test.before('backup current user config if exists', async () => { + try { + await copyFileAsync(configPath, tmpConfigBackupPath) + } catch (_) {} }) test.after.always('cleanup tmp directory and legacy config', async () => { - await copyFileAsync(tmpConfigBackupPath, configPath) - await rmFileAsync(tmpConfigBackupPath) - // Remove legacy config if exists + // Restore user config and remove legacy config if exists try { + await copyFileAsync(tmpConfigBackupPath, configPath) + await rmFileAsync(tmpConfigBackupPath) await rmFileAsync(legacyConfigPath) } catch (_) {} }) From 8a7d8a935e0406e747fb09f2a56fad1e8e638a4f Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 12:23:19 +0000 Subject: [PATCH 06/11] fix: make tests resilient to missing config directories --- src/utils/get-global-config.test.js | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/utils/get-global-config.test.js b/src/utils/get-global-config.test.js index 627f67fbda1..040bf0d9c5a 100644 --- a/src/utils/get-global-config.test.js +++ b/src/utils/get-global-config.test.js @@ -3,7 +3,14 @@ const path = require('path') const test = require('ava') -const { statAsync, writeFileAsync, copyFileAsync, rmFileAsync } = require('../lib/fs') +const { + rmdirRecursiveAsync, + mkdirRecursiveAsync, + statAsync, + writeFileAsync, + copyFileAsync, + rmFileAsync, +} = require('../lib/fs') const { getPathInHome, getLegacyPathInHome } = require('../lib/settings') const getGlobalConfig = require('./get-global-config.js') @@ -19,12 +26,24 @@ test.before('backup current user config if exists', async () => { }) test.after.always('cleanup tmp directory and legacy config', async () => { - // Restore user config and remove legacy config if exists try { + // Restore user config if exists + await mkdirRecursiveAsync(getPathInHome([])) await copyFileAsync(tmpConfigBackupPath, configPath) + // Remove tmp backup if exists await rmFileAsync(tmpConfigBackupPath) - await rmFileAsync(legacyConfigPath) } catch (_) {} + // Remove legacy config path + await rmdirRecursiveAsync(getLegacyPathInHome([])) +}) + +test.beforeEach('recreate clean config directories', async () => { + // Remove config dirs + await rmdirRecursiveAsync(getPathInHome([])) + await rmdirRecursiveAsync(getLegacyPathInHome([])) + // Make config dirs + await mkdirRecursiveAsync(getPathInHome([])) + await mkdirRecursiveAsync(getLegacyPathInHome([])) }) // Not running tests in parallel as we're messing with the same config files @@ -47,8 +66,10 @@ test.serial('should not throw if legacy config is invalid JSON', async (t) => { }) test.serial("should create config in netlify's config dir if none exist", async (t) => { - await rmFileAsync(configPath) - await rmFileAsync(legacyConfigPath) + // Remove config dirs + await rmdirRecursiveAsync(getPathInHome([])) + await rmdirRecursiveAsync(getLegacyPathInHome([])) + await getGlobalConfig() await t.notThrowsAsync(statAsync(configPath)) }) From c3a0671909da2ed293b916b5ddf5bfecf21d4ebe Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 12:54:55 +0000 Subject: [PATCH 07/11] fix: trolled by nodejs fs functions :facepalm: --- src/lib/fs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/fs.js b/src/lib/fs.js index 0fa7e3445b6..3e3e4d32931 100644 --- a/src/lib/fs.js +++ b/src/lib/fs.js @@ -8,7 +8,7 @@ const pathType = require('path-type') const statAsync = promisify(fs.stat) const readFileAsync = promisify(fs.readFile) const writeFileAsync = promisify(fs.writeFile) -const rmFileAsync = promisify(fs.rm) +const rmFileAsync = promisify(fs.unlink) const copyFileAsync = promisify(fs.copyFile) const accessAsync = promisify(fs.access) From 716bbdbbfb3baf467de023940dd64355cfff7317 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 17:29:32 +0000 Subject: [PATCH 08/11] chore: don't delete legacy config and memoise globalConfig result --- src/utils/get-global-config.js | 12 ++++-------- src/utils/get-global-config.test.js | 13 +++++++------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index d22c490ff51..2b57abd28fc 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -1,7 +1,8 @@ const Configstore = require('configstore') +const { once } = require('lodash') const { v4: uuidv4 } = require('uuid') -const { rmFileAsync, readFileAsync } = require('../lib/fs') +const { readFileAsync } = require('../lib/fs') const { getPathInHome, getLegacyPathInHome } = require('../lib/settings') const globalConfigDefaults = { @@ -24,13 +25,8 @@ const getGlobalConfig = async function () { const defaults = { ...globalConfigDefaults, ...legacyConfig } const configStore = new Configstore(null, defaults, { configPath }) - // If legacy config exists we can now safely delete it - if (legacyConfig) { - try { - await rmFileAsync(legacyPath) - } catch (_) {} - } return configStore } -module.exports = getGlobalConfig +// Memoise config result so that we only load it once +module.exports = once(getGlobalConfig) diff --git a/src/utils/get-global-config.test.js b/src/utils/get-global-config.test.js index 040bf0d9c5a..f3a276ef89a 100644 --- a/src/utils/get-global-config.test.js +++ b/src/utils/get-global-config.test.js @@ -6,7 +6,7 @@ const test = require('ava') const { rmdirRecursiveAsync, mkdirRecursiveAsync, - statAsync, + readFileAsync, writeFileAsync, copyFileAsync, rmFileAsync, @@ -48,7 +48,7 @@ test.beforeEach('recreate clean config directories', async () => { // Not running tests in parallel as we're messing with the same config files -test.serial('should use legacy config values as default if exists and delete it', async (t) => { +test.serial('should use legacy config values as default if exists', async (t) => { const legacyConfig = { someOldKey: 'someOldValue', overrideMe: 'oldValue' } const newConfig = { overrideMe: 'newValue' } await writeFileAsync(legacyConfigPath, JSON.stringify(legacyConfig)) @@ -57,7 +57,6 @@ test.serial('should use legacy config values as default if exists and delete it' const globalConfig = await getGlobalConfig() t.is(globalConfig.get('someOldKey'), legacyConfig.someOldKey) t.is(globalConfig.get('overrideMe'), newConfig.overrideMe) - await t.throwsAsync(statAsync(legacyConfigPath)) }) test.serial('should not throw if legacy config is invalid JSON', async (t) => { @@ -65,11 +64,13 @@ test.serial('should not throw if legacy config is invalid JSON', async (t) => { await t.notThrowsAsync(getGlobalConfig) }) -test.serial("should create config in netlify's config dir if none exist", async (t) => { +test.serial("should create config in netlify's config dir if none exists and store new values", async (t) => { // Remove config dirs await rmdirRecursiveAsync(getPathInHome([])) await rmdirRecursiveAsync(getLegacyPathInHome([])) - await getGlobalConfig() - await t.notThrowsAsync(statAsync(configPath)) + const globalConfig = await getGlobalConfig() + globalConfig.set('newProp', 'newValue') + const configFile = JSON.parse(await readFileAsync(configPath)) + t.deepEqual(globalConfig.all, configFile) }) From 8bc2d3354eeb3081f6bf860d2770d1934306b9b7 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 17:41:15 +0000 Subject: [PATCH 09/11] chore: dropping lodash.once as per #1728 and using memoize-one --- package.json | 1 + src/utils/get-global-config.js | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 8cedd05c765..62822583559 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "lodash": "^4.17.20", "log-symbols": "^3.0.0", "make-dir": "^3.0.0", + "memoize-one": "^5.1.1", "minimist": "^1.2.5", "multiparty": "^4.2.1", "netlify": "^6.0.0", diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index 2b57abd28fc..c804e39f487 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -1,4 +1,5 @@ const Configstore = require('configstore') +const { memoizeOne } = require('memoize-one') const { once } = require('lodash') const { v4: uuidv4 } = require('uuid') From e3cf50c82b360c9961f095ec2f7c59152e09cb7f Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 17:42:03 +0000 Subject: [PATCH 10/11] chore: dropping lodash.once as per #1728 and using memoize-one --- src/utils/get-global-config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index c804e39f487..76a6af21fa1 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -1,6 +1,5 @@ const Configstore = require('configstore') const { memoizeOne } = require('memoize-one') -const { once } = require('lodash') const { v4: uuidv4 } = require('uuid') const { readFileAsync } = require('../lib/fs') @@ -30,4 +29,4 @@ const getGlobalConfig = async function () { } // Memoise config result so that we only load it once -module.exports = once(getGlobalConfig) +module.exports = memoizeOne(getGlobalConfig) From 3e87c3d5dbe49c329e0df5c17c1f6a5e228821b9 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Wed, 13 Jan 2021 17:46:56 +0000 Subject: [PATCH 11/11] fix: require memoizeOne :facepalm: --- src/utils/get-global-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/get-global-config.js b/src/utils/get-global-config.js index 76a6af21fa1..d1521e6a787 100644 --- a/src/utils/get-global-config.js +++ b/src/utils/get-global-config.js @@ -1,5 +1,5 @@ const Configstore = require('configstore') -const { memoizeOne } = require('memoize-one') +const memoizeOne = require('memoize-one') const { v4: uuidv4 } = require('uuid') const { readFileAsync } = require('../lib/fs')