diff --git a/package.json b/package.json index 51118e947bef..7bbaf9f6d82a 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "uiFramework:createComponent": "cd packages/osd-ui-framework && yarn createComponent", "uiFramework:documentComponent": "cd packages/osd-ui-framework && yarn documentComponent", "osd:watch": "node scripts/opensearch_dashboards --dev --logging.json=false", - "build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json", + "build:types": "node scripts/remove.js ./target/types && tsc --p tsconfig.types.json", "docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept", "osd:bootstrap": "node scripts/build_ts_refs && node scripts/register_git_hook", "spec_to_console": "node scripts/spec_to_console" @@ -435,6 +435,7 @@ "mutation-observer": "^1.0.3", "ngreact": "^0.5.1", "nock": "12.0.3", + "node-stream-zip": "^1.15.0", "normalize-path": "^3.0.0", "nyc": "^14.1.1", "pixelmatch": "^5.1.0", diff --git a/packages/osd-apm-config-loader/src/utils/get_config_file_paths.test.ts b/packages/osd-apm-config-loader/src/utils/get_config_file_paths.test.ts index 0220135e5a90..ca04cef17b56 100644 --- a/packages/osd-apm-config-loader/src/utils/get_config_file_paths.test.ts +++ b/packages/osd-apm-config-loader/src/utils/get_config_file_paths.test.ts @@ -42,7 +42,7 @@ describe('getConfigurationFilePaths', () => { expect(getConfigurationFilePaths(argv)).toEqual([ resolve(cwd, join('.', 'relative-path')), - '/absolute-path', + resolve('/absolute-path'), ]); }); diff --git a/packages/osd-config-schema/src/errors/__snapshots__/schema_error.test.ts.snap b/packages/osd-config-schema/src/errors/__snapshots__/schema_error.test.ts.snap index 6bcb14760ee5..93fe30cfc71b 100644 --- a/packages/osd-config-schema/src/errors/__snapshots__/schema_error.test.ts.snap +++ b/packages/osd-config-schema/src/errors/__snapshots__/schema_error.test.ts.snap @@ -2,6 +2,6 @@ exports[`includes stack 1`] = ` "Error: test - at Object..it (packages/osd-config-schema/src/errors/schema_error.test.ts:57:11) + at Object..it (packages/osd-config-schema/src/errors/schema_error.test.ts:61:11) at new Promise ()" `; diff --git a/packages/osd-config-schema/src/errors/schema_error.test.ts b/packages/osd-config-schema/src/errors/schema_error.test.ts index 21095d1e944c..004d186e88fe 100644 --- a/packages/osd-config-schema/src/errors/schema_error.test.ts +++ b/packages/osd-config-schema/src/errors/schema_error.test.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { relative } from 'path'; +import { relative, sep } from 'path'; import { SchemaError } from '.'; /** @@ -39,7 +39,7 @@ import { SchemaError } from '.'; export const cleanStack = (stack: string) => stack .split('\n') - .filter((line) => !line.includes('node_modules/') && !line.includes('internal/')) + .filter((line) => !line.includes('node_modules' + sep) && !line.includes('internal/')) .map((line) => { const parts = /.*\((.*)\).?/.exec(line) || []; @@ -48,7 +48,11 @@ export const cleanStack = (stack: string) => } const path = parts[1]; - return line.replace(path, relative(process.cwd(), path)); + // Cannot use `standardize` from `@osd/utils + let relativePath = relative(process.cwd(), path); + if (process.platform === 'win32') relativePath = relativePath.replace(/\\/g, '/'); + + return line.replace(path, relativePath); }) .join('\n'); diff --git a/packages/osd-opensearch-archiver/package.json b/packages/osd-opensearch-archiver/package.json index e1c28cc47484..f130ae44138a 100644 --- a/packages/osd-opensearch-archiver/package.json +++ b/packages/osd-opensearch-archiver/package.json @@ -7,8 +7,8 @@ "devOnly": true }, "scripts": { - "osd:bootstrap": "rm -rf target && tsc", - "osd:watch": "rm -rf target && tsc --watch" + "osd:bootstrap": "node ../../scripts/remove.js target && tsc", + "osd:watch": "node ../../scripts/remove.js target && tsc --watch" }, "dependencies": { "@osd/dev-utils": "1.0.0", @@ -17,4 +17,4 @@ "devDependencies": { "@types/elasticsearch": "^5.0.33" } -} \ No newline at end of file +} diff --git a/packages/osd-opensearch/src/artifact.js b/packages/osd-opensearch/src/artifact.js index cc1f7a9c8ea6..428621c99d24 100644 --- a/packages/osd-opensearch/src/artifact.js +++ b/packages/osd-opensearch/src/artifact.js @@ -182,12 +182,14 @@ async function getArtifactSpecForSnapshotFromUrl(urlVersion, log) { // issue: https://github.com/opensearch-project/OpenSearch-Dashboards/issues/475 const platform = process.platform === 'win32' ? 'windows' : process.platform; const arch = process.arch === 'arm64' ? 'arm64' : 'x64'; - if (platform !== 'linux') { - throw createCliError(`Snapshots are only available for Linux`); + const extension = process.platform === 'win32' ? 'zip' : 'tar.gz'; + + if (platform !== 'linux' && platform !== 'windows') { + throw createCliError(`Snapshots are only available for Linux and Windows`); } const latestUrl = `${DAILY_SNAPSHOTS_BASE_URL}/${desiredVersion}-SNAPSHOT`; - const latestFile = `opensearch-min-${desiredVersion}-SNAPSHOT-${platform}-${arch}-latest.tar.gz`; + const latestFile = `opensearch-min-${desiredVersion}-SNAPSHOT-${platform}-${arch}-latest.${extension}`; const completeLatestUrl = `${latestUrl}/${latestFile}`; let { abc, resp } = await verifySnapshotUrl(completeLatestUrl, log); diff --git a/packages/osd-opensearch/src/artifact.test.js b/packages/osd-opensearch/src/artifact.test.js index bb9fe337ccfc..10da798b8533 100644 --- a/packages/osd-opensearch/src/artifact.test.js +++ b/packages/osd-opensearch/src/artifact.test.js @@ -164,10 +164,10 @@ describe('Artifact', () => { }); }); - it('should throw when on a non-Linux platform', async () => { + it('should throw when on a non-Linux or non-Windows platform', async () => { Object.defineProperties(process, { platform: { - value: 'win32', + value: 'darwin', }, arch: { value: ORIGINAL_ARCHITECTURE, diff --git a/packages/osd-opensearch/src/utils/decompress.test.js b/packages/osd-opensearch/src/utils/decompress.test.js index 1d6528d20435..936fd7a50b98 100644 --- a/packages/osd-opensearch/src/utils/decompress.test.js +++ b/packages/osd-opensearch/src/utils/decompress.test.js @@ -54,8 +54,8 @@ beforeEach(() => { fs.copyFileSync(path.resolve(fixturesFolder, 'snapshot.tar.gz'), tarGzSnapshot); }); -afterEach(() => { - del.sync(tmpFolder, { force: true }); +afterEach(async () => { + await del(tmpFolder, { force: true }); }); test('zip strips root directory', async () => { diff --git a/packages/osd-opensearch/src/utils/extract_config_files.test.js b/packages/osd-opensearch/src/utils/extract_config_files.test.js index 97c56a12c18f..e5a15a40bfb9 100644 --- a/packages/osd-opensearch/src/utils/extract_config_files.test.js +++ b/packages/osd-opensearch/src/utils/extract_config_files.test.js @@ -38,6 +38,7 @@ jest.mock('fs', () => ({ const { extractConfigFiles } = require('./extract_config_files'); const fs = require('fs'); +const path = require('path'); afterEach(() => { jest.clearAllMocks(); @@ -57,7 +58,7 @@ test('copies file', () => { extractConfigFiles(['path=/data/foo.yml'], '/opensearch'); expect(fs.readFileSync.mock.calls[0][0]).toEqual('/data/foo.yml'); - expect(fs.writeFileSync.mock.calls[0][0]).toEqual('/opensearch/config/foo.yml'); + expect(fs.writeFileSync.mock.calls[0][0]).toEqual(path.resolve('/opensearch/config/foo.yml')); }); test('ignores file which does not exist', () => { diff --git a/packages/osd-opensearch/src/utils/find_most_recently_changed.test.js b/packages/osd-opensearch/src/utils/find_most_recently_changed.test.js index 6733e7436569..ba9168d28d66 100644 --- a/packages/osd-opensearch/src/utils/find_most_recently_changed.test.js +++ b/packages/osd-opensearch/src/utils/find_most_recently_changed.test.js @@ -24,6 +24,7 @@ * specific language governing permissions and limitations * under the License. */ +const path = require('path'); /* * Modifications Copyright OpenSearch Contributors. See @@ -59,7 +60,7 @@ const { findMostRecentlyChanged } = require('./find_most_recently_changed'); test('returns newest file', () => { const file = findMostRecentlyChanged('/data/*.yml'); - expect(file).toEqual('/data/newest.yml'); + expect(file).toEqual(path.resolve('/data/newest.yml')); }); afterAll(() => { diff --git a/packages/osd-optimizer/src/common/bundle.test.ts b/packages/osd-optimizer/src/common/bundle.test.ts index 461ab7023376..172b1d74704e 100644 --- a/packages/osd-optimizer/src/common/bundle.test.ts +++ b/packages/osd-optimizer/src/common/bundle.test.ts @@ -30,6 +30,7 @@ * GitHub history for details. */ +import { resolve } from 'path'; import { Bundle, BundleSpec, parseBundles } from './bundle'; jest.mock('fs'); @@ -90,13 +91,16 @@ it('provides the module count from the cache', () => { it('parses bundles from JSON specs', () => { const bundles = parseBundles(JSON.stringify([SPEC])); + let expectedCachePath = resolve('/foo/bar/target/.osd-optimizer-cache'); + // Cannot use `standardize` from `@osd/util` due to mocking of fs + if (process?.platform === 'win32') expectedCachePath = expectedCachePath.replace(/\\/g, '\\\\'); expect(bundles).toMatchInlineSnapshot(` Array [ Bundle { "banner": undefined, "cache": BundleCache { - "path": "/foo/bar/target/.osd-optimizer-cache", + "path": "${expectedCachePath}", "state": undefined, }, "contextDir": "/foo/bar", diff --git a/packages/osd-optimizer/src/optimizer/get_changes.test.ts b/packages/osd-optimizer/src/optimizer/get_changes.test.ts index a7af13283ccc..4b16eeac9467 100644 --- a/packages/osd-optimizer/src/optimizer/get_changes.test.ts +++ b/packages/osd-optimizer/src/optimizer/get_changes.test.ts @@ -30,9 +30,12 @@ * GitHub history for details. */ +import path from 'path'; + jest.mock('execa'); import { getChanges } from './get_changes'; +import { standardize } from '@osd/dev-utils'; const execa: jest.Mock = jest.requireMock('execa'); @@ -58,12 +61,16 @@ it('parses git ls-files output', async () => { }; }); + const rootPath = path.resolve('/foo/bar/x/osd-optimizer') + path.sep; + const srcPath = path.join(rootPath, 'src') + path.sep; + const commonPath = path.join(srcPath, 'common') + path.sep; + await expect(getChanges('/foo/bar/x')).resolves.toMatchInlineSnapshot(` Map { - "/foo/bar/x/osd-optimizer/package.json" => "modified", - "/foo/bar/x/osd-optimizer/src/common/bundle.ts" => "modified", - "/foo/bar/x/osd-optimizer/src/common/bundles.ts" => "deleted", - "/foo/bar/x/osd-optimizer/src/get_bundle_definitions.test.ts" => "deleted", + "${standardize(rootPath, false, true)}package.json" => "modified", + "${standardize(commonPath, false, true)}bundle.ts" => "modified", + "${standardize(commonPath, false, true)}bundles.ts" => "deleted", + "${standardize(srcPath, false, true)}get_bundle_definitions.test.ts" => "deleted", } `); }); diff --git a/packages/osd-optimizer/src/optimizer/get_plugin_bundles.test.ts b/packages/osd-optimizer/src/optimizer/get_plugin_bundles.test.ts index 70dc33569e0b..3b26660c6754 100644 --- a/packages/osd-optimizer/src/optimizer/get_plugin_bundles.test.ts +++ b/packages/osd-optimizer/src/optimizer/get_plugin_bundles.test.ts @@ -33,10 +33,15 @@ import { createAbsolutePathSerializer } from '@osd/dev-utils'; import { getPluginBundles } from './get_plugin_bundles'; +import path from 'path'; expect.addSnapshotSerializer(createAbsolutePathSerializer('/repo', '')); expect.addSnapshotSerializer(createAbsolutePathSerializer('/output', '')); +expect.addSnapshotSerializer(createAbsolutePathSerializer(path.resolve('/output'), '')); expect.addSnapshotSerializer(createAbsolutePathSerializer('/outside/of/repo', '')); +expect.addSnapshotSerializer( + createAbsolutePathSerializer(path.resolve('/outside/of/repo'), '') +); it('returns a bundle for core and each plugin', () => { expect( diff --git a/packages/osd-plugin-generator/src/integration_tests/generate_plugin.test.ts b/packages/osd-plugin-generator/src/integration_tests/generate_plugin.test.ts index b6ee3577bab3..714b26ff4cd0 100644 --- a/packages/osd-plugin-generator/src/integration_tests/generate_plugin.test.ts +++ b/packages/osd-plugin-generator/src/integration_tests/generate_plugin.test.ts @@ -34,13 +34,17 @@ import Path from 'path'; import del from 'del'; import execa from 'execa'; -import { REPO_ROOT } from '@osd/utils'; -import { createAbsolutePathSerializer } from '@osd/dev-utils'; +import { REPO_ROOT, standardize, createAbsolutePathSerializer } from '@osd/dev-utils'; import globby from 'globby'; -const GENERATED_DIR = Path.resolve(REPO_ROOT, `plugins`); +// Has to be a posix reference because it is used to generate glob patterns +const GENERATED_DIR = standardize(Path.resolve(REPO_ROOT, `plugins`), true); -expect.addSnapshotSerializer(createAbsolutePathSerializer()); +expect.addSnapshotSerializer( + createAbsolutePathSerializer( + process?.platform === 'win32' ? standardize(REPO_ROOT, true) : REPO_ROOT + ) +); beforeEach(async () => { await del([`${GENERATED_DIR}/**`, `!${GENERATED_DIR}`, `!${GENERATED_DIR}/.gitignore`], { diff --git a/packages/osd-plugin-helpers/package.json b/packages/osd-plugin-helpers/package.json index 1a8b86fbfea6..04dec1433633 100644 --- a/packages/osd-plugin-helpers/package.json +++ b/packages/osd-plugin-helpers/package.json @@ -12,7 +12,7 @@ "plugin-helpers": "bin/plugin-helpers.js" }, "scripts": { - "osd:bootstrap": "rm -rf target && tsc", + "osd:bootstrap": "node ../../scripts/remove.js && tsc", "osd:watch": "tsc --watch" }, "dependencies": { diff --git a/packages/osd-plugin-helpers/src/integration_tests/build.test.ts b/packages/osd-plugin-helpers/src/integration_tests/build.test.ts index fac2ec1b53e3..c41bec25f8e4 100644 --- a/packages/osd-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/osd-plugin-helpers/src/integration_tests/build.test.ts @@ -34,8 +34,12 @@ import Path from 'path'; import Fs from 'fs'; import execa from 'execa'; -import { REPO_ROOT } from '@osd/utils'; -import { createStripAnsiSerializer, createReplaceSerializer } from '@osd/dev-utils'; +import { + REPO_ROOT, + standardize, + createStripAnsiSerializer, + createReplaceSerializer, +} from '@osd/dev-utils'; import extract from 'extract-zip'; import del from 'del'; import globby from 'globby'; @@ -80,7 +84,7 @@ it('builds a generated plugin into a viable archive', async () => { expect(generateProc.all).toMatchInlineSnapshot(` " succ 🎉 - Your plugin has been created in plugins/foo_test_plugin + Your plugin has been created in ${standardize('plugins/foo_test_plugin', false, true)} " `); @@ -169,7 +173,7 @@ it('builds a non-semver generated plugin into a viable archive', async () => { expect(generateProc.all).toMatchInlineSnapshot(` " succ 🎉 - Your plugin has been created in plugins/foo_test_plugin + Your plugin has been created in ${standardize('plugins/foo_test_plugin', false, true)} " `); diff --git a/packages/osd-pm/src/utils/projects.test.ts b/packages/osd-pm/src/utils/projects.test.ts index f679facd3006..769f87e20610 100644 --- a/packages/osd-pm/src/utils/projects.test.ts +++ b/packages/osd-pm/src/utils/projects.test.ts @@ -55,7 +55,8 @@ describe('#getProjects', () => { await promisify(symlink)( join(__dirname, '__fixtures__/symlinked-plugins/corge'), - join(rootPlugins, 'corge') + join(rootPlugins, 'corge'), + 'junction' // This parameter would only be used on Windows ); }); diff --git a/packages/osd-pm/src/utils/projects_tree.ts b/packages/osd-pm/src/utils/projects_tree.ts index f8d8f20d6671..19c7d41ddee5 100644 --- a/packages/osd-pm/src/utils/projects_tree.ts +++ b/packages/osd-pm/src/utils/projects_tree.ts @@ -33,6 +33,7 @@ import chalk from 'chalk'; import path from 'path'; +import { standardize } from '@osd/utils'; import { Project } from './project'; const projectKey = Symbol('__project'); @@ -119,7 +120,7 @@ function createTreeStructure(tree: IProjectsTree): ITree { // `foo/bar/baz` instead. if (subtree.children && subtree.children.length === 1) { const child = subtree.children[0]; - const newName = chalk.dim(path.join(dir.toString(), child.name!)); + const newName = chalk.dim(standardize(path.join(dir.toString(), child.name!), true)); children.push({ children: child.children, diff --git a/packages/osd-telemetry-tools/src/tools/ts_parser.ts b/packages/osd-telemetry-tools/src/tools/ts_parser.ts index 1a902d0a5113..0010f0f0f103 100644 --- a/packages/osd-telemetry-tools/src/tools/ts_parser.ts +++ b/packages/osd-telemetry-tools/src/tools/ts_parser.ts @@ -33,7 +33,7 @@ import * as ts from 'typescript'; import { createFailError } from '@osd/dev-utils'; import * as path from 'path'; -import { getProperty, getPropertyValue } from './utils'; +import { getProperty, getPropertyValue, normalizePath } from './utils'; import { getDescriptor, Descriptor } from './serializer'; export function* traverseNodes(maybeNodes: ts.Node | ts.Node[]): Generator { @@ -207,7 +207,7 @@ export function* parseUsageCollection( sourceFile: ts.SourceFile, program: ts.Program ): Generator { - const relativePath = path.relative(process.cwd(), sourceFile.fileName); + const relativePath = normalizePath(path.relative(process.cwd(), sourceFile.fileName), false); if (sourceHasUsageCollector(sourceFile)) { for (const node of traverseNodes(sourceFile)) { if (isMakeUsageCollectorFunction(node, sourceFile)) { diff --git a/packages/osd-telemetry-tools/src/tools/utils.ts b/packages/osd-telemetry-tools/src/tools/utils.ts index d65e3431d1a6..a84504c8e565 100644 --- a/packages/osd-telemetry-tools/src/tools/utils.ts +++ b/packages/osd-telemetry-tools/src/tools/utils.ts @@ -313,6 +313,7 @@ export function difference(actual: any, expected: any) { return changes(actual, expected); } -export function normalizePath(inputPath: string) { - return normalize(path.relative('.', inputPath)); +export function normalizePath(inputPath: string, relativeToRoot: boolean = true) { + if (relativeToRoot) return normalize(path.relative('.', inputPath)); + return normalize(inputPath); } diff --git a/packages/osd-test/src/functional_test_runner/lib/suite_tracker.test.ts b/packages/osd-test/src/functional_test_runner/lib/suite_tracker.test.ts index 497ccd04c63c..abf76d6cad04 100644 --- a/packages/osd-test/src/functional_test_runner/lib/suite_tracker.test.ts +++ b/packages/osd-test/src/functional_test_runner/lib/suite_tracker.test.ts @@ -42,7 +42,7 @@ import { REPO_ROOT } from '@osd/dev-utils'; import { Lifecycle } from './lifecycle'; import { SuiteTracker } from './suite_tracker'; -const DEFAULT_TEST_METADATA_PATH = join(REPO_ROOT, 'target', 'test_metadata.json'); +const DEFAULT_TEST_METADATA_PATH = resolve(REPO_ROOT, 'target', 'test_metadata.json'); const MOCK_CONFIG_PATH = join('test', 'config.js'); const MOCK_TEST_PATH = join('test', 'apps', 'test.js'); const ENVS_TO_RESET = ['TEST_METADATA_PATH']; diff --git a/packages/osd-utils/src/path/index.ts b/packages/osd-utils/src/path/index.ts index 63837ece4f0f..ead39b29cd93 100644 --- a/packages/osd-utils/src/path/index.ts +++ b/packages/osd-utils/src/path/index.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { join } from 'path'; +import { join, normalize } from 'path'; import { accessSync, constants } from 'fs'; import { TypeOf, schema } from '@osd/config-schema'; import { REPO_ROOT } from '../repo_root'; @@ -96,3 +96,27 @@ export const config = { data: schema.string({ defaultValue: () => getDataPath() }), }), }; + +/** + * Get a standardized reference to a path + * @param {string} path - the path to standardize + * @param {boolean} [usePosix=true] - produce a posix reference + * @param {boolean} [escapedBackslashes=true] - on Windows, double-backslash the reference + * @internal + */ +export const standardize = ( + path: string, + usePosix: boolean = true, + escapedBackslashes: boolean = true +) => { + /* Force os-dependant separators + * path.posix.normalize doesn't convert backslashes to slashes on Windows so we manually force it afterwards + */ + const normal = normalize(path); + + // Filter out in-browser executions as well as non-windows ones + if (process.platform !== 'win32') return normal; + + if (usePosix) return normal.replace(/\\/g, '/'); + return escapedBackslashes ? normal.replace(/\\/g, '\\\\') : normal; +}; diff --git a/scripts/remove.js b/scripts/remove.js new file mode 100644 index 000000000000..cc3c62739371 --- /dev/null +++ b/scripts/remove.js @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/* eslint no-restricted-syntax: 0 */ +const del = require('del'); +const path = require('path'); + +if (!process.argv.includes(__filename)) { + console.error('Usage: node scripts/remove.js '); + process.exit(1); +} + +const toDeletes = process.argv + .slice(process.argv.indexOf(__filename + 1)) + .map((item) => path.resolve(item)); + +if (toDeletes.length === 0) { + console.warn('Nothing to delete'); + process.exit(0); +} + +(async () => { + const deletedPaths = await del(toDeletes); + if (deletedPaths === 0) { + console.warn('Nothing deleted'); + } else { + console.log('Deleted files and directories:\n\t', deletedPaths.join('\n\t')); + } +})(); diff --git a/src/cli_plugin/install/pack.test.js b/src/cli_plugin/install/pack.test.js index 2bf6e4db57c2..fd35178e0f8a 100644 --- a/src/cli_plugin/install/pack.test.js +++ b/src/cli_plugin/install/pack.test.js @@ -74,10 +74,11 @@ describe('opensearchDashboards cli', function () { Fs.mkdirSync(testWorkingPath, { recursive: true }); }); - afterEach(function () { + afterEach(async () => { logger.log.restore(); logger.error.restore(); - del.sync(workingPathRoot); + + await del(workingPathRoot); }); function copyReplyFile(filename) { diff --git a/src/cli_plugin/install/settings.js b/src/cli_plugin/install/settings.js index 0d4ca970923e..f7678dcf243e 100644 --- a/src/cli_plugin/install/settings.js +++ b/src/cli_plugin/install/settings.js @@ -46,10 +46,8 @@ function generateUrls({ version, plugin }) { function generatePluginUrl(version, plugin) { const platform = process.platform === 'win32' ? 'windows' : process.platform; const arch = process.arch === 'arm64' ? 'arm64' : 'x64'; - if (platform !== 'linux') { - throw new Error('Plugins are only available for Linux'); - } - return `${LATEST_PLUGIN_BASE_URL}/${version}/latest/${platform}/${arch}/builds/opensearch-dashboards/plugins/${plugin}-${version}.zip`; + + return `${LATEST_PLUGIN_BASE_URL}/${version}/latest/${platform}/${arch}/tar/builds/opensearch-dashboards/plugins/${plugin}-${version}.zip`; } export function parseMilliseconds(val) { diff --git a/src/cli_plugin/install/settings.test.js b/src/cli_plugin/install/settings.test.js index 63375dd18723..ea2395e4a4ff 100644 --- a/src/cli_plugin/install/settings.test.js +++ b/src/cli_plugin/install/settings.test.js @@ -96,7 +96,7 @@ describe('parse function', function () { "timeout": 0, "urls": Array [ "plugin name", - "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/x64/builds/opensearch-dashboards/plugins/plugin name-1234.zip", + "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/x64/tar/builds/opensearch-dashboards/plugins/plugin name-1234.zip", ], "version": 1234, "workingPath": /plugins/.plugin.installing, @@ -131,7 +131,7 @@ describe('parse function', function () { "timeout": 0, "urls": Array [ "plugin name", - "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/x64/builds/opensearch-dashboards/plugins/plugin name-1234.zip", + "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/x64/tar/builds/opensearch-dashboards/plugins/plugin name-1234.zip", ], "version": 1234, "workingPath": /plugins/.plugin.installing, @@ -139,7 +139,7 @@ describe('parse function', function () { `); }); - it('should throw when on a non-Linux platform', function () { + it('produces expected results on Windows', function () { Object.defineProperties(process, { platform: { value: 'win32', @@ -148,9 +148,23 @@ describe('parse function', function () { value: 'x64', }, }); - expect(() => parse(command, { ...defaultOptions }, osdPackage)).toThrow( - 'Plugins are only available for Linux' - ); + expect(parse(command, { ...defaultOptions }, osdPackage)).toMatchInlineSnapshot(` + Object { + "config": "", + "plugin": "plugin name", + "pluginDir": /plugins, + "quiet": false, + "silent": false, + "tempArchiveFile": /plugins/.plugin.installing/archive.part, + "timeout": 0, + "urls": Array [ + "plugin name", + "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/windows/x64/tar/builds/opensearch-dashboards/plugins/plugin name-1234.zip", + ], + "version": 1234, + "workingPath": /plugins/.plugin.installing, + } + `); }); it('should not throw when on a non-x64 arch', function () { @@ -173,7 +187,7 @@ describe('parse function', function () { "timeout": 0, "urls": Array [ "plugin name", - "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/arm64/builds/opensearch-dashboards/plugins/plugin name-1234.zip", + "https://ci.opensearch.org/ci/dbc/distribution-build-opensearch-dashboards/1234/latest/linux/arm64/tar/builds/opensearch-dashboards/plugins/plugin name-1234.zip", ], "version": 1234, "workingPath": /plugins/.plugin.installing, diff --git a/src/cli_plugin/install/zip.test.js b/src/cli_plugin/install/zip.test.js index 579bc024b798..fdc2cb086df9 100644 --- a/src/cli_plugin/install/zip.test.js +++ b/src/cli_plugin/install/zip.test.js @@ -50,8 +50,8 @@ describe('opensearchDashboards cli', function () { tempPath = path.resolve(os.tmpdir(), randomDir); }); - afterEach(() => { - del.sync(tempPath, { force: true }); + afterEach(async () => { + await del(tempPath, { force: true }); }); describe('analyzeArchive', function () { diff --git a/src/core/server/metrics/collectors/cgroup.test.ts b/src/core/server/metrics/collectors/cgroup.test.ts index b665e33cfb62..18b5f7aa9900 100644 --- a/src/core/server/metrics/collectors/cgroup.test.ts +++ b/src/core/server/metrics/collectors/cgroup.test.ts @@ -28,6 +28,7 @@ import mockFs from 'mock-fs'; import { loggerMock } from '@osd/logging/target/mocks'; import { OsCgroupMetricsCollector } from './cgroup'; +import path from 'path'; describe('OsCgroupMetricsCollector', () => { afterEach(() => mockFs.restore()); @@ -137,10 +138,14 @@ throttled_time 666 const logger = loggerMock.create(); + const usagePath = + (process.platform === 'win32' ? '\\\\?\\' : '') + + path.resolve('/sys/fs/cgroup/cpuacct/groupname/cpuacct.usage'); + const collector = new OsCgroupMetricsCollector({ logger }); expect(await collector.collect()).toEqual({}); expect(logger.error).toHaveBeenCalledWith( - "cgroup metrics could not be read due to error: [Error: EACCES, permission denied '/sys/fs/cgroup/cpuacct/groupname/cpuacct.usage']" + `cgroup metrics could not be read due to error: [Error: EACCES, permission denied '${usagePath}']` ); }); }); diff --git a/src/core/server/plugins/discovery/plugins_discovery.test.ts b/src/core/server/plugins/discovery/plugins_discovery.test.ts index a672ba3aee15..9e1186744e6f 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.test.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.test.ts @@ -46,6 +46,7 @@ import { discover } from './plugins_discovery'; import { CoreContext } from '../../core_context'; const OPENSEARCH_DASHBOARDS_ROOT = process.cwd(); +const EXTENDED_PATH_PREFIX = process.platform === 'win32' ? '\\\\?\\' : ''; const Plugins = { invalid: () => ({ @@ -245,7 +246,7 @@ describe('plugins discovery system', () => { const srcPluginsPath = resolve(OPENSEARCH_DASHBOARDS_ROOT, 'src', 'plugins'); expect(errors).toEqual( expect.arrayContaining([ - `Error: EACCES, permission denied '${srcPluginsPath}' (invalid-search-path, ${srcPluginsPath})`, + `Error: EACCES, permission denied '${EXTENDED_PATH_PREFIX}${srcPluginsPath}' (invalid-search-path, ${srcPluginsPath})`, ]) ); }); @@ -280,7 +281,7 @@ describe('plugins discovery system', () => { const errorPath = manifestPath('plugin_a'); expect(errors).toEqual( expect.arrayContaining([ - `Error: EACCES, permission denied '${errorPath}' (missing-manifest, ${errorPath})`, + `Error: EACCES, permission denied '${EXTENDED_PATH_PREFIX}${errorPath}' (missing-manifest, ${errorPath})`, ]) ); }); diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.ts b/src/core/server/plugins/integration_tests/plugins_service.test.ts index 9d78829190c6..75eeb7ec6862 100644 --- a/src/core/server/plugins/integration_tests/plugins_service.test.ts +++ b/src/core/server/plugins/integration_tests/plugins_service.test.ts @@ -34,7 +34,7 @@ import { REPO_ROOT } from '@osd/dev-utils'; import { mockPackage, mockDiscover } from './plugins_service.test.mocks'; -import { join } from 'path'; +import { posix } from 'path'; import { PluginsService } from '../plugins_service'; import { ConfigPath, ConfigService, Env } from '../../config'; @@ -165,7 +165,7 @@ describe('PluginsService', () => { } as Plugin); jest.doMock( - join(pluginPath, 'server'), + posix.join(pluginPath, 'server'), () => ({ plugin: pluginInitializer, }), diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 040f7c247aad..22c09ab4feb4 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { join } from 'path'; +import { posix } from 'path'; import { BehaviorSubject } from 'rxjs'; import { REPO_ROOT } from '@osd/dev-utils'; import { schema } from '@osd/config-schema'; @@ -49,6 +49,7 @@ import { InstanceInfo, } from './plugin_context'; +const { join } = posix; const mockPluginInitializer = jest.fn(); const logger = loggingSystemMock.create(); jest.doMock( diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index d7bb9daff28b..48ed6e4beb07 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { join } from 'path'; +import { posix } from 'path'; import typeDetect from 'type-detect'; import { Subject } from 'rxjs'; import { first } from 'rxjs/operators'; @@ -47,6 +47,8 @@ import { } from './types'; import { CoreSetup, CoreStart } from '..'; +const { join } = posix; + /** * Lightweight wrapper around discovered plugin that is responsible for instantiating * plugin and dispatching proper context and dependencies into plugin's lifecycle hooks. diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index 49d0196a398b..1c6f729600f3 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -32,7 +32,7 @@ import { mockDiscover, mockPackage } from './plugins_service.test.mocks'; -import { resolve, join } from 'path'; +import { resolve, posix } from 'path'; import { BehaviorSubject, from } from 'rxjs'; import { schema } from '@osd/config-schema'; import { createAbsolutePathSerializer, REPO_ROOT } from '@osd/dev-utils'; @@ -50,6 +50,7 @@ import { config } from './plugins_config'; import { take } from 'rxjs/operators'; import { DiscoveredPlugin } from './types'; +const { join } = posix; const MockPluginsSystem: jest.Mock = PluginsSystem as any; let pluginsService: PluginsService; diff --git a/src/dev/build/args.test.ts b/src/dev/build/args.test.ts index 5eedbfade448..071e7d3c3d07 100644 --- a/src/dev/build/args.test.ts +++ b/src/dev/build/args.test.ts @@ -59,6 +59,7 @@ it('build dist for current platform, without packages, by default', () => { "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -87,6 +88,7 @@ it('build dist for linux x64 platform, without packages, if --linux is passed', "darwin": false, "linux": true, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -115,6 +117,7 @@ it('build dist for linux arm64 platform, without packages, if --linux-arm is pas "darwin": false, "linux": false, "linuxArm": true, + "windows": false, }, "versionQualifier": "", }, @@ -143,6 +146,36 @@ it('build dist for darwin x64 platform, without packages, if --darwin is passed' "darwin": true, "linux": false, "linuxArm": false, + "windows": false, + }, + "versionQualifier": "", + }, + "log": , + "showHelp": false, + "unknownFlags": Array [], + } + `); +}); + +it('build dist for windows x64 platform, without packages, if --windows is passed', () => { + expect(readCliArgs(['node', 'scripts/build-platform', '--windows'])).toMatchInlineSnapshot(` + Object { + "buildOptions": Object { + "createArchives": true, + "createDebArmPackage": false, + "createDebPackage": false, + "createDockerPackage": false, + "createDockerUbiPackage": false, + "createRpmArmPackage": false, + "createRpmPackage": false, + "downloadFreshNode": true, + "isRelease": false, + "targetAllPlatforms": false, + "targetPlatforms": Object { + "darwin": false, + "linux": false, + "linuxArm": false, + "windows": true, }, "versionQualifier": "", }, @@ -171,6 +204,7 @@ it('builds packages if --all-platforms is passed', () => { "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -199,6 +233,7 @@ it('limits packages if --rpm passed with --all-platforms', () => { "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -227,6 +262,7 @@ it('limits packages if --deb passed with --all-platforms', () => { "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -256,6 +292,7 @@ it('limits packages if --docker passed with --all-platforms', () => { "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, @@ -285,6 +322,7 @@ it('limits packages if --docker passed with --skip-docker-ubi and --all-platform "darwin": false, "linux": false, "linuxArm": false, + "windows": false, }, "versionQualifier": "", }, diff --git a/src/dev/build/args.ts b/src/dev/build/args.ts index c00ccec07e4d..47112bd6f176 100644 --- a/src/dev/build/args.ts +++ b/src/dev/build/args.ts @@ -47,6 +47,7 @@ export function readCliArgs(argv: string[]) { 'verbose', 'debug', 'all-platforms', + 'windows', 'darwin', 'linux', 'linux-arm', @@ -127,6 +128,7 @@ export function readCliArgs(argv: string[]) { createDockerPackage: isOsPackageDesired('docker'), createDockerUbiPackage: isOsPackageDesired('docker') && !Boolean(flags['skip-docker-ubi']), targetPlatforms: { + windows: Boolean(flags.windows), darwin: Boolean(flags.darwin), linux: Boolean(flags.linux), linuxArm: Boolean(flags['linux-arm']), diff --git a/src/dev/build/cli.ts b/src/dev/build/cli.ts index 6ae03c0cab43..15bbeecd1e4e 100644 --- a/src/dev/build/cli.ts +++ b/src/dev/build/cli.ts @@ -55,9 +55,10 @@ if (showHelp) { --skip-archives {dim Don't produce tar/zip archives} --skip-os-packages {dim Don't produce rpm/deb/docker packages} --all-platforms {dim Produce archives for all platforms, not just this one} - --linux {dim Produce archives for only linux x64 platform} - --linux-arm {dim Produce archives for only linux arm64 platform} - --darwin {dim Produce archives for only darwin x64 platform} + --linux {dim Produce archives only for linux x64 platform} + --linux-arm {dim Produce archives only for linux arm64 platform} + --darwin {dim Produce archives only for darwin x64 platform} + --windows {dim Produce archives only for windows x64 platform} --rpm {dim Only build the rpm package} --deb {dim Only build the deb package} --docker {dim Only build the docker image} diff --git a/src/dev/build/lib/config.test.ts b/src/dev/build/lib/config.test.ts index 077076b58c01..4e34699da9fc 100644 --- a/src/dev/build/lib/config.test.ts +++ b/src/dev/build/lib/config.test.ts @@ -27,7 +27,7 @@ import { resolve } from 'path'; -import { REPO_ROOT } from '@osd/utils'; +import { REPO_ROOT, standardize } from '@osd/utils'; import { createAbsolutePathSerializer } from '@osd/dev-utils'; import pkg from '../../../../package.json'; @@ -51,6 +51,7 @@ const setup = async ({ darwin: false, linux: false, linuxArm: false, + windows: false, }, }: { targetAllPlatforms?: boolean; @@ -58,6 +59,7 @@ const setup = async ({ darwin: boolean; linux: boolean; linuxArm: boolean; + windows: boolean; }; } = {}) => { return await Config.create({ @@ -84,7 +86,9 @@ describe('#getNodeVersion()', () => { describe('#getRepoRelativePath()', () => { it('converts an absolute path to relative path, from the root of the repo', async () => { const config = await setup(); - expect(config.getRepoRelativePath(__dirname)).toMatchInlineSnapshot(`"src/dev/build/lib"`); + expect(config.getRepoRelativePath(__dirname)).toMatchInlineSnapshot( + `"${standardize('src/dev/build/lib', false, true)}"` + ); }); }); @@ -112,6 +116,7 @@ describe('#hasSpecifiedPlatform', () => { darwin: true, linux: false, linuxArm: false, + windows: false, }, }); expect(config.hasSpecifiedPlatform() === true); @@ -124,6 +129,7 @@ describe('#hasSpecifiedPlatform', () => { darwin: false, linux: false, linuxArm: true, + windows: false, }, }); expect(config.hasSpecifiedPlatform() === true); @@ -136,6 +142,7 @@ describe('#hasSpecifiedPlatform', () => { darwin: false, linux: true, linuxArm: false, + windows: false, }, }); expect(config.hasSpecifiedPlatform() === true); @@ -202,6 +209,7 @@ describe('#getTargetPlatforms()', () => { darwin: true, linux: false, linuxArm: false, + windows: false, }, }); @@ -224,6 +232,7 @@ describe('#getTargetPlatforms()', () => { darwin: false, linux: true, linuxArm: false, + windows: false, }, }); @@ -246,6 +255,7 @@ describe('#getTargetPlatforms()', () => { darwin: false, linux: false, linuxArm: true, + windows: false, }, }); @@ -268,6 +278,7 @@ describe('#getTargetPlatforms()', () => { darwin: true, linux: false, linuxArm: true, + windows: false, }, }); diff --git a/src/dev/build/lib/config.ts b/src/dev/build/lib/config.ts index 1abaad734140..d8011628f61a 100644 --- a/src/dev/build/lib/config.ts +++ b/src/dev/build/lib/config.ts @@ -140,6 +140,7 @@ export class Config { const platforms: Platform[] = []; if (this.targetPlatforms.darwin) platforms.push(this.getPlatform('darwin', 'x64')); if (this.targetPlatforms.linux) platforms.push(this.getPlatform('linux', 'x64')); + if (this.targetPlatforms.windows) platforms.push(this.getPlatform('win32', 'x64')); if (this.targetPlatforms.linuxArm) platforms.push(this.getPlatform('linux', 'arm64')); if (platforms.length > 0) return platforms; @@ -150,7 +151,7 @@ export class Config { /** * Return the list of Platforms we need/have node downloads for. We always * include the linux platform even if we aren't targeting linux so we can - * reliably get the LICENSE file, which isn't included in the windows version + * reliably get the LICENSE file. */ getNodePlatforms() { if (this.targetAllPlatforms) { @@ -161,6 +162,7 @@ export class Config { return [this.getPlatform('linux', 'x64')]; } + // ToDo: All node dists, including Windows, contain a LICENSE file; do we still need to do this? return [this.getPlatformForThisOs(), this.getPlatform('linux', 'x64')]; } diff --git a/src/dev/build/lib/exec.test.ts b/src/dev/build/lib/exec.test.ts index 67830ffe48a4..e60748616db9 100644 --- a/src/dev/build/lib/exec.test.ts +++ b/src/dev/build/lib/exec.test.ts @@ -36,6 +36,8 @@ import { import { exec } from './exec'; +const escapedPathToNode = Path.sep === '\\' ? '\\\\node.exe' : '/node'; + const testWriter = new ToolingLogCollectingWriter(); const log = new ToolingLog(); log.setWriters([testWriter]); @@ -56,7 +58,7 @@ it('executes a command, logs the command, and logs the output', async () => { await exec(log, process.execPath, ['-e', 'console.log("hi")']); expect(testWriter.messages).toMatchInlineSnapshot(` Array [ - " debg $ /node -e console.log(\\"hi\\")", + " debg $ ${escapedPathToNode} -e console.log(\\"hi\\")", " debg hi", ] `); @@ -68,7 +70,7 @@ it('logs using level: option', async () => { }); expect(testWriter.messages).toMatchInlineSnapshot(` Array [ - " info $ /node -e console.log(\\"hi\\")", + " info $ ${escapedPathToNode} -e console.log(\\"hi\\")", " info hi", ] `); diff --git a/src/dev/build/lib/fs.ts b/src/dev/build/lib/fs.ts index 16b682b53f17..0b735e8d9462 100644 --- a/src/dev/build/lib/fs.ts +++ b/src/dev/build/lib/fs.ts @@ -33,6 +33,7 @@ import { createGunzip } from 'zlib'; import { inspect, promisify } from 'util'; import archiver from 'archiver'; +import * as StreamZip from 'node-stream-zip'; import vfs from 'vinyl-fs'; import File from 'vinyl'; import del from 'del'; @@ -180,7 +181,7 @@ export async function copyAll( destination: string, options: CopyAllOptions = {} ) { - const { select = ['**/*'], dot = false, time = Date.now() } = options; + const { select = ['**/*'], dot = false, time = Date.now() / 1000 } = options; assertAbsolute(sourceDir); assertAbsolute(destination); @@ -263,6 +264,38 @@ export async function gunzip(source: string, destination: string) { ); } +interface UnzipOptions { + strip?: boolean | number; +} + +export async function unzip(source: string, destination: string, options: UnzipOptions) { + assertAbsolute(source); + assertAbsolute(destination); + + await mkdirAsync(destination, { recursive: true }); + + const zip = new StreamZip.async({ file: source }); + + if (!options.strip || !isFinite(options.strip as number)) { + // Extract the entire archive + await zip.extract(null, destination); + } else { + const stripLevels = options.strip === true ? 1 : options.strip; + + // Find the directories that are `stripLevels` deep and extract them only + for (const entry of Object.values(await zip.entries())) { + if (!entry.isDirectory) continue; + + const pathDepth = entry.name.replace(/\/+$/, '').split('/').length; + if (stripLevels === pathDepth) { + await zip.extract(entry.name, destination); + } + } + } + + await zip.close(); +} + interface CompressTarOptions { createRootDirectory: boolean; source: string; @@ -322,3 +355,7 @@ export async function compressZip({ return fileCount; } + +export function normalizePath(loc: string) { + return sep === '\\' ? loc.replace(/\\/g, '/') : loc; +} diff --git a/src/dev/build/lib/platform.ts b/src/dev/build/lib/platform.ts index 349cb094fdba..57c192295a22 100644 --- a/src/dev/build/lib/platform.ts +++ b/src/dev/build/lib/platform.ts @@ -32,6 +32,7 @@ export interface TargetPlatforms { darwin: boolean; linuxArm: boolean; linux: boolean; + windows: boolean; } export class Platform { diff --git a/src/dev/build/tasks/clean_tasks.ts b/src/dev/build/tasks/clean_tasks.ts index 11c6188821bc..93602ff30f0e 100644 --- a/src/dev/build/tasks/clean_tasks.ts +++ b/src/dev/build/tasks/clean_tasks.ts @@ -27,7 +27,7 @@ import minimatch from 'minimatch'; -import { deleteAll, deleteEmptyFolders, scanDelete, Task, GlobalTask } from '../lib'; +import { deleteAll, deleteEmptyFolders, scanDelete, Task, GlobalTask, normalizePath } from '../lib'; export const Clean: GlobalTask = { global: true, @@ -187,8 +187,8 @@ export const CleanExtraBinScripts: Task = { if (platform.isWindows()) { await deleteAll( [ - build.resolvePathForPlatform(platform, 'bin', '*'), - `!${build.resolvePathForPlatform(platform, 'bin', '*.bat')}`, + normalizePath(build.resolvePathForPlatform(platform, 'bin', '*')), + `!${normalizePath(build.resolvePathForPlatform(platform, 'bin', '*.bat'))}`, ], log ); diff --git a/src/dev/build/tasks/nodejs/clean_node_builds_task.ts b/src/dev/build/tasks/nodejs/clean_node_builds_task.ts index 871f61d51402..1e37ff1f6b6b 100644 --- a/src/dev/build/tasks/nodejs/clean_node_builds_task.ts +++ b/src/dev/build/tasks/nodejs/clean_node_builds_task.ts @@ -25,7 +25,7 @@ * under the License. */ -import { deleteAll, Task } from '../../lib'; +import { deleteAll, normalizePath, Task } from '../../lib'; export const CleanNodeBuilds: Task = { description: 'Cleaning npm from node', @@ -34,9 +34,11 @@ export const CleanNodeBuilds: Task = { for (const platform of config.getTargetPlatforms()) { await deleteAll( [ - build.resolvePathForPlatform(platform, 'node/lib/node_modules'), - build.resolvePathForPlatform(platform, 'node/bin/npm'), - build.resolvePathForPlatform(platform, 'node/bin/npx'), + normalizePath(build.resolvePathForPlatform(platform, 'node/**/node_modules')), + normalizePath(build.resolvePathForPlatform(platform, 'node/**/npm*')), + normalizePath(build.resolvePathForPlatform(platform, 'node/**/npx*')), + normalizePath(build.resolvePathForPlatform(platform, 'node/**/corepack*')), + normalizePath(build.resolvePathForPlatform(platform, 'node/**/nodevars*')), ], log ); diff --git a/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts b/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts index 4ba942f9fb18..6c8cb9365cd0 100644 --- a/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts +++ b/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts @@ -66,6 +66,7 @@ async function setup() { linux: false, linuxArm: false, darwin: false, + windows: false, }, }); @@ -98,15 +99,6 @@ it('runs expected fs operations', async () => { expect(usedMethods).toMatchInlineSnapshot(` Object { - "copy": Array [ - Array [ - /.node_binaries//node.exe, - /.node_binaries//win32-x64/node.exe, - Object { - "clone": true, - }, - ], - ], "untar": Array [ Array [ /.node_binaries//node-v-linux-x64.tar.gz, @@ -130,6 +122,15 @@ it('runs expected fs operations', async () => { }, ], ], + "unzip": Array [ + Array [ + /.node_binaries//node-v-win-x64.zip, + /.node_binaries//win32-x64, + Object { + "strip": 1, + }, + ], + ], } `); }); diff --git a/src/dev/build/tasks/nodejs/extract_node_builds_task.ts b/src/dev/build/tasks/nodejs/extract_node_builds_task.ts index 6bb5fef4ec0e..9d9fed13a84b 100644 --- a/src/dev/build/tasks/nodejs/extract_node_builds_task.ts +++ b/src/dev/build/tasks/nodejs/extract_node_builds_task.ts @@ -25,9 +25,7 @@ * under the License. */ -import Path from 'path'; - -import { untar, GlobalTask, copy } from '../../lib'; +import { untar, unzip, GlobalTask } from '../../lib'; import { getNodeDownloadInfo } from './node_download_info'; export const ExtractNodeBuilds: GlobalTask = { @@ -38,10 +36,7 @@ export const ExtractNodeBuilds: GlobalTask = { config.getTargetPlatforms().map(async (platform) => { const { downloadPath, extractDir } = getNodeDownloadInfo(config, platform); if (platform.isWindows()) { - // windows executable is not extractable, it's just an .exe file - await copy(downloadPath, Path.resolve(extractDir, 'node.exe'), { - clone: true, - }); + await unzip(downloadPath, extractDir, { strip: 1 }); } else { await untar(downloadPath, extractDir, { strip: 1 }); } diff --git a/src/dev/build/tasks/nodejs/node_download_info.ts b/src/dev/build/tasks/nodejs/node_download_info.ts index 52f2d140f875..b55f46d767ee 100644 --- a/src/dev/build/tasks/nodejs/node_download_info.ts +++ b/src/dev/build/tasks/nodejs/node_download_info.ts @@ -34,7 +34,7 @@ export function getNodeDownloadInfo(config: Config, platform: Platform) { const arch = platform.getNodeArch(); const downloadName = platform.isWindows() - ? 'win-x64/node.exe' + ? `node-v${version}-win-x64.zip` : `node-v${version}-${arch}.tar.gz`; const url = `https://nodejs.org/dist/v${version}/${downloadName}`; diff --git a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts index 74500a6208a8..ad6b198f5694 100644 --- a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts +++ b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts @@ -53,8 +53,15 @@ describe('telemetry_usage_collector', () => { unreadable: resolve(tempDir, 'tests-telemetry_usage_collector-unreadable.yml'), valid: resolve(tempDir, 'telemetry.yml'), }; - const invalidFiles = [tempFiles.too_big, tempFiles.unreadable]; + const invalidFiles = [tempFiles.too_big]; const validFiles = [tempFiles.blank, tempFiles.empty, tempFiles.valid]; + // Windows cannot create the `unreadable` file as unreadable + if (process.platform === 'win32') { + validFiles.push(tempFiles.unreadable); + } else { + invalidFiles.push(tempFiles.unreadable); + } + const allFiles = Object.values(tempFiles); const expectedObject = { expected: 'value', @@ -100,7 +107,7 @@ describe('telemetry_usage_collector', () => { }); test('returns `true` file that has valid data', async () => { - expect(allFiles.filter(isFileReadable)).toEqual(validFiles); + expect(allFiles.filter(isFileReadable).sort()).toEqual(validFiles.sort()); }); }); diff --git a/src/plugins/url_forwarding/public/forward_app/normalize_path.ts b/src/plugins/url_forwarding/public/forward_app/normalize_path.ts index d2f51a410d7f..968de44a1dbc 100644 --- a/src/plugins/url_forwarding/public/forward_app/normalize_path.ts +++ b/src/plugins/url_forwarding/public/forward_app/normalize_path.ts @@ -30,11 +30,13 @@ * GitHub history for details. */ -import { normalize } from 'path'; +import { normalize, posix } from 'path'; export function normalizePath(path: string) { + // `normalize` in path-browserify is an implementation of `posix.normalize` + const normalizeFunc = posix?.normalize || normalize; // resolve ../ within the path - const normalizedPath = normalize(path); + const normalizedPath = normalizeFunc(path); // strip any leading slashes and dots and replace with single leading slash return normalizedPath.replace(/(\.?\.?\/?)*/, '/'); } diff --git a/test/interpreter_functional/plugins/osd_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/osd_tp_run_pipeline/package.json index f1d3a39bc562..442778a7b9df 100644 --- a/test/interpreter_functional/plugins/osd_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/osd_tp_run_pipeline/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "@elastic/eui": "29.3.2", diff --git a/test/plugin_functional/plugins/app_link_test/package.json b/test/plugin_functional/plugins/app_link_test/package.json index 8b28e62e31b7..dd07b4de638c 100644 --- a/test/plugin_functional/plugins/app_link_test/package.json +++ b/test/plugin_functional/plugins/app_link_test/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_app_status/package.json b/test/plugin_functional/plugins/core_app_status/package.json index 0304da467b46..524e33d8dfb2 100644 --- a/test/plugin_functional/plugins/core_app_status/package.json +++ b/test/plugin_functional/plugins/core_app_status/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_a/package.json b/test/plugin_functional/plugins/core_plugin_a/package.json index 53ea6306f2a1..b57d5783c77e 100644 --- a/test/plugin_functional/plugins/core_plugin_a/package.json +++ b/test/plugin_functional/plugins/core_plugin_a/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_appleave/package.json b/test/plugin_functional/plugins/core_plugin_appleave/package.json index 69e7caea397e..5caa1a70f8d2 100644 --- a/test/plugin_functional/plugins/core_plugin_appleave/package.json +++ b/test/plugin_functional/plugins/core_plugin_appleave/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_b/package.json b/test/plugin_functional/plugins/core_plugin_b/package.json index 56ec66f867f8..d37ffd582e6d 100644 --- a/test/plugin_functional/plugins/core_plugin_b/package.json +++ b/test/plugin_functional/plugins/core_plugin_b/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_chromeless/package.json b/test/plugin_functional/plugins/core_plugin_chromeless/package.json index 33a247924d08..0c444aaf80ca 100644 --- a/test/plugin_functional/plugins/core_plugin_chromeless/package.json +++ b/test/plugin_functional/plugins/core_plugin_chromeless/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_route_timeouts/package.json b/test/plugin_functional/plugins/core_plugin_route_timeouts/package.json index 974d9398dd65..1b03b60ad387 100644 --- a/test/plugin_functional/plugins/core_plugin_route_timeouts/package.json +++ b/test/plugin_functional/plugins/core_plugin_route_timeouts/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/package.json b/test/plugin_functional/plugins/core_plugin_static_assets/package.json index 5b50b579549b..e44a09af12cb 100644 --- a/test/plugin_functional/plugins/core_plugin_static_assets/package.json +++ b/test/plugin_functional/plugins/core_plugin_static_assets/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/core_provider_plugin/package.json b/test/plugin_functional/plugins/core_provider_plugin/package.json index 068d9b0e638d..778d9363e71d 100644 --- a/test/plugin_functional/plugins/core_provider_plugin/package.json +++ b/test/plugin_functional/plugins/core_provider_plugin/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/data_search/package.json b/test/plugin_functional/plugins/data_search/package.json index fcd6ba5260f4..056a79f2139a 100644 --- a/test/plugin_functional/plugins/data_search/package.json +++ b/test/plugin_functional/plugins/data_search/package.json @@ -7,7 +7,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/doc_views_plugin/package.json b/test/plugin_functional/plugins/doc_views_plugin/package.json index 4f0aa8b8ae45..67018cec9d95 100644 --- a/test/plugin_functional/plugins/doc_views_plugin/package.json +++ b/test/plugin_functional/plugins/doc_views_plugin/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/index_patterns/package.json b/test/plugin_functional/plugins/index_patterns/package.json index 114131058ece..3b88f3bf3932 100644 --- a/test/plugin_functional/plugins/index_patterns/package.json +++ b/test/plugin_functional/plugins/index_patterns/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/management_test_plugin/package.json b/test/plugin_functional/plugins/management_test_plugin/package.json index cd0b7eb62b8d..b20971f403aa 100644 --- a/test/plugin_functional/plugins/management_test_plugin/package.json +++ b/test/plugin_functional/plugins/management_test_plugin/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/opensearch_client_plugin/package.json b/test/plugin_functional/plugins/opensearch_client_plugin/package.json index fc7aab14306b..77d31a85f8f5 100644 --- a/test/plugin_functional/plugins/opensearch_client_plugin/package.json +++ b/test/plugin_functional/plugins/opensearch_client_plugin/package.json @@ -7,7 +7,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/osd_sample_panel_action/package.json b/test/plugin_functional/plugins/osd_sample_panel_action/package.json index 5a923a056232..afb904c8e2d7 100644 --- a/test/plugin_functional/plugins/osd_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/osd_sample_panel_action/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "@elastic/eui": "29.3.2", diff --git a/test/plugin_functional/plugins/osd_top_nav/package.json b/test/plugin_functional/plugins/osd_top_nav/package.json index 49076bfe6261..a1a244da27cd 100644 --- a/test/plugin_functional/plugins/osd_top_nav/package.json +++ b/test/plugin_functional/plugins/osd_top_nav/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/osd_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/osd_tp_custom_visualizations/package.json index 041cef8a32ac..7e49a188da55 100644 --- a/test/plugin_functional/plugins/osd_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/osd_tp_custom_visualizations/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "@elastic/eui": "29.3.2", diff --git a/test/plugin_functional/plugins/rendering_plugin/package.json b/test/plugin_functional/plugins/rendering_plugin/package.json index bb651872f1aa..2548cfef508e 100644 --- a/test/plugin_functional/plugins/rendering_plugin/package.json +++ b/test/plugin_functional/plugins/rendering_plugin/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/test/plugin_functional/plugins/ui_settings_plugin/package.json b/test/plugin_functional/plugins/ui_settings_plugin/package.json index f167bfc69946..db9bedec26d0 100644 --- a/test/plugin_functional/plugins/ui_settings_plugin/package.json +++ b/test/plugin_functional/plugins/ui_settings_plugin/package.json @@ -9,7 +9,7 @@ "license": "Apache-2.0", "scripts": { "osd": "node ../../../../scripts/osd.js", - "build": "rm -rf './target' && tsc" + "build": "node ../../scripts/remove.js './target' && tsc" }, "devDependencies": { "typescript": "4.0.2" diff --git a/yarn.lock b/yarn.lock index dcbf9d4c404b..1c6837ebf5af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14838,7 +14838,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2, minimatch@~3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@3.0.x, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@~3.0.2, minimatch@~3.0.4: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -15436,6 +15436,11 @@ node-status-codes@^1.0.0: resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" integrity sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8= +node-stream-zip@^1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" + integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== + nopt@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-2.2.1.tgz#2aa09b7d1768487b3b89a9c5aa52335bff0baea7" @@ -19054,7 +19059,7 @@ sisteransi@^1.0.0: slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== slash@^2.0.0: version "2.0.0"