Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kargo-cli for openSUSE:Factory 
checked in at 2026-06-13 18:48:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kargo-cli (Old)
 and      /work/SRC/openSUSE:Factory/.kargo-cli.new.1981 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kargo-cli"

Sat Jun 13 18:48:29 2026 rev:55 rq:1359087 version:1.10.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/kargo-cli/kargo-cli.changes      2026-06-10 
15:53:30.073583463 +0200
+++ /work/SRC/openSUSE:Factory/.kargo-cli.new.1981/kargo-cli.changes    
2026-06-13 18:50:36.281573634 +0200
@@ -1,0 +2,6 @@
+Sat Jun 13 10:09:11 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 1.10.7:
+  no CLI-related changes or dependency updates
+
+-------------------------------------------------------------------

Old:
----
  kargo-cli-1.10.6.obscpio

New:
----
  kargo-cli-1.10.7.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kargo-cli.spec ++++++
--- /var/tmp/diff_new_pack.D9aLjh/_old  2026-06-13 18:50:37.533625650 +0200
+++ /var/tmp/diff_new_pack.D9aLjh/_new  2026-06-13 18:50:37.533625650 +0200
@@ -19,7 +19,7 @@
 %define executable_name kargo
 
 Name:           kargo-cli
-Version:        1.10.6
+Version:        1.10.7
 Release:        0
 Summary:        CLI for the Kubernetes Application lifecycle orchestration
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.D9aLjh/_old  2026-06-13 18:50:37.565626980 +0200
+++ /var/tmp/diff_new_pack.D9aLjh/_new  2026-06-13 18:50:37.573627312 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/akuity/kargo</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.10.6</param>
+    <param name="revision">v1.10.7</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.D9aLjh/_old  2026-06-13 18:50:37.597628309 +0200
+++ /var/tmp/diff_new_pack.D9aLjh/_new  2026-06-13 18:50:37.601628475 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/akuity/kargo</param>
-              <param 
name="changesrevision">1ec8d6094bdb9b2f29f4858f788f2af13ac37fb1</param></service></servicedata>
+              <param 
name="changesrevision">17077e406ed309fcc830d08776d9b9a47fe6e134</param></service></servicedata>
 (No newline at EOF)
 

++++++ kargo-cli-1.10.6.obscpio -> kargo-cli-1.10.7.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kargo-cli-1.10.6/pkg/webhook/kubernetes/admission.go 
new/kargo-cli-1.10.7/pkg/webhook/kubernetes/admission.go
--- old/kargo-cli-1.10.6/pkg/webhook/kubernetes/admission.go    2026-06-09 
14:17:09.000000000 +0200
+++ new/kargo-cli-1.10.7/pkg/webhook/kubernetes/admission.go    2026-06-12 
02:30:12.000000000 +0200
@@ -2,10 +2,22 @@
 
 import (
        "regexp"
+       "slices"
 
        "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 )
 
+// kubernetesGarbageCollectorUsernames is the set of well-known Kubernetes
+// system identities that perform garbage collection and namespace teardown.
+// These must be allowed to delete replicated secrets when a namespace is
+// removed so that namespaces do not become stuck in Terminating.
+var kubernetesGarbageCollectorUsernames = map[string]struct{}{
+       "system:serviceaccount:kube-system:namespace-controller":      {},
+       "system:serviceaccount:kube-system:generic-garbage-collector": {},
+       // when --use-service-account-credentials=false or unset
+       "system:kube-controller-manager": {},
+}
+
 type IsRequestFromKargoControlplaneFn func(admission.Request) bool
 
 func IsRequestFromKargoControlplane(regex *regexp.Regexp) 
IsRequestFromKargoControlplaneFn {
@@ -17,3 +29,18 @@
                return regex.Match([]byte(req.UserInfo.Username))
        }
 }
