Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- #992: Implement automatic history purge logic
- #973: Enables CORS and JWT configuration for WebApplications in module.xml
- #1095: add -outdated modifier in list command
Comment thread
isc-dchui marked this conversation as resolved.
Outdated

### Fixed
- #1001: The `unmap` and `enable` commands will now only activate CPF merge once after all namespaces have been configured instead after every namespace
Expand Down
37 changes: 35 additions & 2 deletions src/cls/IPM/Main.cls
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ reinstall -env /path/to/env1.json;/path/to/env2.json example-package
<example description="Shows all installed Python packages.">
list -python
</example>
<example description="Lists all installed modules with available updates in the registry.">
list -outdated
</example>

<!-- Parameters -->
<parameter name="searchString" description="Search string, * can be used." />
Expand All @@ -538,6 +541,7 @@ reinstall -env /path/to/env1.json;/path/to/env2.json example-package
<modifier name="showupstream" aliases="su" description="If specified, show the latest version for each module in configured repos if it's different than the local version." />
<modifier name="repository" aliases="repo" value="true" description="If specified, only show modules installed that belong to the provided repository." />
<modifier name="python" aliases="py" description="If specified, lists installed Embedded Python libraries instead of IPM modules." />
<modifier name="outdated" aliases="o" description="Lists installed modules that have available updates in the registry." />
</command>

<command name="list-dependents" aliases="dependents">
Expand Down Expand Up @@ -2757,6 +2761,12 @@ ClassMethod ListInstalled(ByRef pCommandInfo) [ Private ]
do ..DisplayModules(.list,,,, .tModifiers)
quit
}
if $data(pCommandInfo("modifiers","outdated")) {
merge tModifiers = pCommandInfo("modifiers")
do ..GetOutdatedModulesList(.list)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice for the list to have column headers to display

do ..DisplayModules(.list,,,, .tModifiers)
quit
}
if (''$data(pCommandInfo("modifiers","tree"))) {
// Show tree of dependencies as well.
// Modules that are dependencies for no other are shown at the top level.
Expand Down Expand Up @@ -2821,8 +2831,7 @@ ClassMethod GetListModule(
{
new $namespace
set $namespace=ns
set tRes = ##class(%SQL.Statement).%ExecDirect(,
"select * from %IPM_Storage.ModuleItem")
set tRes = ##class(%SQL.Statement).%ExecDirect(, "select * from %IPM_Storage.ModuleItem")
$$$ThrowSQLIfError(tRes.%SQLCODE,tRes.%Message)
set in=""
while tRes.%Next(.tSC) {
Expand Down Expand Up @@ -4171,6 +4180,30 @@ ClassMethod Update(ByRef pCommandInfo)
}
}

ClassMethod GetOutdatedModulesList(Output List)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also check if the new versions satisfy the existing version constraints? If not, it should.

For example, if we have module-a that depends on module-b ^1.3.0, and the available versions of module-b are 1.3.0 and 2.0.0, then list -outdated should not include module-b since 2.0.0 cannot be installed anyway.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @isc-dchui
Thank you for pointing out this excellent case. Currently, the check only determines whether a newer version exists and does not verify whether that version satisfies the existing version constraints.

So, in this scenario, module-b is not a directly installed module; it is installed as a dependency of module-a. Because of that, it likely should not appear in the list -outdated output.
Thank you!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! Let's add a test to make sure this works! (Also you have some failing tests)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. Thank you!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @isc-dchui Thanks for pointing that out. Since the irisjwt module cannot be resolved from the external registry in CI, Could you suggest the best way to utilize local custom modules as test assets to bypass the registry requirement?
Thank you!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @isc-dchui
I’ve implemented the -outdated flag to skip modules installed only as dependencies. Thank you!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplest would probably be adding the test modules to the Integration/_data directory and setting up a filesystem repo to point to it like so:

repo -fs -name local -path /home/irisowner/zpm/tests/integration_tests/Test/PM/Integration/_data/<dtest_directory>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion. Setting up a filesystem repository is a new configuration for me. Could you please point me toward the official documentation or a guide for this? That would be very helpful for my setup.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't much, but here's an example in the wiki:
https://github.com/intersystems/ipm/wiki/02.-CLI-commands#repo

{
do ..GetListModules($namespace,,.installedModules)
do ..GetUpstreamPackageVersions(.serverModuleVersions)
set width = 0
for i=1:1:installedModules {
set moduleInfo = installedModules(i)
set moduleName = $listget(moduleInfo)
continue:moduleName="zpm"
set currentVersion = $listget(moduleInfo,2)
if $data(serverModuleVersions(moduleName)) {
set reg = $order(serverModuleVersions(moduleName,""),1,versionString)
if currentVersion'=versionString {
set currentwidth = $length(moduleName)
set List($increment(List)) = $listbuild(moduleName,$$$FormattedLine($$$Red, currentVersion)_" "_$$$FormattedLine($$$Green,versionString))
if width<currentwidth {
set width = currentwidth
}
}
}
}
set List("width") = width
}

ClassMethod GetPythonInstalledLibs(Output list)
{
set target = ##class(%File).NormalizeDirectory("python", $system.Util.ManagerDirectory())
Expand Down
39 changes: 39 additions & 0 deletions tests/unit_tests/Test/PM/Unit/CLI.cls
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,43 @@ Method TestUninstallWithoutModuleName()
do $$$AssertNotTrue(exists, "Module removed successfully.")
}

/// Validates that the '-outdated' modifier correctly identifies and displays modules with newer registry versions
Method TestListOutdatedModules()
{
set moduleName = "irisjwt"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably add a test with more than one module and one with dependencies.

if $isobject(##class(%IPM.Storage.Module).NameOpen(moduleName)) {
do $$$LogMessage(moduleName_" already exist. So uninstalling the module")
do ..RunCommand("uninstall "_moduleName)
}

set status = ..RunCommand("install "_moduleName_" 1.0.0")
do $$$AssertStatusOK(status, moduleName_" installed at version 1.0.0")
do ##class(%IPM.Main).GetOutdatedModulesList(.list)

set found = 0
for i=1:1:list {
set moduleInfo = list(i)
set currentModuleName = $listget(moduleInfo, 1)
set versionString = $listget(moduleInfo, 2)

// Scrub ANSI color codes
set matcher = ##class(%Regex.Matcher).%New("\x1b\[[0-9;]*m", versionString)
set cleanString = matcher.ReplaceAll("")

set cleanString = $zstrip(cleanString, "<>W")
set currentVersion = $piece(cleanString, " ", 1)
set serverVersion = $piece(cleanString, " ", 2)
if (moduleName = currentModuleName) {
set found = 1
}
if currentVersion'=serverVersion {
do $$$AssertNotEquals(currentVersion, serverVersion, "Version mismatch detected for "_moduleName)
do $$$LogMessage(currentVersion_" "_serverVersion)
do $$$LogMessage("Currently installed "_currentModuleName_" (local:"_currentVersion_") has a newer version available (server:"_serverVersion_")")
}
}
do $$$AssertTrue(found, "The module "_moduleName_" was found in the outdated list")
do ..RunCommand("list -o")
}

}
Loading