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-04-22 17:00:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kargo-cli (Old) and /work/SRC/openSUSE:Factory/.kargo-cli.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kargo-cli" Wed Apr 22 17:00:15 2026 rev:49 rq:1348685 version:1.10.1 Changes: -------- --- /work/SRC/openSUSE:Factory/kargo-cli/kargo-cli.changes 2026-04-18 21:39:40.341681711 +0200 +++ /work/SRC/openSUSE:Factory/.kargo-cli.new.11940/kargo-cli.changes 2026-04-22 17:01:23.540453303 +0200 @@ -1,0 +2,7 @@ +Wed Apr 22 05:59:30 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 1.10.1: + * chore(backport release-1.10): fix: cli and server to match + openapi spec (#6136) + +------------------------------------------------------------------- Old: ---- kargo-cli-1.10.0.obscpio New: ---- kargo-cli-1.10.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kargo-cli.spec ++++++ --- /var/tmp/diff_new_pack.kbRpZ7/_old 2026-04-22 17:01:24.880508599 +0200 +++ /var/tmp/diff_new_pack.kbRpZ7/_new 2026-04-22 17:01:24.888508930 +0200 @@ -19,7 +19,7 @@ %define executable_name kargo Name: kargo-cli -Version: 1.10.0 +Version: 1.10.1 Release: 0 Summary: CLI for the Kubernetes Application lifecycle orchestration License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.kbRpZ7/_old 2026-04-22 17:01:24.956511736 +0200 +++ /var/tmp/diff_new_pack.kbRpZ7/_new 2026-04-22 17:01:24.960511901 +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.0</param> + <param name="revision">v1.10.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.kbRpZ7/_old 2026-04-22 17:01:24.996513386 +0200 +++ /var/tmp/diff_new_pack.kbRpZ7/_new 2026-04-22 17:01:25.004513717 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/akuity/kargo</param> - <param name="changesrevision">f5477e786aa4904425e9bbd547c7c05527b76237</param></service></servicedata> + <param name="changesrevision">6063d52de99ed5c26e5a01856ffe67434f8a9f23</param></service></servicedata> (No newline at EOF) ++++++ kargo-cli-1.10.0.obscpio -> kargo-cli-1.10.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/charts/kargo/templates/api/role-bindings.yaml new/kargo-cli-1.10.1/charts/kargo/templates/api/role-bindings.yaml --- old/kargo-cli-1.10.0/charts/kargo/templates/api/role-bindings.yaml 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/charts/kargo/templates/api/role-bindings.yaml 2026-04-21 23:14:06.000000000 +0200 @@ -3,6 +3,7 @@ kind: RoleBinding metadata: name: kargo-api + namespace: {{ .Release.Namespace }} labels: {{- include "kargo.labels" . | nindent 4 }} roleRef: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/charts/kargo/templates/api/roles.yaml new/kargo-cli-1.10.1/charts/kargo/templates/api/roles.yaml --- old/kargo-cli-1.10.0/charts/kargo/templates/api/roles.yaml 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/charts/kargo/templates/api/roles.yaml 2026-04-21 23:14:06.000000000 +0200 @@ -3,6 +3,7 @@ kind: Role metadata: name: kargo-api + namespace: {{ .Release.Namespace }} labels: {{- include "kargo.labels" . | nindent 4 }} rules: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/charts/kargo/templates/users/role-bindings.yaml new/kargo-cli-1.10.1/charts/kargo/templates/users/role-bindings.yaml --- old/kargo-cli-1.10.0/charts/kargo/templates/users/role-bindings.yaml 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/charts/kargo/templates/users/role-bindings.yaml 2026-04-21 23:14:06.000000000 +0200 @@ -2,6 +2,7 @@ kind: RoleBinding metadata: name: kargo-admin + namespace: {{ .Release.Namespace }} labels: {{- include "kargo.labels" . | nindent 4 }} roleRef: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/charts/kargo/templates/users/roles.yaml new/kargo-cli-1.10.1/charts/kargo/templates/users/roles.yaml --- old/kargo-cli-1.10.0/charts/kargo/templates/users/roles.yaml 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/charts/kargo/templates/users/roles.yaml 2026-04-21 23:14:06.000000000 +0200 @@ -2,6 +2,7 @@ kind: Role metadata: name: kargo-admin + namespace: {{ .Release.Namespace }} labels: {{- include "kargo.labels" . | nindent 4 }} rules: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/docs/docs/80-release-notes/100-deprecations.md new/kargo-cli-1.10.1/docs/docs/80-release-notes/100-deprecations.md --- old/kargo-cli-1.10.0/docs/docs/80-release-notes/100-deprecations.md 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/docs/docs/80-release-notes/100-deprecations.md 2026-04-21 23:14:06.000000000 +0200 @@ -16,11 +16,15 @@ | Feature | Deprecated In | Removed In | Replacement/Notes | |---------|---------------|------------|-------------------| +| `git-commit` step `author` field | [v1.10.0](./89-v1.10.0.md) | Scheduled for v1.12.0 | Configure authorship and signing in the `git-clone` step or via `ClusterConfig`. See [git-commit docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-commit). | +| `git-push` default integration policy (`AlwaysRebase`) | [v1.10.0](./89-v1.10.0.md) | Default changes in v1.12.0 | The default `git-push` push integration policy will change from `AlwaysRebase` to `RebaseOrMerge` in v1.12.0. Set [`controller.gitClient.pushIntegrationPolicy`](https://docs.kargo.io/operator-guide/advanced-installation/common-configurations#push-integration-policy) explicitly if you rely on unconditional rebase. | | SSH URLs and SSH private keys for Git repositories | v1.10.0 | Scheduled for v1.13.0 | Use HTTPS URLs with a personal access token or equivalent. SSH keys cannot authenticate to git provider APIs, forcing users to maintain two sets of credentials. See [#5858](https://github.com/akuity/kargo/issues/5858) for details. | +| The `createTargetBranch` option in the `git-open-pr` promotion step | [v1.10.0](./89-v1.10.0.md) | Scheduled for v1.12.0 | The `createTargetBranch` option has been deprecated as the feature never worked. See [#5847](https://github.com/akuity/kargo/issues/5847) for details. | | The Connect-based API | [v1.9.0](./90-v1.9.0.md) | Scheduled for v1.12.0 | A new, RESTful API has been introduced. Most users will not be impacted beyond simply needing to upgrade their CLI when upgrading the back end to v1.9.0 or greater. | | "global credentials namespace(s)" | [v1.9.0](./90-v1.9.0.md) | Scheduled for v1.12.0 | Replaced with "shared secrets namespace." See [release notes](./90-v1.9.0.md#-the-secret-shuffle) and [docs](../40-operator-guide/40-security/40-managing-secrets.md#transitioning) for details. | | "cluster secrets namespace" | [v1.9.0](./90-v1.9.0.md) | Scheduled for v1.12.0 | Replaced with "system resources namespace." See [release notes](./90-v1.9.0.md#-the-secret-shuffle) and [docs](../40-operator-guide/40-security/40-managing-secrets.md#transitioning) for details. | | `Warehouse`'s container image subscription's `semverConstraint` field | [v1.7.0](./92-v1.7.0.md#new-deprecations) | [v1.9.0](./90-v1.9.0.md) | Users should migrate to using the [`constraint`](https://docs.kargo.io/user-guide/how-to-guides/working-with-warehouses/#image-selection-strategies) field which, accepts the same value but is named to better indicate it can also be used for tag selection (e.g. `latest`) when the image selection strategy is set to `Digest`. | +| `freightMetadata` functions optional second argument for the key name | [v1.8.0](./91-v1.8.0.md#new-deprecations) | [v1.10.0](./89-v1.10.0.md#breaking-changes) | Users should migrate to either dot notation (`freightMetadata(freightName).keyName`) or map access syntax (`freightMetadata(freightName)['key-name']`) to access specific values instead of using the optional second argument. | | `Project` specification | [v1.5.0](./94-v1.5.0.md#new-deprecations) | [v1.7.0](./92-v1.7.0.md#breaking-changes) | Users should migrate to the dedicated [`ProjectConfig` resource](../50-user-guide/20-how-to-guides/20-working-with-projects.md#project-configuration). This resource kind accepts a `.spec` identitical to the `Project`, but allows for fine-grain permissions. | | `secrets` object in the Promotion variables | [v1.5.0](./94-v1.5.0.md#new-deprecations) | [v1.7.0](./92-v1.7.0.md#breaking-changes) | Users should migrate to the [`secret()` function](../50-user-guide/60-reference-docs/40-expressions.md#promotion-variables) which resolves Secrets on-demand, reducing overhead. | | `prNumber` field in `git-open-pr` Promotion Step output | [v1.5.0](./94-v1.5.0.md#new-deprecations) | [v1.7.0](./92-v1.7.0.md#breaking-changes) | Users should migrate to using [the `pr.id`](../50-user-guide/60-reference-docs/30-promotion-steps/git-open-pr.md#output) for referencing pull request IDs. | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/docs/docs/80-release-notes/89-v1.10.0.md new/kargo-cli-1.10.1/docs/docs/80-release-notes/89-v1.10.0.md --- old/kargo-cli-1.10.0/docs/docs/80-release-notes/89-v1.10.0.md 1970-01-01 01:00:00.000000000 +0100 +++ new/kargo-cli-1.10.1/docs/docs/80-release-notes/89-v1.10.0.md 2026-04-21 23:14:06.000000000 +0200 @@ -0,0 +1,239 @@ +🧬 Kargo v1.10.0 is here! This release is packed with a host of UI and quality-of-life enhancements. +The goal for this release was "evolution, not revolution." Highlights are below + +## 🚨 Breaking Changes {#breaking-changes} + +* The optional second arugment for `freightMetadata` that was deprecated in v1.8.0 has now been + removed. If you were using this argument before, use either dot notation + (`freightMetadata(freightName).keyName`) or map access syntax + (`freightMetadata(freightName)['key-name']`) to access specific values + +## ⚠️ New Deprecations {#new-deprecations} + +* **`git-push` Default Integration Policy Changing in v1.12.0**: The `git-push` step now supports + four configurable [push integration + policies](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-push) that control + how remote changes are integrated before pushing: `AlwaysRebase`, `RebaseOrMerge`, `RebaseOrFail`, + and `AlwaysMerge`. The current default remains `AlwaysRebase` (i.e. the current behavior), but + **the default will change to `RebaseOrMerge` in v1.12.0**. `RebaseOrMerge` uses signature-trust + analysis to prefer rebase when safe but falls back to a merge commit when a rebase would alter + commit signature semantics. If you rely on the current unconditional rebase behavior, set the + policy explicitly via the + [`controller.gitClient.pushIntegrationPolicy`](https://docs.kargo.io/operator-guide/advanced-installation/common-configurations#push-integration-policy) + Helm value before upgrading to v1.12.0. + +* **SSH URLs and SSH Private Keys for Git Repositories**: SSH-based Git credentials are deprecated + and scheduled for removal in v1.13.0. SSH keys cannot authenticate to git provider APIs, forcing + users to maintain two sets of credentials. Use HTTPS URLs with a personal access token or + equivalent instead. See [#5858](https://github.com/akuity/kargo/issues/5858) for details. + +* **`createTargetBranch` Option in `git-open-pr` Promotion Step**: The `createTargetBranch` option has + been deprecated as the feature never worked. It is scheduled for removal in v1.12. See + [#5847](https://github.com/akuity/kargo/issues/5847) for details. + +* **`git-commit` Step `author` Field**: The `author` configuration block (including `name`, `email`, + and `signingKey`) on the `git-commit` step is deprecated and scheduled for removal in v1.12.0. + Authorship and signing configuration should be set in the + [`git-clone`](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-clone) step or + via `ClusterConfig` instead, as `git-clone` is the single authority for work tree identity and + signing configuration. All downstream steps inherit from it. + +## 🪜 New and Improved Promotion Steps {#promotion-steps} + +### New Steps + +* **`argocd-wait`**: Blocks a promotion until one or more Argo CD Applications reach desired health, + sync, and operation statuses. Unlike `argocd-update` (which can already wait), `argocd-wait` is + useful when you need to gate on Argo CD application health without triggering a sync -- for + example, waiting for a separate deployment tool to finish before proceeding. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/argocd-wait)) + +* **`oci-push`**: Copies or retags OCI artifacts (container images and Helm charts) between + registries, with support for single images, multi-arch image indexes, and OCI Helm charts. + Supports optional annotation injection and shares credential resolution with the existing + `oci-download` step. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/oci-push)) + +* **`git-tag`**: Creates annotated or lightweight Git tags, with optional GPG signing. Pair with + `git-push` (which now supports pushing tags) to tag a verified build only after it passes + promotion through a testing Stage. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-tag)) + +* **`github-push`**: An alternative to `git-push` that replays commits through the GitHub REST API, + enabling GitHub's native commit verification ("Verified" badge) when authenticating with a GitHub + App installation token. Trust is determined by GPG signature status: commits signed by a trusted + key are verified by GitHub, while untrusted commits preserve their original attribution. Supports + the same push integration policies as `git-push`. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/github-push)) + +* **`fail`**: Unconditionally fails the promotion with a configurable message. Combined with + conditional step execution (`if:` expressions), this provides a clean way to fail a promotion + pipeline based on evaluated conditions. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/fail)) + +* **`set-freight-alias`**: Assigns a custom, human-readable alias to a piece of Freight during a + promotion pipeline, improving visibility in the UI -- especially useful in pre-processing Stages + where a meaningful name can be set before downstream promotions begin. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/set-freight-alias)) + +* **`toml-parse` / `toml-update`**: Parse and update TOML files, complementing the existing JSON and + YAML equivalents. The update step modifies scalar values in-place while preserving all other + bytes. Useful for `kcl.mod` files or other TOML-based configuration. + ([toml-parse](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/toml-parse), + [toml-update](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/toml-update)) + +### Improvements to Existing Steps + +* **`git-merge-pr`**: Now supports a `mergeMethod` field, allowing you to choose between merge, + squash, and rebase strategies when merging pull requests. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-merge-pr)) + +* **`git-open-pr`**: Detects when there are no commits between source and target branches and skips + gracefully rather than failing the promotion. `git-wait-for-pr` is also skipped in that case. This + prevents promotions from failing unnecessarily in multi-stage pipelines where some Stages have no + effective diff to promote. + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/git-open-pr)) + +## 📦 Warehouse Improvements {#warehouse-improvements} + +* **`since` Date Limiter for Git Subscriptions**: A new `since` field limits commit discovery to + commits newer than a specified date, directly addressing performance problems in monorepos with + large commit histories where unbounded `git log` operations were a primary source of slowness. + ([docs](https://docs.kargo.io/user-guide/how-to-guides/working-with-warehouses#git-commit-subscriptions)) + +* **Chart Subscription TLS Skip**: Chart subscriptions now support `insecureSkipTLSVerify`, matching + the option already available on Git and image subscriptions. Useful for internal registries with + self-signed or custom CA certificates. + ([docs](https://docs.kargo.io/user-guide/how-to-guides/working-with-warehouses#helm-chart-repository-subscriptions)) + +* **Webhook Path Filtering**: GitHub push-event webhooks now evaluate each Warehouse's + `includePaths`/`excludePaths` against the files changed in a push *before* marking it for refresh, + rather than refreshing all Warehouses and filtering later during reconciliation. This can + dramatically reduce unnecessary refresh traffic in monorepo environments with many Warehouses. + ([docs](https://docs.kargo.io/user-guide/reference-docs/webhook-receivers/github)) + +## 🔄 Shared Resource Replication {#shared-resource-replication} + +`Secret`s and `ConfigMap`s in the shared resources namespace can now be automatically replicated to +all Project namespaces by annotating them with `kargo.akuity.io/replicate-to: "*"`. This enables +workloads in Project namespaces (such as Argo Rollouts `AnalysisTemplate` Jobs) to consume shared +resources that would otherwise require cross-namespace references. Replicated resources are +immutable and cleaned up automatically when the source is deleted or the annotation is removed. +([docs](https://docs.kargo.io/operator-guide/security/managing-secrets)) + +## 🖥️ UI Improvements {#ui-improvements} + +* **"My Projects" Filter**: The project list now defaults to showing only projects where you've been + explicitly mapped via OIDC claims, making it easier to find your projects in large organizations. + +* **Page Titles**: Browser tabs now reflect the current context (project name, Stage name, etc.) so + you can distinguish between multiple Kargo tabs at a glance. + +* **Version-Matched CLI Downloads**: The CLI download page now links to the specific version of + Kargo currently running rather than always pointing to "latest," preventing inadvertent version + mismatches. + +* **Git Commit Deep Links for Self-Hosted Providers**: Commit links now work correctly for + self-hosted GitHub Enterprise and GitLab instances, not just `github.com` and `gitlab.com`. + +* **Inline Promotion Step Errors**: Errors are now displayed directly beneath the failed step with + the step highlighted in red, rather than only in a disconnected banner. Skipped steps are visually + muted. + +* **Smooth Freight List Scrolling**: The freight list now scrolls smoothly rather than jumping + between positions. + +* **Improved Status Colors**: Non-failed, non-errored statuses now show a neutral color instead of + potentially misleading indicators. + +## ⎈ Helm Chart Improvements {#helm-chart} + +* **`priorityClassName` Configuration**: Operators can now assign scheduling priority to Kargo + components, preventing them from being evicted in favor of higher-priority workloads when + resources are constrained. + +* **Startup Probe for Large Clusters**: The API server now has a startup probe with a 5-minute + window, preventing the pod from being killed before its initial cache sync completes in large + clusters with many resources. + +* **Certificate Group Enforcement**: The `group` field on cert-manager `Certificate` resources is + now explicitly set, preventing renewal failures that could occur after approximately one year. + +## 🔧 API & Developer Experience {#api-developer} + +* **REST API Client Module**: The generated Go client for the Kargo REST API has been extracted into + its own Go module with minimal dependencies, making it easier for external consumers to import + without pulling in the full Kargo dependency tree. + +* **Swagger API Documentation**: Auto-generated OpenAPI documentation for the Kargo REST API is now + embedded in the documentation site. + +* **Port Numbers in OCI Image Refs**: The `oci-download` step now accepts image references with + explicit port numbers (e.g., `registry.internal:5000/image:tag`). + +## 🐛 Notable Bug Fixes {#bug-fixes} + +* **`yaml-update` escaping**: Dots in YAML key names can now be properly escaped using backslash + notation (e.g., `metadata.annotations.example\.com/version`). + ([docs](https://docs.kargo.io/user-guide/reference-docs/promotion-steps/yaml-update)) + +* **Argo CD App Status Responsiveness** (#5995): Eliminated a 10-second cooldown that could cause + promotions to stall for minutes in "Unknown" health state. The controller now trusts health + immediately when Argo CD's `reconciledAt` timestamp confirms a fresh reconciliation, and forces a + hard refresh otherwise. + +* **Path Filtering on Merge Commits** (#5990, #5999): Fixed two related issues where + `includePaths`/`excludePaths` filtering on Warehouses could silently skip changes introduced via + merge commits. The `--first-parent` flag is now used to correctly identify files changed by a + merge. + +* **ClusterRole Permissions in Kargo Roles** (#5916): Fixed a bug since v1.4.4 where `RoleBinding`s + referencing a `ClusterRole` (instead of a namespaced `Role`) caused "Role not found" errors, + breaking the RBAC UI for any namespace with such bindings. + +* **Promotion Working Directory Cleanup** (#5805): Temporary promotion working directories are now + cleaned up when a promotion reaches a terminal state or is deleted, preventing disk space leaks on + the controller. + +* **`git-commit` Custom Author** (#5857): Fixed a regression where using the `author` config block + in the `git-commit` step failed with "Author identity unknown." + +* **Promotion `Failed` vs `Errored` Status** (#5941): Steps that intentionally return `Failed` + status (such as the new `fail` step) are no longer incorrectly reported as `Errored`. + +* **Events Dropped on Shutdown** (#5943): Kubernetes events are no longer silently dropped when the + controller's context is cancelled during shutdown. + +* **API Delete Error Handling** (#5870): The API server no longer silently swallows errors when + deleting resources. + +* **UI: Invalid Metric Chart Date** (#5733): Fixed "Invalid date" display in verification metric + chart tooltips. + +* **UI: Freight Assembly Crash** (#5975): Fixed a crash on the freight assembly page when commits + were not found for a Git subscription. + +## 🙏 Special Thanks {#special-thanks} + +Thank you to community members who made their first contributions in this release or a recent v1.9 +patch release! + +@apt-itude +@bafulton +@bobdoah +@cmontemuino +@danielloader +@edshin24 +@emilyxinyi +@emirot +@EronWright +@evanndev +@henrycatalinismith +@neboman11 +@nikita-unity +@olofsol +@shamsalmon +@ThreePinkApples +@zoeyfyi + +**Full Changelog**: [v1.9.5...v1.10.0](https://github.com/akuity/kargo/compare/v1.9.5...v1.10.0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/docs/docs/80-release-notes/91-v1.8.0.md new/kargo-cli-1.10.1/docs/docs/80-release-notes/91-v1.8.0.md --- old/kargo-cli-1.10.0/docs/docs/80-release-notes/91-v1.8.0.md 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/docs/docs/80-release-notes/91-v1.8.0.md 2026-04-21 23:14:06.000000000 +0200 @@ -6,7 +6,7 @@ ## ⚠️ New Deprecations -None +* **`freightMetadata` function's optional second argument for the key name**: The optional second argument for `freightMetadata` is now scheduled for removal in v1.10.0. Users should migrate to either dot notation (`freightMetadata(freightName).keyName`) or map access syntax (`freightMetadata(freightName)['key-name']`) to access specific values instead of using the optional second argument. ## ✨ Noteworthy Features diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/docs/src/components/VersionDropdown.js new/kargo-cli-1.10.1/docs/src/components/VersionDropdown.js --- old/kargo-cli-1.10.0/docs/src/components/VersionDropdown.js 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/docs/src/components/VersionDropdown.js 2026-04-21 23:14:06.000000000 +0200 @@ -24,10 +24,8 @@ const fetchVersions = async () => { try { - console.log("Before fetching versions"); const response = await fetch(githubApiUrl); const branches = await response.json(); - console.log("Fetched branches are: ", branches); const releaseBranches = branches .map(branch => branch.name) @@ -40,15 +38,10 @@ }; }); - console.log("These are release branches before sorting and updating 0 element: ", releaseBranches); releaseBranches.sort((a, b) => { - if (a.version > b.version) { - return -1; - } - if (a.version < b.version) { - return 1; - } - return 0; + const [aMajor, aMinor] = a.version.slice(1).split('.').map(Number); + const [bMajor, bMinor] = b.version.slice(1).split('.').map(Number); + return bMajor - aMajor || bMinor - aMinor; }); // Overwrite the first element with the latest version releaseBranches[0] = { @@ -69,7 +62,6 @@ url: `${url.protocol}//${url.hostname}${url.port ? `:${url.port}` : ''}` }); } - console.log("These are release branches: ", releaseBranches); setVersions(releaseBranches); setLoading(false); } catch (error) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/pkg/cli/cmd/promote/promote.go new/kargo-cli-1.10.1/pkg/cli/cmd/promote/promote.go --- old/kargo-cli-1.10.0/pkg/cli/cmd/promote/promote.go 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/pkg/cli/cmd/promote/promote.go 2026-04-21 23:14:06.000000000 +0200 @@ -212,14 +212,10 @@ if err != nil { return fmt.Errorf("marshal promotion: %w", err) } - // The response is {"promotion": {...}} - var result struct { - Promotion *kargoapi.Promotion `json:"promotion"` - } - if err = json.Unmarshal(promoJSON, &result); err != nil { + promo := &kargoapi.Promotion{} + if err = json.Unmarshal(promoJSON, promo); err != nil { return fmt.Errorf("unmarshal promotion: %w", err) } - promo := result.Promotion if o.Wait { if err = o.waitForPromotion(ctx, nil, promo); err != nil { return fmt.Errorf("wait for promotion: %w", err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/pkg/server/promote_to_stage_v1alpha1.go new/kargo-cli-1.10.1/pkg/server/promote_to_stage_v1alpha1.go --- old/kargo-cli-1.10.0/pkg/server/promote_to_stage_v1alpha1.go 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/pkg/server/promote_to_stage_v1alpha1.go 2026-04-21 23:14:06.000000000 +0200 @@ -284,5 +284,5 @@ s.recordPromotionCreatedEvent(ctx, promotion, freight) } - c.JSON(http.StatusCreated, gin.H{"promotion": promotion}) + c.JSON(http.StatusCreated, promotion) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/freight/freight-timeline-filters.tsx new/kargo-cli-1.10.1/ui/src/features/project/pipelines/freight/freight-timeline-filters.tsx --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/freight/freight-timeline-filters.tsx 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/freight/freight-timeline-filters.tsx 2026-04-21 23:14:06.000000000 +0200 @@ -1,7 +1,7 @@ import { faDocker, faGitAlt } from '@fortawesome/free-brands-svg-icons'; import { faAnchor, faFilter, faTimes, IconDefinition } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Button, Checkbox, Select, SelectProps } from 'antd'; +import { Badge, Button, Checkbox, Select, SelectProps } from 'antd'; import classNames from 'classnames'; import { useMemo } from 'react'; @@ -24,6 +24,11 @@ }; export const FreightTimelineFilters = (props: FreightTimelineFiltersProps) => { + const isFilterActive = + (props.preferredFilter?.sources?.length ?? 0) > 0 || + props.preferredFilter?.timerange !== 'all-time' || + props.preferredFilter?.hideUnusedFreights === true; + const sourcesDropdownOptions: SelectProps['options'] = useMemo(() => { const freightSourcesCatalogue = catalogueFreights(props.freights); @@ -63,9 +68,11 @@ </div> )} - <Button size='small' className='ml-auto' onClick={props.onCollapseToggle}> - <FontAwesomeIcon icon={props.collapsed ? faFilter : faTimes} /> - </Button> + <Badge dot={props.collapsed && isFilterActive} offset={[-2, 2]} className='ml-auto'> + <Button size='small' onClick={props.onCollapseToggle}> + <FontAwesomeIcon icon={props.collapsed ? faFilter : faTimes} /> + </Button> + </Badge> </span> <div diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/freight/freight-timeline.tsx new/kargo-cli-1.10.1/ui/src/features/project/pipelines/freight/freight-timeline.tsx --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/freight/freight-timeline.tsx 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/freight/freight-timeline.tsx 2026-04-21 23:14:06.000000000 +0200 @@ -2,7 +2,7 @@ import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; -import { useContext, useMemo, useRef, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { generatePath, useNavigate } from 'react-router-dom'; import { paths } from '@ui/config/paths'; @@ -129,8 +129,26 @@ actionContext ]); + const PAGE_SIZE = 20; + const [visibleCount, setVisibleCount] = useState(PAGE_SIZE); + + // Reset visible count and scroll position when filters change + useEffect(() => { + setVisibleCount(PAGE_SIZE); + freightListStyleRef.current?.style.setProperty('right', '0px'); + }, [ + freightTimelineControllerContext.preferredFilter.sources, + freightTimelineControllerContext.preferredFilter.timerange, + freightTimelineControllerContext.preferredFilter.warehouses, + freightTimelineControllerContext.preferredFilter.hideUnusedFreights + ]); + const freightListStyleRef = useRef<HTMLDivElement>(null); + const loadMore = useCallback(() => { + setVisibleCount((prev) => Math.min(prev + PAGE_SIZE, filteredFreights.length)); + }, [filteredFreights.length]); + const scrollCarouselLeft = () => { const right = freightListStyleRef.current?.style.right || '0px'; @@ -149,6 +167,10 @@ const nextRight = +right.slice(0, -2) + 160; if (nextRight >= (freightListStyleRef.current?.clientWidth || 0) / 2) { + // At the edge — load more items if available + if (visibleCount < filteredFreights.length) { + loadMore(); + } return; } @@ -203,7 +225,7 @@ className='flex gap-1 relative right-0 transition-[right] duration-300 ease-out' ref={freightListStyleRef} > - {filteredFreights.map((freight) => { + {filteredFreights.slice(0, visibleCount).map((freight) => { const freightSoakTime = soakTime?.[freight?.metadata?.name || '']; const promotionEligible = Boolean( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/graph/graph.tsx new/kargo-cli-1.10.1/ui/src/features/project/pipelines/graph/graph.tsx --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/graph/graph.tsx 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/graph/graph.tsx 2026-04-21 23:14:06.000000000 +0200 @@ -171,7 +171,7 @@ nodes: nodesExcludingSubscriptionNodes }} proOptions={{ hideAttribution: true }} - minZoom={0} + minZoom={nodes.length > 100 ? 0.6 : 0.1} onlyRenderVisibleElements panOnDrag onInit={(inst) => (reactFlowInstance.current = inst)} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/graph/use-pipeline-graph.ts new/kargo-cli-1.10.1/ui/src/features/project/pipelines/graph/use-pipeline-graph.ts --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/graph/use-pipeline-graph.ts 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/graph/use-pipeline-graph.ts 2026-04-21 23:14:06.000000000 +0200 @@ -1,6 +1,6 @@ import { layout } from '@dagrejs/dagre'; import { Edge, MarkerType, Node } from '@xyflow/react'; -import { useContext, useMemo } from 'react'; +import { useContext, useEffect, useRef, useState } from 'react'; import { ColorContext } from '@ui/context/colors'; import { WarehouseExpanded } from '@ui/extend/types'; @@ -32,121 +32,140 @@ ) => { const { warehouseColorMap } = useContext(ColorContext); - return useMemo(() => { + const [result, setResult] = useState<{ nodes: Node[]; edges: Edge[] }>({ + nodes: [], + edges: [] + }); + const lastRunRef = useRef(0); + const functionCalled = useRef(false); + + useEffect(() => { if (Object.keys(dimensionState).length === 0) { - return { - nodes: [], - edges: [] - }; + setResult({ nodes: [], edges: [] }); + return; } - // eslint-disable-next-line prefer-const - let { graph, stageByName, maxStageHeight } = layoutGraph( - { - stages, - ignore(s) { - return ( - !!pipeline.length && - !s.spec?.requestedFreight?.find((f) => pipeline.includes(f?.origin?.name || '')) - ); - } - }, - { - warehouses, - ignore(w) { - return !!pipeline.length && !pipeline.includes(w?.metadata?.name || ''); - } - }, - dimensionState, - warehouseColorMap, - hideSubscriptions - ); - - graph = stackNodes(stack?.afterNodes || [], graph, stageByName, maxStageHeight); - - layout(graph, { disableOptimalOrderHeuristic: true }); + const compute = () => { + lastRunRef.current = Date.now(); - const reactFlowNodes: Node[] = []; - const reactFlowEdges: Edge[] = []; + // eslint-disable-next-line prefer-const + let { graph, stageByName, maxStageHeight } = layoutGraph( + { + stages, + ignore(s) { + return ( + !!pipeline.length && + !s.spec?.requestedFreight?.find((f) => pipeline.includes(f?.origin?.name || '')) + ); + } + }, + { + warehouses, + ignore(w) { + return !!pipeline.length && !pipeline.includes(w?.metadata?.name || ''); + } + }, + dimensionState, + warehouseColorMap, + hideSubscriptions + ); + + graph = stackNodes(stack?.afterNodes || [], graph, stageByName, maxStageHeight); + + layout(graph, { disableOptimalOrderHeuristic: true }); + + const reactFlowNodes: Node[] = []; + const reactFlowEdges: Edge[] = []; + + for (const node of graph.nodes()) { + const dagreNode = graph.node(node); + + if (stackedIndexer.is(node)) { + const stackedActualHeight = + dimensionState[STACKED_NODE_DUMMY_KEY]?.height || stackSizer.size().height; + reactFlowNodes.push({ + id: node, + type: reactFlowNodeConstants.STACKED_NODE, + position: { + x: dagreNode?.x - dagreNode?.width / 2, + y: dagreNode?.y - stackedActualHeight / 2 + }, + data: { + value: dagreNode?.value, + id: dagreNode?.id, + parentNodeId: dagreNode?.parentNodeId + } + }); + continue; + } - for (const node of graph.nodes()) { - const dagreNode = graph.node(node); + // All nodes share a uniform virtual height in dagre (= max stage height) + // so edges connect at the same center. Use the actual measured height to + // visually center each node within its virtual slot. + const actualHeight = dimensionState[node]?.height || dagreNode?.height; - if (stackedIndexer.is(node)) { - const stackedActualHeight = - dimensionState[STACKED_NODE_DUMMY_KEY]?.height || stackSizer.size().height; reactFlowNodes.push({ id: node, - type: reactFlowNodeConstants.STACKED_NODE, + type: reactFlowNodeConstants.CUSTOM_NODE, position: { x: dagreNode?.x - dagreNode?.width / 2, - y: dagreNode?.y - stackedActualHeight / 2 + y: dagreNode?.y - actualHeight / 2 }, data: { - value: dagreNode?.value, - id: dagreNode?.id, - parentNodeId: dagreNode?.parentNodeId + label: node, + value: dagreNode?.warehouse || dagreNode?.subscription || dagreNode?.stage, + subscriptionParent: dagreNode?.subscriptionParent, + // Fixed pixel offset from the node's top to the dagre center point. + // Stored at layout time so handles stay anchored even when node content + // grows and the rendered height changes (node position is not updated). + handleOffsetY: actualHeight / 2 } }); - continue; } - // All nodes share a uniform virtual height in dagre (= max stage height) - // so edges connect at the same center. Use the actual measured height to - // visually center each node within its virtual slot. - const actualHeight = dimensionState[node]?.height || dagreNode?.height; - - reactFlowNodes.push({ - id: node, - type: reactFlowNodeConstants.CUSTOM_NODE, - position: { - x: dagreNode?.x - dagreNode?.width / 2, - y: dagreNode?.y - actualHeight / 2 - }, - data: { - label: node, - value: dagreNode?.warehouse || dagreNode?.subscription || dagreNode?.stage, - subscriptionParent: dagreNode?.subscriptionParent, - // Fixed pixel offset from the node's top to the dagre center point. - // Stored at layout time so handles stay anchored even when node content - // grows and the rendered height changes (node position is not updated). - handleOffsetY: actualHeight / 2 - } - }); - } + for (const edge of graph.edges()) { + const belongsToWarehouse = warehouseIndexer.getWarehouseName(edge.name || ''); - for (const edge of graph.edges()) { - const belongsToWarehouse = warehouseIndexer.getWarehouseName(edge.name || ''); + const dagreEdge = graph.edge(edge); - const dagreEdge = graph.edge(edge); + reactFlowEdges.push({ + id: edgeIndexer.index(belongsToWarehouse, edge.v, edge.w), + source: edge.v, + target: edge.w, + animated: false, + type: + (graph.successors(edge.v)?.length || 0) > 1 || + (graph.predecessors(edge.w)?.length || 0) > 1 + ? 'step' + : '', + sourceHandle: belongsToWarehouse, + targetHandle: belongsToWarehouse, + markerEnd: { + type: MarkerType.ArrowClosed, + color: dagreEdge.edgeColor || '' + }, + style: { + strokeWidth: 2, + stroke: dagreEdge.edgeColor || '', + transition: 'd 0.3s ease' + } + }); + } - reactFlowEdges.push({ - id: edgeIndexer.index(belongsToWarehouse, edge.v, edge.w), - source: edge.v, - target: edge.w, - animated: false, - type: - (graph.successors(edge.v)?.length || 0) > 1 || - (graph.predecessors(edge.w)?.length || 0) > 1 - ? 'step' - : '', - sourceHandle: belongsToWarehouse, - targetHandle: belongsToWarehouse, - markerEnd: { - type: MarkerType.ArrowClosed, - color: dagreEdge.edgeColor || '' - }, - style: { - strokeWidth: 2, - stroke: dagreEdge.edgeColor || '', - transition: 'd 0.3s ease' - } - }); + setResult({ nodes: reactFlowNodes, edges: reactFlowEdges }); + }; + + if (!functionCalled.current) { + functionCalled.current = true; + compute(); + return; } - return { - nodes: reactFlowNodes, - edges: reactFlowEdges - }; + const elapsed = Date.now() - lastRunRef.current; + const delay = Math.max(0, 3000 - elapsed); + const id = setTimeout(compute, delay); + return () => clearTimeout(id); }, [stack?.afterNodes, pipeline, redraw, warehouseColorMap, hideSubscriptions, dimensionState]); + + return result; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/nodes/stage-node.tsx new/kargo-cli-1.10.1/ui/src/features/project/pipelines/nodes/stage-node.tsx --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/nodes/stage-node.tsx 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/nodes/stage-node.tsx 2026-04-21 23:14:06.000000000 +0200 @@ -191,7 +191,7 @@ 'postiion-relative' )} size='small' - variant='borderless' + // variant='borderless' > <DropOverlay isOver={isOver} stage={props.stage} /> {controlFlow && ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/pipelines.tsx new/kargo-cli-1.10.1/ui/src/features/project/pipelines/pipelines.tsx --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/pipelines.tsx 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/pipelines.tsx 2026-04-21 23:14:06.000000000 +0200 @@ -97,7 +97,6 @@ projectQuery.isLoading || getFreightQuery.isLoading || listWarehousesQuery.isLoading || - listStagesQuery.isLoading || getConfigQuery.isLoading; const promote = freight && stage ? { freight, stage } : undefined; @@ -301,14 +300,19 @@ /> </div> )} - {pipelineView === 'graph' && ( + {listStagesQuery.isLoading && ( + <div className='mt-20'> + <LoadingState /> + </div> + )} + {pipelineView === 'graph' && listStagesQuery.data?.stages && ( <Graph project={project.metadata?.name || ''} warehouses={listWarehousesQuery.data?.warehouses || []} stages={listStagesQuery.data?.stages || []} /> )} - {pipelineView === 'list' && ( + {pipelineView === 'list' && listStagesQuery.data?.stages && ( <PipelineListView stages={listStagesQuery.data?.stages || []} warehouses={listWarehousesQuery.data?.warehouses || []} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/url-params/use-freight-timeline-controller-store.ts new/kargo-cli-1.10.1/ui/src/features/project/pipelines/url-params/use-freight-timeline-controller-store.ts --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/url-params/use-freight-timeline-controller-store.ts 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/url-params/use-freight-timeline-controller-store.ts 2026-04-21 23:14:06.000000000 +0200 @@ -24,7 +24,9 @@ showMinimap: true }; - if (searchParams.size === 0) { + const hasFilterParams = Object.keys(filters).some((name) => searchParams.has(name)); + + if (!hasFilterParams) { return { ...filters, ...getFreightTimelineFiltersLocalStorage(project) }; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/use-watch-freight.ts new/kargo-cli-1.10.1/ui/src/features/project/pipelines/use-watch-freight.ts --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/use-watch-freight.ts 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/use-watch-freight.ts 2026-04-21 23:14:06.000000000 +0200 @@ -68,6 +68,17 @@ } const currentFreight = queryCache.freight.get(project); + + // Skip ADDED events for freight that already exists in the cache. + // Kubernetes watches replay all existing objects as ADDED on connect, + // which duplicates the initial GET and causes unnecessary re-renders. + if (e.type === 'ADDED') { + const existing = currentFreight?.groups?.['']?.freight || []; + if (existing.some((f) => f?.metadata?.name === freight?.metadata?.name)) { + continue; + } + } + const updatedFreight = e.type === 'DELETED' ? deleteFreight(currentFreight, freight) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kargo-cli-1.10.0/ui/src/features/project/pipelines/watcher.ts new/kargo-cli-1.10.1/ui/src/features/project/pipelines/watcher.ts --- old/kargo-cli-1.10.0/ui/src/features/project/pipelines/watcher.ts 2026-04-16 22:35:17.000000000 +0200 +++ new/kargo-cli-1.10.1/ui/src/features/project/pipelines/watcher.ts 2026-04-21 23:14:06.000000000 +0200 @@ -30,6 +30,7 @@ getter: (e: T) => S, callback: (item: S, data: S[]) => void ) { + let timer: ReturnType<typeof setTimeout> | undefined; for await (const e of stream) { let data = getData(); const index = data.findIndex((item) => item.metadata?.name === getter(e).metadata?.name); @@ -45,7 +46,8 @@ } } - callback(getter(e), data); + clearTimeout(timer); + timer = setTimeout(() => callback(getter(e), data)); } } ++++++ kargo-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.kbRpZ7/_old 2026-04-22 17:01:33.128848964 +0200 +++ /var/tmp/diff_new_pack.kbRpZ7/_new 2026-04-22 17:01:33.180851110 +0200 @@ -1,5 +1,5 @@ name: kargo-cli -version: 1.10.0 -mtime: 1776371717 -commit: f5477e786aa4904425e9bbd547c7c05527b76237 +version: 1.10.1 +mtime: 1776806046 +commit: 6063d52de99ed5c26e5a01856ffe67434f8a9f23 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/kargo-cli/vendor.tar.gz /work/SRC/openSUSE:Factory/.kargo-cli.new.11940/vendor.tar.gz differ: char 13, line 1