+
+// IsRequestFromKubernetesGarbageCollector returns true when the admission
+// request originates from one of the well-known Kubernetes system controllers
+// responsible for garbage collection and namespace teardown.
+func IsRequestFromKubernetesGarbageCollector(req admission.Request) bool {
+       _, ok := kubernetesGarbageCollectorUsernames[req.UserInfo.Username]
+       return ok
+}
+
+// IsRequestFromClusterAdmin returns true when the admission request originates
+// from a member of the system:masters group, which maps to cluster-admin
+// privileges and is used for break-glass operations.
+func IsRequestFromClusterAdmin(req admission.Request) bool {
+       return slices.Contains(req.UserInfo.Groups, "system:masters")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/pkg/webhook/kubernetes/admission_test.go 
new/kargo-cli-1.10.7/pkg/webhook/kubernetes/admission_test.go
--- old/kargo-cli-1.10.6/pkg/webhook/kubernetes/admission_test.go       
2026-06-09 14:17:09.000000000 +0200
+++ new/kargo-cli-1.10.7/pkg/webhook/kubernetes/admission_test.go       
2026-06-12 02:30:12.000000000 +0200
@@ -11,6 +11,85 @@
        "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 )
 
+func TestIsRequestFromKubernetesGarbageCollector(t *testing.T) {
+       testCases := []struct {
+               name     string
+               username string
+               expected bool
+       }{
+               {
+                       name:     "namespace-controller is allowed",
+                       username: 
"system:serviceaccount:kube-system:namespace-controller",
+                       expected: true,
+               },
+               {
+                       name:     "generic-garbage-collector is allowed",
+                       username: 
"system:serviceaccount:kube-system:generic-garbage-collector",
+                       expected: true,
+               },
+               {
+                       name:     "kube-controller-manager is allowed",
+                       username: "system:kube-controller-manager",
+                       expected: true,
+               },
+               {
+                       name:     "other user is not allowed",
+                       username: "some-user",
+                       expected: false,
+               },
+       }
+       for _, testCase := range testCases {
+               t.Run(testCase.name, func(t *testing.T) {
+                       t.Parallel()
+                       req := admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       UserInfo: authnv1.UserInfo{Username: 
testCase.username},
+                               },
+                       }
+                       require.Equal(t, testCase.expected, 
IsRequestFromKubernetesGarbageCollector(req))
+               })
+       }
+}
+
+func TestIsRequestFromClusterAdmin(t *testing.T) {
+       testCases := []struct {
+               name     string
+               groups   []string
+               expected bool
+       }{
+               {
+                       name:     "system:masters group member is allowed",
+                       groups:   []string{"system:masters"},
+                       expected: true,
+               },
+               {
+                       name:     "system:masters among multiple groups is 
allowed",
+                       groups:   []string{"some-group", "system:masters"},
+                       expected: true,
+               },
+               {
+                       name:     "no groups is not allowed",
+                       expected: false,
+               },
+               {
+                       name:     "other groups only is not allowed",
+                       groups:   []string{"some-group"},
+                       expected: false,
+               },
+       }
+       for _, testCase := range testCases {
+               t.Run(testCase.name, func(t *testing.T) {
+                       t.Parallel()
+                       req := admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       UserInfo: authnv1.UserInfo{Groups: 
testCase.groups},
+                               },
+                       }
+                       require.Equal(t, testCase.expected, 
IsRequestFromClusterAdmin(req))
+               })
+       }
+}
+
 func TestIsRequestFromKargoControlplane(t *testing.T) {
        testCases := map[string]struct {
                regex    *regexp.Regexp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/pkg/webhook/kubernetes/replicatedresource/webhook.go 
new/kargo-cli-1.10.7/pkg/webhook/kubernetes/replicatedresource/webhook.go
--- old/kargo-cli-1.10.6/pkg/webhook/kubernetes/replicatedresource/webhook.go   
2026-06-09 14:17:09.000000000 +0200
+++ new/kargo-cli-1.10.7/pkg/webhook/kubernetes/replicatedresource/webhook.go   
2026-06-12 02:30:12.000000000 +0200
@@ -3,6 +3,7 @@
 import (
        "context"
 
+       admissionv1 "k8s.io/api/admission/v1"
        ctrl "sigs.k8s.io/controller-runtime"
        "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
@@ -38,6 +39,15 @@
        if req.UserInfo.Username == w.cfg.ManagementControllerUsername {
                return admission.Allowed("request from Kargo management 
controller")
        }
+       // Namespace and GC controller are allowed to delete replicated 
resources
+       if req.Operation == admissionv1.Delete &&
+               libWebhook.IsRequestFromKubernetesGarbageCollector(req) {
+               return admission.Allowed("request from Kubernetes system 
controller")
+       }
+       // Cluster administrators are allowed to perform any operation
+       if libWebhook.IsRequestFromClusterAdmin(req) {
+               return admission.Allowed("request from cluster administrator")
+       }
        return admission.Denied(
                "replicated resources are managed by Kargo" +
                        " and cannot be created, modified, or deleted by end 
users",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/pkg/webhook/kubernetes/replicatedresource/webhook_test.go 
new/kargo-cli-1.10.7/pkg/webhook/kubernetes/replicatedresource/webhook_test.go
--- 
old/kargo-cli-1.10.6/pkg/webhook/kubernetes/replicatedresource/webhook_test.go  
    2026-06-09 14:17:09.000000000 +0200
+++ 
new/kargo-cli-1.10.7/pkg/webhook/kubernetes/replicatedresource/webhook_test.go  
    2026-06-12 02:30:12.000000000 +0200
@@ -76,6 +76,92 @@
                        },
                },
                {
+                       name: "namespace-controller DELETE is allowed",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Delete,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: 
"system:serviceaccount:kube-system:namespace-controller",
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.True(t, resp.Allowed)
+                       },
+               },
+               {
+                       name: "generic-garbage-collector DELETE is allowed",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Delete,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: 
"system:serviceaccount:kube-system:generic-garbage-collector",
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.True(t, resp.Allowed)
+                       },
+               },
+               {
+                       name: "kube-controller-manager DELETE is allowed",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Delete,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: 
"system:kube-controller-manager",
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.True(t, resp.Allowed)
+                       },
+               },
+               {
+                       name: "system:masters group member DELETE is allowed",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Delete,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: "cluster-admin",
+                                               Groups:   
[]string{"system:masters"},
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.True(t, resp.Allowed)
+                       },
+               },
+               {
+                       name: "system:masters group member UPDATE is allowed",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Update,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: "cluster-admin",
+                                               Groups:   
[]string{"system:masters"},
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.True(t, resp.Allowed)
+                       },
+               },
+               {
+                       name: "garbage collector non-DELETE is denied",
+                       req: admission.Request{
+                               AdmissionRequest: admissionv1.AdmissionRequest{
+                                       Operation: admissionv1.Update,
+                                       UserInfo: authnv1.UserInfo{
+                                               Username: 
"system:serviceaccount:kube-system:namespace-controller",
+                                       },
+                               },
+                       },
+                       assert: func(t *testing.T, resp admission.Response) {
+                               require.False(t, resp.Allowed)
+                       },
+               },
+               {
                        name: "other controlplane component is denied",
                        req: admission.Request{
                                AdmissionRequest: admissionv1.AdmissionRequest{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/ui/src/features/project/pipelines/graph/use-events-watcher.ts
 
new/kargo-cli-1.10.7/ui/src/features/project/pipelines/graph/use-events-watcher.ts
--- 
old/kargo-cli-1.10.6/ui/src/features/project/pipelines/graph/use-events-watcher.ts
  2026-06-09 14:17:09.000000000 +0200
+++ 
new/kargo-cli-1.10.7/ui/src/features/project/pipelines/graph/use-events-watcher.ts
  2026-06-12 02:30:12.000000000 +0200
@@ -4,7 +4,6 @@
 import { Watcher } from '@ui/features/project/pipelines/watcher';
 import { queryCache } from '@ui/features/utils/cache';
 import { Stage, Warehouse } from '@ui/gen/api/v1alpha1/generated_pb';
-import { useDocumentEvent } from '@ui/utils/document';
 
 export const useEventsWatcher = (
   project: string,
@@ -15,26 +14,44 @@
   warehouses?: string[]
 ) => {
   const client = useQueryClient();
-  const isWindowVisible = useDocumentEvent(
-    'visibilitychange',
-    () => document.visibilityState === 'visible'
-  );
 
   useEffect(() => {
-    if (!isWindowVisible || !project) {
+    if (!project) {
       return;
     }
 
-    const watcher = new Watcher(project, client);
+    let watcher: Watcher | undefined;
 
-    watcher.watchStages(act?.onStage, warehouses);
-    watcher.watchWarehouses({
-      onWarehouseEvent: act?.onWarehouse,
-      refreshHook: queryCache.freight.refetchQueryFreight
-    });
+    // (Re)establish the watch streams. Aborts any previous watcher first so we
+    // never leak a connection.
+    const connect = () => {
+      watcher?.cancelWatch();
+      watcher = new Watcher(project, client);
+      watcher.watchStages(act?.onStage, warehouses);
+      watcher.watchWarehouses({
+        onWarehouseEvent: act?.onWarehouse,
+        refreshHook: queryCache.freight.refetchQueryFreight
+      });
+    };
+
+    connect();
+
+    // Reconnect when the tab becomes visible again. The watch is left running
+    // while the tab is hidden (we do NOT cancel on leave), but a hidden tab 
can
+    // be throttled/frozen and have its stream silently dropped -- reconnecting
+    // on return guarantees a live stream again.
+    const onVisibilityChange = () => {
+      // Reuse the existing connection if it is still alive; only reconnect 
when
+      // the stream has actually ended (e.g. dropped while the tab was hidden).
+      if (document.visibilityState === 'visible' && !watcher?.isActive()) {
+        connect();
+      }
+    };
+    document.addEventListener('visibilitychange', onVisibilityChange);
 
     return () => {
-      watcher.cancelWatch();
+      document.removeEventListener('visibilitychange', onVisibilityChange);
+      watcher?.cancelWatch();
     };
-  }, [isWindowVisible, project, (warehouses || []).join(',')]);
+  }, [project, (warehouses || []).join(',')]);
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/ui/src/features/project/pipelines/use-watch-freight.ts 
new/kargo-cli-1.10.7/ui/src/features/project/pipelines/use-watch-freight.ts
--- old/kargo-cli-1.10.6/ui/src/features/project/pipelines/use-watch-freight.ts 
2026-06-09 14:17:09.000000000 +0200
+++ new/kargo-cli-1.10.7/ui/src/features/project/pipelines/use-watch-freight.ts 
2026-06-12 02:30:12.000000000 +0200
@@ -95,14 +95,24 @@
             (current) => deleteFreight(current, freight)
           );
         } else {
-          const updatedFreight = upsertFreight(currentFreight, freight);
-          const queryFreightKey = createConnectQueryKey({
-            cardinality: 'finite',
-            schema: queryFreight,
-            input: { project },
-            transport: transportWithAuth
-          });
-          client.setQueryData(queryFreightKey, updatedFreight);
+          // Update all queryFreight caches for this project, including
+          // warehouse-filtered variants, which use a different cache key.
+          // Using setQueriesData (rather than setQueryData) ensures we only
+          // touch caches that already have an active query backing them,
+          // avoiding orphaned entries with no queryFn that would crash on
+          // refetch.
+          client.setQueriesData<QueryFreightResponse>(
+            {
+              queryKey: createConnectQueryKey({
+                cardinality: 'finite',
+                schema: queryFreight,
+                input: { project },
+                transport: transportWithAuth
+              }),
+              exact: false
+            },
+            (current) => upsertFreight(current, freight)
+          );
         }
       }
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kargo-cli-1.10.6/ui/src/features/project/pipelines/watcher.ts 
new/kargo-cli-1.10.7/ui/src/features/project/pipelines/watcher.ts
--- old/kargo-cli-1.10.6/ui/src/features/project/pipelines/watcher.ts   
2026-06-09 14:17:09.000000000 +0200
+++ new/kargo-cli-1.10.7/ui/src/features/project/pipelines/watcher.ts   
2026-06-12 02:30:12.000000000 +0200
@@ -54,6 +54,10 @@
   client: QueryClient;
   promiseClient: Client<typeof KargoService>;
   project: string;
