Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
fix: postupdate hook doesn't use npm anymore
Browse files Browse the repository at this point in the history
  • Loading branch information
RodEsp committed Nov 2, 2021
1 parent 17eac5c commit d1f4e21
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 86 deletions.
22 changes: 11 additions & 11 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,24 +334,24 @@ workflows:
branches:
only:
- dev
- release-management/release-package:
tag: dev
github-release: false
prerelease: true
requires:
- approval
filters:
branches:
only:
- dev
# - release-management/release-package:
# tag: dev
# github-release: false
# prerelease: true
# requires:
# - approval
# filters:
# branches:
# only:
# - dev
- pack-and-upload-tarballs:
filters:
branches:
only:
- dev
requires:
- approval
- release-management/release-package
# - release-management/release-package
- pack-and-upload-macos-installer:
filters:
branches:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "sfdx-cli",
"description": "Salesforce CLI",
"version": "7.126.0-dev.5",
"version": "7.126.0-dev.6",
"author": "Salesforce",
"license": "BSD-3-Clause",
"bugs": "https://github.com/forcedotcom/cli/issues",
Expand Down
111 changes: 37 additions & 74 deletions src/hooks/postupdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as os from 'os';
import * as path from 'path';
import { exec, which } from 'shelljs';

import { cli } from 'cli-ux';
import { readFileSync, readJsonSync, writeFileSync } from 'fs-extra';
import { chmod, exec } from 'shelljs';

import { TelemetryGlobal } from '@salesforce/plugin-telemetry/lib/telemetryGlobal';
import { AppInsights } from '@salesforce/telemetry/lib/appInsights';
import { JsonMap } from '@salesforce/ts-types';
import { cli } from 'cli-ux';

declare const global: TelemetryGlobal;

Expand All @@ -21,8 +25,10 @@ function sendEvent(data: JsonMap): void {
}

function suggestAlternatives(): void {
cli.log('Failed to install sf. Try one of the following:');
cli.log('- npm: npm install @salesforce/cli --global');
cli.log('Failed to update sf. Try uninstalling the CLI and re-installing it.');
cli.log(
'Uninstall instructions: https://developer.salesforce.com/docs/atlas.en-us.234.0.sfdx_setup.meta/sfdx_setup/sfdx_setup_uninstall.htm'
);
if (process.platform === 'win32') {
cli.log('- installer: https://developer.salesforce.com/media/salesforce-cli/sf/channels/stable/sf-x64.exe');
} else if (process.platform === 'darwin') {
Expand All @@ -33,97 +39,54 @@ function suggestAlternatives(): void {
}

/**
* Return true if any part of the sf executable path contains a string that is known
* to be part of an npm path.
*/
function isNpmInstall(sfPath: string): boolean {
const nodePathParts = ['node', 'nodejs', '.nvm', '.asdf', 'node_modules', 'npm', '.npm'];
const sfPathParts = sfPath.split(path.sep);
return sfPathParts.filter((p) => nodePathParts.includes(p.toLowerCase())).length > 0;
}

/**
* We want to skip the sf installation if there's an existing installation that is NOT
* from npm. In other words, if the user has already installed sf with the installer,
* we do not want to overwrite it.
*/
function isBinaryInstall(): boolean {
const existingSf = which('sf')?.stdout;
if (existingSf) return !isNpmInstall(existingSf);
return false;
}

/**
* In order to install sf for users who use the installers, we've added
* this hook which will install sf via npm after sfdx update completes.
*
* This is not a sufficient solution as there are likely many users who
* do not have npm installed on their machine. For this reason, we are
* logging that information to app insights so that we decide which solutions
* we need to build next to ensure sf is available to all sfdx users.
*
* In order to make the bundled version of `sf` available after
* users run `sfdx update` we've added this hook which will copy
* the sfdx executable and modify it for `sf`.
*/
// eslint-disable-next-line @typescript-eslint/require-await
const hook = async function (): Promise<void> {
let succcess = false;
let success = false;

const sfdxVersion = exec('sfdx --version', { silent: true })?.stdout || 'unknown';

// Skip the install if there's an existing sf that was installed by an installer
if (isBinaryInstall()) {
succcess = true;
return;
}

cli.action.start('sfdx-cli: Installing sf');
cli.action.start('sfdx-cli: Updating sf');

try {
const npmInstallation = which('npm')?.stdout;
if (!npmInstallation) {
sendEvent({
eventName: 'POST_SFDX_UPDATE_SF_INSTALL_ERROR',
type: 'EVENT',
message: 'npm not installed on machine',
sfdxVersion,
});
return;
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const pjson = readJsonSync(path.join(__dirname, '../../package.json')) as { oclif: { dirname: string } };

const installResult = exec('npm install -g @salesforce/cli', { silent: true });
if (installResult.code > 0) {
sendEvent({
eventName: 'POST_SFDX_UPDATE_SF_INSTALL_ERROR',
type: 'EVENT',
message: 'npm global install failed',
stackTrace: installResult.stderr?.replace(new RegExp(os.homedir(), 'g'), AppInsights.GDPR_HIDDEN),
sfdxVersion,
});
return;
let dataDirBin;
let sfdxExec;
let sfExec;
if (os.type() === 'Windows_NT') {
dataDirBin = path.join(process.env.LOCALAPPDATA as string, pjson.oclif.dirname, 'client', 'bin');
sfdxExec = sfExec = path.join(dataDirBin, 'sfdx.cmd');
sfExec = path.join(dataDirBin, 'sf.cmd');
} else {
dataDirBin = path.join(process.env.HOME as string, pjson.oclif.dirname, 'client', 'bin');
sfdxExec = path.join(dataDirBin, 'sfdx');
sfExec = path.join(dataDirBin, 'sf');
}

succcess = true;
const sfVersion = exec('sf --version', { silent: true }).stdout;
sendEvent({
eventName: 'POST_SFDX_UPDATE_SF_INSTALL_SUCCESS',
type: 'EVENT',
message: 'sf install succeeded',
sfVersion,
sfdxVersion,
});
writeFileSync(sfExec, readFileSync(sfdxExec, { encoding: 'utf-8' }).replace(/sfdx/g, 'sf').replace(/SFDX/g, 'SF'));
chmod('+x', path.join(dataDirBin, sfExec));

success = true;
} catch (error) {
const err = error as Error;
succcess = false;
success = false;
sendEvent({
eventName: 'POST_SFDX_UPDATE_SF_INSTALL_ERROR',
eventName: 'POST_SFDX_UPDATE_SF_UPDATE_ERROR',
type: 'EVENT',
message: err.message,
stackTrace: err?.stack?.replace(new RegExp(os.homedir(), 'g'), AppInsights.GDPR_HIDDEN),
sfdxVersion,
});
return;
} finally {
cli.action.stop(succcess ? 'done' : 'failed');
if (!succcess) suggestAlternatives();
cli.action.stop(success ? 'done' : 'failed');
if (!success) suggestAlternatives();
}
};

Expand Down

0 comments on commit d1f4e21

Please sign in to comment.