Skip to content

Commit

Permalink
[Plugin Helpers] Facilitate version changes (opensearch-project#2398)
Browse files Browse the repository at this point in the history
Signed-off-by: Miki <miki@amazon.com>

Signed-off-by: Miki <miki@amazon.com>
(cherry picked from commit 48fe60b)
  • Loading branch information
AMoo-Miki authored and joshuarrrr committed Sep 30, 2022
1 parent cc31854 commit ad053cb
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 35 deletions.
93 changes: 71 additions & 22 deletions packages/osd-plugin-helpers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ yarn osd bootstrap

## Usage

This simple CLI has a build task that plugin devs can run from to easily package OpenSearch Dashboards plugins.
This CLI has a `build` command that plugin devs can run to easily package OpenSearch Dashboards plugins. It also has a `version`
command which updates a plugin's `version` and `opensearchDashboardsVersion` in the `opensearch_dashboards.json` and the `version`,
`opensearchDashboards.version`, and `opensearchDashboards.templateVersion` in the `package.json` files to match the version of
OpenSearch Dashboards or ones supplied.

Previously you could also use that tool to start and test your plugin. Currently you can run
your plugin along with OpenSearch Dashboards running `yarn start` in the OpenSearch Dashboards repository root folder. Finally to test
Previously you could also use that tool to start and test your plugin. Currently, you can run
your plugin along with OpenSearch Dashboards running `yarn start` in the OpenSearch Dashboards repository root folder. Finally, to test
your plugin you should now configure and use your own tools.

```sh
Expand All @@ -37,37 +40,76 @@ $ plugin-helpers help
Usage: plugin-helpers [command] [options]

Commands:
build
Copies files from the source into a zip archive that can be distributed for
installation into production OpenSearch Dashboards installs. The archive includes the non-
development npm dependencies and builds itself using raw files in the source
directory so make sure they are clean/up to date. The resulting archive can
be found at:

build/{plugin.id}-{opensearchDashboardsVersion}.zip

Options:
--skip-archive Don't create the zip file, just create the build/opensearch-dashboards directory
--opensearch-dashboards-version, -v OpenSearch Dashboards version that the
build
Copies files from the source into a zip archive that can be distributed for installation into production
OpenSearch Dashboards installs. The archive includes the non-development npm dependencies and builds itself using
raw files in the source directory so make sure they are clean/up to date. The resulting archive can be found at:

build/{plugin.id}-{opensearchDashboardsVersion}.zip

Options:
--skip-archive Don't create the zip file, just create the build/opensearch-dashboards directory
--opensearch-dashboards-version, -v OpenSearch Dashboards version that the built plugin will target
version
Without any options, it would display information about the versions found in the manifest file. With options, it
updates the version and opensearchDashboardsVersion in the opensearch_dashboards.json and the version,
opensearchDashboards.version, and opensearchDashboards.templateVersion in the package.json files to the values
provided or syncs them with the version of OpenSearch Dashboards. The versions are expected to start with #.#.#
where # are numbers.
Options:
--sync Update the versions to match OpenSearch Dashboards'
--plugin-version Update the plugin's version to the one specified
--compatibility-version Update the plugin's compatibility version to the one specified


Global options:
--verbose, -v Log verbosely
--debug Log debug messages (less than verbose)
--quiet Only log errors
--silent Don't log anything
--help Show this message
--verbose, -v Log verbosely
--debug Log debug messages (less than verbose)
--quiet Only log errors
--silent Don't log anything
--help Show this message
```
### Examples
To produce build artifacts of a plugin in the `build/opensearch-dashboards` directory, without generating a zip archive, and while targeting OpenSearch Dashboards 3.0.0:
```
yarn plugin-helpers build --skip-archive --opensearch-dashboards-version="3.0.0"
```
To synchronize the versions used in a plugin's `opensearch_dashboards.json` and `package.json` files with the version of OpenSearch Dashboards:
```
yarn plugin-helpers version --sync
```
If legacy plugin versions are required:
```
yarn plugin-helpers version --sync legacy
```
To update the compatibility version of the plugin in the `opensearch_dashboards.json` and `package.json` files:
```
yarn plugin-helpers version --compatibility-version="3.0.0"
// or
yarn plugin-helpers version --compatibility-version 3.0.0
```
To synchronize the compatibility version of the plugin with the version of OpenSearch Dashboards but set a specific version for the plugin:
```
yarn plugin-helpers version --sync --plugin-version 1.1.0
```
## Versions
The plugins helpers in the OpenSearch Dashboards repo are available for OpenSearch Dashboards 1.0 and greater. Just checkout the branch of OpenSearch Dashboards you want to build against and the plugin helpers should be up to date for that version of OpenSearch Dashboards.
The plugins helpers in the OpenSearch Dashboards repo are available for OpenSearch Dashboards 1.0 and greater. Just checkout the branch of OpenSearch Dashboards you want to build against and the plugin helpers should be up-to-date for that version of OpenSearch Dashboards.
## Configuration
`plugin-helpers` accepts a number of settings, which can be specified at runtime, or included in a `.opensearch_dashboards-plugin-helpers.json` file if you'd like to bundle those settings with your project.
`plugin-helpers` accepts a number of settings for the `build` command which can be specified at runtime or included in a `.opensearch_dashboards-plugin-helpers.json` file if you'd like to bundle those settings with your project.
It will also observe a `.opensearch_dashboards-plugin-helpers.dev.json`, much like OpenSearch Dashboards does, which we encourage you to add to your `.gitignore` file and use for local settings that you don't intend to share. These "dev" settings will override any settings in the normal json config.
Expand All @@ -84,6 +126,13 @@ Setting | Description
`skipInstallDependencies` | Don't install dependencies defined in package.json into build output
`opensearchDashboardsVersion` | OpenSearch Dashboards version for the build output (added to package.json)
### Settings for `version`
Setting | Description
------- | -----------
`sync` | As the default behavior, it uses the version of OpenSearch Dashboards to update the plugin's `opensearch_dashboards.json` and `package.json` files.
`set` | Defines the version to be used in the plugin's `opensearch_dashboards.json` and `package.json` files.
## TypeScript support
Plugin code can be written in [TypeScript](http://www.typescriptlang.org/) if desired. To enable TypeScript support create a `tsconfig.json` file at the root of your plugin that looks something like this:
Expand Down
144 changes: 137 additions & 7 deletions packages/osd-plugin-helpers/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,24 @@ import { RunWithCommands, createFlagError, createFailError } from '@osd/dev-util
import { findOpenSearchDashboardsJson } from './find_opensearch_dashboards_json';
import { loadOpenSearchDashboardsPlatformPlugin } from './load_opensearch_dashboards_platform_plugin';
import * as Tasks from './tasks';
import { BuildContext } from './build_context';
import { BuildContext, VersionContext } from './contexts';
import { resolveOpenSearchDashboardsVersion } from './resolve_opensearch_dashboards_version';
import { loadConfig } from './config';

const VERSION_PARAM_MATCH_DASHBOARDS = 'sync';
const VERSION_PARAM_USE_INPUT_FOR_PLUGIN = 'plugin-version';
const VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY = 'compatibility-version';

export function runCli() {
new RunWithCommands({
description: 'Some helper tasks for plugin-authors',
})
.command({
name: 'build',
description: `
Copies files from the source into a zip archive that can be distributed for
installation into production OpenSearch Dashboards installs. The archive includes the non-
development npm dependencies and builds itself using raw files in the source
directory so make sure they are clean/up to date. The resulting archive can
be found at:
Copies files from the source into a zip archive that can be distributed for installation into production
OpenSearch Dashboards installs. The archive includes the non-development npm dependencies and builds itself using
raw files in the source directory so make sure they are clean/up to date. The resulting archive can be found at:
build/{plugin.id}-{opensearchDashboardsVersion}.zip
Expand All @@ -64,7 +66,7 @@ export function runCli() {
k: 'opensearch-dashboards-version',
},
help: `
--skip-archive Don't create the zip file, just create the build/opensearch-dashboards directory
--skip-archive Don't create the zip file, just create the build/opensearch-dashboards directory
--opensearch-dashboards-version, -v OpenSearch version that the
`,
},
Expand Down Expand Up @@ -120,5 +122,133 @@ export function runCli() {
}
},
})
.command({
name: 'version',
description: `
Without any options, it would display information about the versions found in the manifest file. With options, it
updates the version and opensearchDashboardsVersion in the opensearch_dashboards.json and the version,
opensearchDashboards.version, and opensearchDashboards.templateVersion in the package.json files to the values
provided or syncs them with the version of OpenSearch Dashboards. The versions are expected to start with #.#.#
where # are numbers.
`,
flags: {
string: [VERSION_PARAM_USE_INPUT_FOR_PLUGIN, VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY],
help: `
--${VERSION_PARAM_MATCH_DASHBOARDS.padEnd(
35,
' '
)}Update the versions to match OpenSearch Dashboards'
--${VERSION_PARAM_USE_INPUT_FOR_PLUGIN.padEnd(
35,
' '
)}Update the plugin's version to the one specified
--${VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY.padEnd(
35,
' '
)}Update the plugin's compatibility version to the one specified
`,
allowUnexpected: true,
},
async run({ log, flags }) {
const pluginDir = await findOpenSearchDashboardsJson(process.cwd());
if (!pluginDir) {
throw createFailError(
`Unable to find OpenSearch Dashboards Platform plugin in [${process.cwd()}] or any of its parent directories. Has it been migrated properly? Does it have a opensearch_dashboards.json file?`
);
}

let dashboardsPackage;
try {
dashboardsPackage = await import(Path.join(process.cwd(), '../../package.json'));
} catch (ex) {
throw createFailError(`Unable to parse the OpenSearch Dashboards' package.json file`);
}

let pluginPackage;
try {
pluginPackage = await import(Path.join(process.cwd(), 'package.json'));
} catch (ex) {
throw createFailError(`Unable to parse the plugin's package.json file`);
}

let manifestFile;
try {
manifestFile = await import(Path.join(process.cwd(), 'opensearch_dashboards.json'));
} catch (ex) {
throw createFailError(`Unable to parse the plugin's opensearch_dashboards.json file`);
}

const dashboardsVersion = dashboardsPackage.version;
const pluginVersion = pluginPackage.version;
const manifestCompatibilityVersion = manifestFile.opensearchDashboardsVersion;

log.info(
`The plugin is on v${pluginVersion} and requires OpenSearch Dashboards v${manifestCompatibilityVersion}, ${
manifestCompatibilityVersion === dashboardsVersion ? 'and' : 'but'
} the one found in the directory hierarchy is on v${dashboardsVersion}.`
);

let askedToChange = false;
let updatedPluginVersion = pluginVersion;
let updatedCompatibilityVersion = manifestCompatibilityVersion;

const doSync = flags[VERSION_PARAM_MATCH_DASHBOARDS];
if (doSync) {
if (!['boolean', 'string'].includes(typeof doSync))
throw createFlagError(`expected a single --${VERSION_PARAM_MATCH_DASHBOARDS} flag`);

/* if using legacy versions, the plugin's version has a now-redundant `.0` appended to the semantic
* version number of OpenSearch Dashboards. If OpenSearch Dashboards has a version with a suffix, the
* suffix has to be removed before we append the `.0`.
*/
updatedPluginVersion =
doSync === 'legacy'
? `${dashboardsVersion.replace(/^(\d+\.\d+\.\d+)(-.*)?$/, '$1')}.0`
: dashboardsVersion;
updatedCompatibilityVersion = `${dashboardsVersion}`;

askedToChange = true;
}

const pluginVersionValue = flags[VERSION_PARAM_USE_INPUT_FOR_PLUGIN];
if (pluginVersionValue) {
if (typeof pluginVersionValue !== 'string')
throw createFlagError(`expected a single --${VERSION_PARAM_USE_INPUT_FOR_PLUGIN} flag`);
if (!/^\d+(\.\d+){2,}(-\S+)?$/.test(pluginVersionValue))
throw createFlagError(
`expected a valid version starting with #.#.# where # are numbers to follow the --${VERSION_PARAM_USE_INPUT_FOR_PLUGIN} flag`
);

updatedPluginVersion = pluginVersionValue;
askedToChange = true;
}

const compatibilityVersionValue = flags[VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY];
if (compatibilityVersionValue) {
if (typeof compatibilityVersionValue !== 'string')
throw createFlagError(
`expected a single --${VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY} flag`
);
if (!/^\d+(\.\d+){2,}(-\S+)?$/.test(compatibilityVersionValue))
throw createFlagError(
`expected a valid version starting with #.#.# where # are numbers to follow the --${VERSION_PARAM_USE_INPUT_FOR_COMPATIBILITY} flag`
);

updatedCompatibilityVersion = compatibilityVersionValue;
askedToChange = true;
}

if (!askedToChange) return;

const context: VersionContext = {
log,
sourceDir: process.cwd(),
pluginVersion: updatedPluginVersion,
compatibilityVersion: updatedCompatibilityVersion,
};

await Tasks.updateVersions(context);
},
})
.execute();
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,25 @@ export interface BuildContext {
buildDir: string;
opensearchDashboardsVersion: string;
}

export interface VersionContext {
log: ToolingLog;
sourceDir: string;
pluginVersion?: string;
compatibilityVersion?: string;
}

interface NestedObject {
[key: string]: NestedObject | string | undefined;
}

export interface FileUpdateContext {
log: ToolingLog;
file: string;
updates: NestedObject;
}

export interface ObjectUpdateContext {
original: { [key: string]: any };
updates: NestedObject;
}
2 changes: 1 addition & 1 deletion packages/osd-plugin-helpers/src/tasks/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { promisify } from 'util';

import del from 'del';

import { BuildContext } from '../build_context';
import { BuildContext } from '../contexts';

const asyncMkdir = promisify(Fs.mkdir);

Expand Down
2 changes: 1 addition & 1 deletion packages/osd-plugin-helpers/src/tasks/create_archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import del from 'del';
import vfs from 'vinyl-fs';
import zip from 'gulp-zip';

import { BuildContext } from '../build_context';
import { BuildContext } from '../contexts';

const asyncPipeline = promisify(pipeline);

Expand Down
1 change: 1 addition & 0 deletions packages/osd-plugin-helpers/src/tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
export * from './clean';
export * from './create_archive';
export * from './optimize';
export * from './update_versions';
export * from './write_public_assets';
export * from './write_server_files';
export * from './yarn_install';
2 changes: 1 addition & 1 deletion packages/osd-plugin-helpers/src/tasks/optimize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { promisify } from 'util';
import { REPO_ROOT } from '@osd/utils';
import { OptimizerConfig, runOptimizer, logOptimizerState } from '@osd/optimizer';

import { BuildContext } from '../build_context';
import { BuildContext } from '../contexts';

const asyncRename = promisify(Fs.rename);

Expand Down
Loading

0 comments on commit ad053cb

Please sign in to comment.