+  // Set once either stream ends or errors for a reason other than an
+  // intentional cancel. Used by isActive() so callers can reuse a live watcher
+  // instead of needlessly reconnecting.
+  private ended = false;
 
   constructor(project: string, client: QueryClient) {
     this.cancel = new AbortController();
@@ -66,6 +70,18 @@
     this.cancel.abort();
   }
 
+  // Whether the watch is still running: not cancelled and neither stream has
+  // ended/errored.
+  isActive() {
+    return !this.cancel.signal.aborted && !this.ended;
+  }
+
+  private markEnded() {
+    if (!this.cancel.signal.aborted) {
+      this.ended = true;
+    }
+  }
+
   async watchStages(
     // utilise the fact that something changed in this stage
     // avoid as much as re-construction of data as possible by using this 
parameter
@@ -130,7 +146,9 @@
 
         onStageEvent?.(stage);
       }
-    );
+    )
+      .catch(() => {})
+      .finally(() => this.markEnded());
   }
 
   async watchWarehouses(opts?: {
@@ -204,6 +222,8 @@
 
         opts?.onWarehouseEvent?.(warehouse);
       }
-    );
+    )
+      .catch(() => {})
+      .finally(() => this.markEnded());
   }
 }

++++++ kargo-cli.obsinfo ++++++
--- /var/tmp/diff_new_pack.D9aLjh/_old  2026-06-13 18:50:41.493790176 +0200
+++ /var/tmp/diff_new_pack.D9aLjh/_new  2026-06-13 18:50:41.501790508 +0200
@@ -1,5 +1,5 @@
 name: kargo-cli
-version: 1.10.6
-mtime: 1781007429
-commit: 1ec8d6094bdb9b2f29f4858f788f2af13ac37fb1
+version: 1.10.7
+mtime: 1781224212
+commit: 17077e406ed309fcc830d08776d9b9a47fe6e134
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/kargo-cli/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.kargo-cli.new.1981/vendor.tar.gz differ: char 13, 
line 1

Reply via email to