Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v3] Plugin registry field #2189

Merged
merged 28 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3684c04
resolved bug which resulted in plugins always containing the same pub…
jace-roell Jul 2, 2024
3c18197
add changelog
jace-roell Jul 2, 2024
039cf08
consolidated changelog for automation requirements
jace-roell Jul 2, 2024
cdea0da
removed unused variable
jace-roell Jul 2, 2024
5035b16
added getScopeRegistry() unit test
jace-roell Jul 2, 2024
e4dc68c
update
jace-roell Jul 2, 2024
c8631fb
unused variable
jace-roell Jul 2, 2024
1c339aa
removed test case
jace-roell Jul 2, 2024
815a9c6
Merge branch 'next' into plugin-registry-field
jace-roell Jul 2, 2024
115a2fb
changelog
jace-roell Jul 2, 2024
4c6f6d9
rename registry to location
jace-roell Jul 2, 2024
799460e
getScopeRegistry() unit test
jace-roell Jul 2, 2024
9c0795c
added awai to funciton mock
jace-roell Jul 2, 2024
0078fc1
integration tests (wip)
jace-roell Jul 3, 2024
f89eff1
resolving integration tests
jace-roell Jul 3, 2024
3886533
check if installRegistry is already declared before setting value
jace-roell Jul 8, 2024
46d1649
added ';'
jace-roell Jul 8, 2024
a9ea9fc
lint fixes
jace-roell Jul 8, 2024
0afeb95
added handling for undefined scope registry inside of getScopeRegistry()
jace-roell Jul 9, 2024
60240e2
fixed changelog
jace-roell Jul 9, 2024
1ed51d7
modified location testing type to be a function
jace-roell Jul 10, 2024
60fb21f
Merge branch 'next' into plugin-registry-field
jace-roell Jul 11, 2024
b1ac4ec
added backward compatibility for plugins installed on previous versio…
jace-roell Jul 12, 2024
bbd63dd
Merge branch 'next' into plugin-registry-field
jace-roell Jul 12, 2024
7565b08
Revert "added backward compatibility for plugins installed on previou…
jace-roell Jul 16, 2024
809ba84
fixed integration test update, refactored plugin list display
jace-roell Jul 16, 2024
f9b6099
removed snapshot update
jace-roell Jul 17, 2024
570b713
updated snapshots
jace-roell Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
/* eslint-disable max-len */

