Skip to content

Commit

Permalink
[FEATURE] Prefer local over global CLI version (#59)
Browse files Browse the repository at this point in the history
When running the global "ui5" command while a local @ui5/cli version is
installed for the current project, the local one should be preferred.
In this case an information will be logged to the console.

This can be disabled by setting an environment variable:
`UI5_CLI_NO_LOCAL=true`

`ui5 --version` now also displays the CLI location for better troubleshooting.

Fixes: #58
  • Loading branch information
matz3 authored Nov 15, 2018
1 parent b268ce7 commit 3c2a0a8
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 21 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,28 @@ Options:
--loglevel Set the logging level (error|warn|info|verbose|silly). [string] [default: "info"]
```

### Local vs. Global Installation
In general a global installation of the UI5 CLI (`npm install --global @ui5/cli`) is recommended.

However, it makes sense to add the UI5 CLI as a [devDependency](https://docs.npmjs.com/files/package.json#devdependencies) (`npm install --save-dev @ui5/cli`) for a project that is using `ui5`-commands in its build or test scripts or otherwise depends on the UI5 CLI for development workflows (like Continuous Integration).

In case you have both, a local installation in one of your projects as well as a global installation, the UI5 CLI will always try to invoke the local installation. This is in part because [npm scripts](https://docs.npmjs.com/misc/scripts) defined in your `package.json` will also always invoke the local installation.

This behavior can be disabled by setting the environment variable `UI5_CLI_NO_LOCAL`.

**Example**
You have a project located at `/my-application`. The project has a devDependency to `@ui5/cli` and defines a start-script `"ui5 serve"`.

Current Working Directory | Command | Uses globally installed UI5 CLI | Uses locally installed UI5 CLI
--- | --- | :---: | :---:
`/``ui5 --version` | ✔️ |
`/my-application``ui5 --version` | | ✔️
`/my-application``ui5 serve` | | ✔️
`/my-application``npm start` | | ✔️
`/my-application``UI5_CLI_NO_LOCAL=X ui5 serve` | ✔️ |
`/my-application``UI5_CLI_NO_LOCAL=X npm start` | | ✔️


## Contributing
Please check our [Contribution Guidelines](https://github.com/SAP/ui5-tooling/blob/master/CONTRIBUTING.md).

Expand Down
57 changes: 43 additions & 14 deletions bin/ui5.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,50 @@ if (pkg.engines && pkg.engines.node && !semver.satisfies(nodeVersion, pkg.engine
process.exit(1);
}

const updateNotifier = require("update-notifier");
const cli = require("yargs");
// Timeout is required to log info when importing from local installation
setTimeout(() => {
if (!process.env.UI5_CLI_NO_LOCAL) {
const importLocal = require("import-local");
// Prefer a local installation of @ui5/cli.
// This will invoke the local CLI, so no further action required
if (importLocal(__filename)) {
if (process.argv.includes("--verbose")) {
console.info(`INFO: This project contains an individual ${pkg.name} installation which ` +
"will be used over the global one.");
console.info("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details.");
console.info("");
} else {
console.info(`INFO: Using local ${pkg.name} installation`);
console.info("");
}
return;
}
}

updateNotifier({
pkg,
updateCheckInterval: 1000 * 60 * 60 * 24, // 1 day
shouldNotifyInNpmScript: true
}).notify();
const updateNotifier = require("update-notifier");
const cli = require("yargs");

// CLI modules
cli.commandDir("../lib/cli/commands");
updateNotifier({
pkg,
updateCheckInterval: 1000 * 60 * 60 * 24, // 1 day
shouldNotifyInNpmScript: true
}).notify();

// Format terminal output to full available width
cli.wrap(cli.terminalWidth());
// Explicitly set CLI version as the yargs default might
// be wrong in case a local CLI installation is used
// Also add CLI location
cli.version(`${pkg.version} (from ${__filename})`);

// yargs registers a get method on the argv property.
// The property needs to be accessed to initialize everything.
cli.argv;
// Explicitly set script name to prevent windows from displaying "ui5.js"
cli.scriptName("ui5");

// CLI modules
cli.commandDir("../lib/cli/commands");

// Format terminal output to full available width
cli.wrap(cli.terminalWidth());

// yargs registers a get method on the argv property.
// The property needs to be accessed to initialize everything.
cli.argv;
}, 0);
67 changes: 62 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"@ui5/logger": "^0.2.0",
"@ui5/project": "^0.2.0",
"@ui5/server": "^0.2.1",
"import-local": "^2.0.0",
"js-yaml": "^3.10.0",
"opn": "^5.1.0",
"semver": "^5.5.0",
Expand Down
4 changes: 2 additions & 2 deletions test/lib/cli/commands/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const ui5 = (args, options = {}) => execa(ui5Cli, args, options);

test("ui5 --version", async (t) => {
const {stdout} = await ui5(["--version"]);
t.is(stdout, pkg.version);
t.is(stdout, `${pkg.version} (from ${ui5Cli})`);
});

test("ui5 -v", async (t) => {
const {stdout} = await ui5(["-v"]);
t.is(stdout, pkg.version);
t.is(stdout, `${pkg.version} (from ${ui5Cli})`);
});

0 comments on commit 3c2a0a8

Please sign in to comment.