Skip to content

Commit

Permalink
Llb ts desktop no cli (#2491)
Browse files Browse the repository at this point in the history
Changes to allow Desktop client build with no CLI
---------
Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
  • Loading branch information
calcaide authored Oct 4, 2024
1 parent 9c31154 commit 401ff35
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 39 deletions.
16 changes: 5 additions & 11 deletions ui/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,12 @@ To run as a desktop app:

- `yarn start:desktop`

The Boundary CLI is downloaded and extracted to `electron-app/cli/` folder as part of
build. CLI version is defined in `electron-app/config/cli.js`.
The Boundary CLI is NOT downloaded by default, to download and extract the CLI to `electron-app/cli` folder as part of the build, you need to set the environment variable `SETUP_CLI` to true. Example: `SETUP_CLI=true yarn start:desktop`.
The CLI version is defined in `electron-app/config/cli/VERSION`.

### Developing Using Non-Release Versions of Boundary

You can also develop using a non-release version of Boundary - bypassing the
above CLI download behavior - by manually placing the version of Boundary that
you want to develop with in the `electron-app/cli/` directly (you may need to
create the directory).

After doing this, run yarn with `BYPASS_CLI_SETUP=true`; example:
`BYPASS_CLI_SETUP=true yarn start:desktop`.
To develop using a non-release version of Boundary, download the Boundary CLI version you want to use and extract it to the `electron-app/cli` folder. You may need to create the directory or clean it up beforehand.

### Environment Variables (DEV)

Expand All @@ -106,7 +100,7 @@ These environment variables may be used to customized the build.
| `APP_UPDATER_CURRENT_VERSION` | Version of client. |
| `APP_UPDATER_LATEST_VERSION_TAG` | Next version for comparison with current version. |
| `APP_UPDATER_LATEST_VERSION_LOCATION` | Location of app release to use for updating client. Can be a filepath or url. |
| `BYPASS_CLI_SETUP` | Disable download and extraction of cli. For development use only. |
| `SETUP_CLI` | Enable download and extraction of CLI. |
| `BYPASS_APP_UPDATER` | Disable app updater feature. For development use only. |
| `DISABLE_WINDOW_CHROME` | Disable window chrome. For internal use only. |
| `ENABLE_MIRAGE` | Enable (`true`) or disable (`false`) mirage. Default value is `true`. |
Expand Down Expand Up @@ -150,7 +144,7 @@ These environment variables may be used to customized the build.
| -------- | ------------- | ----------- |
| `APP_NAME` | Application Name | The user-facing name of the application, appearing in titles, etc. |
| `BOUNDARY_DESKTOP_SIGNING_IDENTITY` | | The name of the certificate to use when signing (e.g. Developer ID Application: \* (*)). |
| `BYPASS_CLI_SETUP` | Set to `true` to launch without bootstrapping the CLI (see above). ||
| `SETUP_CLI` | Enable download and extraction of CLI. |

### Running Tests

Expand Down
26 changes: 13 additions & 13 deletions ui/desktop/electron-app/config/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,20 @@ const extract = async (artifactPath, destination) => {

module.exports = {
setup: async () => {
if (process.env.BYPASS_CLI_SETUP) {
if (process.env.SETUP_CLI === 'true') {
try {
const artifactVersion = await fs.promises.readFile(
path.resolve(__dirname, 'cli', 'VERSION'),
'utf8',
);
const artifactPath = await downloadArtifact(artifactVersion.trim());
await extract(artifactPath, artifactDestination);
} catch (e) {
console.error('ERROR: Failed setting up CLI.', e);
process.exit(1);
}
} else {
console.warn('WARNING: Bypassing cli setup');
return;
}
try {
const artifactVersion = await fs.promises.readFile(
path.resolve(__dirname, 'cli', 'VERSION'),
'utf8',
);
const artifactPath = await downloadArtifact(artifactVersion.trim());
await extract(artifactPath, artifactDestination);
} catch (e) {
console.error('ERROR: Failed setting up CLI.', e);
process.exit(1);
}
},
};
9 changes: 8 additions & 1 deletion ui/desktop/electron-app/config/forge.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ const { isMac } = require('../src/helpers/platform.js');
const fs = require('fs');
const path = require('path');

// When SETUP_CLI=false we do not download the CLI. If there is no cli directory present
// we will not copy the CLI to the output binary.app
let extraResource = [];
if (fs.existsSync('./cli')) {
extraResource = ['./cli'];
}

module.exports = {
packagerConfig: {
ignore: ['/ember-test(/|$)', '/tests(/|$)'],
Expand Down Expand Up @@ -39,7 +46,7 @@ module.exports = {
done();
},
],
extraResource: ['./cli'],
extraResource,
},
makers: [
{
Expand Down
6 changes: 4 additions & 2 deletions ui/desktop/electron-app/src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
*/

const { spawnSync } = require('../helpers/spawn-promise.js');
const { path } = require('./path.js');
const { path, isBuiltInCli } = require('./path.js');

module.exports = {
// Check boundary cli existence
exists: () => Boolean(path()),
exists: () => Boolean(path),

isBuiltInCli,

// Returns JSON-formatted version information from the CLI
version: () => {
Expand Down
37 changes: 28 additions & 9 deletions ui/desktop/electron-app/src/cli/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,34 @@
const path = require('path');
const { isWindows } = require('../helpers/platform.js');
const isDev = require('electron-is-dev');
const { existsSync } = require('node:fs');
const which = require('which');

module.exports = {
// Returns boundary cli path
path: () => {
const name = isWindows() ? 'boundary.exe' : 'boundary';
const binaryName = isWindows() ? 'boundary.exe' : 'boundary';
const builtInCliPath = isDev
? path.resolve(__dirname, '..', '..', 'cli', binaryName)
: path.resolve(process.resourcesPath, 'cli', binaryName);

// Return true if the CLI in usage is the built in. False if relies on system CLI.
const isBuiltInCli = existsSync(builtInCliPath);

/**
* Returns Boundary CLI path if the CLI is built in or the Boundary binary name
* if not, so we assume boundary is available within user $PATH.
*/
const pathBoundary = isBuiltInCli
? builtInCliPath
: // On Windows, we need to filter out the path that is within the current working directory.
// This is necessary because the spawn methods may not always find the correct binary path.
// The `which` module returns an array of all available paths for the 'boundary' binary.
// We then filter out the path that is within the current working directory.
isWindows()
? which
.sync(binaryName, { nothrow: true, all: true })
.filter((binary) => !binary.startsWith(process.cwd()))[0]
: binaryName;

// The CLI will be located in a different location once packaged up in an ASAR
return isDev
? path.resolve(__dirname, '..', '..', 'cli', name)
: path.resolve(process.resourcesPath, 'cli', name);
},
module.exports = {
path: pathBoundary,
isBuiltInCli,
};
6 changes: 6 additions & 0 deletions ui/desktop/electron-app/src/helpers/app-updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { autoUpdater, dialog, app } = require('electron');
const { isWindows, isLinux } = require('../helpers/platform.js');
const config = require('../../config/config.js');
const log = require('electron-log/main');
const boundaryCli = require('../cli/index.js');

let currentVersion = config.releaseVersion;
const debug = process.env.DEBUG_APP_UPDATER;
Expand Down Expand Up @@ -170,6 +171,11 @@ module.exports = {
*/
if (isWindows() || isLinux()) return;

/**
* Skip the app updater if we are NOT using the built in CLI
*/
if (!boundaryCli.isBuiltInCli) return;

let latestVersion;
if (debug) {
latestVersion = process.env.APP_UPDATER_LATEST_VERSION_TAG;
Expand Down
6 changes: 3 additions & 3 deletions ui/desktop/electron-app/src/helpers/spawn-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = {
*/
spawnAsyncJSONPromise(command, token) {
return new Promise((resolve, reject) => {
const childProcess = spawn(path(), command, {
const childProcess = spawn(path, command, {
env: {
...process.env,
BOUNDARY_TOKEN: token,
Expand Down Expand Up @@ -77,7 +77,7 @@ module.exports = {
* @param {object} envVars
* @returns {{stdout: string | undefined, stderr: string | undefined}} */
spawnSync(args, envVars = {}) {
const childProcess = spawnSync(path(), args, {
const childProcess = spawnSync(path, args, {
// Some of our outputs (namely cache daemon searching) can be very large.
// This an undocumented hack to allow for an unlimited buffer size which
// could change at any time. If it does, we should just set an arbitrarily
Expand All @@ -103,7 +103,7 @@ module.exports = {
*/
spawn(command, options) {
return new Promise((resolve, reject) => {
const childProcess = spawn(path(), command, options);
const childProcess = spawn(path, command, options);
childProcess.stdout.on('data', (data) => {
resolve({ childProcess, stdout: data.toString() });
});
Expand Down

0 comments on commit 401ff35

Please sign in to comment.