diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9691bec7..62c56ab2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,14 +132,13 @@ jobs: timeout-minutes: 15 run: | docker rm -f registry || true - docker run --rm -d \ + REGISTRY=$(docker run --rm -d \ --network zpm \ --name registry \ -p 52773:52773 \ --network-alias registry \ registry-image \ - -a "iris session iris -U%SYS '##class(Security.Users).UnExpireUserPasswords(\"*\")'" - REGISTRY=`docker ps -lq` + -a "iris session iris -U%SYS '##class(Security.Users).UnExpireUserPasswords(\"*\")'") sleep 5; docker exec $REGISTRY /usr/irissys/dev/Cloud/ICM/waitReady.sh docker exec -i $REGISTRY iris session iris -UUSER << EOF zpm "install zpm-registry" @@ -251,17 +250,12 @@ jobs: timeout-minutes: 15 run: | wget http://localhost:52773/registry/packages/zpm/latest/installer -O zpm-${{ needs.prepare.outputs.version }}.xml - - name: Stop ORAS registry + - name: Stop containers if: always() run: | - docker stop oras - - name: Stop temporary registry - if: always() - run: | - CONTAINER=`docker ps -lq` - docker stop $CONTAINER - docker stop registry - docker network rm zpm + # Stops the registries and any test container a failed or timed-out step left running. + docker ps -q --filter network=zpm | xargs -r docker stop || true + docker network rm zpm || true - uses: actions/upload-artifact@v4 if: matrix.image == needs.prepare.outputs.main with: diff --git a/tests/integration_tests/Test/PM/Integration/ModuleRoot.cls b/tests/integration_tests/Test/PM/Integration/ModuleRoot.cls index e956ba0d..4a12d8c9 100644 --- a/tests/integration_tests/Test/PM/Integration/ModuleRoot.cls +++ b/tests/integration_tests/Test/PM/Integration/ModuleRoot.cls @@ -1,23 +1,35 @@ Class Test.PM.Integration.ModuleRoot Extends Test.PM.Integration.Base { +Parameter ModuleName = "simplest-module"; + +Parameter ModuleVersion = "1.0.0"; + +/// Filesystem repos load modules in place, so the module comes from the local ORAS registry to exercise ModuleRoot. +/// It is published once for all tests because every test installs the same unchanged package. Method OnBeforeAllTests() As %Status { - set sc = ##class(%IPM.Main).Shell("repo -remote -n registry -url https://pm.community.intersystems.com/ -user """" -pass """"") - do $$$AssertStatusOK(sc, "Community registry configured.") - return sc + do $$$AssertStatusOK(##class(%IPM.Main).Shell("repo -delete-all"), "Deleted repos.") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("repo -o -name oras -url http://oras:5000 -publish 1"), "Configured ORAS repo.") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("load " _ ..GetModuleDir(..#ModuleName, ..#ModuleVersion)), "Loaded test module.") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("publish " _ ..#ModuleName _ " -r oras"), "Published test module.") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall " _ ..#ModuleName), "Uninstalled test module.") + return $$$OK } Method OnAfterAllTests() As %Status { - set sc = ##class(%IPM.Main).Shell("uninstall objectscript-math -force") - set sc = ##class(%IPM.Main).Shell("repo -delete -n registry") - do $$$AssertStatusOK(sc, "Community registry removed.") - return sc + do ##class(%IPM.Main).Shell("unpublish oras/" _ ..#ModuleName _ " " _ ..#ModuleVersion _ " -force") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("repo -delete-all"), "Deleted repos.") + do $$$AssertStatusOK(##class(%IPM.Main).Shell("repo -reset-defaults"), "Reset repos to defaults.") + return $$$OK } Method OnAfterOneTest(testname As %String) As %Status { + if ##class(%IPM.Storage.Module).NameExists(..#ModuleName) { + do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall " _ ..#ModuleName), "Uninstalled test module.") + } set sc = ##class(%IPM.Repo.UniversalSettings).ResetToDefault(##class(%IPM.Repo.UniversalSettings).#ModuleRoot) do $$$AssertStatusOK(sc, "ModuleRoot reset to default after test.") for dir = "ipm-test-root-exists/","ipm-test-root-new/" { @@ -29,21 +41,20 @@ Method OnAfterOneTest(testname As %String) As %Status return sc } +/// Installs the test module and returns the directory it was installed under, minus the module's own subfolder. +Method InstallAndGetRoot() As %String +{ + do $$$AssertStatusOK(##class(%IPM.Main).Shell("install " _ ..#ModuleName _ " " _ ..#ModuleVersion), "Installed test module.") + set moduleObj = ##class(%IPM.Storage.Module).NameOpen(..#ModuleName) + return ##class(%File).NormalizeDirectory($piece(moduleObj.Root, ..#ModuleName)) +} + Method TestModuleRootDefault() { - set sc = $$$OK try { set defaultRoot = ##class(%File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm/") - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - if $isobject(moduleObj) { - do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall objectscript-math"), "Uninstalled objectscript-math before test.") - } - - do $$$AssertStatusOK(##class(%IPM.Main).Shell("install objectscript-math"), "Installed objectscript-math using default ModuleRoot.") - - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - set moduleRoot = ##class(%File).NormalizeDirectory($piece(moduleObj.Root, "objectscript-math")) + set moduleRoot = ..InstallAndGetRoot() do $$$AssertEquals(moduleRoot, defaultRoot, "Module installed into default root.") } catch ex { do $$$AssertStatusOK(ex.AsStatus(), "Unexpected exception in TestModuleRootDefault.") @@ -52,7 +63,6 @@ Method TestModuleRootDefault() Method TestModuleRootCustomPathExists() { - set sc = $$$OK try { set defaultRoot = ##class(%File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm/") set customPath = ##class(%File).NormalizeDirectory(##class(%File).ManagerDirectory() _ "ipm-test-root-exists/") @@ -62,15 +72,7 @@ Method TestModuleRootCustomPathExists() do $$$AssertStatusOK(##class(%IPM.Repo.UniversalSettings).UpdateOne("ModuleRoot", customPath), "Set ModuleRoot to existing custom path.") do $$$AssertEquals(##class(%IPM.Repo.UniversalSettings).GetModuleRoot(), customPath, "ModuleRoot stored as normalized path.") - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - if $isobject(moduleObj) { - do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall objectscript-math"), "Uninstalled objectscript-math before relocation test.") - } - - do $$$AssertStatusOK(##class(%IPM.Main).Shell("install objectscript-math"), "Installed objectscript-math using existing custom ModuleRoot.") - - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - set moduleRoot = ##class(%File).NormalizeDirectory($piece(moduleObj.Root, "objectscript-math")) + set moduleRoot = ..InstallAndGetRoot() do $$$AssertTrue(moduleRoot '= defaultRoot, "Module is no longer in default root.") do $$$AssertTrue(moduleRoot [ customPath, "Module is installed in custom root: " _ moduleRoot) } catch ex { @@ -80,7 +82,6 @@ Method TestModuleRootCustomPathExists() Method TestModuleRootCustomPathCreated() { - set sc = $$$OK try { set defaultRoot = ##class(%File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm/") set customPath = ##class(%File).NormalizeDirectory(##class(%File).ManagerDirectory() _ "ipm-test-root-new/") @@ -91,18 +92,10 @@ Method TestModuleRootCustomPathCreated() } do $$$AssertTrue('##class(%File).DirectoryExists(customPath), "Custom path does not exist before config set.") - do $$$AssertStatusOK(##class(%IPM.Repo.UniversalSettings).UpdateOne("ModuleRoot", customPath), "Set ModuleRoot to nonexistent path — should create it.") + do $$$AssertStatusOK(##class(%IPM.Repo.UniversalSettings).UpdateOne("ModuleRoot", customPath), "Set ModuleRoot to nonexistent path, which should create it.") do $$$AssertTrue(##class(%File).DirectoryExists(customPath), "Directory was created by config set.") - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - if $isobject(moduleObj) { - do $$$AssertStatusOK(##class(%IPM.Main).Shell("uninstall objectscript-math"), "Uninstalled objectscript-math before relocation test.") - } - - do $$$AssertStatusOK(##class(%IPM.Main).Shell("install objectscript-math"), "Installed objectscript-math into auto-created custom ModuleRoot.") - - set moduleObj = ##class(%IPM.Storage.Module).NameOpen("objectscript-math") - set moduleRoot = ##class(%File).NormalizeDirectory($piece(moduleObj.Root, "objectscript-math")) + set moduleRoot = ..InstallAndGetRoot() do $$$AssertTrue(moduleRoot '= defaultRoot, "Module is no longer in default root.") do $$$AssertTrue(moduleRoot [ customPath, "Module is installed in auto-created root: " _ moduleRoot) } catch ex { diff --git a/tests/unit_tests/Test/PM/Unit/CLI.cls b/tests/unit_tests/Test/PM/Unit/CLI.cls index 04f45ed3..ee786ce9 100644 --- a/tests/unit_tests/Test/PM/Unit/CLI.cls +++ b/tests/unit_tests/Test/PM/Unit/CLI.cls @@ -432,13 +432,6 @@ Method TestUninstallWithoutModuleName() do $$$LogMessage("Run Uninstall command without module name") set status = ..RunCommand("uninstall") do $$$AssertStatusNotOK(status, $system.Status.GetErrorText(status)) - set status = ..RunCommand("install objectscript-math") - do $$$AssertStatusOK(status, "objectscript-math module installed successfully.") - set exists = ##class(%IPM.Storage.Module).NameExists("objectscript-math") - do $$$AssertTrue(exists, "objectscript-math Module exists in storage after installation.") - do ..RunCommand("uninstall objectscript-math") - set exists = ##class(%IPM.Storage.Module).NameExists("objectscript-math") - do $$$AssertNotTrue(exists, "Module removed successfully.") } /// Specifies the serialization format (json, toon, yaml) for unit and integration test results in the shell.