describe("Imperative Secure Tests", () => {
require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest");
require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest");
require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest");
require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest");
require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest");
require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest");
require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest");
Expand Down
6 changes: 6 additions & 0 deletions packages/imperative/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@

All notable changes to the Imperative package will be documented in this file.

## Recent Changes

- BugFix: Resolved bug that resulted in each plug-in to have identical public registries regardless of actual installation location/reference. [#2189](https://github.com/zowe/zowe-cli/pull/2189)
- BugFix: Resolved bug that resulted in every plug-in to have the same registry location field as the first if multiple plugins were installed in the same command. [#2189](https://github.com/zowe/zowe-cli/pull/2189)

## `8.0.0-next.202407051717`

- BugFix: V3 Breaking: Modified the ConvertV1Profiles.convert API to accept a new ProfileInfo option and initialize components sufficiently to enable VSCode apps to convert V1 profiles. [#2170](https://github.com/zowe/zowe-cli/issues/2170)

## `8.0.0-next.202407021516`

- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188)

- Update: See `5.25.0` for details

## `8.0.0-next.202406201950`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe("Installing Plugins", () => {
name: "override-plugin",
usage: "override-plugin"
},
registry: {
location: {
location: "imperative-sample-plugin",
name: "imperative-sample-plugin",
usage: "sample-plugin"
Expand Down Expand Up @@ -256,7 +256,7 @@ describe("Installing Plugins", () => {
}

const strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + envNpmRegistry);
expect(strippedOutput).toContain("Location = " + plugins.normal.location);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`);

// Now verify that it got added to the tree
Expand Down Expand Up @@ -387,7 +387,7 @@ describe("Installing Plugins", () => {
setCurrCredMgr(defaultCredMgrDisplayNm);

const strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + envNpmRegistry);
expect(strippedOutput).toContain("Location = " + plugins.override.location);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.override.name}'`);

// confirm it was installed
Expand Down Expand Up @@ -417,7 +417,7 @@ describe("Installing Plugins", () => {
}

const strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + TEST_REGISTRY);
expect(strippedOutput).toContain("Location = " + TEST_REGISTRY);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal2.name}'`);

Expand All @@ -443,7 +443,7 @@ describe("Installing Plugins", () => {
}

let strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + envNpmRegistry);
expect(strippedOutput).toContain("Location = " + plugins.normal.location);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`);

const afterInstall = executeCommandString(this, "--help");
Expand All @@ -466,7 +466,7 @@ describe("Installing Plugins", () => {
}

strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + envNpmRegistry);
expect(strippedOutput).toContain("Location = " + plugins.normal.location);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`);

result = executeCommandString(this, "--help");
Expand All @@ -492,7 +492,7 @@ describe("Installing Plugins", () => {
}

const strippedOutput = T.stripNewLines(result.stdout);
expect(strippedOutput).toContain("Registry = " + envNpmRegistry);
expect(strippedOutput).toContain("Location = " + plugins.space_in_path.location);
expect(strippedOutput).toContain(`Installed plugin name = '${plugins.space_in_path.name}'`);

// Now verify that it got added to the tree
Expand Down Expand Up @@ -618,7 +618,7 @@ describe("Installing Plugins", () => {
},
[plugins.normal2.name]: {
package: plugins.normal2.location,
registry: TEST_REGISTRY,
location: TEST_REGISTRY,
version: "1.0.2"
},
};
Expand Down Expand Up @@ -667,7 +667,7 @@ describe("Installing Plugins", () => {
const savedPluginJson = readFileSync(pluginJsonLocation);
const expectedContent: IPluginJson = fileContent as IPluginJson;

expectedContent[plugins.normal.name].registry = envNpmRegistry;
expectedContent[plugins.normal.name].location = envNpmRegistry;

expect(savedPluginJson).toEqual(expectedContent);
});
Expand Down Expand Up @@ -735,12 +735,12 @@ describe("Installing Plugins", () => {
const actualJson = readFileSync(pluginJsonLocation);

// Add missing registry to expected
expectedJson[plugins.normal.name].registry = envNpmRegistry;
expectedJson[plugins.normal.name].location = envNpmRegistry;

// Add missing normal2 plugin not present in before each
expectedJson[plugins.normal3.name] = {
package: plugins.normal3.location,
registry: TEST_REGISTRY,
location: TEST_REGISTRY,
version: "1.0.3"
};

Expand All @@ -751,7 +751,7 @@ describe("Installing Plugins", () => {
it("should error when a package and --file is specified", function () {
expect(
T.stripNewLines(
executeCommandString(this, `${pluginGroup} install ${plugins.registry.location} --file ${testFile}`).stderr
executeCommandString(this, `${pluginGroup} install ${plugins.location.location} --file ${testFile}`).stderr
)
).toContain("Option --file can not be specified if positional package... is as well. They are mutually exclusive.");
});
Expand All @@ -760,7 +760,7 @@ describe("Installing Plugins", () => {
expect(
T.stripNewLines(
executeCommandString(this,
`${pluginGroup} install ${plugins.registry.location} --file ${testFile} --registry ${TEST_REGISTRY}`).stderr
`${pluginGroup} install ${plugins.location.location} --file ${testFile} --registry ${TEST_REGISTRY}`).stderr
)
).toContain("The following options conflict (mutually exclusive)");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("List plugin", () => {
expect(result.stdout).toContain(`pluginName: ${pluginName}`);
expect(result.stdout).toContain(`package:`);
expect(result.stdout).toContain(`version:`);
expect(result.stdout).toContain(`registry:`);
expect(result.stdout).toContain(`location:`);
});

it("should display proper message when no plugin is installed", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ describe("Plugin Management Facility", () => {
const knownOverridePluginNm = CredentialManagerOverride.getKnownCredMgrs()[1].credMgrPluginName as string;

const mockInstalledPlugins: IPluginJson = {
firstPlugin: {package: "1", registry: "1", version: "1"},
secondPlugin: {package: "2", registry: "2", version: "2"}
firstPlugin: {package: "1", location: "1", version: "1"},
secondPlugin: {package: "2", location: "2", version: "2"}
};
const loadPluginCfgPropsReal: any = PMF.loadPluginCfgProps;
const loadPluginCfgPropsMock = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,21 @@ import { Logger } from "../../../../../logger";
import { readFileSync, writeFileSync } from "jsonfile";
import { PMFConstants } from "../../../../src/plugins/utilities/PMFConstants";
import { TextUtils } from "../../../../../utilities";
import { getRegistry, npmLogin } from "../../../../src/plugins/utilities/NpmFunctions";
import { getRegistry, getScopeRegistry, npmLogin } from "../../../../src/plugins/utilities/NpmFunctions";
import * as spawn from "cross-spawn";
import { IO } from "../../../../../io";

describe("Plugin Management Facility install handler", () => {

// Objects created so types are correct.
const mocks = {
npmLogin: npmLogin as Mock<typeof npmLogin>,
getRegistry: getRegistry as unknown as Mock<typeof getRegistry>,
getScopeRegistry: getScopeRegistry as unknown as Mock<typeof getScopeRegistry>,
readFileSync: readFileSync as Mock<typeof readFileSync>,
writeFileSync: writeFileSync as Mock<typeof writeFileSync>,
install: install as unknown as Mock<typeof install>,
runValidatePlugin: runValidatePlugin as unknown as Mock<typeof runValidatePlugin>
runValidatePlugin: runValidatePlugin as unknown as Mock<typeof runValidatePlugin>,
};

// two plugin set of values
Expand Down Expand Up @@ -180,12 +182,12 @@ describe("Plugin Management Facility install handler", () => {
const fileJson: IPluginJson = {
a: {
package: packageName,
registry: "",
location: "",
version: packageVersion
},
plugin2: {
package: packageName2,
registry: packageRegistry2,
location: packageRegistry2,
version: packageVersion2
}
};
Expand Down Expand Up @@ -379,5 +381,73 @@ describe("Plugin Management Facility install handler", () => {
expect(expectedError.additionalDetails).toContain("Command failed");
expect(expectedError.additionalDetails).toContain("npm");
});
it("should handle installed plugins via public scope", async () => {
const handler = new InstallHandler();

const params = getIHandlerParametersObject();
params.arguments.plugin = ["@public/sample1"];

mocks.getScopeRegistry.mockReturnValueOnce("publicRegistryUrl" as any);

try {
await handler.process(params);
} catch (e) {
expect(e).toBeUndefined();
}

expect(mocks.install).toHaveBeenCalledWith("@public/sample1","publicRegistryUrl");
});
it("should handle installed plugins via project/directory", async () => {
const handler = new InstallHandler();

const params = getIHandlerParametersObject();
params.arguments.plugin = ["path/to/dir"];
jest.spyOn(IO, 'isDir').mockReturnValue(true);

try{
await handler.process(params);
}
catch(e){
expect(e).toBeUndefined();
}

expect(mocks.install).toHaveBeenCalledWith("path/to/dir","path/to/dir");
});
it("should handle installed plugins via tarball file", async () => {
const handler = new InstallHandler();

const params = getIHandlerParametersObject();
params.arguments.plugin = ["path/to/dir/file.tgz"];

try{
await handler.process(params);
}
catch(e){
expect(e).toBeUndefined();
}

expect(mocks.install).toHaveBeenCalledWith("path/to/dir/file.tgz","path/to/dir/file.tgz");
});
it("should handle multiple installed plugins via tarball, director, public registry, and private registry", async () => {
const handler = new InstallHandler();

const params = getIHandlerParametersObject();
params.arguments.plugin = ["@public/sample1","@private/sample1","path/to/dir","path/to/dir/file.tgz"];
mocks.getScopeRegistry.mockReturnValueOnce("publicRegistryUrl" as any);
mocks.getScopeRegistry.mockReturnValueOnce("privateRegistryUrl" as any);
jest.spyOn(IO, 'isDir').mockReturnValue(true);

try{
await handler.process(params);
}
catch(e){
expect(e).toBeUndefined();
}

expect(mocks.install).toHaveBeenCalledWith("@public/sample1","publicRegistryUrl");
expect(mocks.install).toHaveBeenCalledWith("@private/sample1","privateRegistryUrl");
expect(mocks.install).toHaveBeenCalledWith("path/to/dir","path/to/dir");
expect(mocks.install).toHaveBeenCalledWith("path/to/dir/file.tgz","path/to/dir/file.tgz");
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ Installed plugins:
-- pluginName: a
-- package: a
-- version: 22.1.0
-- registry: http://imperative-npm-registry:4873/
-- location: http://imperative-npm-registry:4873/

-- pluginName: plugin1
-- package: plugin1
-- version: 2.0.3
-- registry: http://imperative-npm-registry:4873/
-- location: http://imperative-npm-registry:4873/

"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ describe("Plugin Management Facility list handler", () => {
const fileJson: IPluginJson = {
plugin1: {
package: packageName2,
registry: packageRegistry2,
location: packageRegistry2,
version: packageVersion2
},
a: {
package: packageName,
registry: packageRegistry,
location: packageRegistry,
version: packageVersion
}
};
Expand All @@ -119,12 +119,12 @@ describe("Plugin Management Facility list handler", () => {
const fileJson: IPluginJson = {
plugin1: {
package: packageName2,
registry: packageRegistry2,
location: packageRegistry2,
version: packageVersion2
},
a: {
package: packageName,
registry: packageRegistry,
location: packageRegistry,
version: packageVersion
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ describe("Plugin Management Facility uninstall handler", () => {
const fileJson: IPluginJson = {
a: {
package: packageName,
registry: "",
location: "",
version: packageVersion
},
plugin1: {
package: packageName2,
registry: packageRegistry2,
location: packageRegistry2,
version: packageVersion2
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ describe("Plugin Management Facility update handler", () => {
const fileJson: IPluginJson = {
"imperative-sample-plugin": {
package: packageName,
registry: packageRegistry,
location: packageRegistry,
version: packageVersion
},
"plugin1": {
package: packageName2,
registry: packageRegistry2,
location: packageRegistry2,
version: packageVersion2
}
};
Expand Down Expand Up @@ -173,7 +173,7 @@ describe("Plugin Management Facility update handler", () => {
const fileJson: IPluginJson = {
"imperative-sample-plugin": {
package: resolveVal,
registry: packageRegistry,
location: packageRegistry,
version: "1.0.1"
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import * as npmPackageArg from "npm-package-arg";
import * as pacote from "pacote";
import * as npmFunctions from "../../../src/plugins/utilities/NpmFunctions";
import { PMFConstants } from "../../../src/plugins/utilities/PMFConstants";
import { ExecUtils } from "../../../../utilities";
Fixed Show fixed Hide fixed

jest.mock("cross-spawn");
jest.mock("jsonfile");
Expand Down Expand Up @@ -134,5 +135,14 @@ describe("NpmFunctions", () => {
expect(actualInfo).toBe(expectedInfo);
expect(pacote.manifest).toHaveBeenCalledTimes(1);
});

it("getScopeRegistry() should return registry for 'test' scope", async () => {
const spawnSpy = jest.spyOn(ExecUtils, "spawnAndGetOutput");
spawnSpy.mockReturnValueOnce("https://test123.com");
const result = await npmFunctions.getScopeRegistry("test");
expect(result).toBe("https://test123.com");
expect(spawnSpy).toHaveBeenCalledTimes(1);
});

});
});
Loading
Loading