Skip to content

Commit

Permalink
refactor(CLI): Export resolved local installation path directly
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Jan 27, 2022
1 parent 040be5f commit fb3b39a
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 69 deletions.
3 changes: 1 addition & 2 deletions lib/Serverless.js
Expand Up @@ -24,7 +24,7 @@ const isStandaloneExecutable = require('./utils/isStandaloneExecutable');
const resolveConfigurationPath = require('./cli/resolve-configuration-path');
const logDeprecation = require('./utils/logDeprecation');
const eventuallyUpdate = require('./utils/eventuallyUpdate');
const resolveLocalServerlessPath = require('./cli/resolve-local-serverless-path');
const localServerlessPath = require('./cli/local-serverless-path');
const commmandsSchema = require('./cli/commands-schema');
const resolveCliInput = require('./cli/resolve-input');
const readConfiguration = require('./configuration/read');
Expand Down Expand Up @@ -214,7 +214,6 @@ class Serverless {
);
}
if (this.isLocallyInstalled) return;
const localServerlessPath = resolveLocalServerlessPath();
if (!localServerlessPath) return;
if (localServerlessPath === serverlessPath) {
this.isLocallyInstalled = true;
Expand Down
4 changes: 1 addition & 3 deletions lib/cli/handle-error.js
Expand Up @@ -20,7 +20,7 @@ const { storeLocally: storeTelemetryLocally, send: sendTelemetry } = require('..
const generateTelemetryPayload = require('../utils/telemetry/generatePayload');
const resolveErrorLocation = require('../utils/telemetry/resolve-error-location');
const resolveInput = require('./resolve-input');
const resolveLocalServerlessPath = require('./resolve-local-serverless-path');
const localServerlessPath = require('./local-serverless-path');

const writeMessage = (title, message) => {
let line = '';
Expand Down Expand Up @@ -65,8 +65,6 @@ module.exports = async (exception, options = {}) => {
// If provided serverless instance is a local fallback, and we're not in context of it
// Pass error handling to this local fallback implementation
if (isInvokedByGlobalInstallation && !resolveIsLocallyInstalled()) {
const localServerlessPath = resolveLocalServerlessPath();

const localErrorHandlerData = (() => {
try {
return {
Expand Down
17 changes: 17 additions & 0 deletions lib/cli/local-serverless-path.js
@@ -0,0 +1,17 @@
'use strict';

// This module should be dependencies free (as it's used at local fallback triage) and
// kept async (as telemetry payload generation depends on it)
try {
const path = require('path');
const { createRequire } = require('module');

module.exports = path.resolve(
path.dirname(
createRequire(path.resolve(process.cwd(), 'require-resolver')).resolve('serverless')
),
'..'
);
} catch {
module.exports = null;
}
4 changes: 1 addition & 3 deletions lib/cli/render-version.js
Expand Up @@ -8,7 +8,7 @@ const { version: dashboardPluginVersion } = require('@serverless/dashboard-plugi
const { platformClientVersion } = require('@serverless/dashboard-plugin');
const { legacy, log, writeText } = require('@serverless/utils/log');
const isStandaloneExecutable = require('../utils/isStandaloneExecutable');
const resolveLocalServerlessPath = require('./resolve-local-serverless-path');
const localServerlessPath = require('./local-serverless-path');
const chalk = require('chalk');
const ServerlessError = require('../serverless-error');

Expand All @@ -35,8 +35,6 @@ const resolveTencentCliVersion = async () => {
};

module.exports = async () => {
const localServerlessPath = resolveLocalServerlessPath();

if (localServerlessPath) {
// If the version is already local, do not try to fallback for version resolution to avoid falling into the loop
// TODO: Remove local version fallback with next major (when its moved to the top of the process)
Expand Down
21 changes: 0 additions & 21 deletions lib/cli/resolve-local-serverless-path.js

This file was deleted.

7 changes: 2 additions & 5 deletions lib/utils/is-locally-installed.js
@@ -1,14 +1,11 @@
'use strict';

const path = require('path');
const resolveLocalServerlessPath = require('../cli/resolve-local-serverless-path');
const localServerlessPath = require('../cli/local-serverless-path');

const serverlessPath = path.resolve(__dirname, '../..');

// This method should be kept as sync. The reason for it is the fact that
// telemetry generation and persistence needs to be run in sync manner
// and it depends on this function, either directly or indirectly.
module.exports = () => {
const localServerlessPath = resolveLocalServerlessPath();
return serverlessPath === localServerlessPath;
};
module.exports = () => serverlessPath === localServerlessPath;
3 changes: 1 addition & 2 deletions lib/utils/telemetry/generatePayload.js
Expand Up @@ -11,7 +11,7 @@ const isStandalone = require('../isStandaloneExecutable');
const { getConfigurationValidationResult } = require('../../classes/ConfigSchemaHandler');
const { triggeredDeprecations } = require('../logDeprecation');
const isNpmGlobal = require('../npmPackage/isGlobal');
const resolveLocalServerlessPath = require('../../cli/resolve-local-serverless-path');
const localServerlessPath = require('../../cli/local-serverless-path');
const resolveIsLocallyInstalled = require('../../utils/is-locally-installed');
const getRequire = require('../../utils/get-require');
const ci = require('ci-info');
Expand Down Expand Up @@ -197,7 +197,6 @@ module.exports = ({
'@serverless/dashboard-plugin': require('@serverless/dashboard-plugin/package').version,
};
}
const localServerlessPath = resolveLocalServerlessPath();
try {
require.resolve(path.resolve(localServerlessPath, 'package.json'));
} catch {
Expand Down
7 changes: 4 additions & 3 deletions test/mochaPatch.js
Expand Up @@ -46,7 +46,8 @@ patchCallback('open');
patchCallback('readFile');

const ensureArtifact = require('../lib/utils/ensureArtifact');
const resolveLocalServerless = require('../lib/cli/resolve-local-serverless-path');

const localServerlessPathModulePath = require.resolve('../lib/cli/local-serverless-path');
const resolveInput = require('../lib/cli/resolve-input');

const BbPromise = require('bluebird');
Expand All @@ -64,14 +65,14 @@ runnerEmitter.on('runner', (runner) => {
resolveInput.clear();
// Ensure to reset cache for local serverless installation resolution
// Leaking it across test files may introduce wrong assumptions when result is used for testing
if (resolveLocalServerless._has('data')) {
if (require.cache[localServerlessPathModulePath]) {
// As we rely on native require.resolve, we need to ensure that it's cache related to
// tmp homedir is cleared
const homedir = require('os').homedir();
for (const key of Object.keys(Module._pathCache)) {
if (key.includes(homedir)) delete Module._pathCache[key];
}
resolveLocalServerless.clear();
delete require.cache[localServerlessPathModulePath];
}
// Ensure to reset memoization on artifacts generation after each test file run.
// Reason is that homedir is automatically cleaned for each test,
Expand Down
Expand Up @@ -5,15 +5,17 @@ const path = require('path');
const os = require('os');
const fsp = require('fs').promises;
const fse = require('fs-extra');
const resolveLocalServerless = require('../../../../lib/cli/resolve-local-serverless-path');

describe('test/unit/lib/cli/resolve-local-serverless.test.js', () => {
describe('test/unit/lib/cli/local-serverless.test.js', () => {
beforeEach(() => {
delete require.cache[require.resolve('../../../../lib/cli/local-serverless-path')];
});

it('should resolve with `null` when no local installation is found', () => {
expect(resolveLocalServerless()).to.equal(null);
expect(require('../../../../lib/cli/local-serverless-path')).to.equal(null);
});

it('should resolve with `null` when no local installation is found', async () => {
resolveLocalServerless.delete();
const tmpServerlessPath = path.resolve(
await fsp.realpath(os.homedir()),
'node_modules/serverless'
Expand All @@ -26,6 +28,8 @@ describe('test/unit/lib/cli/resolve-local-serverless.test.js', () => {
JSON.stringify({ main: 'lib/Serverless.js' })
),
]);
expect(await fsp.realpath(resolveLocalServerless())).to.equal(tmpServerlessPath);
expect(await fsp.realpath(require('../../../../lib/cli/local-serverless-path'))).to.equal(
tmpServerlessPath
);
});
});

0 comments on commit fb3b39a

Please sign in to comment.