From 0b5445ef39220b3de42c0499891453383fbbff20 Mon Sep 17 00:00:00 2001 From: Cameron Macintosh Date: Tue, 9 Dec 2025 13:12:59 -0600 Subject: [PATCH 1/5] fix: Catch and save any errors thown by OnPull (#909) --- cls/SourceControl/Git/PullEventHandler.cls | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cls/SourceControl/Git/PullEventHandler.cls b/cls/SourceControl/Git/PullEventHandler.cls index ea7cfeae..5efd2c0e 100644 --- a/cls/SourceControl/Git/PullEventHandler.cls +++ b/cls/SourceControl/Git/PullEventHandler.cls @@ -24,7 +24,9 @@ Method OnPull() As %Status [ Abstract ] /// pullEventClass: if defined, override the configured pull event class ClassMethod ForModifications(ByRef files, pullEventClass As %String) As %Status { - set st = $$$OK + #Dim err As %Exception.AbstractException + #Dim pullError As %Exception.AbstractException + #Dim st As %Status = $$$OK try { set log = ##class(SourceControl.Git.DeploymentLog).%New() set log.HeadRevision = ##class(SourceControl.Git.Utils).GetCurrentRevision() @@ -33,15 +35,20 @@ ClassMethod ForModifications(ByRef files, pullEventClass As %String) As %Status quit:$$$ISERR(st) set event = $classmethod( $select( - $data(pullEventClass)#2: pullEventClass, + $data(pullEventClass)#2: pullEventClass, 1: ##class(SourceControl.Git.Utils).PullEventClass()) ,"%New") set event.LocalRoot = ##class(SourceControl.Git.Utils).TempFolder() merge event.ModifiedFiles = files - set st = event.OnPull() + try { + set st = event.OnPull() + } + catch pullError { + set st = pullError.AsStatus() + } set log.EndTimestamp = $zdatetime($ztimestamp,3) set log.Status = st - set st = log.%Save() + set st = log.%Save() // this hides any errors returned or thrown by OnPull() quit:$$$ISERR(st) } catch err { set st = err.AsStatus() From 1371e5731d377df10a526031230f41833c6edeba Mon Sep 17 00:00:00 2001 From: Cameron Macintosh Date: Tue, 9 Dec 2025 13:15:56 -0600 Subject: [PATCH 2/5] chore: Update change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 546ee5a0..3d7cb084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Fixed - Web UI workspace view labels changes as Merge Conflict if there are unmerged changes (#890) - Web UI workspace view displays diff correctly for files with merge conflicts (#898) +- Catch and log exceptions thrown by pull handler (#909) ## [2.14.0] - 2025-11-07 From 669d28e4e3f11fe2f3a1b69f172020fb6a7a8641 Mon Sep 17 00:00:00 2001 From: Cameron Macintosh Date: Tue, 9 Dec 2025 13:17:58 -0600 Subject: [PATCH 3/5] Fix: logging statement spacing. --- cls/SourceControl/Git/Utils.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cls/SourceControl/Git/Utils.cls b/cls/SourceControl/Git/Utils.cls index 76c2f3f0..1aad9205 100644 --- a/cls/SourceControl/Git/Utils.cls +++ b/cls/SourceControl/Git/Utils.cls @@ -1469,7 +1469,7 @@ ClassMethod ImportItem(InternalName As %String, force As %Boolean = 0, verbose A write !, InternalName," has been imported from ", filename } } else { - write !, "ERROR importing" ,InternalName, ! + write !, "ERROR importing " ,InternalName, ! do $system.Status.DisplayError(sc) } } elseif verbose { From 5d753e9d8707cfb0832b2c516383d590e9f8e6d5 Mon Sep 17 00:00:00 2001 From: Cameron Macintosh Date: Mon, 15 Dec 2025 08:58:26 -0600 Subject: [PATCH 4/5] fix: IncrementalLoad correctly deletes business items before classes (#907) --- CHANGELOG.md | 3 +- .../Git/PullEventHandler/IncrementalLoad.cls | 54 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7cb084..f9ce3625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Fixed - Web UI workspace view labels changes as Merge Conflict if there are unmerged changes (#890) - Web UI workspace view displays diff correctly for files with merge conflicts (#898) -- Catch and log exceptions thrown by pull handler (#909) +- Catch and log exceptions thrown by pull handlers (#909) +- Fix Incremental Load to first remove production items before removing classes (#907) ## [2.14.0] - 2025-11-07 diff --git a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls index 1f453ca5..fe633368 100644 --- a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls +++ b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls @@ -9,7 +9,7 @@ Parameter DESCRIPTION = "Performs an incremental load and compile of all changes Method OnPull() As %Status { - set sc = $$$OK + #Dim sc As %Status = $$$OK // certain items must be imported before everything else. for i=1:1:$get(..ModifiedFiles) { @@ -21,22 +21,20 @@ Method OnPull() As %Status } set nFiles = 0 - for i=1:1:$get(..ModifiedFiles){ set internalName = ..ModifiedFiles(i).internalName - + // Don't import the config file a second time continue:internalName=##class(SourceControl.Git.Settings.Document).#INTERNALNAME - + set tExternalName = ..ModifiedFiles(i).externalName + if ((internalName = "") && (..ModifiedFiles(i).changeType '= "D")) { - write !, ..ModifiedFiles(i).externalName, " was not imported into the database and will not be compiled. " + write !, tExternalName, " was not imported into the database and will not be compiled. " } elseif (..ModifiedFiles(i).changeType = "D") { - set delSC = ..DeleteFile(internalName, ..ModifiedFiles(i).externalName) - if delSC { - write !, ..ModifiedFiles(i).externalName, " was deleted." - } else { - write !, "WARNING: Deletion of ", ..ModifiedFiles(i).externalName, " failed." - } + #; Deleted production items will not have an internal name + set delIndex = $select(##class(SourceControl.Git.Util.Production).ItemIsPTD(tExternalName): 1, 1: 2) + set:(delIndex=1) internalName = "-"_i ;; This is a total hack because deleted production items will not have an internal name + set delList(delIndex, internalName) = tExternalName } else { set nFiles = nFiles + 1 if (##class(SourceControl.Git.Utils).Type(internalName) = "ptd") { @@ -48,25 +46,53 @@ Method OnPull() As %Status } } + #; First remove production items, then everything else + write:$data(delList) !!,"Removing items..." + for orderIndex = 1,2 { + set item = $order(delList(orderIndex, ""), 1, tExternalName) + while (item '= "") { + set delSC = ..RemoveItem(item, tExternalName) + set item = $order(delList(orderIndex, item), 1, tExternalName) + } + } + if (nFiles = 0) { write !, "Nothing to compile." quit $$$OK } + write ! set sc = $$$ADDSC(sc,$system.OBJ.CompileList(.compilelist, "ckbryu")) + // after compilation, deploy any PTD items + set start = $zhorolog set key = $order(ptdList("")) while (key '= "") { set sc = $$$ADDSC(sc, ##class(SourceControl.Git.Utils).ImportItem(key,1)) set key = $order(ptdList(key)) } + write:$data(ptdList) !,"Production items updated in ",($zhorolog-start),"s" if $$$comClassDefined("Ens.Director") && ##class(Ens.Director).IsProductionRunning() { + set start = $zhorolog write !,"Updating production... " set sc = $$$ADDSC(sc,##class(Ens.Director).UpdateProduction()) - write "done." + write "done in ",($zhorolog-start),"s." } quit sc } +Method RemoveItem(pInternalName, pExternalName) As %Status +{ + #Dim delSC As %Status + set delSC = ..DeleteFile(pInternalName, pExternalName) + if delSC { + write !, pExternalName, " was deleted." + } else { + write !, "WARNING: Deletion of ", pExternalName, " failed." + write !,?3,$system.Status.DisplayError(delSC) + } + quit delSC +} + Method DeleteFile(item As %String = "", externalName As %String = "") As %Status { try { @@ -101,7 +127,7 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status } else { set deleted = 0 } - + if deleted && $$$ISOK(sc) { if (item '= "") { do ##class(SourceControl.Git.Utils).RemoveRoutineTSH(item) @@ -124,7 +150,7 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status } else { // Item still exists and was not deleted -- bad set sc = e.AsStatus() - do e.Log() + do e.Log() } } return sc From 847e09b6664c5369256a6098ff017c48a5b78dc4 Mon Sep 17 00:00:00 2001 From: Cameron Macintosh Date: Mon, 15 Dec 2025 09:07:33 -0600 Subject: [PATCH 5/5] fix: More specific IncrementalLoad log messages. (#907) --- .../Git/PullEventHandler/IncrementalLoad.cls | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls index fe633368..e6e1ad5e 100644 --- a/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls +++ b/cls/SourceControl/Git/PullEventHandler/IncrementalLoad.cls @@ -55,22 +55,31 @@ Method OnPull() As %Status set item = $order(delList(orderIndex, item), 1, tExternalName) } } - if (nFiles = 0) { - write !, "Nothing to compile." + write !, "Nothing to Load." quit $$$OK } - write ! - set sc = $$$ADDSC(sc,$system.OBJ.CompileList(.compilelist, "ckbryu")) - - // after compilation, deploy any PTD items - set start = $zhorolog - set key = $order(ptdList("")) - while (key '= "") { - set sc = $$$ADDSC(sc, ##class(SourceControl.Git.Utils).ImportItem(key,1)) - set key = $order(ptdList(key)) + + if $data(compilelist) { + write ! + set sc = $$$ADDSC(sc,$system.OBJ.CompileList(.compilelist, "ckbryu")) + } + else { + write !,"Nothing to Compile." } - write:$data(ptdList) !,"Production items updated in ",($zhorolog-start),"s" + + #; Deploy any PTD items + if $data(ptdList) { + write !,"Loading production items..." + set start = $zhorolog + set key = $order(ptdList("")) + while (key '= "") { + set sc = $$$ADDSC(sc, ##class(SourceControl.Git.Utils).ImportItem(key,1)) + set key = $order(ptdList(key)) + } + write !,"Production items imported in ",($zhorolog-start),"s" + } + if $$$comClassDefined("Ens.Director") && ##class(Ens.Director).IsProductionRunning() { set start = $zhorolog write !,"Updating production... " @@ -95,8 +104,9 @@ Method RemoveItem(pInternalName, pExternalName) As %Status Method DeleteFile(item As %String = "", externalName As %String = "") As %Status { + #Dim sc As %Status = $$$OK + #Dim err As %Exception.AbstractException try { - set sc = $$$OK set type = $select( ##class(SourceControl.Git.Util.Production).ItemIsPTD(externalName): "ptd", 1: ##class(SourceControl.Git.Utils).Type(item) @@ -106,15 +116,15 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status set deleted = 1 if type = "prj" { set sc = $system.OBJ.DeleteProject(name) - }elseif type = "cls" { + } elseif type = "cls" { if ##class(SourceControl.Git.Utils).ItemIsProductionToDecompose(name) { write !, "Production decomposition enabled, skipping delete of production class" } else { set sc = $system.OBJ.Delete(item) } - }elseif $listfind($listbuild("mac","int","inc","bas","mvb","mvi"), type) > 0 { + } elseif $listfind($listbuild("mac","int","inc","bas","mvb","mvi"), type) > 0 { set sc = ##class(%Routine).Delete(item) - }elseif type = "csp" { + } elseif type = "csp" { set sc = $System.CSP.DeletePage(item) } elseif settings.decomposeProductions && (type = "ptd") { set normalizedFilePath = ##class(%File).NormalizeFilename(##class(SourceControl.Git.Utils).TempFolder()_externalName) @@ -122,7 +132,7 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status ##class(SourceControl.Git.Production).RemoveItemByExternalName(normalizedFilePath,"FullExternalName"), ##class(%Library.RoutineMgr).Delete(item) ) - }elseif ##class(SourceControl.Git.Utils).UserTypeCached(item) { + } elseif ##class(SourceControl.Git.Utils).UserTypeCached(item) { set sc = ##class(%Library.RoutineMgr).Delete(item) } else { set deleted = 0 @@ -141,7 +151,7 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status } // Force the catch if failing $$$ThrowOnError(sc) - } catch e { + } catch err { set filename = ##class(SourceControl.Git.Utils).FullExternalName(item) if (filename = "") || '##class(%File).Exists(filename) { do ##class(SourceControl.Git.Utils).RemoveRoutineTSH(item) @@ -149,8 +159,8 @@ Method DeleteFile(item As %String = "", externalName As %String = "") As %Status set sc = $$$OK } else { // Item still exists and was not deleted -- bad - set sc = e.AsStatus() - do e.Log() + set sc = err.AsStatus() + do err.Log() } } return sc