From 36e13be94e3b6bc68f4a5c6a9bdc6330f35ef360 Mon Sep 17 00:00:00 2001 From: Evgeny Shvarov Date: Sat, 13 May 2023 11:02:41 +0400 Subject: [PATCH 01/42] Add one-liner to install IPM --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 302dc9e0..e81ef7b9 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,13 @@ Helps to install ObjectScript classes and routines, globals, Embedded Python mod ## Installing ObjectScript Package Manager Client: +0. Use one-liner in terminal call or programmatically: +``` +s r=##class(%Net.HttpRequest).%New(),r.Server="pm.community.intersystems.com",r.SSLConfiguration="ISC.FeatureTracker.SSL.Config" d r.Get("/packages/zpm/latest/installer"),$system.OBJ.LoadStream(r.HttpResponse.Data,"c") +``` + +OR: + 1. Download the [latest version](https://pm.community.intersystems.com/packages/zpm/latest/installer) of zpm from the registry 2. Import the zpm.xml into IRIS and compile via any desired way (Management Portal, Studio or Terminal) From e5dfffc3c8f947df5223547701786a857ef18712 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:15:20 -0400 Subject: [PATCH 02/42] Normalize package name *after* using $order to check for multiple documents in module.xml Fixes #367 --- src/%ZPM/PackageManager/Developer/Utils.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/%ZPM/PackageManager/Developer/Utils.cls b/src/%ZPM/PackageManager/Developer/Utils.cls index 5e401574..f1f2e4e6 100644 --- a/src/%ZPM/PackageManager/Developer/Utils.cls +++ b/src/%ZPM/PackageManager/Developer/Utils.cls @@ -953,14 +953,14 @@ ClassMethod LoadNewModule(pDirectory As %String, ByRef pParams, pRepository As % Set tSC = $System.OBJ.Load(pDirectory_"module.xml",$Select(tVerbose:"d",1:"-d"),,.tLoadedList) $$$ThrowOnError(tSC) - Set tFirstLoaded = $$$lcase($Order(tLoadedList(""))) - + Set tFirstLoaded = $Order(tLoadedList("")) If (tFirstLoaded = "") { $$$ThrowStatus($$$ERROR($$$GeneralError,"No module definition found.")) } If ($Order(tLoadedList(tFirstLoaded)) '= "") { $$$ThrowStatus($$$ERROR($$$GeneralError,"module.xml contains multiple documents.")) } + Set tFirstLoaded = $$$lcase(tFirstLoaded) If ($Piece(tFirstLoaded,".",*) '= "zpm") { $$$ThrowStatus($$$ERROR($$$GeneralError,"No module definition found.")) } From c34accd4965ba26e4c175f12e39942098a0f49a4 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Mon, 12 Jun 2023 16:14:48 +0100 Subject: [PATCH 03/42] Set up for `intersystems-community.testingmanager` VS Code extension --- .vscode/extensions.json | 8 ++++++++ .vscode/settings.json | 4 ++-- Dockerfile | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..0183ebba --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "intersystems.language-server", + "intersystems-community.testingmanager", + "intersystems-community.vscode-objectscript", + "ms-azuretools.vscode-docker" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 52c75072..0c52d889 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,6 @@ "username": "_system", "password": "SYS", "ns": "%SYS" - } - + }, + "intersystems.testingManager.client.relativeTestRoot": "tests/unit_tests" } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 1c98e828..eb5e6c1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,5 @@ RUN --mount=type=bind,src=.,dst=/home/irisowner/zpm/ \ iris start iris && \ iris session iris "##class(%SYSTEM.OBJ).Load(\"/home/irisowner/zpm/Installer.cls\",\"ck\")" && \ iris session iris "##class(%ZPM.Installer).setup(\"/home/irisowner/zpm/\",3)" && \ + iris session iris "##class(%ZPM.PackageManager).Shell(\"install vscode-per-namespace-settings\")" && \ iris stop iris quietly \ No newline at end of file From 64f5495b8d03e963ebef6a7b168df5a6aa91863a Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Mon, 12 Jun 2023 16:29:42 +0100 Subject: [PATCH 04/42] Fix broken `exec` command --- src/%ZPM/PackageManager.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/%ZPM/PackageManager.cls b/src/%ZPM/PackageManager.cls index 3f3c37ff..42470f75 100644 --- a/src/%ZPM/PackageManager.cls +++ b/src/%ZPM/PackageManager.cls @@ -524,7 +524,7 @@ ClassMethod ShellInternal(pCommand As %String, Output pException As %Exception.A Do ..Repository(.tCommandInfo) } ElseIf (tCommandInfo = "load") { Do ..Load(.tCommandInfo) - } ElseIf (tCommandInfo = "cos") { + } ElseIf (tCommandInfo = "exec") { Write ! Xecute tCommandInfo("parameters","cos") } ElseIf (tCommandInfo = "install") { From e3f6be42dc204e76490b9b734f1d42d46074965a Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 16 Jun 2023 10:17:49 -0400 Subject: [PATCH 05/42] Use prefix to work around filename length limits Fixes #416 This just changes tar generation, so it's actually backward-compatible with old IPM versions loading the package. (Which is neat.) --- src/%ZPM/Utils/FileBinaryTar.cls | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/%ZPM/Utils/FileBinaryTar.cls b/src/%ZPM/Utils/FileBinaryTar.cls index 4973909d..e4b95bd3 100644 --- a/src/%ZPM/Utils/FileBinaryTar.cls +++ b/src/%ZPM/Utils/FileBinaryTar.cls @@ -314,14 +314,19 @@ ClassMethod ConstructTar(Path As %String, RelativeTo As %String, archive As %Str set blockSize = ..#BLOCKSIZE if ##class(%File).DirectoryExists(Path) { set Path = ##class(%File).NormalizeDirectory(Path) + set prefix = ##class(%File).GetDirectory($Extract(Path,1,*-1)) + set prefix = $PIECE(Path, RelativeTo, 2, *) set flag = 5 // Directory set size = 0 + set name = ##class(%File).GetFilename($Extract(Path,1,*-1)) } else { set Path = ##class(%File).NormalizeFilename(Path) + set prefix = ##class(%File).GetDirectory(Path) + set prefix = $PIECE(prefix, RelativeTo, 2, *) set flag = 0 // Ordinary File set size = ##class(%File).GetFileSize(Path) + set name = ##class(%File).GetFilename(Path) } - set name = $PIECE(Path, RelativeTo, 2, *) set mtime = ##class(%File).GetFileDateModified(Path, 1) set mtime = $ZDATETIME(mtime, -2) @@ -332,6 +337,7 @@ ClassMethod ConstructTar(Path As %String, RelativeTo As %String, archive As %Str if name'="" { set obj = ..%New() set obj.name = name + set obj.prefix = prefix set obj.size = size set obj.mode = mode set obj.mtime = mtime From 3ef095fec0460aeceec93c13c9dd8f278318e5f5 Mon Sep 17 00:00:00 2001 From: Dmitry Maslennikov Date: Mon, 19 Jun 2023 18:38:23 +0400 Subject: [PATCH 06/42] fixed installing python dependencies for ipm dependencies --- src/%ZPM/PackageManager/Developer/Utils.cls | 1 + 1 file changed, 1 insertion(+) diff --git a/src/%ZPM/PackageManager/Developer/Utils.cls b/src/%ZPM/PackageManager/Developer/Utils.cls index 5e401574..b68101d3 100644 --- a/src/%ZPM/PackageManager/Developer/Utils.cls +++ b/src/%ZPM/PackageManager/Developer/Utils.cls @@ -445,6 +445,7 @@ ClassMethod LoadModuleFromDirectory(pDirectory As %String, ByRef pParams, pOverr // Only propagate selected settings that should apply to dependencies. Set tParams("DeveloperMode") = $Get(pOverrideDeveloperMode,0) Set tParams("Verbose") = tVerbose + Set tParams("cmd") = "install" Merge tParams("NoLock") = pParams("NoLock") Merge tParams("NoMapping") = pParams("NoMapping") Merge tParams("NoTransaction") = pParams("NoTransaction") From c42968e798ef67360958e89a709effa301f7a63b Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 21 Jun 2023 22:30:31 +0000 Subject: [PATCH 07/42] auto bump version with release --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index d94a4ee1..35a99844 100644 --- a/module.xml +++ b/module.xml @@ -3,7 +3,7 @@ ZPM true - 0.6.1-SNAPSHOT + 0.7.1-SNAPSHOT Package Management System Provides development tools and infrastructure for defining, building, distributing, and installing modules and applications. Package Manager From 37bbdb278191965cf3b9a3033a38252a28a94b18 Mon Sep 17 00:00:00 2001 From: gjsjohnmurray Date: Thu, 22 Jun 2023 01:27:47 +0100 Subject: [PATCH 08/42] Set the ^UnitTestRoot node when building the container --- Dockerfile | 4 +--- iris.script | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 iris.script diff --git a/Dockerfile b/Dockerfile index eb5e6c1a..95d397a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,5 @@ ARG REGISTRY=https://pm.community.intersystems.com RUN --mount=type=bind,src=.,dst=/home/irisowner/zpm/ \ iris start iris && \ - iris session iris "##class(%SYSTEM.OBJ).Load(\"/home/irisowner/zpm/Installer.cls\",\"ck\")" && \ - iris session iris "##class(%ZPM.Installer).setup(\"/home/irisowner/zpm/\",3)" && \ - iris session iris "##class(%ZPM.PackageManager).Shell(\"install vscode-per-namespace-settings\")" && \ + iris session IRIS < /home/irisowner/zpm/iris.script && \ iris stop iris quietly \ No newline at end of file diff --git a/iris.script b/iris.script new file mode 100644 index 00000000..9843d74f --- /dev/null +++ b/iris.script @@ -0,0 +1,6 @@ + zn "%SYS" + do ##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm/Installer.cls","ck") + do ##class(%ZPM.Installer).setup("/home/irisowner/zpm/",3) + do ##class(%ZPM.PackageManager).Shell("install vscode-per-namespace-settings") + set ^UnitTestRoot="/usr/irissys/.vscode/%SYS/UnitTestRoot" + halt From 67d2a571f333c75bbf9bbbe5c09e61446585b87f Mon Sep 17 00:00:00 2001 From: Dmitry Maslennikov Date: Mon, 10 Jul 2023 12:13:16 +0400 Subject: [PATCH 09/42] EnableEnsemble for Verify stage --- src/%ZPM/PackageManager/Developer/Lifecycle/Base.cls | 2 ++ src/%ZPM/PackageManager/Developer/SystemRequirements.cls | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/%ZPM/PackageManager/Developer/Lifecycle/Base.cls b/src/%ZPM/PackageManager/Developer/Lifecycle/Base.cls index 393412f7..f4e9e242 100644 --- a/src/%ZPM/PackageManager/Developer/Lifecycle/Base.cls +++ b/src/%ZPM/PackageManager/Developer/Lifecycle/Base.cls @@ -1048,6 +1048,8 @@ Method %Verify(ByRef pParams) As %Status // Create a new namespace and load the module in it. #dim tNSConfig As %ZPM.PackageManager.Developer.ModuleSetting.NamespaceConfig Set tNSConfig = ..Module.GetNamespaceConfig() + Set tSysReqs = ..Module.SystemRequirements + If $IsObject(tSysReqs), tSysReqs.Interoperability = "enabled" Set tNSConfig.EnableEnsemble = 1 // Create namespace in which to run tests and switch to it. $$$ThrowOnError(##class(%ZPM.PackageManager.Developer.Build).InitializeNamespace("VERIFY",tVerbose,.tNewNamespace,tNSConfig)) diff --git a/src/%ZPM/PackageManager/Developer/SystemRequirements.cls b/src/%ZPM/PackageManager/Developer/SystemRequirements.cls index 6ea28109..64d8cc3c 100644 --- a/src/%ZPM/PackageManager/Developer/SystemRequirements.cls +++ b/src/%ZPM/PackageManager/Developer/SystemRequirements.cls @@ -41,8 +41,7 @@ Method CheckVersion() As %Status Method CheckInteroperability() As %Status { - - If ( (..Interoperability="enabled") && '##class(%EnsembleMgr).IsEnsembleNamespace($Namespace) ) { + If (..Interoperability="enabled") && (('##class(%EnsembleMgr).IsEnsembleNamespace($Namespace)) || ('##class(%EnsembleMgr).validateNamespace($Namespace, 1))) { Return $$$ERROR($$$GeneralError, "The module requires Interoperability Production Enabled. Namespace <"_$Namespace_"> doesn't support Interoperability Production") } Return $$$OK From d6ee9312279e9d321cb8a2d88b040087483736c4 Mon Sep 17 00:00:00 2001 From: mihaylenko_sv Date: Thu, 20 Jul 2023 11:33:25 +0300 Subject: [PATCH 10/42] add zpm version and current refistry --- src/%ZPM/PackageManager.cls | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) mode change 100644 => 100755 src/%ZPM/PackageManager.cls diff --git a/src/%ZPM/PackageManager.cls b/src/%ZPM/PackageManager.cls old mode 100644 new mode 100755 index 42470f75..b4d7e540 --- a/src/%ZPM/PackageManager.cls +++ b/src/%ZPM/PackageManager.cls @@ -468,6 +468,30 @@ ClassMethod TerminalPrompt() As %String Quit prompt } +/// @API.Method +/// Get Version modules and current registry +/// example do ##class(%ZPM.PackageManager).GetVersion("zpm,zpm-registry",.out,.list) +ClassMethod GetVersion(ModuleName, ByRef out, list) +{ + Do ..GetListModules("*", ModuleName, .list) + for i=1:1 { quit:'$d(list(i),ns) + set ns=$lg(ns,1) + for ii=1:1 { quit:'$d(list(i,"modules",ii),module) + set out($lg(module,1))=$lb(ns,$lg(module,2)) + } + } + set sc=$$$OK + set sql="select URL from %ZPM_PackageManager_Client.RemoteServerDefinition where Enabled = 1" + ,rs=##class(%ResultSet).%New() + ,sc=rs.Prepare(sql) + Set:sc sc=rs.Execute("") + If sc { + Quit:'rs.%Next() + set out=rs.Get("URL") + } + Quit sc +} + /// For use in unit tests that need to test if a command threw any exceptions. ClassMethod ShellInternal(pCommand As %String, Output pException As %Exception.AbstractException) [ Internal ] { @@ -477,9 +501,11 @@ ClassMethod ShellInternal(pCommand As %String, Output pException As %Exception.A If (tCommand '= "") { Set tOneCommand = 1 } + do ##class(%ZPM.PackageManager).GetVersion("zpm",.out) Set introMessageList = $ListBuild( - "Welcome to the Package Manager Shell (ZPM).", - "Enter q/quit to exit the shell. Enter ?/help to view available commands" + "Welcome to the Package Manager Shell (ZPM). version "_$$$FormattedLine($$$Cyan,$lg($g(out("zpm")),2)), + "Enter q/quit to exit the shell. Enter ?/help to view available commands", + "Current registry "_$$$FormattedLine($$$Cyan,$g(out)) ) Set tInShell = 0 For { @@ -2508,3 +2534,4 @@ ClassMethod DisplayModules(ByRef pList, pNumbered As %Boolean = 0, pWithNamespac } } + From 532aa7aa09cac9b5ac090afe79a42ffdd0db0790 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:10:23 -0500 Subject: [PATCH 11/42] fix: update to new set-output syntax per https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index da98aff5..6dd9f906 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -9,7 +9,7 @@ jobs: - id: set-matrix run: | matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s` - echo "::set-output name=matrix::$matrix" + echo "matrix=$matrix" >> $GITHUB_OUTPUT job2: needs: job1 runs-on: ubuntu-latest From daf66036f1a341d9a78b8958e7d4bf78e4848e99 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:18:32 -0500 Subject: [PATCH 12/42] Update packages.yml --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 6dd9f906..bce39e91 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -9,7 +9,7 @@ jobs: - id: set-matrix run: | matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s` - echo "matrix=$matrix" >> $GITHUB_OUTPUT + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" job2: needs: job1 runs-on: ubuntu-latest From 32246609606d3c045a237b2af14e368386236105 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:21:18 -0500 Subject: [PATCH 13/42] Update packages.yml Eventually... --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index bce39e91..1f3c6a0f 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -9,7 +9,7 @@ jobs: - id: set-matrix run: | matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s` - echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: needs: job1 runs-on: ubuntu-latest From c57fa5688913e3747b2c15fcde6287d088f5acc9 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:22:44 -0500 Subject: [PATCH 14/42] Update packages.yml Strip newlines --- .github/workflows/packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 1f3c6a0f..7fdd9181 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,8 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s` + matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s | tr -d '\n\t\r '` + echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: needs: job1 From 6401156c000774ea56a07113168aae0bc615a243 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:28:26 -0500 Subject: [PATCH 15/42] Update packages.yml Move packages to attribute? --- .github/workflows/packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 7fdd9181..2100d4a0 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -15,6 +15,7 @@ jobs: needs: job1 runs-on: ubuntu-latest strategy: - matrix: ${{fromJson(needs.job1.outputs.matrix)}} + matrix: + package: ${{fromJson(needs.job1.outputs.matrix)}} steps: - run: echo test \ No newline at end of file From 29e4eceb0c61c4c09ff86e6274db839c646872c9 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:04:23 -0500 Subject: [PATCH 16/42] To stay under GitHub actions jobs threshold, only test packages with 3+ releases --- .github/workflows/packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 2100d4a0..49a9d3c0 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,8 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s | tr -d '\n\t\r '` + minVersions=3 + matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= ${minVersions} then . + [$item.name] end)' | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From 290c0b4f05b5a57532f0f80a65fea8627b517552 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:08:50 -0500 Subject: [PATCH 17/42] Fix URL, maybe issue with parameter? --- .github/workflows/packages.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 49a9d3c0..3d53daae 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,8 +8,7 @@ jobs: steps: - id: set-matrix run: | - minVersions=3 - matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= ${minVersions} then . + [$item.name] end)' | tr -d '\n\t\r '` + matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] end)' | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From f16a6af59434aaf0612a2a7fa24a57d0120a15c1 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:18:11 -0500 Subject: [PATCH 18/42] Update packages.yml Change quoting approach to see if this works better? --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 3d53daae..94cc0516 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,7 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] end)' | tr -d '\n\t\r '` + matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq "reduce .[] as \$item ([]; if \$item.allVersions | length >= 3 then . + [\$item.name] end)" | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From da9d924c53e6cdb984d37d68c53594e5ae40400c Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:24:32 -0500 Subject: [PATCH 19/42] Revert "Update packages.yml" This reverts commit f16a6af59434aaf0612a2a7fa24a57d0120a15c1. --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 94cc0516..3d53daae 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,7 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq "reduce .[] as \$item ([]; if \$item.allVersions | length >= 3 then . + [\$item.name] end)" | tr -d '\n\t\r '` + matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] end)' | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From 97740e5956f34ebc49c0666c856a78aff31e2049 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:26:04 -0500 Subject: [PATCH 20/42] Update packages.yml Maybe needs else? --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 3d53daae..9e0c67ea 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,7 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] end)' | tr -d '\n\t\r '` + matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] else . end)' | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From 56f5d238e24f93556b8c6e185db287943fd5d2d5 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:28:21 -0500 Subject: [PATCH 21/42] Update packages.yml Raise threshold while in testing --- .github/workflows/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 9e0c67ea..5fc0264c 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -8,7 +8,7 @@ jobs: steps: - id: set-matrix run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 3 then . + [$item.name] else . end)' | tr -d '\n\t\r '` + matrix=`curl https://pm.community.intersystems.com/packages/-/all?allVersions=1 | jq 'reduce .[] as $item ([]; if $item.allVersions | length >= 10 then . + [$item.name] else . end)' | tr -d '\n\t\r '` echo $matrix echo "matrix=${matrix}" >> "$GITHUB_OUTPUT" job2: From e6839244a77e59f810b19562c6141dd682e76c9d Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Fri, 19 Jan 2024 12:26:05 -0500 Subject: [PATCH 22/42] (fix) various %ZPM -> %IPM equivalents from community modifications --- iris.script | 8 ++++---- scripts/make-release.sh | 2 +- src/cls/IPM/Main.cls | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/iris.script b/iris.script index 9843d74f..e0186071 100644 --- a/iris.script +++ b/iris.script @@ -1,6 +1,6 @@ - zn "%SYS" - do ##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm/Installer.cls","ck") - do ##class(%ZPM.Installer).setup("/home/irisowner/zpm/",3) - do ##class(%ZPM.PackageManager).Shell("install vscode-per-namespace-settings") + zn "USER" + do $System.OBJ.Load("/home/irisowner/zpm/Installer.cls","ck") + do ##class(IPM.Installer).setup("/home/irisowner/zpm/",3) + do ##class(%IPM.Main).Shell("install vscode-per-namespace-settings") set ^UnitTestRoot="/usr/irissys/.vscode/%SYS/UnitTestRoot" halt diff --git a/scripts/make-release.sh b/scripts/make-release.sh index 3298d884..8c8b9f19 100755 --- a/scripts/make-release.sh +++ b/scripts/make-release.sh @@ -8,7 +8,7 @@ rm -rf /opt/out/* iris start $ISC_PACKAGE_INSTANCENAME /bin/echo -e \ " zpm \"package zpm -only -p \"\"/tmp/zpm-${VERSION}\"\" \":1\n" \ - " set sc = ##class(%ZPM.Installer).MakeFile(\"/tmp/zpm-${VERSION}.tgz\", \"${RELEASE_FILE}\")\n" \ + " set sc = ##class(IPM.Installer).MakeFile(\"/tmp/zpm-${VERSION}.tgz\", \"${RELEASE_FILE}\")\n" \ " halt" \ | iris session $ISC_PACKAGE_INSTANCENAME -U%SYS diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index a3882638..b22333e5 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -678,7 +678,7 @@ ClassMethod TerminalPrompt() As %String /// @API.Method /// Get Version modules and current registry -/// example do ##class(%ZPM.PackageManager).GetVersion("zpm,zpm-registry",.out,.list) +/// example do ##class(%IPM.Main).GetVersion("zpm,zpm-registry",.out,.list) ClassMethod GetVersion(ModuleName, ByRef out, list) { Do ..GetListModules("*", ModuleName, .list) @@ -689,7 +689,7 @@ ClassMethod GetVersion(ModuleName, ByRef out, list) } } set sc=$$$OK - set sql="select URL from %ZPM_PackageManager_Client.RemoteServerDefinition where Enabled = 1" + set sql="select URL from %IPM_Repo_Remote.Definition where Enabled = 1" ,rs=##class(%ResultSet).%New() ,sc=rs.Prepare(sql) Set:sc sc=rs.Execute("") @@ -709,7 +709,7 @@ ClassMethod ShellInternal(pCommand As %String, Output pException As %Exception.A If (tCommand '= "") { Set tOneCommand = 1 } - do ##class(%ZPM.PackageManager).GetVersion("zpm",.out) + do ##class(%IPM.Main).GetVersion("zpm",.out) Set introMessageList = $ListBuild( "Welcome to the Package Manager Shell (ZPM). Version: "_$$$FormattedLine($$$Green, ..GetVersionModule("zpm")), "Enter q/quit to exit the shell. Enter ?/help to view available commands", From 79c1f54cbea3fb8230b7fb4579abecda48a8608f Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:46:11 -0500 Subject: [PATCH 23/42] Merge in internal updates --- CHANGELOG.md | 43 +++++++++++++++++++ src/cls/IPM/DependencyAnalyzer.cls | 2 +- .../CompositeMethodOverrides.cls | 2 +- src/cls/IPM/General/ModuleInfo.cls | 22 +++++++--- src/cls/IPM/Lifecycle/Base.cls | 3 +- src/cls/IPM/Main.cls | 12 +++--- src/cls/IPM/Repo/Filesystem/Cache.cls | 2 +- src/cls/IPM/Repo/Manager.cls | 41 ++++++++++-------- .../ResourceProcessor/Default/Document.cls | 32 ++++++++------ .../Default/LocalizedMessages.cls | 4 -- .../IPM/ResourceProcessor/Default/Package.cls | 8 ++-- src/cls/IPM/Storage/LoadedResource.cls | 9 +++- src/cls/IPM/Storage/Module.cls | 27 +++++++++--- src/cls/IPM/Storage/ModuleInfo.cls | 3 +- src/cls/IPM/Storage/ModuleReference.cls | 9 +++- src/cls/IPM/Storage/QualifiedModuleInfo.cls | 3 +- src/cls/IPM/Utils/Build.cls | 4 ++ src/cls/IPM/Utils/Module.cls | 7 ++- 18 files changed, 167 insertions(+), 66 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..61e7c0b1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,43 @@ +# InterSystems Package Manager + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased - 0.9.0+snapshot] + +### Added +- + +### Changed +- HSIEO-9484: Add additional argument to buildDepsGraph to allow putting in an additional list element of dependency's DisplayName +- HSIEO-9484: Add additional property DisplayName to %IPM.Storage.ModuleReference + +### Fixed +- HSIEO-9269, HSIEO-9402: % percent perforce directories are no longer necessary +- HSIEO-9269, HSIEO-9404: Repo check should happen in the order to repo creation, not by repo name +- HSIEO-9269, HSIEO-9411: Make sure can load and export xml Package-type resource +- HSIEO-9269, HSIEO-9403: Ensure studio project uses display name. +- HSIEO-9269, HSIEO-9404: Repo check should happen in the order to repo creation, not by repo name +- HSIEO-9269, HSIEO-9366: Make sure VersionInfo uses exact database namespace instead +- HSIEO-9269, HSIEO-9384: %IPM.Utils.Build:CreateNamespace should not call %IPM class from %SYS namespace +- HSIEO-9269, HSIEO-9333: OnDetermineResourceDeployability should make sure to check uppercase of item suffix +- HSIEO-9269, HSIEO-9315: HSCC needs to re-create %IPM mapping for application namespace because of its mapping deletion +- HSIEO-9269, HSIEO-9276: Fix dependency analyzer issue +- HSIEO-9269, HSIEO-9275: IsAvailable() method need to work robustly +- HSIEO-9269, HSIEO-9277, HSIEO-9235: Remove exportDeployedItem temporarily until HSIEO-9235 +- HSIEO-9269, HSIEO-9278: Mark based module as non deployed if install in dev mode +- HSIEO-9269, HSIEO-9279: Enable resource mapping creation during build +- HSIEO-9269, HSIEO-9280: Load unittest code during module install +- HSIEO-9430: Module definition should not expose DisplayName + deprecate DisplayNameInternal as it will not be used anymore +- HSIEO-9924: RunDev needs to do complete installation of component and dependencies via ignoreInstalled, so adding ignoreInstalledModules checker in syncLoadDependencies + +### Security +- + +### Removed +- + +### Deprecated +- \ No newline at end of file diff --git a/src/cls/IPM/DependencyAnalyzer.cls b/src/cls/IPM/DependencyAnalyzer.cls index 31cc5a84..e4edb697 100644 --- a/src/cls/IPM/DependencyAnalyzer.cls +++ b/src/cls/IPM/DependencyAnalyzer.cls @@ -371,7 +371,7 @@ ClassMethod FindReferenceHelper(pIsModule As %Boolean, pName As %String = "", pI If $IsObject(tHomeModule) { Set tHomeModuleName = tHomeModule.Name } - If 'pIsModule && ($ZConvert(tRawFileName_tFileType,"U") '= $ZConvert(pName,"U")) { + If pIsModule || ('pIsModule && ($ZConvert(tRawFileName_tFileType,"U") '= $ZConvert(pName,"U"))) { // For non modules, need to ensure references to class itself aren't output Merge pReferences(tHomeModuleName,tRawFileName,tFileType) = $$$ZPMDependencyTempData(tNextCounter,tReferenceKey) } diff --git a/src/cls/IPM/ExtensionBase/CompositeMethodOverrides.cls b/src/cls/IPM/ExtensionBase/CompositeMethodOverrides.cls index 08e56350..b73e2257 100644 --- a/src/cls/IPM/ExtensionBase/CompositeMethodOverrides.cls +++ b/src/cls/IPM/ExtensionBase/CompositeMethodOverrides.cls @@ -128,7 +128,7 @@ ClassMethod SetSubExtensionClasses(pClassNames As %List) As %Status } } $$$ThrowOnError(tStatus) - Set @..#SUBEXTENSIONGBL = tClassNames + Set @..#SUBEXTENSIONGBL = pClassNames } Catch e { Set tStatus = e.AsStatus() } diff --git a/src/cls/IPM/General/ModuleInfo.cls b/src/cls/IPM/General/ModuleInfo.cls index 1aed7a76..83b3e456 100644 --- a/src/cls/IPM/General/ModuleInfo.cls +++ b/src/cls/IPM/General/ModuleInfo.cls @@ -9,7 +9,7 @@ Parameter XMLIGNOREINVALIDTAG = 1; Parameter XMLIGNOREINVALIDATTRIBUTE = 1; /// lowercase storage name of the module -Property Name As %IPM.DataType.ModuleName(%JSONFIELDNAME = "name") [ Required ]; +Property Name As %IPM.DataType.ModuleName(%JSONINCLUDE = "NONE", XMLPROJECTION = "NONE") [ Required ]; Property Description As %String(%JSONFIELDNAME = "description", MAXLEN = 1000); @@ -31,14 +31,24 @@ Property PlatformVersion As %String(%JSONFIELDNAME = "platform_version", MAXLEN Property Repository As %String(MAXLEN = "", XMLPROJECTION = "NONE"); /// Case-sensitive display name of the module as it appears in the module manifest -Property DisplayNameInternal As %IPM.DataType.ModuleName(%JSONINCLUDE = "NONE") [ Internal ]; +Property DisplayName As %IPM.DataType.ModuleName(%JSONFIELDNAME = "name", XMLNAME = "Name"); -Property DisplayName As %IPM.DataType.ModuleName(%JSONFIELDNAME = "displayName") [ Calculated, SqlComputeCode = { Set {*} = $Case({DisplayNameInternal}, "": {Name}, : {DisplayNameInternal})}, SqlComputed ]; +Method NameSet(val As %String) As %Status +{ + Set i%Name = $$$lcase(val) + Set i%DisplayName = val + Return $$$OK +} -Method NameSet(val As %RawString) As %Status +Method DisplayNameSet(val As %String) As %Status { + If (i%Name '= "") { + If (i%Name '= $$$lcase(val)) { + Return $$$ERROR($$$GeneralError, "DisplayName needs to be case sensitive form of module name: "_i%Name) + } + } + Set i%DisplayName = val Set i%Name = $$$lcase(val) - Set i%DisplayNameInternal = val Return $$$OK } @@ -54,4 +64,4 @@ Method VersionStringGet() As %String Quit ..Version.ToString() } -} +} \ No newline at end of file diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 77c31193..9dfe5531 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -1494,7 +1494,7 @@ Method OnDetermineResourceDeployability(ByRef pParams, ByRef pResourceInfo, Outp Set tSC = $$$OK Try { If $Data(pParams("Deploy","Parameter"),tDeployParameter)#2 && (tDeployParameter '= "") { - If ($Piece(pResourceInfo("Name"),".",*) = "CLS") { + If ($ZCVT($Piece(pResourceInfo("Name"),".",*), "U") = "CLS") { Set tClass = $Piece(pResourceInfo("Name"),".",1,*-1) If $$$comClassDefined(tClass) && $$$defMemberDefined(tClass,$$$cCLASSparameter,tDeployParameter) { // e.g., HSDEPLOY, HSAADEPLOY @@ -1610,4 +1610,3 @@ Query Packaging(pPackaging As %String = "") As %SQLQuery [ Final, SqlProc ] } } - diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index b22333e5..a4625f7a 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -1153,12 +1153,14 @@ ClassMethod IsAvailable(pModuleName As %String, pNamespace As %String = "", pArg If pNamespace'="" { Set $namespace = pNamespace } - Set module = ##class(%IPM.Storage.Module).NameOpen(pModuleName,0,.sc) - $$$ThrowOnError(sc) - If module.AvailabilityClass ="" { - Quit 1 + If '##class(%IPM.Storage.Module).NameExists(pModuleName,.id) { + Return 0 + } + Set availabilityClass = ##class(%IPM.Storage.Module).AvailabilityClassGetStored(id) + If availabilityClass = "" { + Return 1 } - Quit $ClassMethod(module.AvailabilityClass,"IsAvailable",pNamespace,pArgs...) + Quit $ClassMethod(availabilityClass,"IsAvailable",pNamespace,pArgs...) } ClassMethod GetNamespaceDefaultModifiers(Output pDefaultArray) [ Internal ] diff --git a/src/cls/IPM/Repo/Filesystem/Cache.cls b/src/cls/IPM/Repo/Filesystem/Cache.cls index 8f7cd9c7..047748d5 100644 --- a/src/cls/IPM/Repo/Filesystem/Cache.cls +++ b/src/cls/IPM/Repo/Filesystem/Cache.cls @@ -150,7 +150,7 @@ Storage Default PlatformVersion -DisplayNameInternal +DisplayName ^IPM.Repo.Filesystem.CacheD diff --git a/src/cls/IPM/Repo/Manager.cls b/src/cls/IPM/Repo/Manager.cls index 68bff6dd..ef19511d 100644 --- a/src/cls/IPM/Repo/Manager.cls +++ b/src/cls/IPM/Repo/Manager.cls @@ -61,8 +61,8 @@ Method SearchRepositoriesForModule(pSearchCriteria As %IPM.Repo.SearchCriteria, If $$$ISERR(tSC) { Quit } - - Set tServer = ##class(%IPM.Repo.Definition).%OpenId(tRes.%Get("ID"),,.tSC) + Set repoID = tRes.%Get("ID") + Set tServer = ##class(%IPM.Repo.Definition).%OpenId(repoID,,.tSC) If $$$ISERR(tSC) { Quit } @@ -93,34 +93,39 @@ Method SearchRepositoriesForModule(pSearchCriteria As %IPM.Repo.SearchCriteria, For i=1:1:tServerResults.Count() { Set item = tServerResults.GetAt(i) #; Sorting versions - Set versions(tServer.Name, +item.Version.Major, +item.Version.Minor, +item.Version.Patch, " "_item.Version.Patch_"_"_item.Version.Prerelease) = item + Set versions(+item.Version.Major, +item.Version.Minor, +item.Version.Patch, " "_item.Version.Patch_"_"_item.Version.Prerelease, repoID, tServer.Name) = item } } - Set name = "" - For { - Set name = $Order(versions(name)) - Quit:name="" - Set major = "" - For { - Set major = $Order(versions(name, major), -1) - Quit:major="" - Set minor = "" - For { - Set minor = $Order(versions(name, major, minor), -1) + Set major = "" + For { + Set major = $Order(versions(major), -1) + Quit:major="" + Set minor = "" + For { + Set minor = $Order(versions(major, minor), -1) Quit:minor="" Set patch = "" For { - Set patch = $Order(versions(name, major, minor, patch), -1) + Set patch = $Order(versions(major, minor, patch), -1) Quit:patch="" Set sub = "" For { - Set sub = $Order(versions(name, major, minor, patch, sub), 1, item) + Set sub = $Order(versions(major, minor, patch, sub), 1) Quit:sub="" - Do pResults.Insert(##class(%IPM.Storage.QualifiedModuleInfo).%New(name, item)) + Set repoOrder = "" + For { + Set repoOrder = $Order(versions(major, minor, patch, sub, repoOrder), 1) + Quit:repoOrder="" + Set name = "" + For { + Set name = $Order(versions(major, minor, patch, sub, repoOrder, name), 1, item) + Quit:name="" + Do pResults.Insert(##class(%IPM.Storage.QualifiedModuleInfo).%New(name, item)) + } + } } } } - } } } Catch e { If (e.Name["ZSOAP") && $Data(%objlasterror) { diff --git a/src/cls/IPM/ResourceProcessor/Default/Document.cls b/src/cls/IPM/ResourceProcessor/Default/Document.cls index ec89daa7..f754a516 100644 --- a/src/cls/IPM/ResourceProcessor/Default/Document.cls +++ b/src/cls/IPM/ResourceProcessor/Default/Document.cls @@ -90,10 +90,11 @@ Method OnPhase(pPhase As %String, ByRef pParams, Output pResourceHandled As %Boo Set tSourcesPrefix = $c($parameter("%IPM.ExtensionBase.SourceControl.Interface","NOPREFIXCHARCODE")) If '$Get(pParams("NoMapping"),0) { - // Disabled mapping of resources. It creates more problems than solves. - // Moreover, the removal of mapping during uninstallation is not implemented. - // $$$ThrowOnError(..OnConfigureMappings(.pParams)) - } + // Currently, still need mapping creation, since if a module is installed with a resource + // already presented in another namespace and have a upperlevel mapping to another namespace, + // then it should have a package mapping of this specific resource to its namespace database + $$$ThrowOnError(..OnConfigureMappings(.pParams)) + } If ..ResourceReference.Generated { Set pResourceHandled = 1 Quit @@ -173,7 +174,9 @@ Method OnPhase(pPhase As %String, ByRef pParams, Output pResourceHandled As %Boo Method OnExportItem(pFullExportPath As %String, pItemName As %String, ByRef pItemParams, ByRef pParams, Output pItemHandled As %Boolean = 0) As %Status { - Set tSC = ..OnExportDeployedItem(pFullExportPath, pItemName, .pItemParams, .pParams, .pItemHandled) + // Resolve the issue in HSIEO-9235 before enabling deployed item export + // Set tSC = ..OnExportDeployedItem(pFullExportPath, pItemName, .pItemParams, .pParams, .pItemHandled) + Set tSC = $$$OK If pItemHandled || $$$ISERR(tSC) { Quit tSC } @@ -370,12 +373,18 @@ Method OnLoad(pFullResourcePath As %String, pVerbose As %Boolean, pCompile As %B $Select($Tlevel||..ResourceReference.Deploy:"/multicompile=0",1:"") If ..LoadAsDirectory { - Set tSC = $System.OBJ.ImportDir(pFullResourcePath, "*", tFlags, , 1, .pLoadedList) - $$$ThrowOnError(tSC) - If $Data(pLoadedList)>1 { - Merge tResult = pLoadedList - Set pLoadedList = "" - } + Set tSC = $System.OBJ.ImportDir(pFullResourcePath, "*"_..FilenameExtension, tFlags, , 1, .pLoadedList) + $$$ThrowOnError(tSC) + Set pLoadedList = "" // ImportDir returns as an array and clears the top node + Set tResourceKey = "" + For { + Set tResourceKey = $Order(pLoadedList(tResourceKey)) + If (tResourceKey = "") { + Quit + } + Set pLoadedList = pLoadedList_$ListBuild(tResourceKey) + } + Set pLoadedList = $ListToString(pLoadedList) } ElseIf (..Format = "%RO") { // This tolerates some unusual %RO header formats that $System.OBJ.Load does not respect. Set pLoadedList = "" @@ -591,4 +600,3 @@ ClassMethod FileExistsInCurrentNS(pFileName As %String) As %Boolean } } - diff --git a/src/cls/IPM/ResourceProcessor/Default/LocalizedMessages.cls b/src/cls/IPM/ResourceProcessor/Default/LocalizedMessages.cls index 4b4d58b3..f49ceee3 100644 --- a/src/cls/IPM/ResourceProcessor/Default/LocalizedMessages.cls +++ b/src/cls/IPM/ResourceProcessor/Default/LocalizedMessages.cls @@ -8,10 +8,6 @@ Parameter DESCRIPTION As STRING = "Standard resource processor for localized err /// The only expected use case at this point is class packages (.PKG, but Extension will be .CLS) Parameter EXTENSION = "LOC"; -/// Characters in the filename to use as the associator in $translate when determining the resource's filename on disk -/// The default behavior is to replace "." with "/" and change "%" to "_" -Property FilenameTranslateAssociator As %String [ InitialExpression = "/_" ]; - /// Directory relative to module root containing the exported resource. /// Defaults to the resource's extension (lower-case) if unspecified. Property Directory As %String(MAXLEN = "") [ InitialExpression = "localize" ]; diff --git a/src/cls/IPM/ResourceProcessor/Default/Package.cls b/src/cls/IPM/ResourceProcessor/Default/Package.cls index 63b5ab75..16c876df 100644 --- a/src/cls/IPM/ResourceProcessor/Default/Package.cls +++ b/src/cls/IPM/ResourceProcessor/Default/Package.cls @@ -15,6 +15,9 @@ Property Directory As %String(MAXLEN = "") [ InitialExpression = "cls" ]; Property LoadAsDirectory As %Boolean [ InitialExpression = 1 ]; +/// Extension for individual filename(s) that comprise this resource +Property FilenameExtension As %String [ InitialExpression = "" ]; + /// Subclasses may override to customize mapping behavior at the beginning of the Reload phase. Method OnConfigureMappings(ByRef pParams) As %Status { @@ -61,7 +64,7 @@ Method OnItemRelativePath(pItemName As %String, pIsUnitTest As %Boolean = 0) As Set tSourceRoot = tSourceRoot _ "/" } } - set fileNameExtension = $$$lcase($Piece(pItemName, ".", *)) + set fileNameExtension = $Select(..FilenameExtension = "": $$$lcase($Piece(pItemName, ".", *)), 1: ..FilenameExtension) set directory = ..Directory #; set directory = fileNameExtension set fileName = $tr($Piece(pItemName, ".", 1, *-1),..FilenameTranslateIdentifier,..FilenameTranslateAssociator) _ "." _ fileNameExtension @@ -70,9 +73,8 @@ Method OnItemRelativePath(pItemName As %String, pIsUnitTest As %Boolean = 0) As Method OnExportItem(pFullExportPath As %String, pItemName As %String, ByRef pItemParams, ByRef pParams, Output pItemHandled As %Boolean = 0) As %Status { - set ..Format = "UDL" + Set ..Format = $Case($$$lcase(..FilenameExtension),"xml":"XML",:"UDL") Quit ##super(pFullExportPath, pItemName, .pItemParams, .pParams, .pItemHandled) } } - diff --git a/src/cls/IPM/Storage/LoadedResource.cls b/src/cls/IPM/Storage/LoadedResource.cls index 05c2c779..1ac7d430 100644 --- a/src/cls/IPM/Storage/LoadedResource.cls +++ b/src/cls/IPM/Storage/LoadedResource.cls @@ -32,7 +32,14 @@ ClassMethod TrackResourceNames(pModuleName As %String, pResourceName As %String, "where Namespace = ? and ModuleName = ? and ResourceUniqueName = ?", pNamespace,pModuleName,pResourceName) If (tResult.%SQLCODE < 0) { - Throw ##class(%Exception.SQL).CreateFromSQLCODE(tResult.%SQLCODE,tResult.%Message) + // Purge cached query and retry + Do $SYSTEM.SQL.PurgeCQClass("%sqlcq."_pNamespace_".cls1") + Set tNewResult = ##class(%SQL.Statement).%ExecDirect(,"delete from %IPM_Storage.LoadedResource "_ + "where Namespace = ? and ModuleName = ? and ResourceUniqueName = ?", + pNamespace,pModuleName,pResourceName) + If (tNewResult.%SQLCODE < 0) { + Throw ##class(%Exception.SQL).CreateFromSQLCODE(tNewResult.%SQLCODE,tNewResult.%Message) + } } Set tResourceList = $ListFromString(pResourceList) diff --git a/src/cls/IPM/Storage/Module.cls b/src/cls/IPM/Storage/Module.cls index f4094df6..fdd6573d 100644 --- a/src/cls/IPM/Storage/Module.cls +++ b/src/cls/IPM/Storage/Module.cls @@ -542,7 +542,7 @@ Method LoadDependencies(pPhaseList As %List, ByRef pParams) As %Status Quit tSC } -Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pForceSnapshotReload As %Boolean = 0, ByRef qstruct, pPhases As %String = "", ByRef pSubModules, pPass As %Integer = 1, pModulePath As %List = {$ListBuild(..Name)}, pIgnoreInstalledModules As %Boolean = 0, pKnownDependencies As %List = {..GetKnownDependencies(..Name)}, pPermitDowngrade As %Boolean = 0, pCheckNestedScoped As %Boolean = 0, ByRef pSearchList) As %Status +Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pForceSnapshotReload As %Boolean = 0, ByRef qstruct, pPhases As %String = "", ByRef pSubModules, pPass As %Integer = 1, pModulePath As %List = {$ListBuild(..Name)}, pIgnoreInstalledModules As %Boolean = 0, pKnownDependencies As %List = {..GetKnownDependencies(..Name)}, pPermitDowngrade As %Boolean = 0, pCheckNestedScoped As %Boolean = 0, ByRef pSearchList, pIncludeDisplayName As %Boolean = 0) As %Status { #define EXACT 1 #define FUZZY 2 @@ -663,6 +663,9 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor Set tLocalMod = 1 Set tDepth = $Select(tPreviousDepth=0:pDepth,tPreviousDepth>pDepth:tPreviousDepth,1:pDepth) Set pDependencyGraph(tDep.Name) = $ListBuild(pDepth,"",tLocalObj.VersionString) + If (pIncludeDisplayName) { + Set pDependencyGraph(tDep.Name) = pDependencyGraph(tDep.Name)_$ListBuild(tDep.DisplayName) + } Set pDependencyGraph(tDep.Name,..Name_" "_..VersionString) = tDep.VersionString Set pSubModules(tDepth,tDep.Name) = tLocalObj Set pSubModules(tDepth,tDep.Name,$$$SCOPE) = tDep.Scope @@ -754,12 +757,15 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor If (pPass = $$$EXACT) { Set pDependencyGraph(tDep.Name) = $ListBuild(pDepth, tQualifiedReference.ServerName, tModule.VersionString, tQualifiedReference.Deployed, tQualifiedReference.PlatformVersion) + If (pIncludeDisplayName) { + Set pDependencyGraph(tDep.Name) = pDependencyGraph(tDep.Name)_$ListBuild(tDep.DisplayName) + } Set pDependencyGraph(tDep.Name,..Name_" "_..VersionString) = tDep.VersionString Set pSubModules(tDepth,tDep.Name) = tModule Set pSubModules(tDepth,tDep.Name,$$$SCOPE) = tDep.Scope // If we have an exact match, attempt to resolve exact dependencies recursively. - Set tSC = tModule.BuildDependencyGraph(.pDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.pSubModules,,tModulePath_$ListBuild(tDep.Name),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList) + Set tSC = tModule.BuildDependencyGraph(.pDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.pSubModules,,tModulePath_$ListBuild(tDep.Name),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList,pIncludeDisplayName) // Failure to resolve any of these dependencies is an immediate failure, and can be descriptive. If $$$ISERR(tSC) { @@ -772,13 +778,16 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor If (pPass = $$$FUZZY) { Set tDependencyGraph(tDep.Name) = $ListBuild(tDepth,tQualifiedReference.ServerName,tModule.VersionString) + If (pIncludeDisplayName) { + Set tDependencyGraph(tDep.Name) = tDependencyGraph(tDep.Name)_$ListBuild(tDep.DisplayName) + } Set tDependencyGraph(tDep.Name,..Name_" "_..VersionString) = tDep.VersionString Set tSubModules(tDepth,tDep.Name) = tModule // For fuzzy version matching, preview the next graph step; move to the next version if it would lead to failure. // If not, update. - Set tPossibleSC = tModule.BuildDependencyGraph(.tDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.tSubModules,,tModulePath_$ListBuild(tDep.Name),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList) + Set tPossibleSC = tModule.BuildDependencyGraph(.tDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.tSubModules,,tModulePath_$ListBuild(tDep.Name),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList,pIncludeDisplayName) If $$$ISOK(tPossibleSC) { // We have a match - let's go with it. Actually dependency resolution will be done later, breadth-first. // TODO: Caching of results to avoid duplicate web service calls. @@ -795,6 +804,9 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor // We don't actually care if a valid result was found. // There will always be something in here, it just might lead to a descriptive error later on in the case of fuzzy matching with no valid option. Set pDependencyGraph(tDep.Name) = $ListBuild(pDepth,tQualifiedReference.ServerName,tModule.VersionString) + If (pIncludeDisplayName) { + Set pDependencyGraph(tDep.Name) = pDependencyGraph(tDep.Name)_$ListBuild(tDep.DisplayName) + } Set pDependencyGraph(tDep.Name,..Name_" "_..VersionString) = tDep.VersionString Set pSubModules(tDepth,tDep.Name) = tModule Set pSubModules(tDepth,tDep.Name,$$$SCOPE) = tDep.Scope @@ -807,7 +819,7 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor If (pPass = $$$EXACT) { // Call for second pass (fuzzy version matching) - Set tSC = ..BuildDependencyGraph(.pDependencyGraph,pDepth,pForceSnapshotReload,.qstruct,pPhases,.pSubModules,$$$FUZZY,pModulePath,pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList) + Set tSC = ..BuildDependencyGraph(.pDependencyGraph,pDepth,pForceSnapshotReload,.qstruct,pPhases,.pSubModules,$$$FUZZY,pModulePath,pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList,pIncludeDisplayName) If $$$ISERR(tSC) { Quit } @@ -822,7 +834,7 @@ Method BuildDependencyGraph(ByRef pDependencyGraph, pDepth As %Integer = 1, pFor Set tModName = $Order(pSubModules(pDepth,tModName),1,tModule) Quit:tModName="" Set tModulePath = $Case(pSubModules(pDepth,tModName,$$$SCOPE),"":pModulePath,:"") - Set tSC = tModule.BuildDependencyGraph(.pDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.pSubModules,,tModulePath_$ListBuild(tModName),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList) + Set tSC = tModule.BuildDependencyGraph(.pDependencyGraph,pDepth+1,pForceSnapshotReload,.qstruct,tPhases,.pSubModules,,tModulePath_$ListBuild(tModName),pIgnoreInstalledModules,pKnownDependencies,pPermitDowngrade,,.pSearchList,pIncludeDisplayName) If $$$ISERR(tSC) { Quit } @@ -1264,7 +1276,7 @@ Method GetStudioProject(Output pProject As %Studio.Project, pDeployedCode As %Bo { Set tSC = $$$OK Try { - Set tProjectName = $Replace(..Name,".","_")_$Case(pProjectSuffix,"":"",:"_"_pProjectSuffix) + Set tProjectName = $Replace(..DisplayName,".","_")_$Case(pProjectSuffix,"":"",:"_"_pProjectSuffix) If ##class(%Studio.Project).%ExistsId(tProjectName) { Set pProject = ##class(%Studio.Project).%OpenId(tProjectName,,.tSC) $$$ThrowOnError(tSC) @@ -1508,7 +1520,7 @@ Storage Default PlatformVersion -DisplayNameInternal +DisplayName AvailabilityClass @@ -1523,3 +1535,4 @@ Storage Default } } + diff --git a/src/cls/IPM/Storage/ModuleInfo.cls b/src/cls/IPM/Storage/ModuleInfo.cls index 6cbbccc1..1f27d5d4 100644 --- a/src/cls/IPM/Storage/ModuleInfo.cls +++ b/src/cls/IPM/Storage/ModuleInfo.cls @@ -40,7 +40,7 @@ Storage Default PlatformVersions -DisplayNameInternal +DisplayName ModuleInfoState @@ -49,3 +49,4 @@ Storage Default } } + diff --git a/src/cls/IPM/Storage/ModuleReference.cls b/src/cls/IPM/Storage/ModuleReference.cls index 72c21d3e..8bd299d6 100644 --- a/src/cls/IPM/Storage/ModuleReference.cls +++ b/src/cls/IPM/Storage/ModuleReference.cls @@ -17,6 +17,8 @@ Property VersionString As %String(MAXLEN = 100, XMLNAME = "Version") [ Required /// Restrict the scope in which this reference is relevant. Default is "all scopes" Property Scope As %String(VALUELIST = ",test,verify", XMLPROJECTION = "ATTRIBUTE"); +Property DisplayName As %String(MAXLEN = 255) [ Internal ]; + Method VersionStringSet(tValue) As %Status { Set i%VersionString = tValue @@ -29,7 +31,8 @@ Method VersionStringSet(tValue) As %Status Method NameSet(val As %RawString) As %Status { - set i%Name = $$$lcase(val) + Set i%DisplayName = val + Set i%Name = $$$lcase(val) QUIT $$$OK } @@ -48,6 +51,9 @@ Storage Default Scope + +DisplayName + ModuleReferenceState ^IPM.Storage.ModuleReferenceS @@ -55,3 +61,4 @@ Storage Default } } + diff --git a/src/cls/IPM/Storage/QualifiedModuleInfo.cls b/src/cls/IPM/Storage/QualifiedModuleInfo.cls index 89f4214d..ffceb05c 100644 --- a/src/cls/IPM/Storage/QualifiedModuleInfo.cls +++ b/src/cls/IPM/Storage/QualifiedModuleInfo.cls @@ -59,10 +59,11 @@ Storage Default PlatformVersions -DisplayNameInternal +DisplayName %Storage.Serial } } + diff --git a/src/cls/IPM/Utils/Build.cls b/src/cls/IPM/Utils/Build.cls index 472fc3ec..9d3512f0 100644 --- a/src/cls/IPM/Utils/Build.cls +++ b/src/cls/IPM/Utils/Build.cls @@ -319,6 +319,7 @@ ClassMethod DeleteDatabase(pDBName As %String, pIsLibraryDatabase As %Boolean = ClassMethod CreateNamespace(pNSName As %String, pCodeDBName As %String, pDataDBName As %String, pVerbose As %Boolean = 1, pNSConfig As %IPM.Storage.ModuleSetting.NamespaceConfig) As %Status { + Set prevNS = $Namespace New $Namespace Set tSC = $$$OK Try { @@ -377,10 +378,13 @@ ClassMethod CreateNamespace(pNSName As %String, pCodeDBName As %String, pDataDBN } // Always add mapping for ^%IPM.Dev.* to the CODE database (for modules) + // Switch back from %SYS to previous namespace as %SYS does not contain IPM classes + Set $Namespace = prevNS Set tSC = ##class(%IPM.Utils.Module).AddGlobalMapping(pNSName,"HS.PM.Dev.*",pCodeDBName) If $$$ISERR(tSC) { Quit } + Set $Namespace = "%SYS" If pNSConfig.EnableHealthShare { // Create default web application diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index f9094ff2..fa49e7a0 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -1162,7 +1162,9 @@ ClassMethod LoadNewModule(pDirectory As %String, ByRef pParams, pRepository As % $$$ThrowOnError(tSC) Set tModule.Repository = pRepository - If 'tModule.Deployed,$Data(pParams("DeveloperMode"),tDeveloperMode) { + If $Data(pParams("DeveloperMode"),tDeveloperMode) { + // Mark module as not deployed if installing with dev mode + Set tModule.Deployed = 0 Set tModule.DeveloperMode = tDeveloperMode Set tModule.Root = pDirectory Set tSC = tModule.%Save() @@ -1259,8 +1261,9 @@ ClassMethod SyncLoadDependencies(pModule As %IPM.Storage.Module, ByRef pParams) Set reloadSnapshots = +$Get(pParams("UpdateSnapshots")) Set permitDowngrade = +$Get(pParams("PermitDowngrade")) + Set ignoreInstalled = +$Get(pParams("IgnoreInstalled")) Write !, "Building dependency graph..." // Intentionally always write even in non-verbose mode - Set sc = pModule.BuildDependencyGraph(.depdendencyGraph,,reloadSnapshots,,"",,,,,,permitDowngrade) + Set sc = pModule.BuildDependencyGraph(.depdendencyGraph,,reloadSnapshots,,"",,,,ignoreInstalled,,permitDowngrade) $$$ThrowOnError(sc) Write "Done." From 6d1be2d9e156a8432b940fd73feda66078b4fdd0 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:25:43 -0500 Subject: [PATCH 24/42] CI workflow changes Suppress clean install current version / test new one until we make it work Theoretically show output from docker run on the current device? --- .github/workflows/main.yml | 52 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 137031ab..8d625b13 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -131,7 +131,8 @@ jobs: - name: Test and publish to temporary registry timeout-minutes: 15 run: | - docker run --network zpm -d --rm -v `pwd`:/home/irisowner/zpm/ zpm ${{ steps.image.outputs.flags }} + docker run --network zpm -d --rm -v `pwd`:/home/irisowner/zpm/ zpm ${{ steps.image.outputs.flags }} \ + --log-driver=none -a stdin -a stdout -a stderr CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh /bin/echo -e '' \ @@ -147,34 +148,35 @@ jobs: 'halt\n' \ | docker exec -i $CONTAINER iris session iris -U%SYS docker stop $CONTAINER - - name: Clean install current version and test new one. (Permitted to fail on 2023.1+) - timeout-minutes: 15 - run: | - curl http://localhost:52773/registry/packages/-/all | jq - curl http://localhost:52773/registry/packages/zpm/ | jq - wget https://pm.community.intersystems.com/packages/zpm/latest/installer -O /tmp/zpm.xml - docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} - CONTAINER=`docker ps -lq` - sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh - /bin/echo -e '' \ - 'set sc = ##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm.xml", "ck")\n' \ - 'if +sc=0 { halt:$System.Version.GetMajor()>=2023 do ##class(%SYSTEM.Process).Terminate(,1) }\n' \ - 'zpm "list":1\n' \ - 'zpm "repo -r -name registry -url ""http://registry:52773/registry/"" -username admin -password SYS":1\n' \ - 'zpm "repo -list"\n' \ - 'zpm "search":1\n' \ - 'zpm "install sslclient":1\n' \ - 'zpm "install zpm -v":1\n' \ - 'zpm "list":1\n' \ - 'zpm "version":1\n' \ - 'halt\n' \ - | docker exec -i $CONTAINER iris session iris -U%SYS - docker stop $CONTAINER + # - name: Clean install current version and test new one. (Permitted to fail on 2023.1+) + # timeout-minutes: 15 + # run: | + # curl http://localhost:52773/registry/packages/-/all | jq + # curl http://localhost:52773/registry/packages/zpm/ | jq + # wget https://pm.community.intersystems.com/packages/zpm/latest/installer -O /tmp/zpm.xml + # docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} + # CONTAINER=`docker ps -lq` + # sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh + # /bin/echo -e '' \ + # 'set sc = ##class(%SYSTEM.OBJ).Load("/home/irisowner/zpm.xml", "ck")\n' \ + # 'if +sc=0 { halt:$System.Version.GetMajor()>=2023 do ##class(%SYSTEM.Process).Terminate(,1) }\n' \ + # 'zpm "list":1\n' \ + # 'zpm "repo -r -name registry -url ""http://registry:52773/registry/"" -username admin -password SYS":1\n' \ + # 'zpm "repo -list"\n' \ + # 'zpm "search":1\n' \ + # 'zpm "install sslclient":1\n' \ + # 'zpm "install zpm -v":1\n' \ + # 'zpm "list":1\n' \ + # 'zpm "version":1\n' \ + # 'halt\n' \ + # | docker exec -i $CONTAINER iris session iris -U%SYS + # docker stop $CONTAINER - name: Clean install and test timeout-minutes: 15 run: | wget http://localhost:52773/registry/packages/zpm/latest/installer -O /tmp/zpm.xml - docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} + docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} \ + --log-driver=none -a stdin -a stdout -a stderr CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh /bin/echo -e '' \ From b554c023283c3bf2f2acb3f10beb843bdb487d09 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:55:31 -0500 Subject: [PATCH 25/42] Support act for running CI on a dev's machine e.g. with: act -j "build" --input IMAGE="[\"iris-community:latest-em\"]" --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8d625b13..2396d5a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,6 +26,7 @@ jobs: - uses: actions/checkout@master - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Images list + if: ${{ !env.ACT }} id: set-matrix run: | images="" @@ -51,7 +52,7 @@ jobs: strategy: fail-fast: false matrix: - image: ${{ fromJson(needs.prepare.outputs.images) }} + image: ${{ fromJson(github.event.inputs.IMAGE || needs.prepare.outputs.images) }} runs-on: ubuntu-latest steps: - uses: actions/checkout@master From 18fac8c881f1a09df4eac3869cea437932a70b6b Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:35:48 -0500 Subject: [PATCH 26/42] Shorten image list and break into separate file Easier to run via act for testing. We now omit old previews and no longer truncate valid tags containing dashes --- .github/workflows/images.yml | 33 +++++++++++++++++++++++++++++++++ .github/workflows/main.yml | 26 +++++++++----------------- 2 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/images.yml diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml new file mode 100644 index 00000000..ffe8a4e8 --- /dev/null +++ b/.github/workflows/images.yml @@ -0,0 +1,33 @@ +name: Images List +on: + workflow_call: + outputs: + images: + description: "The full list of images to use, as a JSON array of imagename:tag" + value: ${{ jobs.images.outputs.images }} + secondword: + description: "The main image to use (earliest relevant version) to generate the installer XML file" + value: ${{ jobs.images.outputs.main }} + +env: + name: | + irishealth-community + iris-community + +jobs: + images: + runs-on: ubuntu-latest + outputs: + images: ${{ steps.set-matrix.outputs.images }} + main: ${{ steps.set-matrix.outputs.main }} + steps: + - name: Images list + id: set-matrix + run: | + images="" + for n in $name; do + tags=$(curl -su ":" https://containers.intersystems.com/v2/intersystems/${n}/tags/list | jq -r '.tags[]' | awk '!/(-linux)|([1-4]-preview)/' | awk '!/\.[1-4]\.0\./' | uniq) + for tag in $tags; do images+='"'${n}:${tag}'",'; done + done; + echo images="[${images%?}]" >> $GITHUB_OUTPUT + echo main=${images%%,*} >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2396d5a1..a3f3245d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,31 +11,21 @@ on: release: types: - released -env: - name: | - irishealth-community - iris-community + jobs: + images: + uses: ./.github/workflows/images.yml + prepare: runs-on: ubuntu-latest + needs: images outputs: - images: ${{ steps.set-matrix.outputs.images }} - main: ${{ steps.set-matrix.outputs.main }} + images: ${{ needs.images.outputs.images }} + main: ${{ needs.images.outputs.main }} version: ${{ steps.version.outputs.number }} steps: - uses: actions/checkout@master - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - name: Images list - if: ${{ !env.ACT }} - id: set-matrix - run: | - images="" - for n in $name; do - tags=$(curl -su ":" https://containers.intersystems.com/v2/intersystems/${n}/tags/list | jq -r '.tags[]' | cut -d '-' -f1 | uniq) - for tag in $tags; do images+='"'${n}:${tag}'",'; done - done; - echo images="[${images%?}]" >> $GITHUB_OUTPUT - echo main=${images%%,*} >> $GITHUB_OUTPUT - name: Setup version id: version run: | @@ -45,6 +35,7 @@ jobs: [ $GITHUB_EVENT_NAME == 'push' ] && VERSION+=-beta && VERSION+=.$(($(git tag -l "v$VERSION.*" | sort -nt. -k4 2>/dev/null | tail -1 | cut -d. -f4)+1)) [ $GITHUB_EVENT_NAME == 'pull_request' ] && VERSION+=-dev.${{ github.event.pull_request.number }} && VERSION+=.$(($(git tag -l "v$VERSION.*" | sort -nt. -k4 2>/dev/null | tail -1 | cut -d. -f5)+1)) echo number=${VERSION} >> $GITHUB_OUTPUT + build: timeout-minutes: 20 needs: @@ -203,6 +194,7 @@ jobs: with: name: zpm-${{ needs.prepare.outputs.version }} path: zpm-${{ needs.prepare.outputs.version }}.xml + release: runs-on: ubuntu-latest if: github.event.repository.fork == false From 3d00bf63433e1c68d5a31e428a42edbed1c516d5 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:49:01 -0500 Subject: [PATCH 27/42] More logging; always clean up Running locally on act, would previously leave the registry and zpm network after failure. --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a3f3245d..92b5bbbd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,6 +105,7 @@ jobs: 'zpm "verify zpm -v -only":1' \ 'halt\n' \ | docker exec -i $CONTAINER iris session iris -U%SYS + docker logs $CONTAINER docker stop $CONTAINER - name: Restart temporary registry timeout-minutes: 15 @@ -139,6 +140,7 @@ jobs: 'zpm "search":1' \ 'halt\n' \ | docker exec -i $CONTAINER iris session iris -U%SYS + docker logs $CONTAINER docker stop $CONTAINER # - name: Clean install current version and test new one. (Permitted to fail on 2023.1+) # timeout-minutes: 15 @@ -180,12 +182,14 @@ jobs: 'zpm "list":1\n' \ 'halt\n' \ | docker exec -i $CONTAINER iris session iris -U%SYS + docker logs $CONTAINER docker stop $CONTAINER - name: Prepare XML Installer timeout-minutes: 15 run: | wget http://localhost:52773/registry/packages/zpm/latest/installer -O zpm-${{ needs.prepare.outputs.version }}.xml - name: Stop temporary registry + if: always() run: | docker stop registry docker network rm zpm From 3f899c501b514f8ef5d4b278d962118c3aa32b33 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Tue, 30 Jan 2024 11:42:08 -0500 Subject: [PATCH 28/42] ci: add ci to test popular packages --- .github/workflows/packages.yml | 69 +++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index da98aff5..97e92890 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -1,19 +1,68 @@ -name: Test all packages +name: Test major packages on: workflow_dispatch + jobs: - job1: + matrix-setup: runs-on: ubuntu-latest + env: + PM_URL: https://pm.community.intersystems.com/packages/-/all?allVersions=1 + JQ_SCRIPT: reduce .[] as $item ([]; if $item.allVersions | length >= 65 then . + [$item.name] else . end) outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - - id: set-matrix - run: | - matrix=`curl https://pm.community.intersystems.com/packages/-/all | jq '.[].name' | jq -s` - echo "::set-output name=matrix::$matrix" - job2: - needs: job1 + - id: set-matrix + run: | + matrix=$(curl -L "$PM_URL" | jq -cr "$JQ_SCRIPT") + echo "matrix=$matrix" >> $GITHUB_OUTPUT + + run-builds: + timeout-minutes: 20 runs-on: ubuntu-latest + needs: matrix-setup strategy: - matrix: ${{fromJson(needs.job1.outputs.matrix)}} + fail-fast: false + matrix: + package: ${{ fromJson(needs.matrix-setup.outputs.matrix) }} + env: + IMAGE: containers.intersystems.com/intersystems/iris-community:latest-em steps: - - run: echo test \ No newline at end of file + - uses: actions/checkout@master + - name: Build + uses: docker/build-push-action@v4 + with: + context: . + push: false + load: true + tags: zpm + build-args: Base=${{ env.IMAGE }} + - name: Container Setup + id: setup-zpm + timeout-minutes: 15 + run: | + # Don't specify the container name because `act` will run multiple jobs in parallel and cause name conflicts + CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm) + echo "CONTAINER=$CONTAINER" >> $GITHUB_OUTPUT + docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh + docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF + zpm "list":1 + zpm "test zpm -v -only":1 + zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1 + halt + EOF + - name: Test ${{ matrix.package }} + timeout-minutes: 15 + env: + CONTAINER: ${{ steps.setup-zpm.outputs.CONTAINER }} + test-flags: >- + -verbose -DUnitTest.ManagerClass=UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml + -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=UnitTest.Manager + run: | + docker exec -i ${{ env.CONTAINER }} iris session IRIS -U%SYS << EOF + zpm "install ${{ matrix.package }}":1 + zpm "${{ matrix.package }} test -only ${{ env.test-flags }}":1:1 + EOF || echo -e "'\nExit code: $?' + - name: Stop Container + run: | + # To ensure a clean state after using `act` locally + docker stop -t 5 ${{ steps.setup-zpm.outputs.CONTAINER }} + docker ps From e5b48e9db8e5a23228a415285e25e1e271641ec3 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:13:01 -0500 Subject: [PATCH 29/42] Changes to run properly in act Mounts don't seem to work properly in act, so copying files instead. Fix Default.Document resource processor to not force a category subdirectory --- .github/workflows/main.yml | 24 ++++++++++--------- .vscode/settings.json | 2 +- iris.script | 7 ++++-- src/cls/IPM/Main.cls | 5 +++- .../ResourceProcessor/Default/Document.cls | 6 +++-- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 92b5bbbd..a0d55c29 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,17 +95,17 @@ jobs: -e TEST_REGISTRY=http://registry:52773/registry/ \ -e TEST_REGISTRY_USER=admin \ -e TEST_REGISTRY_PASSWORD=SYS \ - -v `pwd`:/home/irisowner/zpm/ \ zpm ${{ steps.image.outputs.flags }} CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh + docker cp . $CONTAINER:/home/irisowner/zpm/ + echo `docker exec -i --workdir /home/irisowner/zpm/ $CONTAINER ls -rtl` /bin/echo -e '' \ 'zpm "list":1\n' \ - 'zpm "test zpm -v -only":1\n' \ - 'zpm "verify zpm -v -only":1' \ + 'zpm "test zpm -v -only"\n' \ + 'zpm "verify zpm -v -only"\n' \ 'halt\n' \ - | docker exec -i $CONTAINER iris session iris -U%SYS - docker logs $CONTAINER + | docker exec -i $CONTAINER iris session iris -UUSER docker stop $CONTAINER - name: Restart temporary registry timeout-minutes: 15 @@ -124,10 +124,10 @@ jobs: - name: Test and publish to temporary registry timeout-minutes: 15 run: | - docker run --network zpm -d --rm -v `pwd`:/home/irisowner/zpm/ zpm ${{ steps.image.outputs.flags }} \ - --log-driver=none -a stdin -a stdout -a stderr + docker run --network zpm -d --rm zpm ${{ steps.image.outputs.flags }} CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh + docker cp . $CONTAINER:/home/irisowner/zpm/ /bin/echo -e '' \ 'zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1\n' \ 'zpm "repo -list":1\n' \ @@ -139,7 +139,7 @@ jobs: 'zpm "publish sslclient -v":1' \ 'zpm "search":1' \ 'halt\n' \ - | docker exec -i $CONTAINER iris session iris -U%SYS + | docker exec -i $CONTAINER iris session iris -UUSER docker logs $CONTAINER docker stop $CONTAINER # - name: Clean install current version and test new one. (Permitted to fail on 2023.1+) @@ -163,7 +163,7 @@ jobs: # 'zpm "list":1\n' \ # 'zpm "version":1\n' \ # 'halt\n' \ - # | docker exec -i $CONTAINER iris session iris -U%SYS + # | docker exec -i $CONTAINER iris session iris -UUSER # docker stop $CONTAINER - name: Clean install and test timeout-minutes: 15 @@ -191,6 +191,8 @@ jobs: - name: Stop temporary registry if: always() run: | + CONTAINER=`docker ps -lq` + docker stop $CONTAINER docker stop registry docker network rm zpm - uses: actions/upload-artifact@v3 @@ -240,7 +242,7 @@ jobs: run: | sed -i -E "s/(.*)<\/Version>/${VERSION}<\/Version>/" module.xml cat module.xml - docker run -d --rm -v `pwd`:/home/irisowner/zpm/ containers.intersystems.com/intersystems/${{ needs.prepare.outputs.main }} --check-caps false + docker run -d --rm -v $(pwd):/home/irisowner/zpm/ containers.intersystems.com/intersystems/${{ needs.prepare.outputs.main }} --check-caps false CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh /bin/echo -e '' \ @@ -249,7 +251,7 @@ jobs: 'zpm "repo -r -name registry -url ""https://pm.community.intersystems.com/"" -username ${{ secrets.REGISTRY_USERNAME }} -password ${{ secrets.REGISTRY_PASSWORD }}":1\n' \ 'zpm "publish zpm -v":1' \ 'halt\n' \ - | docker exec -i $CONTAINER iris session iris -U%SYS + | docker exec -i $CONTAINER iris session iris -UUSER docker stop $CONTAINER - name: Upload Public Release Asset uses: actions/upload-release-asset@v1 diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c52d889..6b0c540f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,7 @@ "host": "localhost", "username": "_system", "password": "SYS", - "ns": "%SYS" + "ns": "USER" }, "intersystems.testingManager.client.relativeTestRoot": "tests/unit_tests" } \ No newline at end of file diff --git a/iris.script b/iris.script index e0186071..7bd50301 100644 --- a/iris.script +++ b/iris.script @@ -1,6 +1,9 @@ zn "USER" do $System.OBJ.Load("/home/irisowner/zpm/Installer.cls","ck") do ##class(IPM.Installer).setup("/home/irisowner/zpm/",3) - do ##class(%IPM.Main).Shell("install vscode-per-namespace-settings") - set ^UnitTestRoot="/usr/irissys/.vscode/%SYS/UnitTestRoot" + zpm "repo -n registry -url repo -r -name registry -url https://pm.community.intersystems.com/" halt + + // Currently broken for %IPM due to differing default behavior for packages starting with % - vscode-per-namespace-settings passes through as-is, IPM expects to strip %. + do ##class(%IPM.Main).Shell("install vscode-per-namespace-settings") + set ^UnitTestRoot="/usr/irissys/.vscode/%SYS/UnitTestRoot" \ No newline at end of file diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index a4625f7a..8baac091 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -941,6 +941,10 @@ ClassMethod GetListModules(pNamespace As %String = {$Namespace}, pSearch As %Str Quit } } + If '$$$comClassDefined("%IPM.Storage.ModuleItem") { + // Don't error in namespaces without IPM enabled + Quit + } Set tArgs = 0 Set tQuery = "SELECT Name,VersionString,Description,ExternalName,DeveloperMode FROM %IPM_Storage.ModuleItem" Set pSearch = $ZStrip(pSearch, "<>WC") @@ -2973,4 +2977,3 @@ ClassMethod DisplayModules(ByRef pList, pNumbered As %Boolean = 0, pWithNamespac } } - diff --git a/src/cls/IPM/ResourceProcessor/Default/Document.cls b/src/cls/IPM/ResourceProcessor/Default/Document.cls index f754a516..332e8a2c 100644 --- a/src/cls/IPM/ResourceProcessor/Default/Document.cls +++ b/src/cls/IPM/ResourceProcessor/Default/Document.cls @@ -113,8 +113,10 @@ Method OnPhase(pPhase As %String, ByRef pParams, Output pResourceHandled As %Boo If (##class(%File).DirectoryExists(tResourceCatDirectory)) { Quit } - } - Set tResourceDirectory = tResourceCatDirectory + } + If ##class(%File).DirectoryExists(tResourceCatDirectory) { + Set tResourceDirectory = tResourceCatDirectory + } If tDeveloperMode && (..Extension '= "") && (tName '= "") { Set ^Sources(..Extension,tName_..#NAMEPOSTFIX) = tSourcesPrefix _ tResourceDirectory From 4b8c676b3543f6e9b0cde38977702a9276bc3806 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Wed, 31 Jan 2024 08:45:54 -0500 Subject: [PATCH 30/42] ci: share container among jobs --- .github/workflows/packages.yml | 41 +++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 97e92890..7a7148fd 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -15,26 +15,51 @@ jobs: matrix=$(curl -L "$PM_URL" | jq -cr "$JQ_SCRIPT") echo "matrix=$matrix" >> $GITHUB_OUTPUT - run-builds: + prepare-image: timeout-minutes: 20 runs-on: ubuntu-latest - needs: matrix-setup - strategy: - fail-fast: false - matrix: - package: ${{ fromJson(needs.matrix-setup.outputs.matrix) }} env: IMAGE: containers.intersystems.com/intersystems/iris-community:latest-em steps: - uses: actions/checkout@master - - name: Build + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Build Image uses: docker/build-push-action@v4 with: context: . push: false load: true - tags: zpm + tags: zpm:latest build-args: Base=${{ env.IMAGE }} + outputs: type=docker,dest=/tmp/zpmimage.tar + - name: Upload Image + uses: actions/upload-artifact@v2 + with: + name: zpmimage + path: /tmp/zpmimage.tar + + run-tests: + needs: + - matrix-setup + - prepare-image + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + package: ${{ fromJson(needs.matrix-setup.outputs.matrix) }} + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Download artifact + uses: actions/download-artifact@v2 + with: + name: zpmimage + path: /tmp + - name: Load Image + run: | + docker load -i /tmp/zpmimage.tar + docker image ls - name: Container Setup id: setup-zpm timeout-minutes: 15 From f0cef1c78a972f455627662718f455f4ff6b05c9 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Wed, 31 Jan 2024 11:14:07 -0500 Subject: [PATCH 31/42] ci: checkout source code in each job --- .github/workflows/packages.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 7a7148fd..e43c8127 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -49,9 +49,10 @@ jobs: matrix: package: ${{ fromJson(needs.matrix-setup.outputs.matrix) }} steps: + - uses: actions/checkout@master - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Download artifact + - name: Download Artifact uses: actions/download-artifact@v2 with: name: zpmimage From f2c2e7190dbd89d6d531aa549a4b70f19d3cc6ab Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Wed, 31 Jan 2024 12:01:38 -0500 Subject: [PATCH 32/42] fix bug in ci workflow --- .github/workflows/packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 43dfa49c..de9322dd 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -86,9 +86,9 @@ jobs: docker exec -i ${{ env.CONTAINER }} iris session IRIS -U%SYS << EOF zpm "install ${{ matrix.package }}":1 zpm "${{ matrix.package }} test -only ${{ env.test-flags }}":1:1 - EOF || echo -e "'\nExit code: $?' + EOF - name: Stop Container run: | # To ensure a clean state after using `act` locally docker stop -t 5 ${{ steps.setup-zpm.outputs.CONTAINER }} - docker ps \ No newline at end of file + docker ps From 60e154d321caf06a3f742ea0b2672ac2ee6506c6 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Wed, 31 Jan 2024 12:58:30 -0500 Subject: [PATCH 33/42] ci: parameterize minVersionCount for packages.yml --- .github/workflows/packages.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index e43c8127..b369a19a 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -1,12 +1,19 @@ name: Test major packages -on: workflow_dispatch +on: + workflow_dispatch: + inputs: + minVersionCount: + description: "Minimum number of versions a package must have to be tested" + required: true + type: number + default: 10 jobs: matrix-setup: runs-on: ubuntu-latest env: PM_URL: https://pm.community.intersystems.com/packages/-/all?allVersions=1 - JQ_SCRIPT: reduce .[] as $item ([]; if $item.allVersions | length >= 65 then . + [$item.name] else . end) + JQ_SCRIPT: reduce .[] as $item ([]; if $item.allVersions | length >= ${{ inputs.minVersionCount }} then . + [$item.name] else . end) outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: @@ -33,6 +40,14 @@ jobs: tags: zpm:latest build-args: Base=${{ env.IMAGE }} outputs: type=docker,dest=/tmp/zpmimage.tar + - name: Test Image + run: | + CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm) + docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh + docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF + zpm "list":1 + zpm "test zpm -v -only":1:1 + EOF - name: Upload Image uses: actions/upload-artifact@v2 with: @@ -70,8 +85,6 @@ jobs: echo "CONTAINER=$CONTAINER" >> $GITHUB_OUTPUT docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF - zpm "list":1 - zpm "test zpm -v -only":1 zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1 halt EOF @@ -86,7 +99,7 @@ jobs: docker exec -i ${{ env.CONTAINER }} iris session IRIS -U%SYS << EOF zpm "install ${{ matrix.package }}":1 zpm "${{ matrix.package }} test -only ${{ env.test-flags }}":1:1 - EOF || echo -e "'\nExit code: $?' + EOF - name: Stop Container run: | # To ensure a clean state after using `act` locally From 926cd19946bea36a0960e78f0e437bc0fdaf504f Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Wed, 31 Jan 2024 13:10:58 -0500 Subject: [PATCH 34/42] ci: bug fix --- .github/workflows/packages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index b369a19a..2ce44243 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -42,6 +42,8 @@ jobs: outputs: type=docker,dest=/tmp/zpmimage.tar - name: Test Image run: | + docker load -i /tmp/zpmimage.tar + docker image ls CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm) docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF From 34d6ce48b81532eaa9ae59d6132ccf4a0b4f4191 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Thu, 1 Feb 2024 08:51:50 -0500 Subject: [PATCH 35/42] run ci in USER instead of %SYS --- .github/workflows/packages.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 2ce44243..3a55f04f 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -46,7 +46,7 @@ jobs: docker image ls CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm) docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh - docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF + docker exec -i $CONTAINER iris session IRIS << EOF zpm "list":1 zpm "test zpm -v -only":1:1 EOF @@ -86,7 +86,7 @@ jobs: CONTAINER=$(docker run -d --rm -v `pwd`:/home/irisowner/zpm/ zpm) echo "CONTAINER=$CONTAINER" >> $GITHUB_OUTPUT docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh - docker exec -i $CONTAINER iris session IRIS -U%SYS << EOF + docker exec -i $CONTAINER iris session IRIS << EOF zpm "repo -r -name registry -url https://pm.community.intersystems.com/":1 halt EOF @@ -98,7 +98,7 @@ jobs: -verbose -DUnitTest.ManagerClass=UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=UnitTest.Manager run: | - docker exec -i ${{ env.CONTAINER }} iris session IRIS -U%SYS << EOF + docker exec -i ${{ env.CONTAINER }} iris session IRIS << EOF zpm "install ${{ matrix.package }}":1 zpm "${{ matrix.package }} test -only ${{ env.test-flags }}":1:1 EOF From e8db00efac679ef332c60a3b3431071924f7bab8 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Thu, 1 Feb 2024 09:16:22 -0500 Subject: [PATCH 36/42] run zpm test in %SYS --- .github/workflows/packages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 3a55f04f..313b026e 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -48,6 +48,7 @@ jobs: docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh docker exec -i $CONTAINER iris session IRIS << EOF zpm "list":1 + zn "%SYS" zpm "test zpm -v -only":1:1 EOF - name: Upload Image From fe2475f5609208eb79910116f78b513124ab3126 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Thu, 1 Feb 2024 11:06:15 -0500 Subject: [PATCH 37/42] ci: fix type in %UnitTest.Manager name --- .github/workflows/packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 2ce44243..ac078bef 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -95,8 +95,8 @@ jobs: env: CONTAINER: ${{ steps.setup-zpm.outputs.CONTAINER }} test-flags: >- - -verbose -DUnitTest.ManagerClass=UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml - -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=UnitTest.Manager + -verbose -DUnitTest.ManagerClass=%UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml + -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=%UnitTest.Manager run: | docker exec -i ${{ env.CONTAINER }} iris session IRIS -U%SYS << EOF zpm "install ${{ matrix.package }}":1 From 82e2f870311ee73c0251edaf51b4e2e3b1515085 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Thu, 1 Feb 2024 12:04:16 -0500 Subject: [PATCH 38/42] typo fix --- .github/workflows/packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 313b026e..e3d67afc 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -96,8 +96,8 @@ jobs: env: CONTAINER: ${{ steps.setup-zpm.outputs.CONTAINER }} test-flags: >- - -verbose -DUnitTest.ManagerClass=UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml - -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=UnitTest.Manager + -verbose -DUnitTest.ManagerClass=%UnitTest.Manager -DUnitTest.JUnitOutput=/test-reports/junit.xml + -DUnitTest.FailuresAreFatal=1 -DUnitTest.Manager=%UnitTest.Manager run: | docker exec -i ${{ env.CONTAINER }} iris session IRIS << EOF zpm "install ${{ matrix.package }}":1 From d53fc9ad89d1d57f903c0427fd3ba61eb2289aa4 Mon Sep 17 00:00:00 2001 From: Shuheng Liu Date: Thu, 1 Feb 2024 13:28:13 -0500 Subject: [PATCH 39/42] typo fix --- .github/workflows/images.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index ffe8a4e8..37ddc3a2 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -5,7 +5,7 @@ on: images: description: "The full list of images to use, as a JSON array of imagename:tag" value: ${{ jobs.images.outputs.images }} - secondword: + main: description: "The main image to use (earliest relevant version) to generate the installer XML file" value: ${{ jobs.images.outputs.main }} From fb2b2ba0345b6d18da41dbeec26eef640ada5d32 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:53:34 -0400 Subject: [PATCH 40/42] Merge in internal updates --- CHANGELOG.md | 2 + src/cls/IPM/DependencyAnalyzer.cls | 652 +----------------- .../IPM/DependencyAnalyzer/ModuleResults.cls | 93 --- src/cls/IPM/DependencyAnalyzer/Problem.cls | 81 --- src/cls/IPM/Lifecycle/StudioProject.cls | 40 +- src/cls/IPM/Main.cls | 4 + src/cls/IPM/Utils/Build.cls | 3 +- 7 files changed, 45 insertions(+), 830 deletions(-) delete mode 100644 src/cls/IPM/DependencyAnalyzer/ModuleResults.cls delete mode 100644 src/cls/IPM/DependencyAnalyzer/Problem.cls diff --git a/CHANGELOG.md b/CHANGELOG.md index 61e7c0b1..e2c2d2ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - HSIEO-9484: Add additional argument to buildDepsGraph to allow putting in an additional list element of dependency's DisplayName - HSIEO-9484: Add additional property DisplayName to %IPM.Storage.ModuleReference +- HSIEO-10274: Separate DependencyAnalyzer out from IPM ### Fixed - HSIEO-9269, HSIEO-9402: % percent perforce directories are no longer necessary @@ -32,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - HSIEO-9269, HSIEO-9280: Load unittest code during module install - HSIEO-9430: Module definition should not expose DisplayName + deprecate DisplayNameInternal as it will not be used anymore - HSIEO-9924: RunDev needs to do complete installation of component and dependencies via ignoreInstalled, so adding ignoreInstalledModules checker in syncLoadDependencies +- HSIEO-10267: Bug Fix - Resource name should be the fifth argument of CreateDatabase ### Security - diff --git a/src/cls/IPM/DependencyAnalyzer.cls b/src/cls/IPM/DependencyAnalyzer.cls index e4edb697..608d5193 100644 --- a/src/cls/IPM/DependencyAnalyzer.cls +++ b/src/cls/IPM/DependencyAnalyzer.cls @@ -3,7 +3,7 @@ Include %IPM.Common Class %IPM.DependencyAnalyzer { -/// Prefix to indentify .inc files +/// Prefix to indentify .inc files. Parameter INCPREFIX = "!!!INC."; // Suffix for supported item types: .inc, .cls @@ -63,7 +63,7 @@ ClassMethod RunForAllReferences(pName As %String, Output pReferences, pVerbose A Set tModule = ##class(%IPM.ExtensionBase.Utils).FindHomeModule($$$ucase(pName)) If '$IsObject(tModule) { Write !, "No home module found for item: " _ pName ,! - // set a placeholder module name for %IPM.DependencyAnalyzer.ModuleResults's required property - it will not be used other than indexing + // set a placeholder module name for %pkg.isc.dependencyAnalyzer.ModuleResults's required property - it will not be used other than indexing Set tModuleName = $c(0) } Else { Set tModuleName = tModule.Name @@ -74,7 +74,7 @@ ClassMethod RunForAllReferences(pName As %String, Output pReferences, pVerbose A Do ..FindReferenceHelper(tIsModule, pName, 0, pProgressListener, pIgnoredStringRef, pDirectDepsOnly, .pReferences) // Represent results as objects - Set tRun = ..PresentReferenceAsObject(tModuleName, 0, .pReferences) + Set tRun = $ClassMethod("%pkg.isc.dependencyAnalyzer.Utils", "PresentReferenceAsObject", tModuleName, 0, .pReferences) If pSave { $$$ThrowOnError(tRun.%Save()) @@ -128,7 +128,7 @@ ClassMethod RunForInvalidReferences(pName As %String, Output pInvalidReferences, Do ..FindReferenceHelper(tIsModule, pName, 1, pProgressListener, pIgnoredStringRef, pDirectDepsOnly, .pInvalidReferences) // Represent results as objects - Set tRun = ..PresentReferenceAsObject(tModuleName, 1, .pInvalidReferences) + Set tRun = $ClassMethod("%pkg.isc.dependencyAnalyzer.Utils","PresentReferenceAsObject", tModuleName, 1, .pInvalidReferences) If pSave { $$$ThrowOnError(tRun.%Save()) @@ -196,7 +196,7 @@ ClassMethod FindReferenceHelper(pIsModule As %Boolean, pName As %String = "", pI Do ..GetSysPackageNames(.tSYSPackages) // Accumulate package names in current namespace into a temp global // Do accumulation once for performance rather than repeating accumulation - Do ..AccumulatePackageNamesInCurrentNamespace() + Do $ClassMethod("%pkg.isc.dependencyAnalyzer.Utils", "AccumulatePackageNamesInCurrentNamespace") // Parallelize search #dim tQueue As %SYSTEM.WorkMgr @@ -242,13 +242,13 @@ ClassMethod FindReferenceHelper(pIsModule As %Boolean, pName As %String = "", pI If (tExt = "CLS") { Set tClass = $Piece(tChildKey,".",1,*-1) // Queue search of class - Set tSC = tQueue.QueueCallback("##class("_$classname()_").ExtractClassReferencesToName","##class("_$classname()_").ClassExtractionComplete",tClass,tNextCounter,pProgressListener,pIgnoredStringRef) + Set tSC = tQueue.QueueCallback("##class(%pkg.isc.dependencyAnalyzer.Utils).ExtractClassReferencesToName","##class(%pkg.isc.dependencyAnalyzer.Utils).ClassExtractionComplete",tClass,tNextCounter,pProgressListener,pIgnoredStringRef) $$$ThrowOnError(tSC) Set tClassCount = tClassCount + 1 } ElseIf (tExt = "INC") { Set tClass = $Piece(tChildKey,".",1,*-1) // Queue search of include file - Set tSC = tQueue.QueueCallback("##class("_$classname()_").ExtractIncludeReferencesToName","##class("_$classname()_").ClassExtractionComplete",tClass,tNextCounter,pProgressListener,pIgnoredStringRef) + Set tSC = tQueue.QueueCallback("##class(%pkg.isc.dependencyAnalyzer.Utils).ExtractIncludeReferencesToName","##class(%pkg.isc.dependencyAnalyzer.Utils).ClassExtractionComplete",tClass,tNextCounter,pProgressListener,pIgnoredStringRef) $$$ThrowOnError(tSC) Set tClassCount = tClassCount + 1 } @@ -260,13 +260,13 @@ ClassMethod FindReferenceHelper(pIsModule As %Boolean, pName As %String = "", pI If (tExt = "CLS") { Set tClass = $Piece(pName,".",1,*-1) // Queue search of class - Set tSC = tQueue.QueueCallback("##class("_$classname()_").ExtractClassReferencesToName","##class("_$classname()_").ClassExtractionComplete",tClass,tNextCounter,pProgressListener, pIgnoredStringRef) + Set tSC = tQueue.QueueCallback("##class(%pkg.isc.dependencyAnalyzer.Utils).ExtractClassReferencesToName","##class(%pkg.isc.dependencyAnalyzer.Utils).ClassExtractionComplete",tClass,tNextCounter,pProgressListener, pIgnoredStringRef) $$$ThrowOnError(tSC) Set tClassCount = 1 } ElseIf (tExt = "INC") { Set tClass = $Piece(pName,".",1,*-1) // Queue search of include file - Set tSC = tQueue.QueueCallback("##class("_$classname()_").ExtractIncludeReferencesToName","##class("_$classname()_").ClassExtractionComplete",tClass,tNextCounter,pProgressListener, pIgnoredStringRef) + Set tSC = tQueue.QueueCallback("##class(%pkg.isc.dependencyAnalyzer.Utils).ExtractIncludeReferencesToName","##class(%pkg.isc.dependencyAnalyzer.Utils).ClassExtractionComplete",tClass,tNextCounter,pProgressListener, pIgnoredStringRef) $$$ThrowOnError(tSC) Set tClassCount = 1 } @@ -401,85 +401,6 @@ ClassMethod GetDependenciesForModule(pModule As %IPM.Storage.Module, pDirectDeps } } -/// Based on multi-dim array, construct and return an ModuleResults object where info of the reference is stored -/// pModuleName: Name of the module itself / home module for the item -/// pInvalidOnly: Whether or not only look for invalid references. Default to 1 -/// pReferences: multi-dim references -ClassMethod PresentReferenceAsObject(pModuleName As %String, pInvalidOnly As %Boolean = 1, ByRef pReferences) As %IPM.DependencyAnalyzer.ModuleResults [ Internal ] -{ - Set tRun = ##class(%IPM.DependencyAnalyzer.ModuleResults).%New() - Set tRun.TargetModule = pModuleName - - Set tModuleKey = "" - For { - Set tModuleKey = $Order(pReferences(tModuleKey)) - If (tModuleKey = "") { - Quit - } - - Set tReferencedClassKey = "" - For { - Set tReferencedClassKey = $Order(pReferences(tModuleKey,tReferencedClassKey)) - If (tReferencedClassKey = "") { - Quit - } - - Set tFileTypeKey = "" - For { - Set tFileTypeKey = $Order(pReferences(tModuleKey,tReferencedClassKey,tFileTypeKey)) - If (tFileTypeKey = "") { - Quit - } - Set tReferencingClassKey = "" - For { - Set tReferencingClassKey = $Order(pReferences(tModuleKey,tReferencedClassKey,tFileTypeKey, tReferencingClassKey)) - If (tReferencingClassKey = "") { - Quit - } - If (tReferencedClassKey = tReferencingClassKey) { - // This sometimes happens if the class is not compiled. - Continue - } - - Set tMemberKey = "" - For { - Set tMemberKey = $Order(pReferences(tModuleKey,tReferencedClassKey,tFileTypeKey, tReferencingClassKey,tMemberKey)) - If (tMemberKey = "") { - Quit - } - - Set tLineKey = "" - For { - Set tLineKey = $Order(pReferences(tModuleKey,tReferencedClassKey,tFileTypeKey, tReferencingClassKey,tMemberKey,tLineKey),1,tLine) - If (tLineKey = "") { - Quit - } - - Set tProblem = ##class(%IPM.DependencyAnalyzer.Problem).%New() - Set tProblem.ReferencedFileType = tFileTypeKey - Set tProblem.ReferencedModule = $Case(tModuleKey,$c(0):"",:tModuleKey) - Set tProblem.ReferencedItemExists = (tModuleKey '= $c(0)) - Set tProblem.ReferencedItem = tReferencedClassKey - Set tProblem.ProblemItem = tReferencingClassKey - Set tProblem.ProblemMember = tMemberKey - Set tProblem.ProblemLine = tLineKey - Set tProblem.ProblemCode = tLine - Set tProblem.InvalidOnly = pInvalidOnly - Set tSC = tProblem.%ValidateObject() - If $$$ISOK(tSC) { - Do tRun.Problems.Insert(tProblem) - } Else { - Do ##class(%IPM.General.LogManager).Warning("Could not save problem: "_tProblem.ToString()_$c(13,10,9)_"Error: "_$System.Status.GetErrorText(tSC),1) - } - } - } - } - } - } - } - Return tRun -} - /// Get the names of all non % packages in %SYS as keys of the output /// subscripted array. ClassMethod GetSysPackageNames(Output pSysPackageNameArray) [ Internal ] @@ -501,541 +422,6 @@ ClassMethod GetSysPackageNames(Output pSysPackageNameArray) [ Internal ] $$$ThrowOnError(sc) } -/// Get names of all packages in the current namespace and store output in a temp -/// global. -ClassMethod AccumulatePackageNamesInCurrentNamespace() -{ - Do ..AccumulatePackageNamesInNamespace($Namespace, .packages) - Merge $$$ZPMDependencyNsPackages = packages -} - -ClassMethod AccumulatePackageNamesInNamespace(pNamespace As %String, Output pPackages) [ Internal, Private ] -{ - Kill pPackages - New $Namespace - Set $Namespace = pNamespace - Set query = "SELECT DISTINCT $Piece(Name, '.') As Package FROM %Dictionary.CompiledClass" - Set statement = ##class(%SQL.Statement).%New() - $$$ThrowOnError(statement.%Prepare(query)) - Set resultSet = statement.%Execute() - If (resultSet.%SQLCODE < 0) { - Throw ##class(%Exception.SQL).CreateFromSQLCODE(resultSet.%SQLCODE, resultSet.%Message) - } - While resultSet.%Next(.sc) { - $$$ThrowOnError(sc) - Set pPackages(resultSet.%Get("Package")) = "" - } - $$$ThrowOnError(sc) -} - -/// @API.Query -/// @Modifier Availability InterSystems -Query LatestResults(pProblemModule As %String) As %SQLQuery [ SqlProc ] -{ - select Run->TargetModule,ProblemItem,ReferencedModule,ReferencedItem,ProblemMember,ProblemLine,ProblemCode - from %IPM_DependencyAnalyzer.Problem - where :pProblemModule is null or :pProblemModule = Run->TargetModule - having Run->ID = MAX(Run->ID %FOREACH (Run->TargetModule)) -} - -ClassMethod ClassExtractionComplete(pSourceClass As %String, pTargetSubscript As %String) As %Status -{ - Quit $$$OK -} - -// ////////////////////// Extraction methods called on FILES ///////////////////////////////// - -/// Called directly by RunforAllReferences() / RunforInvalidReferences() on .inc files -ClassMethod ExtractIncludeReferencesToName(pSourceClass As %String, pTargetSubscript As %String, pProgressListener = {$$$NULLOREF}, pIgnoredStringRef As %String) As %Status -{ - Set tSC = ..ExtractFileReferencesFromIncludeFile(pSourceClass,.tResults, pIgnoredStringRef) - $$$ThrowOnError(tSC) - Merge $$$ZPMDependencyTempData(pTargetSubscript) = tResults - Quit tSC -} - -/// Called directly by RunforAllReferences() / RunforInvalidReferences() on .cls files -ClassMethod ExtractClassReferencesToName(pSourceClass As %String, pTargetSubscript As %String, pProgressListener = {$$$NULLOREF}, pIgnoredStringRef As %String) As %Status -{ - Set tSC = ..ExtractFileReferencesFromClass(pSourceClass,.tResults, pIgnoredStringRef) - $$$ThrowOnError(tSC) - Merge $$$ZPMDependencyTempData(pTargetSubscript) = tResults - Quit tSC -} - -/// This method extracts all referenced classes from a give .inc file -ClassMethod ExtractFileReferencesFromIncludeFile(pSourceIncludeFile As %String, ByRef pRefArray, pIgnoredStringRef As %String) As %Status -{ - Set tSC = $$$OK - Try { - #dim rtn As %Library.Routine - Set rtn = ##class(%Library.Routine).%OpenId(pSourceIncludeFile) - #dim stream As %Stream.TmpCharacter - Set stream = ##class(%Stream.TmpCharacter).%New() - While 'rtn.AtEnd { - Set tDocLine = rtn.ReadLine() - Do stream.WriteLine(tDocLine) - } - Set tSC = ##class(%Library.SyntaxColorReader).FromCode(stream,"COS","A",.tSCReader) - $$$ThrowOnError(tSC) - Do rtn.Rewind() - Set tLine = 0 - While tSCReader.NextLine(.tLineTokenList) { - Set tLine = tLine + 1 - Set tDocLine = rtn.ReadLine() - Do ..ExtractReferencesFromIncludeFileLine(pSourceIncludeFile," ",tLine,tLineTokenList,.pRefArray,tDocLine, pIgnoredStringRef) - } - } Catch e { - Set tSC = e.AsStatus() - } - Quit tSC -} - -/// This method extracts all referenced classes from a given .cls file -/// calls ExtractIncludeFileReferencesFromLine() to handle line with include file, -/// calls ExtractClassReferencesFromLine() to handle other lines -ClassMethod ExtractFileReferencesFromClass(pSourceClass As %String, ByRef pRefArray, pIgnoredStringRef As %String) As %Status -{ - Set tSC = $$$OK - Try { - // Get references in UDL - $$$ThrowOnError(##class(%Compiler.UDL.TextServices).GetTextAsStream(,pSourceClass,.tSourceStream)) - - Set tSC = ##class(%Library.SyntaxColorReader).FromCode(tSourceStream,"CLS","A",.tSCReader) - $$$ThrowOnError(tSC) - - // Get references in COS - $$$ThrowOnError(##class(%Compiler.UDL.TextServices).GetTextAsArray(,pSourceClass,.tDocumentText)) - // tDocumentText: an array, each line is a line in the class - Set tDocumentText = $Order(tDocumentText(""),-1) //Set top level node to # of lines. - - // Iterate to find all class references and include file references - Set tMember = "" - // tInMember will be set to query or method - Set tInMember = "" - Set tMemberStarted = 0 - Set tIncludeFileChecked = 0 - For tDocLine=1:1:tDocumentText { - Set tLine = tDocumentText(tDocLine) - Do tSCReader.NextLine(.tLineTokenList) - If (tInMember = "") { - Set pExecutableFlags(tDocLine) = 0 - // Extract line offset of method in class - Set tStart = $Extract(tLine,1,6) - // Check for include files only once, since all refer to inc files should be on the same line - If ('tIncludeFileChecked && (tStart = "Includ")) { - Set tIncludeFileChecked = 1 - Do ..ExtractIncludeFileReferencesFromLine(pSourceClass," ",tDocLine,tLineTokenList,.pRefArray,.tDocumentText) - Continue - } - If (tStart = "ClassM") || (tStart = "Method") || (tStart = "Query ") { - Set tMember = $Piece($Piece(tLine,"(")," ",2) - Kill tMemberCode - Set tInMember = $Case(tStart,"Query ":"query",:"method") - } - - // Look at the next line of tokens from UDL. - Do ..ExtractClassReferencesFromLine(pSourceClass," ",tDocLine,tLineTokenList,.pRefArray,.tDocumentText, pIgnoredStringRef) - } Else { - If $Extract(tLine) = "{" { - Set tMemberStarted = 1 - Set tMethodMap(tMember) = tDocLine + 1 - } ElseIf ($Extract(tLine) = "}") { - If (tMember '= "") { - If (tInMember = "method") { - Set tSC = ..ExtractClassReferencesFromMethod(pSourceClass,tMember,.tMemberCode,.tMethodMap,.pRefArray, pIgnoredStringRef) - $$$ThrowOnError(tSC) - } ElseIf (tInMember = "query") { - Set tSC = ..ExtractClassReferencesFromQuery(pSourceClass,tMember,.tMemberCode,.tMethodMap,.pRefArray, pIgnoredStringRef) - $$$ThrowOnError(tSC) - } - } - Set tInMember = "" - Set tMemberStarted = 0 - } Else { - // Aggregate lines from the method body to look at later. - Set tMemberCode($i(tMemberCode)) = tLine - } - } - } - } Catch e { - Set tSC = e.AsStatus() - } - Quit tSC -} - -/// Helper method called by ExtractFileReferencesFromClass(). -/// Handles lines inside a method by calling ExtractClassReferencesFromLine() -ClassMethod ExtractClassReferencesFromMethod(pSourceClass As %String, pMethod As %String, ByRef pMethodCode, ByRef pMethodMap, ByRef pRefArray, pIgnoredStringRef As %String) As %Status -{ - Set tSC = $$$OK - Try { - Set tCodeMode = $$$defMemberKeyGet(pSourceClass,$$$cCLASSmethod,pMethod,$$$cMETHcodemode) - If (tCodeMode = $$$cMETHCODEMODEGENERATOR) || (tCodeMode = $$$cMETHCODEMODEOBJECTGENERATOR) || '$Data(^rMAP(pSourceClass,"CLS","INT",pMethod)) { - Quit - } - Set tSourceStream = ##class(%Stream.GlobalCharacter).%New() - Set tSourceStream.LineTerminator = $c(13,10) - For tMethodLine=1:1:$Get(pMethodCode) { - Do tSourceStream.WriteLine(pMethodCode(tMethodLine)) - } - - Set tSC = ##class(%Library.SyntaxColorReader).FromCode(tSourceStream,"COS","A",.tSCReader) - $$$ThrowOnError(tSC) - - Set tOffset = pMethodMap(pMethod) - Set tLine = 1 - While tSCReader.NextLine(.tLineTokenList) { - If (tLine = 0) && (tCodeMode = $$$cMETHCODEMODEEXPRESSION) { - // Simulate a normal method. - Set tLineTokenList = $ListBuild($ListBuild("COS","Command","Quit"))_tLineTokenList - } - Do ..ExtractClassReferencesFromLine(pSourceClass,pMethod,tLine,tLineTokenList,.pRefArray,.pMethodCode, pIgnoredStringRef) - Set tLine = tLine + 1 - } - } Catch e { - Set tSC = e.AsStatus() - } - Quit tSC -} - -/// Helper method called by ExtractFileReferencesFromClass(). -/// Handles lines inside a query by calling ExtractClassReferencesFromLine() -ClassMethod ExtractClassReferencesFromQuery(pSourceClass As %String, pQuery As %String, ByRef pMethodCode, ByRef pMethodMap, ByRef pRefArray, pIgnoredStringRef As %String) As %Status -{ - Set tSC = $$$OK - Try { - Set tSourceStream = ##class(%Stream.GlobalCharacter).%New() - Set tSourceStream.LineTerminator = $c(13,10) - For tMethodLine=1:1:$Get(pMethodCode) { - Do tSourceStream.WriteLine(pMethodCode(tMethodLine)) - } - - Set tSC = ##class(%Library.SyntaxColorReader).FromCode(tSourceStream,"SQL","A",.tSCReader) - $$$ThrowOnError(tSC) - - Set tOffset = pMethodMap(pQuery) - Set tLine = 1 - While tSCReader.NextLine(.tLineTokenList) { - Do ..ExtractClassReferencesFromLine(pSourceClass,pQuery,tLine,tLineTokenList,.pRefArray,.pMethodCode, pIgnoredStringRef) - Set tLine = tLine + 1 - } - } Catch e { - Set tSC = e.AsStatus() - } - Quit tSC -} - -// ////////////////////// END OF Extraction methods called on FILES ///////////////////////// - -// ////////////////////// Extraction methods called on LINES //////////////////////////////// - -/// Called by ExtractFileReferencesFromClass(), FromMethod() and FromQuery() -ClassMethod ExtractClassReferencesFromLine(pSourceClass As %String, pMethod As %String, pLine As %Integer, pLineTokenList As %List, ByRef pRefArray, ByRef pMethodCode, pIgnoredStringRef As %String) -{ - /* - // Like $$$NormalizeClassname from %occClassname.inc, but relative to another class (for references to the same package) - #define NormalizeClassname(%class,%source) $s(%class="":"",%class[".":%class,$e(%class)'="%":$$$ClassPackageName(%source)_"."_%class,1:"%Library."_$e(%class,2,*)) - #define AddReference(%classname) Set pRefArray($$$NormalizeClassname(%classname,pSourceClass),pSourceClass,pMethod,pLine) = $ZStrip(pMethodCode(pLine),"<>W") - */ - #define AddReference(%classname) $$$NormalizeClassnameByDef(%classname,pSourceClass) Set pRefArray(%classname,pSourceClass_..#CLSSUFFIX,pMethod,pLine) = $ZStrip(pMethodCode(pLine),"<>W") - Set tInClassname = 0 - Set tInTableName = 0 - Set tClassName = "" - Set tTableName = "" - Set tPointer = 0 - Set tTableState = 0 - Set tIgnoreAllStr = 0 - Set tIgnoreStrList = "" - If pIgnoredStringRef = $char(0) { - Set tIgnoreAllStr = 1 - } Else { - Set tIgnoreStrList = $ListFromString(pIgnoredStringRef, ",") - } - While $ListNext(pLineTokenList,tPointer,tLineToken) { - Set $ListBuild(tLanguage,tType,tValue) = tLineToken - If tInTableName { - // Table name has format: - // Identifier Delimiter (.) Identifier - // With possible intervening whitespace. - - // Values of tTableState: - // 1: just saw something indicating that a table name might be about to appear (e.g., from, join), and expect an identifier. - // 2: just saw first identifier (schema), and expect a delimiter. - // 3: just saw delimiter (.), and expect a table name - If (tType = "White Space") { - } ElseIf (tType = "Delimiter") && (tValue = ".") && (tTableState = 2) { - Set tTableName = tTableName_tValue - Set tTableState = 3 - } ElseIf (tType = "Identifier") && ((tTableState = 1) || (tTableState = 3)) { - Set tTableName = tTableName_$Translate(tValue,"""") - Set tTableState = tTableState + 1 - } Else { - If (tTableName '= "") { - Set tSC = ..GetClassNameFromTableName(pSourceClass,tTableName,.tClassName) - $$$ThrowOnError(tSC) - If (tClassName '= "") { - $$$AddReference(tClassName) - } - } - Set tTableName = "" - Set tInTableName = 0 - Set tTableState = 0 - } - } - If (tLanguage = "COS") { - // ##class(Some.Class) - If (tType = "Object (Class)") { - Set tInClassname = 1 - Set tClassName = "" - } ElseIf (tType = "Object name") { - If ($Extract(tValue) = """") { - // Quoted classname. - Set tValue = $Extract(tValue,2,*-1) - } - Set tClassName = tClassName_tValue - } ElseIf tInClassname && (tType = "Delimiter") && (tValue = ")") { - // Avoid in cases where the full class name is a macro (for example) - If (tClassName '= "") { - $$$AddReference(tClassName) - } - Set tClassName = "" - Set tInClassname = 0 - } ElseIf (tType = "String") { - // Dynamic class call. Can have classname as a string. - If tIgnoreAllStr { - Continue - } - If ($Extract(tValue) = """") { - // Quoted classname so remove additional quotes - Set tValue = $Extract(tValue,2,*-1) - Set tIsValidClassname = ##class(%Dictionary.Classname).IsValid(tValue) - If tIsValidClassname { - Set tPackageExists = $Data($$$ZPMDependencyNsPackages($Piece(tValue, ".", 1))) - Set tIsFullClassname = $Piece(tValue, ".", 2) '= "" - If (tPackageExists && tIsFullClassname) { - // The package name already exists in the namespace. Can - // safely assume no non-existent packages are being referenced. - // This check is to prevent red herrings such as simple - // strings like "POS" or "Hello" getting flagged as invalid - // references. - If ($Extract($ZConvert(tValue, "U"), *-3, *) = ".CLS") { - // If reference ends in ".cls", strip it so that class's module can be detected - Set tValue = $Extract(tValue, 1, *-4) - } - If '$ListFind(tIgnoreStrList, tValue) { - $$$AddReference(tValue) - } - } - } - } - } - } ElseIf (tLanguage = "CLS") { - If (tType = "Class Name") { - Set tInClassname = 1 - Set tClassName = tClassName_tValue - } ElseIf tInClassname { - $$$AddReference(tClassName) - Set tClassName = "" - Set tInClassname = 0 - } - } ElseIf (tLanguage = "SQL") { - If 'tInTableName { - Set tLowerValue = $ZConvert(tValue,"L") - If (tType = "Qualifier keyword") && ((tLowerValue = "from") || (tLowerValue = "join")) { - Set tInTableName = 1 - Set tTableState = 1 - } - } - } - } - // If we ended with the classname being the last element, for example, extends - If (tInClassname && (tClassName '= "")) { - $$$AddReference(tClassName) - } - - // If we ended a table name on the line. - If (tInTableName && (tTableName '= "")) { - Set tSC = ..GetClassNameFromTableName(pSourceClass,tTableName,.tClassName) - $$$ThrowOnError(tSC) - If (tClassName '= "") { - $$$AddReference(tClassName) - } - } -} - -/// Extracts include file referenced in a class by an Include tag -/// We assume that this method will only be called with the line starts with "Include" -ClassMethod ExtractIncludeFileReferencesFromLine(pSourceClass As %String, pMethod As %String, pLine As %Integer, pLineTokenList As %List, ByRef pRefArray, ByRef pMethodCode) -{ - #define AddReference(%classname) $$$NormalizeClassnameByDef(%classname,pSourceClass) Set pRefArray(%classname,pSourceClass_..#CLSSUFFIX,pMethod,pLine) = $ZStrip(pMethodCode(pLine),"<>W") - Set tRoutineName = ..#INCPREFIX - Set tPointer = 0 - While $ListNext(pLineTokenList,tPointer,tLineToken) { - Set $ListBuild(tLanguage,tType,tValue) = tLineToken - If (tLanguage = "CLS") { - If (tType = "Routine Name") { - Set tRoutineName = tRoutineName_tValue - } ElseIf (tType = "Delimiter") { - If (tValue = ".") { - Set tRoutineName = tRoutineName_tValue - } ElseIf (tValue = ",") { - // add the include file as a reference - $$$AddReference(tRoutineName) - Set tRoutineName = ..#INCPREFIX - } - } - } - } - If (tRoutineName '= ..#INCPREFIX) { - $$$AddReference(tRoutineName) - } -} - -/// Called by ExtractFileReferencesFromIncludeFile, will only process lines in an include file -ClassMethod ExtractReferencesFromIncludeFileLine(pSourceClass As %String, pMethod As %String, pLine As %Integer, pLineTokenList As %List, ByRef pRefArray, pLineCode As %String, pIgnoredStringRef As %String) -{ - #define AddReference(%classname) $$$NormalizeClassnameByDef(%classname,pSourceClass) Set pRefArray(%classname,pSourceClass_..#INCSUFFIX,pMethod,pLine) = $ZStrip(pLineCode,"<>W") - Set tPointer = 0 - // looking for a line starting with #define - Set tHasPoundSign = 0 - Set tHasDefineTag = 0 - Set tHasIncludeTag = 0 - Set tReferencedClassName = "" - Set tReferencedIncludeFileName = "" - // this flag checks whether we are within the parentheses of #define ... ##class( <...> ) - Set tInMember = 0 - Set tPrevValue = "" - Set tIgnoreAllStr = 0 - Set tIgnoreStrList = "" - If pIgnoredStringRef = $char(0) { - Set tIgnoreAllStr = 1 - } Else { - Set tIgnoreStrList = $ListFromString(pIgnoredStringRef, ",") - } - While $ListNext(pLineTokenList,tPointer,tLineToken) { - Set $ListBuild(tLanguage,tType,tValue) = tLineToken - If (tLanguage = "COS") { - If (tType = "Pre-Processor Command") { - If (tValue = "#") { - Set tHasPoundSign = 1 - } ElseIf (tHasPoundSign && ($ZConvert(tValue,"L") = "include")) { - Set tHasIncludeTag = 1 - } ElseIf (tHasPoundSign && ($ZConvert(tValue,"L") = "define")) { - Set tHasDefineTag = 1 - } - } ElseIf (tType = "Pre-Processor Function") { - If (tInMember && (tValue '= "(")) { - If tValue = ")" { - // get the closing parenthesis, record the class name - $$$AddReference(tReferencedClassName) - Set tInMember = 0 - Set tReferencedClassName = "" - } Else { - // in between two parentheses, keep constructing the class name - Set tReferencedClassName = tReferencedClassName_tValue - } - } Else { - If tHasDefineTag { - // get a "##" and a "class", indicating that we are about to touch a referenced class - If (($ZConvert(tValue, "L") = "class") && (tPrevValue = "##")) { - Set tInMember = 1 - } - } - } - } ElseIf (tType = "Name") { - // #include HS.HC, or, #include %ZHSLIB, for instance. - // it will be displayed as <$lb("COS","Name","HS"),$lb("COS","White Space",".HC"))> / <$lb("COS","Name","%ZHSLIB")> - // it is not valid to have #include (A, B) in .inc file, so we only consider this situation - If tHasIncludeTag { - Set tReferencedIncludeFileName = ..#INCPREFIX_$ZStrip(tValue, "<>WC") - } - } ElseIf (tType = "White Space") { - If (tReferencedIncludeFileName '= "") { - Set tReferencedIncludeFileName = tReferencedIncludeFileName_$ZStrip(tValue, "<>WC") - } - } ElseIf (tType = "String") { - // Dynamic class call. Can have classname as a string. - If tIgnoreAllStr { - Continue - } - If ($Extract(tValue) = """") { - // Quoted classname so remove additional quotes - Set tValue = $Extract(tValue,2,*-1) - Set tIsValidClassname = ##class(%Dictionary.Classname).IsValid(tValue) - If tIsValidClassname { - Set tPackageExists = $Data($$$ZPMDependencyNsPackages($Piece(tValue, ".", 1))) - Set tIsFullClassname = $Piece(tValue, ".", 2) '= "" - If (tPackageExists && tIsFullClassname) { - // The package name already exists in the namespace. Can - // safely assume no non-existent packages are being referenced. - // This check is to prevent red herrings such as simple - // strings like "POS" or "Hello" getting flagged as invalid - // references. - If ($Extract($ZConvert(tValue, "U"), *-3, *) = ".CLS") { - // If reference ends in ".cls", strip it so that class's module can be detected - Set tValue = $Extract(tValue, 1, *-4) - } - If '$ListFind(tIgnoreStrList, tValue) { - $$$AddReference(tValue) - } - } - } - } - } - Set tPrevValue = tValue - } - } - If tReferencedClassName '= "" { - $$$AddReference(tReferencedClassName) - } - If tReferencedIncludeFileName '= "" { - $$$AddReference(tReferencedIncludeFileName) - } -} - -// ////////////////////// END of Extraction methods called on LINES ///////////////////////// - -ClassMethod GetClassNameFromTableName(pSourceClass As %String, pFullTableName As %String, Output pClassName) As %Status -{ - Set tSC = $$$OK - Try { - Set pClassName = "" - - // Default: same SQL schema - If ($Length(pFullTableName,".") > 1) { - Set tSchemaName = $Piece(pFullTableName,".") - } Else { - Set tSchemaName = $$$comClassKeyGet(pSourceClass,$$$cCLASSsqlschemaname) - } - Set tTableName = $Piece(pFullTableName,".",*) - - Set tResult = ##class(%SQL.Statement).%ExecDirect(, - "select NVL(NVL("_ - "(select CLASSNAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = ? and TABLE_NAME = ?),"_ - "(select CLASSNAME from INFORMATION_SCHEMA.ROUTINES where SPECIFIC_SCHEMA = ? and SPECIFIC_NAME = ?)),"_ - "(select CLASSNAME from INFORMATION_SCHEMA.VIEWS where TABLE_SCHEMA = ? and TABLE_NAME = ?))", - tSchemaName,tTableName,tSchemaName,tTableName,tSchemaName,tTableName) - If (tResult.%SQLCODE < 0) { - Throw ##class(%Exception.SQL).CreateFromSQLCODE(tResult.%SQLCODE,tResult.%Message) - } - If tResult.%Next(.tSC) { - $$$ThrowOnError(tSC) - Set pClassName = tResult.%GetData(1) - } Else { - $$$ThrowOnError(tSC) - } - If (pClassName = "") { - Do ##class(%IPM.General.LogManager).Warning("Table name not found: "_pFullTableName,1) - Set pClassName = "" - } - } Catch e { - Set pClassName = "" - Set tSC = e.AsStatus() - } - Quit tSC -} - /// Validate item name is an existing class or include file ClassMethod ValidateItemName(pItemName As %String) [ Internal, Private ] { @@ -1044,25 +430,5 @@ ClassMethod ValidateItemName(pItemName As %String) [ Internal, Private ] } } -/// Left in as a tool for developers working to enhance this class in the future. -/// This shows all the tokens for a given class. -ClassMethod Test(pClass As %String) [ Internal ] -{ - Set tSC = $$$OK - Try { - $$$ThrowOnError(##class(%Compiler.UDL.TextServices).GetTextAsStream(,pClass,.tSourceStream)) - - Set tSC = ##class(%Library.SyntaxColorReader).FromCode(tSourceStream,"CLS","A",.tSCReader) - $$$ThrowOnError(tSC) - - While tSCReader.NextLine(.tLineTokenList) { - zw tLineTokenList - } - } Catch e { - Set tSC = e.AsStatus() - Write !,$System.Status.GetErrorText(e) - } - Quit tSC } -} diff --git a/src/cls/IPM/DependencyAnalyzer/ModuleResults.cls b/src/cls/IPM/DependencyAnalyzer/ModuleResults.cls deleted file mode 100644 index b8d15519..00000000 --- a/src/cls/IPM/DependencyAnalyzer/ModuleResults.cls +++ /dev/null @@ -1,93 +0,0 @@ -Class %IPM.DependencyAnalyzer.ModuleResults Extends %Persistent -{ - -Parameter DEFAULTGLOBAL = "^IPM.DependencyAnalyzer.Module"; - -Index TargetModule On TargetModule; - -/// Module (or the home module of the file) on which the dependencyAnalyzer is run on -Property TargetModule As %String(MAXLEN = 255) [ Required ]; - -Property TimeStamp As %TimeStamp [ InitialExpression = {$zdt($zts,3)} ]; - -Relationship Problems As %IPM.DependencyAnalyzer.Problem [ Cardinality = many, Inverse = Run ]; - -/// Displays the module's results; particularly effective writing to the Studio output window, where lines can be clicked to jump to that spot in code. -Method Display() -{ - Set tProblemKey = "" - // all problems should have the same indication of whether or not only display invalid references or all references - Set tInvalidOnly = 1 - For { - #dim tProblem As %IPM.DependencyAnalyzer.Problem - Set tProblem = ..Problems.GetNext(.tProblemKey) - If (tProblemKey = "") { - Quit - } - - Set tSub1 = $Select(tProblem.ReferencedItemExists:tProblem.ReferencedModule,1:" ") - Set tSub2 = tProblem.ReferencedFileType - Set tSub3 = tProblem.ReferencedItem - Set tInvalidOnly = tProblem.InvalidOnly - Set tProblemMap(tSub1,tSub2,tSub3, $Increment(tProblemMap(tSub1,tSub2,tSub3))) = tProblem.ToString() - } - - Set tReferencedModuleKey = "" - For { - Set tReferencedModuleKey = $Order(tProblemMap(tReferencedModuleKey)) - If (tReferencedModuleKey = "") { - Quit - } - If ($Increment(tIsFirst) > 1) { - Write !! - } - If (tReferencedModuleKey = " ") { - Write $Select(tInvalidOnly=0: "References to ", 1: "Invalid references to missing ")_"classes/include files:" - } Else { - Write $Select(tInvalidOnly=0: "References ", 1: "Invalid references ")_"to module ",tReferencedModuleKey," :" - } - - Set tFileTypeKey = "" - For { - Set tFileTypeKey = $Order(tProblemMap(tReferencedModuleKey, tFileTypeKey)) - If (tFileTypeKey = "") { - Quit - } - Set tReferencedItemKey = "" - For { - Set tReferencedItemKey = $Order(tProblemMap(tReferencedModuleKey, tFileTypeKey, tReferencedItemKey),1,tLineCount) - If (tReferencedItemKey = "") { - Quit - } - Write !, $Case(tFileTypeKey, ".INC": "Include File ",:"Class "),tReferencedItemKey_tFileTypeKey,$Case(tReferencedModuleKey," ": $Select(tInvalidOnly: " (missing)", 1: ""),:" (@ "_tReferencedModuleKey_")") - - For tLine=1:1:tLineCount { - Write !,tProblemMap(tReferencedModuleKey, tFileTypeKey, tReferencedItemKey, tLine) - } - } - } - } -} - -Storage Default -{ - - -%%CLASSNAME - - -TargetModule - - -TimeStamp - - -^IPM.DependencyAnalyzer.ModuleD -ModuleResultsDefaultData -^IPM.DependencyAnalyzer.ModuleD -^IPM.DependencyAnalyzer.ModuleI -^IPM.DependencyAnalyzer.ModuleS -%Storage.Persistent -} - -} diff --git a/src/cls/IPM/DependencyAnalyzer/Problem.cls b/src/cls/IPM/DependencyAnalyzer/Problem.cls deleted file mode 100644 index 5381d9ca..00000000 --- a/src/cls/IPM/DependencyAnalyzer/Problem.cls +++ /dev/null @@ -1,81 +0,0 @@ -Class %IPM.DependencyAnalyzer.Problem Extends %Persistent -{ - -Parameter DEFAULTGLOBAL = "^IPM.DependencyAnalyzer.Problem"; - -Index Run On Run [ Type = bitmap ]; - -Relationship Run As %IPM.DependencyAnalyzer.ModuleResults [ Cardinality = one, Inverse = Problems ]; - -/// Caller item with file type suffix -Property ProblemItem As %String(MAXLEN = 255) [ Required ]; - -Property ProblemMember As %Dictionary.Identifier [ Required ]; - -Property ProblemLine As %Integer(MINVAL = 0) [ Required ]; - -Property ProblemCode As %String(MAXLEN = "") [ Required ]; - -Property ReferencedModule As %String(MAXLEN = 255); - -Property ReferencedItem As %String(MAXLEN = 255) [ Required ]; - -Property ReferencedFileType As %String(MAXLEN = 255) [ InitialExpression = ".CLS" ]; - -Property ReferencedItemExists As %Boolean [ InitialExpression = 1 ]; - -Property InvalidOnly As %Boolean [ InitialExpression = 1 ]; - -/// Returns a string that, when shown in the Studio output pane, can be clicked to jump to this location in code. -Method ToString() As %String [ CodeMode = expression ] -{ -..ProblemItem_"("_..ProblemMember_"+"_..ProblemLine_") "_..ProblemCode -} - -Storage Default -{ - - -%%CLASSNAME - - -Run - - -ProblemItem - - -ProblemMember - - -ProblemLine - - -ProblemCode - - -ReferencedModule - - -ReferencedItem - - -ReferencedFileType - - -ReferencedItemExists - - -InvalidOnly - - - -^IPM.DependencyAnalyzer.ProblemD -ProblemDefaultData -^IPM.DependencyAnalyzer.ProblemD -^IPM.DependencyAnalyzer.ProblemI -^IPM.DependencyAnalyzer.ProblemS -%Storage.Persistent -} - -} diff --git a/src/cls/IPM/Lifecycle/StudioProject.cls b/src/cls/IPM/Lifecycle/StudioProject.cls index 5b48465b..483a85f5 100644 --- a/src/cls/IPM/Lifecycle/StudioProject.cls +++ b/src/cls/IPM/Lifecycle/StudioProject.cls @@ -33,12 +33,12 @@ Method %Package(ByRef pParams) As %Status // Possibly, include package manager in package and install it if needed. If tIncludePackageManager { - If ##class(%IPM.Storage.Module).NameExists("ZHSLIB") { - Set tZPMModule = ##class(%IPM.Storage.Module).NameOpen("ZHSLIB",,.tSC) + If ##class(%IPM.Storage.Module).NameExists($$$IPMModuleName) { + Set tIPMModule = ##class(%IPM.Storage.Module).NameOpen($$$IPMModuleName,,.tSC) $$$ThrowOnError(tSC) - Do ..PackageOneModule(tZPMModule,tTarget,.pParams,.tModuleLocations,.tRtn) + Do ..PackageOneModule(tIPMModule,tTarget,.pParams,.tModuleLocations,.tRtn) } Else { - $$$ThrowStatus($$$ERROR($$$GeneralError,"Attempted to include package manager, but ZHSLIB module not defined in this namespace.")) + $$$ThrowStatus($$$ERROR($$$GeneralError,"Attempted to include package manager, but module not defined in this namespace.")) } } @@ -80,12 +80,12 @@ Method %Package(ByRef pParams) As %Status Set tRtn($i(tRtn)) = "MAIN" For tIndex = 1:1:tModuleLocations { Set tModuleName = tModuleLocations(tIndex) - Set tIsPackageManager = (tModuleName = "ZHSLIB") && (..Module.Name '= "ZHSLIB") + Set tIsPackageManager = (tModuleName = $$$IPMModuleName) && (..Module.Name '= $$$IPMModuleName) If tIsPackageManager { Set tRtn($i(tRtn)) = " If '$$$comClassDefined(""%IPM.Main"") {" } If tIncludePackageManager { - If (tModuleName = "ZHSLIB") { + If (tModuleName = $$$IPMModuleName) { // No-op - handled in PackageOneModule. } Else { Set tUndeployableItems(tModuleName_".ZPM") = "" @@ -129,7 +129,7 @@ Method PackageOneModule(pModule As %IPM.Storage.Module, pTargetGlobal As %String Set tVerbose = $Get(pParams("Verbose"),0) Set tDeployDefault = $Get(pParams("Package","Deploy"),0) Set tIncludePackageManager = $Get(pParams("Package","Manager"),0) - Set tIsPackageManager = (pModule.Name = "ZHSLIB") + Set tIsPackageManager = (pModule.Name = $$$IPMModuleName) Set tKeepGenerated = $Get(pParams("Package","KeepGenerated"),0) Set pModuleLocations(0,pModule.Name) = $Increment(pModuleLocations) @@ -144,9 +144,9 @@ Method PackageOneModule(pModule As %IPM.Storage.Module, pTargetGlobal As %String $$$ThrowOnError(pModule.GetStudioProject(.tProject,1,tDeployDefault,"object")) If tIsPackageManager { - Set tPackedZHSLIBClass = "zTemp.PackageManager.Container.ZHSLIB" - $$$ThrowOnError(##class(%IPM.Lifecycle.StudioProject.ContainerClass).Create(tPackedZHSLIBClass,"ZHSLIB.ZPM",tVerbose)) - Do tProject.AddItem(tPackedZHSLIBClass_".CLS") + Set tPackedIPMClass = "zTemp.PackageManager.Container."_$$$IPMModuleName + $$$ThrowOnError(##class(%IPM.Lifecycle.StudioProject.ContainerClass).Create(tPackedIPMClass,$$$IPMModuleName_".ZPM",tVerbose)) + Do tProject.AddItem(tPackedIPMClass_".CLS") } $$$ThrowOnError(tProject.DeployToGbl($Name(@pTargetGlobal@(pModuleLocations,"object")),$Select(tVerbose:"d-k",1:"-d-k"),1)) @@ -202,6 +202,21 @@ Method PackageOneModule(pModule As %IPM.Storage.Module, pTargetGlobal As %String $$$ThrowOnError(tSourceProject.DeployToGbl($Name(@pTargetGlobal@(pModuleLocations,"source")),$Select(tVerbose:"d",1:"-d")_$Select(tKeepGenerated:"k",1:"-k"))) + // Map %IPM to current routine database + If tIsPackageManager { + Set pInstallerCode($i(pInstallerCode)) = " Set currentNS = $Namespace" + Set pInstallerCode($i(pInstallerCode)) = " Set mapping = ""%IPM""" + Set pInstallerCode($i(pInstallerCode)) = " New $Namespace " + Set pInstallerCode($i(pInstallerCode)) = " Set $Namespace = ""%SYS""" + Set pInstallerCode($i(pInstallerCode)) = " If '##class(Config.MapPackages).Exists(currentNS, mapping) {" + Set pInstallerCode($i(pInstallerCode)) = " Kill NSprops" + Set pInstallerCode($i(pInstallerCode)) = " $$$ThrowOnError(##class(Config.Namespaces).Get(currentNS, .NSprops))" + Set pInstallerCode($i(pInstallerCode)) = " Kill tProps" + Set pInstallerCode($i(pInstallerCode)) = " Set tProps(""Database"") = $Get(NSprops(""Routines""))" + Set pInstallerCode($i(pInstallerCode)) = " $$$ThrowOnError(##class(Config.MapPackages).Create(currentNS, mapping, .tProps))" + Set pInstallerCode($i(pInstallerCode)) = " }" + Set pInstallerCode($i(pInstallerCode)) = " Set $Namespace = currentNS" + } Set pInstallerCode($i(pInstallerCode)) = " $$$ThrowOnError(##class(%Studio.Project).InstallFromGbl("_$$$QUOTE($Name(@pTargetGlobal@(pModuleLocations,"object")))_",""-d"",0))" Set pInstallerCode($i(pInstallerCode)) = " $$$ThrowOnError(##class(%Studio.Project).InstallFromGbl("_$$$QUOTE($Name(@pTargetGlobal@(pModuleLocations,"source")))_",""-d"",0))" @@ -210,8 +225,8 @@ Method PackageOneModule(pModule As %IPM.Storage.Module, pTargetGlobal As %String $$$ThrowOnError(tArchive.GenerateInstallerCode("tExtractDirectory",.pInstallerCode)) If tIsPackageManager { - // Note: only unpack ZHSLIB module manifest if ZHSLIB module was installed. - Set pInstallerCode($i(pInstallerCode)) = " Do ##class("_tPackedZHSLIBClass_").Unpack()" + // Note: only unpack package manager module manifest if module was installed. + Set pInstallerCode($i(pInstallerCode)) = " Do ##class("_tPackedIPMClass_").Unpack()" } // TODO: Support CSP/other files @@ -265,3 +280,4 @@ Method OnInstallFromPayload(ByRef pParams) As %Status } } + diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index 8baac091..aa8fb0fc 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -2088,6 +2088,9 @@ ClassMethod ModuleAction(ByRef pCommandInfo) [ Internal ] /// Run Dependency Analyzer for the given module ClassMethod RunDependencyAnalyzer(ByRef pCommandInfo) { + If '$$$comClassDefined("%pkg.isc.dependencyAnalyzer.Utils") { + $$$ThrowStatus($$$ERROR($$$GeneralError, "Dependency Analyzer package must be installed before running the dependency analyzer.")) + } Set ignoredStringRef = $$$GetModifier(pCommandInfo,"ignore-str") Set ignoreAll = $$$HasModifier(pCommandInfo,"ignore-str-all") Set invalidOnly = $$$GetModifier(pCommandInfo,"invalid-only") @@ -2977,3 +2980,4 @@ ClassMethod DisplayModules(ByRef pList, pNumbered As %Boolean = 0, pWithNamespac } } + diff --git a/src/cls/IPM/Utils/Build.cls b/src/cls/IPM/Utils/Build.cls index 9d3512f0..c8d92969 100644 --- a/src/cls/IPM/Utils/Build.cls +++ b/src/cls/IPM/Utils/Build.cls @@ -208,7 +208,7 @@ ClassMethod CreateDatabase(pDBName As %String, pInitFile As %String = "", pOverw // Create database Set tExists = 0 If '##class(SYS.Database).%ExistsId(tPath) { - Set tSC = ##class(SYS.Database).CreateDatabase(tPath,,,tRoleResourceName) + Set tSC = ##class(SYS.Database).CreateDatabase(tPath,,,,tRoleResourceName) If $$$ISERR(tSC) { Quit } @@ -704,3 +704,4 @@ ClassMethod Backup() As %Status [ Internal ] } } + From c9073bef454c2dd3344093128f52507eb2c2856e Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:01:36 -0400 Subject: [PATCH 41/42] fix: typo in class name ModuleItem is the table name; should have checked for Module class. --- src/cls/IPM/Main.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index aa8fb0fc..eed47e57 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -941,7 +941,7 @@ ClassMethod GetListModules(pNamespace As %String = {$Namespace}, pSearch As %Str Quit } } - If '$$$comClassDefined("%IPM.Storage.ModuleItem") { + If '$$$comClassDefined("%IPM.Storage.Module") { // Don't error in namespaces without IPM enabled Quit } From 8cb271156d7dd6c91cfa7a4d2ee8cc3c5e6f2302 Mon Sep 17 00:00:00 2001 From: isc-tleavitt <73311181+isc-tleavitt@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:41:02 -0400 Subject: [PATCH 42/42] fix: docker run flags in "Clean install and test" Looking at history these were added fairly recently and it's failing here, so maybe removing them will fix it. --- .github/workflows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a0d55c29..34bd7f51 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -169,8 +169,7 @@ jobs: timeout-minutes: 15 run: | wget http://localhost:52773/registry/packages/zpm/latest/installer -O /tmp/zpm.xml - docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} \ - --log-driver=none -a stdin -a stdout -a stderr + docker run --network zpm --rm -d -v /tmp/zpm.xml:/home/irisowner/zpm.xml ${{ steps.image.outputs.name }} ${{ steps.image.outputs.flags }} CONTAINER=`docker ps -lq` sleep 5; docker exec $CONTAINER /usr/irissys/dev/Cloud/ICM/waitISC.sh /bin/echo -e '' \