github akuity/kargo v1.12.0

3 hours ago

🚀 Kargo v1.12.0 is here! This release retires the legacy gRPC API, teaches image discovery to trust the right timestamp, brings Kargo's own Prometheus metrics, rounds out the OCI packaging story -- and, at long last, turns out the lights.

🔭 Up Next: Kargo 2.0

There will be no v1.13.0. The next minor release of Kargo is a major one -- v2.0.0.

Kargo's largest installations have grown to a scale that strains the architecture that got it this far. v2.0 replaces the plumbing underneath Kargo -- how it stores state and how its components learn about changes -- to make room for far larger installations and to keep more history than Kubernetes objects can comfortably hold.

This is an evolution, not a revolution. The resources you manage with GitOps today keep working, and your promotion processes run as they do now. What changes is under the floorboards. More details, including what to expect when upgrading, are coming soon to the public roadmap.

🚨 Breaking Changes

  • The Connect-Based (gRPC) API Has Been Removed (#6617): As announced in the v1.9.0 release notes and reiterated in the v1.11.0 release notes, the Connect-based gRPC API is gone. The UI completed its migration to the REST API in v1.11.0, so the legacy API had no first-party consumers left. If you maintain integrations built against it, migrate them to the REST API before upgrading. Upgrade the CLI to v1.12.0 alongside your server -- older CLIs may still reach for endpoints that no longer exist.

  • createTargetBranch Removed from the git-open-pr Step (#6916): Deprecated in v1.10.0, the createTargetBranch option has been removed. The feature never actually worked; see #5847 for the details. Remove the field from any promotion steps or promotion tasks that still set it.

  • author Removed from the git-commit Step (#7314): Also deprecated in v1.10.0, the author block (name, email, and signingKey) has been removed from git-commit. Authorship and commit signing are configured once, on the git-clone step or in ClusterConfig, and apply to every commit made in that working tree. See the git-commit docs for details.

  • git-push Defaults to RebaseOrMerge (#7319): As announced in v1.10.0, the default push integration policy for the git-push and github-push steps has changed from AlwaysRebase to RebaseOrMerge. Unconditionally rebasing onto a remote that has moved ahead rewrites commits, and rewriting a signed commit either strips its signature or re-signs it as someone else. RebaseOrMerge rebases only when it can tell that's safe and otherwise integrates with a merge commit. To keep the old behavior, set controller.gitClient.pushIntegrationPolicy: AlwaysRebase in your Helm values. See Push Integration Policy.

  • Legacy Secret Namespace Settings Now Fail the Upgrade (#7320): v1.9.0 replaced the "cluster secrets namespace" and "global credentials namespaces" with the system resources and shared resources namespaces, and shipped a controller that kept Secrets in sync between the old and new locations while you transitioned. That bridge is gone. The chart values global.clusterSecretsNamespace, global.createClusterSecretsNamespace, global.createClusterSecretsRBAC, and controller.globalCredentials.namespaces have been removed, and a helm install or helm upgrade that still sets either legacy namespace fails with a message explaining what to do. Before upgrading, confirm the Secrets you rely on already exist in the namespaces named by global.systemResources.namespace and global.sharedResources.namespace -- especially if you manage them with a GitOps agent, since Kargo will no longer copy them for you. See Migrating from Kargo < 1.9.0.

  • Image Creation Times Are Read Differently (#6777): Kargo previously preferred an image's org.opencontainers.image.created or org.label-schema.build-date label over the creation time recorded in its config. Labels are inherited from the base image unless a build overwrites them, so an image that sets no label of its own reported the build time of the image it was built from -- and every image built from the same base between two republishes of that base reported an identical time. With the NewestBuild image selection strategy, those ties fell back to reverse lexical tag order and were then truncated to discoveryLimit, so genuinely new images could go undiscovered rather than merely mis-ranked.

    Creation time is now taken from the outermost metadata that claims one -- an index's annotations, then an index's reference to an image, then the image's own manifest -- and, failing all of those, from the later of the config's creation time and any claim in its labels. As a bonus, multi-arch builds annotated with docker buildx --annotation index:... are now understood.

    On upgrade, images that were previously mis-ranked or truncated away may become visible for the first time. On a Warehouse whose Freight feeds a Stage with auto-promotion enabled, that can trigger promotions of artifacts that already existed. This is precisely why the fix was held back from v1.11.x patch releases.

➡️ Promotion Improvements

  • Package and Push Local Artifacts: The new tar step archives a file or directory from the promotion workspace (gzipped by default), and the oci-push step gained a srcPath option that uploads a local file as a proper OCI 1.1 artifact -- streamed from disk, with a top-level artifactType mirrored onto the config media type for Flux, Helm, and ORAS compatibility. Together they close the loop: render manifests during a promotion, package them, and publish them to a registry for a GitOps agent to sync. (#6666, #6893)

  • http Step Bodies from Files: A new bodyFromFile option takes the request body from a path in the promotion work directory, so a payload produced by an earlier step no longer has to be squeezed through an inline expression. Mutually exclusive with body. (docs, #6753)

  • Clean Up After git-merge-pr: Pipelines that chain git-open-pr and git-merge-pr leave a kargo/promotion/<promotion name> branch behind for every promotion, and GitHub's "automatically delete head branches" setting ignores merges performed with a GitHub App installation token -- which is how Kargo authenticates when given GitHub App credentials. A new deleteSourceBranch option deletes the PR's source branch after a successful merge, on every supported provider. Because the merge is the step's real job, a failed deletion is reported in the step's message rather than failing the step. (docs, #7271)

  • repoCredentials() Expression Function: secret() returns the raw contents of a Secret selected by name, which is no help when the credentials you actually need are minted on the fly -- a GitHub App installation token, say, or a cloud provider's ambient credentials. The new repoCredentials(repoURL, type) function resolves credentials for a Git, Helm, or image repository by URL through the same machinery built-in steps like git-clone use, returning a username, password, and sshPrivateKey. Custom and generic steps, such as an http step calling a provider's API, can finally authenticate the way built-in steps do. (docs, #6558)

  • freightStatus() Expression Helper: A new expression function retrieves the entire status object of a named piece of Freight -- currentlyIn, verifiedIn, approvedFor, and metadata -- making it straightforward to branch a promotion on, say, whether Freight was approved rather than verified. (docs, #6725)

  • Argo CD Deep Links from argocd-wait: The kargo.akuity.io/argocd-context annotation that powers the UI's deep links into Argo CD was derived solely from health check criteria registered by argocd-update. Because argocd-wait registers no health check, Stages promoted with it got no links -- and a Stage that switched from argocd-update to argocd-wait lost the links it already had. Both steps now report the Applications they resolved as step output, and the annotation is built from that. (#6766)

📦 Warehouse & Freight Improvements

  • Named Subscriptions: A Warehouse's subscriptions can now carry an optional name -- a unique, RFC 1123-compliant label recorded on discovered artifacts and on the artifact references of the Freight produced from them. The UI shows the name wherever it previously showed only a lengthy repository URL. This is also a stepping stone toward letting a single Warehouse subscribe to the same repository more than once. (docs, #6207, #6868)

  • Cross-Account ECR: Kargo can now pull image metadata from an Elastic Container Registry in a different AWS account than the controller's. Role assumption is attempted in order -- kargo-project-<project name> in the registry's account, then the same role in the controller's account, then the controller's own role -- so Project-level isolation is preserved instead of silently collapsing to a shared role. (docs, #6722)

📊 Observability

  • Kargo's Own Prometheus Metrics: v1.11.0 made the controllers' metrics endpoints scrapeable; this release gives them something Kargo-specific to say. An initial, deliberately compact set of metrics covers completed promotions, promotion duration, promotion step duration, and Stages grouped by ready reason. (docs, #6892)

  • PromotionDiscarded Events: Every other way a Promotion can end -- succeeded, failed, errored, aborted -- records an event explaining itself. A Promotion removed while still Pending simply stopped existing, leaving whoever requested it a few minutes earlier with nothing to look at. Kargo now records a PromotionDiscarded event for a Promotion removed before it ever ran. (docs, #6733)

  • Who Did That?: Every API server request log line now names its actor -- admin, email:..., or kubernetes:system:serviceaccount:... -- in the same form already used to attribute Promotions and events. API tokens leave a trail too: a new token's Secret is annotated with who minted it, and APITokenCreated and APITokenDeleted events record the token's name, Role, and actor. (docs, #7344)

🌙 Dark Theme

The most-requested cosmetic feature in Kargo's history has arrived. The UI now ships a full dark theme -- pipelines, drawers, YAML editors, messages, notifications, and UI extensions included -- selectable from user settings. (#6838, #6884, #7014)

🖥️ UI Improvements

  • Guided Project Creation: A new wizard walks you through creating a Project, so getting from an empty installation to a working pipeline no longer starts with a blank YAML editor. (#6736)

  • Per-Step Timings: Promotion views showed a duration for the promotion as a whole, but individual steps showed only their status. Each step now renders its elapsed time -- measured from start to finish once complete, and counting up on a one-second tick while running, which is what distinguishes a step that's stuck from one that's merely slow. (#6807)

  • Step Logs and Retry Status: Promotion steps that emit log output now render it inline, and a step being retried says so rather than looking ambiguously unfinished. (#7035, #7259)

  • Toggle the Embedded Argo CD View: A new setting turns the embedded Argo CD view on or off, for installations where it isn't wanted. (#6881)

  • Counted +N more Artifacts: A Freight card's +N more tooltip now breaks the hidden artifacts down by type instead of leaving you to guess. (#6879)

💻 CLI Improvements

  • The SSO Callback Port Is Remembered: kargo login <server> --sso --port 8085 now persists the port alongside the server address and auth method, and a later bare kargo login reuses all three. This helps with identity providers that require redirect URIs to be registered exactly, port included -- Entra ID among them. When no port is ever specified, the CLI keeps picking a random unprivileged one. (#6803)

🐛 Notable Bug Fixes

  • Webhooks No Longer Rewrite Untouched Duration Fields (#7150): Kargo's mutating admission webhooks canonicalized duration fields on every write, including fields the writer never touched -- so 10m became 10m0s and a GitOps agent syncing the original manifest saw perpetual drift. The webhooks now leave untouched duration fields alone. Note that this prevents further occurrences but does not repair values already rewritten.

  • config Is Now Optional in Step Definitions (#6760): The controller errored on a promotion step with no config field. Steps that legitimately require no configuration can now omit it.

  • Correct Promotion Actor for CLI Tokens (#6754): Promotions created with a token from kargo create token left ctx.meta.promotion.actor unset. Kargo now resolves the token's Kubernetes-authenticated identity via a TokenReview, so the actor is recorded consistently regardless of which path authenticated the request.

  • Coalesced Credential Refreshes (#6747): Credential providers that cache short-lived tokens used a plain check-then-act against their caches, so concurrent callers missing the same key each performed a full token acquisition. Those callers now share a single in-flight acquisition.

  • The Login Page Now Leaves After Logging In (#7190): When an identity provider still held a session, signing in from a bare /login page succeeded silently but stayed put on /login?code=.... A reload replayed the authorization code, which the provider refused. The UI now always navigates away after a successful login.

  • Chart Fixes (#6867, #6915): A ServiceMonitor pointed at a path that returned 404, and the system-resources RoleBinding for the external webhooks server was rendered even when that component was disabled. Both are fixed.

🙏 Special Thanks

Thank you to community members who made their first contributions in this release or a recent v1.11 patch release!

Full Changelog: v1.11.6...v1.12.0

Don't miss a new kargo release

NewReleases is sending notifications on new releases.