Spinnaker Release 2026.4.0

Breaking Changes

Helmfile hooks and post-renderers are now blocked by default

#8015 and #8034 close a local-code-execution vector in Rosco’s helmfile baking: a helmfile.yaml (a user-supplied input artifact, potentially from a git branch anyone can push to) could declare hooks: or postRenderers:/--post-renderer args that run an arbitrary local command during an otherwise side-effect-free helmfile template bake.

Rosco now parses the resolved helmfile.yaml (including local bases:/helmfiles: fragments) and refuses to bake content that declares hooks or post-renderers, fails closed on anything it can’t fully parse (Go template control-flow, deeply nested YAML, unresolvable remote references), and sets HELMFILE_DISABLE_HOOKS=true / HELMFILE_DISABLE_INSECURE_FEATURES=true on the helmfile subprocess itself to close gaps static YAML inspection can’t see (exec/envExec/readFile/readDir template functions). Plain helm template and kustomize build baking are unaffected.

Operators who trust their helmfile sources and rely on hooks or post-renderers can opt back in with:

helmfile:
  allow-hooks-and-post-renderers: true

Namespace allow-lists are now enforced when a request omits a namespace

#7998 fixes a Kubernetes account namespaces allow-list bypass: a manifest operation (deploy, delete, patch, scale, enable/disable, rollout pause/resume/undo, rolling restart, resize-server-group) that omitted a namespace skipped the allow-list check entirely, while kubectl still resolved a real target underneath — the kubeconfig context’s default namespace, typically default.

A blank, namespace-scoped coordinate is now defaulted to "default" before validation, so it’s checked like any other namespace. Accounts with a namespaces allow-list that does not include "default" will now reject an operation that omits a namespace, where before it silently succeeded against whatever the kubeconfig context resolved to. Accounts whose allow-list includes "default", or that don’t restrict namespaces at all, see no change.

GitHub organization check needs the read:org scope and organization approval

#8187 changes how Gate’s GitHub provider-requirements.organization check looks up a user’s membership. Gate used to call the public organizations_url from GitHub’s /user response (/users/{login}/orgs), which only lists memberships the user has made public. It now calls the private GET <user-info-uri>/memberships/orgs/{org} endpoint on behalf of the authenticated user and requires the membership to be active, so users no longer have to make their membership public.

This breaks logins for setups that restrict access to an organization unless both of the following hold, otherwise GitHub denies the lookup and every user is rejected:

  • The github client registration requests the read:org scope.
  • The organization has approved the OAuth app, if it restricts OAuth app access.

See the GitHub setup guide for the configuration.

A user info response without organizations_url no longer skips the check.

If you enabled the opt-in flag from the 2026.3.x backport ( #8193 ), provider-requirements.include-private-memberships: true, remove it. That flag does not exist in 2026.4.0 because this behavior is now always on, and it needs the same read:org scope.

Java 25 required to build

#8014 upgrades every service’s build toolchain from Java 17 to Java 25 (Dockerfiles, CI workflows, and Gradle toolchain/source/target compatibility). Anyone building services or plugins from source needs a Java 25 JDK.

Spring Boot 4.1.1

#7996 migrates the codebase to Spring Boot 4.1.1 (Spring Cloud 2025.1.3, Kotlin 2.3.21, Gradle 9.6.1), still running on Java 17 at the framework level. The migration is intended to preserve existing behavior and public contracts, but this is a broad framework major-version upgrade touching Jakarta, Security, OpenSAML, health endpoints, Redis, JDBC, Quartz, and more — plugins or forks with custom Spring configuration should review compatibility before upgrading.

com.netflix.awsobjectmapper removed — last real path to the AWS SDK v1

#8020 removes awsobjectmapper, which transitively pulled in the entire AWS SDK v1 (25 aws-java-sdk-* artifacts) purely to configure clouddriver’s shared ObjectMapper. It’s replaced with a small in-repo factory (AwsObjectMapperFactory) carrying the same Jackson feature flags, including FAIL_ON_UNKNOWN_PROPERTIES=false for reading already-persisted JSON. Any plugin or fork that still depends on AWS SDK v1 types transitively through clouddriver should vendor that dependency directly going forward. Paired with #8038 , which updates the AWS SDK v2 dependency itself to its latest release.

Deck plugins now build with Vite

#8119 moves Deck’s package builds from Rollup to Vite 7, including the build config that @spinnaker/pluginsdk provides to Deck plugins. The SDK no longer ships pluginconfig/rollup.config.js, so an existing plugin stops building as soon as it upgrades @spinnaker/pluginsdk. The SDK packages are versioned with Spinnaker releases, so nothing in the version number warns plugin authors about this.

The build produces the same output as before. It writes an ES module to build/dist that bundles the plugin’s own dependencies, and maps the libraries Deck shares with plugins (@spinnaker/core, react, rxjs and so on) to the globals Deck exposes at runtime. It still doesn’t type-check the plugin or emit declaration files. Vite 7 needs Node.js 20.19+ or 22.12+.

To migrate a plugin:

  1. Upgrade the SDK packages and add @spinnaker/scripts, which now runs the build:
    pnpm add @spinnaker/pluginsdk@latest @spinnaker/pluginsdk-peerdeps@latest @spinnaker/scripts@latest
    npx check-peer-dependencies --install
    
  2. Delete rollup.config.js, then run check-plugin --fix to restore the scaffold’s vite.config.js and update the build and watch scripts:
    rm rollup.config.js
    npx check-plugin --fix
    
    Afterwards package.json has "build": "NODE_ENV=production spinnaker-scripts build" and "watch": "spinnaker-scripts start", and vite.config.js contains:
    module.exports = require('@spinnaker/pluginsdk/pluginconfig/vite.config');
    
  3. Remove rollup, @rollup/* and rollup-plugin-* from devDependencies, unless your own code still uses them.
  4. If you customised rollup.config.js, move the changes into vite.config.js by wrapping the SDK config. Most Rollup plugins also work as Vite plugins:
    const pluginConfig = require('@spinnaker/pluginsdk/pluginconfig/vite.config');
    
    module.exports = async () => {
      const config = await pluginConfig();
      config.plugins.push(myPlugin());
      return config;
    };
    

Kayenta and Deck must be upgraded together for canary query templates

Spinnaker PR #7900 collapses the two per-metric template fields (customInlineTemplate and customFilterTemplate) into a single template field. Deck only reads template, while an older Kayenta only returns customInlineTemplate, so existing templates will not appear in the Deck metric editor if the two are out of step. Upgrade Kayenta and Deck together.

Kayenta still writes the template under both template and customInlineTemplate, so rolling deploys and rollbacks keep working. Other things to be aware of:

  • Reading or saving a canary config through the API now returns metrics with template populated from any customFilterTemplate they reference. GitOps or API consumers that diff the stored config against what they read back will see that addition.
  • The copy is a snapshot. Once a metric has its own template, later edits to the shared entry in the config’s top-level templates map no longer affect that metric. customFilterTemplate and the templates map are left in place, so nothing is lost on rollback.
  • A customFilterTemplate that does not resolve still fails the analysis rather than falling back to the guided query.
  • Prometheus: a template is now a complete PromQL expression and the PromQL: prefix is optional. A config that has a guided metricName plus a template without the prefix keeps its old meaning (label matchers combined with the guided fields).

Artifact accounts that send credentials must list allowedDomains

#8171 stops Clouddriver from starting when an http, gitlab, bitbucket or gitea artifact account has credentials (username/password, token or token file) but no urlRestrictions.allowedDomains. Entries are regular expressions matched against the whole host name:

artifacts:
  gitlab:
    accounts:
    - name: my-gitlab
      token: ...
      urlRestrictions:
        allowedDomains:
        - gitlab\.example\.com
        allowedSchemes:
        - https
  • github accounts default to github.com, api.github.com, codeload.github.com, raw.githubusercontent.com, media.githubusercontent.com and objects.githubusercontent.com. GitHub Enterprise accounts must set their own hosts.
  • Accounts without credentials are unaffected.
  • .* keeps the previous behavior of not restricting hosts. Escape the dots, and only list hosts the credentials should be sent to.

The same change makes Echo derive a git webhook’s artifacts only from its payload (an artifacts key in the body is ignored), and applies the repository checks the Gitea extractor already had to the GitHub and GitLab extractors.

#8099 moves URL restriction checks for Orca and Clouddriver into kork-web, with existing YAML unchanged. It fixes artifact accounts with urlRestrictions rejecting every URL, and Orca’s rejectedIps rejecting every hostname. Resolved addresses are now checked (all of them, not just the first), so URLs that were previously rejected by mistake may start working, and Orca gains allowedDomains.

Fiat extension resources: upgrade clients before Fiat, or use a patched release

Fiat returns resource types it doesn’t model itself (such as artifact accounts, added in #7892 ) in the extensionResources of a user’s permissions. Releases before the fix cannot deserialize that part of the response, because Authorizable is an interface and no deserializer was registered for it ( #8253 ). When Fiat returns an extension resource, any service that is still on an unfixed release fails to read the user’s permissions. Gate logins fail with a SpinnakerConversionException (“Cannot construct instance of com.netflix.spinnaker.fiat.model.resources.Authorizable”), and permission lookups in Clouddriver, Orca, Echo, Igor, Front50 and Keel fail the same way.

Artifact accounts are a Fiat resource by default in 2026.4.0, so this applies to every upgrade to 2026.4.0 that doesn’t deploy all services together. Plugins that register their own Fiat resource provider can trigger the same failure on older releases.

Either:

  • Upgrade to a release that has the fix on the 2026.3 or 2026.2 line first (2026.3.2 or 2026.2.5), then move to 2026.4.0. Do this for all Fiat clients, not only Gate.
  • Or upgrade one service at a time in this order: Gate first, then Clouddriver, Orca, Echo, Igor, Front50 and Keel, and Fiat last.

This doesn’t matter if every service is deployed together at 2026.4.0 or a fixed release. Rolling back in any order is safe.

Orca CI task classes renamed

#8205 renames StartJenkinsJobTask, MonitorJenkinsJobTask, MonitorQueuedJenkinsJobTask and StopJenkinsJobTask to StartBuildJobTask, MonitorBuildJobTask, MonitorQueuedBuildJobTask and StopBuildJobTask, since Jenkins, Travis, GitLab CI and Script stages all share them. Persisted task names are unchanged, so stored and in-flight executions are unaffected. Orca plugins that reference the old classes need updating. Failure breadcrumbs now link to the actual build URL instead of saying “see Jenkins”.

Keel deletes Titus resources and environment entries on startup

#8095 removes Titus, and Keel’s 20260926-remove-titus-resources Liquibase migration cleans up after it the first time Keel 2026.4.0 starts against your database. It permanently deletes every titus/% resource together with its events, diff fingerprints, paused state, versions and environment links, and strips the Titus test-container verifications and promote-candidate-jar post-deploy actions from stored environments. It halts the migration if any test-container entries remain. The SQL needs MySQL JSON functions. Back up the Keel database before upgrading if any delivery config manages Titus resources, and remove those resources from your delivery configs first.

Clouddriver redis.scheduler: sort and redis.parallelism are gone

#8073 removes the sort-based Redis agent scheduler. redis.scheduler now only accepts default; any other value, including sort, fails Clouddriver’s startup with redis.scheduler must be 'default'. redis.parallelism no longer exists, so delete it from your profiles. Plugins that provided their own agent scheduler need updating.

Default kubectl is now 1.36 (was 1.30)

#8183 bundles kubectl 1.30 through 1.37 in the Clouddriver images and makes 1.36 the default kubectl; the default used to be 1.30.14. Kubernetes supports one minor version of skew, so a default kubectl 1.36 is only guaranteed to work against clusters on 1.35 to 1.37. Clusters older than that need the global or per-account kubectlExecutable set to a bundled matching client (/usr/local/bin/kubectl-1.30 and so on); see Kubernetes: kubectl bundled for every supported EKS version .

Igor: spring.jackson.serialization.write_dates_as_timestamps fails startup

Jackson 3 (part of the Spring Boot 4 upgrade) moved the WRITE_DATES_AS_TIMESTAMPS feature from SerializationFeature to DateTimeFeature, and Spring Boot 4 binds spring.jackson.* to Jackson 3 only. An Igor profile that still sets spring.jackson.serialization.write_dates_as_timestamps fails to start. Replace it with:

spring.jackson.datatype.datetime.write-dates-as-timestamps: false

Check every service’s local profiles for other spring.jackson.serialization.*, deserialization.* and mapper.* keys. Jackson 2 settings, where still needed, now live under spring.jackson2.*.

Removals and Deprecations

Titus, Yandex and the Stackdriver metrics push are removed

  • #8095 removes the Titus cloud provider across Clouddriver, Orca, Deck and Keel, including the Titus-only stages (UpsertDisruptionBudget, UpdateJobProcesses) and TitusPreconfiguredJobProperties from the orca-api plugin API.
  • #8186 removes the Yandex provider from Clouddriver.
  • #8107 removes kork-stackdriver. spectator.stackdriver.enabled=true is now silently ignored and metrics are no longer pushed to Stackdriver; use an OpenTelemetry agent or the observability plugin instead. Kayenta’s Stackdriver metrics source is unaffected.
  • #8106 deletes the public ProviderCacheConfiguration class from clouddriver-api, now that full cache eviction is always on. Plugins or forks that implement it, or call the two-argument NamedCacheFactory.getCache / SqlCache constructor, will no longer compile.

Canary “Guided” metric forms are deprecated

The provider-specific guided query forms (for example Prometheus metricName/labelBindings, Stackdriver resourceType, Atlas q) and the customInlineTemplate / customFilterTemplate fields are deprecated in favor of the single template field. They keep working in 2026.4.0, 2027.0 and 2027.1, and will be removed after the 2027.1.x release. There is no forced migration before then.

Features

Opt-in native Amazon ECS deployments

#8210 adds a native deployment mode to the Amazon ECS provider. Instead of creating a new ECS service per deploy and keeping the previous ones as separate server groups, a native deploy keeps one durable service per cluster (fixed name, tagged spinnaker:provider=ecs-native) and updates it in place with the ECS deployment features: rolling or blue/green strategy, minimum/maximum healthy percent, circuit-breaker and alarm-based rollback, bake time, and an optional pause at an ECS lifecycle hook that new Continue ECS Native Service Deployment and Stop ECS Native Service Deployment pipeline stages act on. The deploy stage waits for the exact ECS service deployment to succeed. Rollback picks an earlier task-definition revision of the same service.

The mode is selected per deploy stage with the “Use native ECS deployment” checkbox; nothing changes for existing ECS pipelines or classic server groups, and both kinds can share a cluster and target group. The account must support ECS service tagging (long resource ID format), and the SpinnakerManaged role needs the ECS service deployment APIs in addition to the classic permissions.

Things to know before switching a service: there is no in-place migration (deploy the native service next to the classic server groups, then disable and destroy the classic ones); Disable sets the single service to a desired count of 0, so it stops the application rather than failing over to a sibling; Enable brings it back at the scalable target’s maximum (or 1), the same as the classic provider does once every server group of a cluster is disabled. Clone, terminate instances and scaling-policy edits are not supported for native server groups. See Amazon ECS native deployments and the account requirements .

SQL-backed artifact/entity store

#8000 adds a SQL-backed ArtifactStoreGetter/ArtifactStoreStorer implementation alongside the existing S3-compatible artifact store , so operators on Azure, or anyone without an S3-compatible object store, can use entity storage. Content is addressed by (application, hash) — the same identity the S3 backend uses — so identical content stored more than once collapses to a single row.

The SQL backend reuses the host service’s existing sql.connection-pools by default (artifact-store.sql.connectionPool can point it elsewhere), and manages its own Liquibase migration independently of the host service’s own schema. As with the S3 backend, every participating service (clouddriver, orca) must point at the same physical database for stored references to be readable across services.

Per-service SBOM generation, starting with clouddriver

#8019 adds a cyclonedxBom Gradle task to every service, producing a CycloneDX 1.6 software bill of materials that aggregates all of a service’s subprojects — matching the unit Spinnaker actually ships (one container image per service). It’s wired into the release pipeline for clouddriver first, attaching a buildx/Syft SBOM attestation to published container images; other services default to no behavior change until they’re opted in.

Discover project pipelines by tag

#7934 lets a Deck project dashboard combine manually configured pipelines with pipelines discovered by an exact, case-sensitive project tag match, grouped by application, alongside each one’s latest execution (or a Never run link). Includes an RBAC-filtered fallback to the manual pipeline list if discovery fails.

Opt-in support for hyphenated SpEL variable names

#7983 addresses a long-standing SpEL limitation: an expression like ${my-container-name} is tokenized as my - container - name (arithmetic) rather than a variable named my-container-name, which breaks any manifest, parameter, or context value with a legitimate hyphen (for example, Kubernetes container or label names).

Enable it with:

expression:
  dashed-identifiers:
    enabled: true

When enabled, an expression that fails to evaluate because its entire body is a hyphen-joined bareword is retried as a literal key lookup before failing. This is off by default and never changes the result of an expression that already succeeds (real arithmetic like ${trigger.buildNumber - 1} is untouched); Deck’s “Evaluate Variables” stage validator picks up the same flag via /capabilities/expressions so the UI and runtime can’t disagree. Compound paths mixing . and - (for example ${metadata.labels.app-name}) are not yet rewritten.

Distinguish same-kind Kubernetes manifests in Deploy (Manifest) status

#8044 adds the manifest name alongside its kind in the Deploy (Manifest) stage status, so it’s possible to tell apart multiple manifests of the same kind (for example several ConfigMaps or Secrets) at a glance.

Deployment provenance annotations

#8100 lets Clouddriver stamp Kubernetes resources it deploys with the Spinnaker user and pipeline execution behind them, writing provenance.spinnaker.io/deployed-by and provenance.spinnaker.io/execution-id to the top-level metadata.annotations of each manifest. That makes it possible to answer “who deployed this, and from which pipeline?” by looking at a live cluster, without correlating against Spinnaker’s own execution history. Both Deploy (Manifest) and Run Job stages are covered, and the values show up under Reserved annotations .

Orca resolves the user from the request that triggered the stage, falling back to the authenticated principal recorded on the execution, and always records the execution id. The annotations are opt-in, so no existing deployment changes behavior until an operator enables them in clouddriver-local.yml:

kubernetes:
  v2:
    apply-provenance-annotations: true

Canary metrics use a single query template for every provider

Spinnaker PR #7900 replaces the provider-specific guided query forms in the canary config editor with one query template field, for every Kayenta metrics provider. You write the query in your metrics provider’s own syntax with ${scope}, ${location} and similar variables, and each provider’s starter example and variable list is shown in the editor. Existing metrics open in whichever form matches their data, so nothing changes for them.

This is the default for new metrics. To keep showing only the guided forms, set canary.templatesEnabled to false in Deck’s settings.js (TEMPLATES_ENABLED=false in the stock settings file). The canary.telemetry.query metric gains a queryMode tag (template, namedTemplate or guided) so you can watch adoption and failure rates. See the canary config docs for details.

GitLab CI stage

#8222 adds a gitlabCi stage so Orca can trigger and monitor native GitLab CI pipelines, building on Igor’s GitLab CI trigger/cancel support and the shared CI tasks. It also fixes CI stages (Jenkins, Travis, GitLab CI, Script) failing with Query map was null when started through the API without a parameters field.

#8259 makes Igor’s GitLab CI trigger forward every parameter other than ref to GitLab as a pipeline variable (variables[KEY]=value); before, only the trigger token and ref were sent and the rest were silently dropped. Parameters with a null value are skipped. #8278 fixes reading build properties back from GitLab CI: GitLab prefixes each job-log line with a timestamp and stream code, so SPINNAKER_PROPERTY_* lines never matched and the getBuildProperties task failed with “Expected properties file … missing, empty or contained invalid syntax”.

Gitea and Forgejo artifacts and webhook triggers

#8153 adds a gitea/file artifact type (enable with artifacts.gitea.enabled), a /webhooks/git/gitea handler in Echo with X-Gitea-Signature HMAC verification, and Gitea as a Git trigger repo type and artifact editor in Deck. If neither the trigger nor the shared secret configures a secret, Gitea events are accepted unsigned. The same change fixes GitHub webhook branch events losing their event type after the Spring Boot 4 migration (case-sensitive header lookup).

Deck dark theme

#8194 adds a dark theme to Deck with theme switching.

Faster Deck loads and a Vite application build

#8175 pre-compresses Deck’s JavaScript and CSS with Brotli and gzip when building the container image and serves them according to Accept-Encoding; settings*.js stays uncompressed so runtime configuration stays current. #8118 moves Deck’s application build and dev server from Webpack to Vite 7, and #8121/#8124 move unit tests to Vitest and React Testing Library.

Branded sign-in page for basic auth and LDAP

#8084 serves a Spinnaker-branded sign-in page from Gate, instead of Spring Security’s default form, for security.basicform.enabled and ldap.enabled. #8212 makes the form post through Gate’s context path.

  • #8184 adds mcp.server.allowed-tools so operators can limit which MCP tools Gate exposes. If unset, all tools stay enabled.
  • #8027 adds an opt-in includeDeletedPipelines parameter (default false) to Orca’s pipeline search and GET /applications/{application}/pipelines, passed through Gate and the search_executions MCP tool, to find executions of pipelines deleted from Front50. It has no effect when a pipeline name filter is also given.

Fiat permissions for artifact accounts

#7892 makes artifact accounts a Fiat resource type (artifact_account), so access is authorized per user instead of open to any authenticated caller. Artifact accounts accept permissions, GET /artifacts/credentials is filtered by READ, fetching requires WRITE, and a denied account returns 404. Both Fiat toggles (auth.permissions.source.artifact-account.resource.enabled and auth.permissions.provider.artifact-account) default to enabled, so review account permissions before upgrading.

Kubernetes: custom resource health and faster artifact lookups

  • #8102 lets Clouddriver evaluate the health of custom resources (observed generation, Stalled/Reconciling/Ready conditions, status.phase) instead of always reporting them healthy. It is off by default:
    kubernetes:
      customResourceStatus:
        enabled: true
    
  • #8045 passes label selectors to the kubectl get calls used for artifact lookups, avoiding large memory spikes in busy namespaces, and fixes Orca’s CleanupArtifactsTask not passing them.
  • #8101 shows controller-written status text as plain text.

Clouddriver: kubectl bundled for every supported EKS version

#8183 packages kubectl 1.34–1.37 alongside the existing 1.31–1.33 clients in both Clouddriver image variants (Dockerfile.slim and Dockerfile.ubuntu), covering the full EKS 1.31–1.37 support range, and keeps 1.30.14 as an explicit compatibility option. Every binary is verified against Kubernetes’ published SHA-512 checksum. The unversioned kubectl now points at 1.36.5 (it was 1.30). Kubernetes allows one minor version of skew between client and server, so clusters more than one minor away from 1.36 should set the global or per-account kubectl executable to a matching bundled version.

AWS and ECS

  • #8104 adds optional tcpEstablishedTimeout, udpStreamTimeout and udpTimeout (seconds) to AWS launch templates, applied as the primary interface’s connection tracking specification. Nitro v6 instance types otherwise drop idle established TCP connections after 350 seconds.
  • #8048 and #8049 copy ECS service monitoring configuration to new server groups and make it configurable in the server group wizard.
  • #8132 makes AWS bootstrapping calls use the account’s first region.

Stage metric tags

#8005 lets a stage context carry an additionalMetricTags map that is added to the stage’s metrics, for example "additionalMetricTags": {"service": "foo"}. #8140 adds a metric for system errors when starting executions.

Deck conveniences

#8094 adds copy-to-clipboard for artifact and image references and shows the Kubernetes load balancer FQDN. #8025 and #8156 show stored manifest references as syntax-highlighted YAML.

Redis-backed pub/sub (foundation)

#8031 adds kork-pubsub-redis: Redis Streams single-delivery and native Pub/Sub broadcast. It is a foundation for later work and isn’t used by default. Tests now run against Valkey 8 ( #8029 ).

Major Fiat Performance Fixes

Three changes cut the cost of Fiat’s per-user permission resolution and role sync. The figures below come from the authors’ local, synthetic benchmarks, not production, so treat them as ballpark.

Role-name checks no longer copy roles per resource

#8093 stops Permissions from copying a user’s role names into a new set for every resource, which made resolving a user O(resources × roles). With 5,000 roles per user, 17,000 accounts and applications, and 500 service accounts, login permission resolution dropped from about 2.7 s to about 15 ms (Redis), and a full role sync from roughly 23 minutes to 21–27 seconds. Permissions.getAuthorizations(List<String>) became getAuthorizationsForRoleNames(Set<String>), so code that calls it directly needs updating.

Restricted resources are indexed by group

#8136 builds, once per cache refresh, an index from permission group to the restricted resources that list it, instead of scanning every resource for every user. Service account role checks also use sets instead of list lookups, and predicates are built lazily. In a benchmark with 17,000 applications and 200 users holding 2,000 roles each, restricted-resource lookup went from about 1.4 s to about 170 ms and service account checks from about 300–350 ms to about 25 ms. ServiceAccountPredicateProvider gains a default Set-based overload, so existing implementations still compile. This applies to every resource provider, including the new artifact account provider.

Resources are serialized once per sync and unchanged Redis writes are skipped

#8137 serializes each resource once per sync instead of once per user that can see it, and skips rewriting a user’s Redis keys when their content hasn’t changed. It tracks this with digest keys (<prefix>:permissions-v2-digest:<user>:<type>) stored beside the data. In the authors' benchmark (1,000 users, 5,000 applications), a steady-state unchanged sync went from 115 ms to 46 ms wall time and from 469 ms to 152 ms JVM CPU. The first sync after a deploy costs Redis slightly more because of the digest writes.

Configuration, all under fiat.redis.repository:

Property Default Meaning
skip-unchanged-writes true Set to false to rewrite every key on every put.
write-digest-ttl unset A positive duration expires digest keys; intended only for temporary use during a mixed-version rollout or rollback.
write-digest-generation "1" Changing it invalidates all stored digests, so the next sync rewrites everything.

The key schema and value format are unchanged, and older Fiat versions ignore the digest keys, so rolling back is safe. After a rollback, bump write-digest-generation in the same change as the roll-forward (and once every pod runs the new version) so a same-size rewrite by old code can’t be mistaken for unchanged data.

#8093 and #8136 were also backported to the supported release branches.

  • artifacts: add Fiat permissions to artifact accounts (#7892) ( b77b37c2 )
  • aws: support connection tracking timeouts on launch templates (#8104) ( 03f03a78 )
  • canary: Change canaries for all providers to use a standard template and enhanced UI for query contents (#7900) ( 8987bef8 )
  • change: feat: add Gitea file artifacts and webhook triggers (#8153) ( 22f9ef68 )
  • clouddriver: bundle kubectl for supported EKS versions (#8183) ( 4cf47c52 )
  • deck: add copy-to-clipboard for artifact and image references and show K8s load balancer FQDN (#8094) ( 47664453 )
  • deck: compress JS assets (#8175) ( a2b52a38 )
  • deck: discover project pipelines by tag (#7934) ( 6917e22c )
  • deck: distinguish same-kind manifests in Deploy (Manifest) status (#8044) ( 781a68f8 )
  • deck: migrate application build from Webpack to Vite 7 (#8118) ( 70c4d24c )
  • deck: migrate package builds from Rollup to Vite 7 (#8119) ( 461773aa )
  • ecs: configure service monitoring resolution in server group wizard (#8049) ( 0f6a9bec )
  • ecs: copy service monitoring configuration to new server groups (#8048) ( 5b3b3c48 )
  • ecs: opt-in ecs-native provider for in-place ECS deployments (#8210) ( 725d11f0 )
  • entity-store: add a SQL-backed artifact/entity store (#8000) ( 41372c67 )
  • entity-store: pretty-print stored manifest references as YAML (#8025) ( f3bccd6f )
  • gate: add an allowlist for MCP tools (#8184) ( 96d37ef8 )
  • gate: serve branded Spinnaker sign-in page for basic auth and LDAP form login (#8084) ( e44da804 )
  • gitlabci: forward pipeline variables and ref on trigger (#8259) ( d2eaa598 )
  • google: add GCP Regional External load balancers (#7749) ( f2699cc5 )
  • k8s: annotate deployed manifests with deployment provenance (#8100) ( ea8b72bd )
  • kubernetes: evaluate health status of custom resources (#8102) ( 9159be7a )
  • orca,gate: allow searches to include executions from deleted pipelines (#8027) ( 5f73be14 )
  • orca: Add opt-in feature to rewrite dashed SpeL variables (#7983) ( 070bc2b4 )
  • orca: add GitlabCiStage for native GitLab CI pipelines (#8222) ( b3552488 )
  • orca: add metric for system errors when starting executions (#8140) ( 4700124b )
  • orca: support additional metric tags on stage execution context (#8005) ( 543d4670 )
  • pubsub: add kork-pubsub-redis (Streams single-delivery + native Pub/Sub broadcast) (#8031) ( 49b5d7e3 )
  • sbom: generate a per-service CycloneDX SBOM, starting with clouddriver (#8019) ( 02e14592 )
  • type: Move identifier queries to a set type which they were already to begin with… (#7643) ( e07b992d )
  • ui: Feat/deck dark theme, theme switching (#8194) ( be4670f8 )

Configuration

New settings in 2026.4.0 (defaults in parentheses). Settings that must change when you upgrade are under Breaking Changes .

Clouddriver

  • clouddriver.operations.executor.{maxThreads (500), queueCapacity (0), retryAfterSeconds (5)}: sizes the atomic-operation executor and sets the Retry-After hint returned when it is saturated ( #8173 ).
  • kubernetes.v2.apply-provenance-annotations (false): annotate deployed manifests with deployment provenance ( #8100 ).
  • kubernetes.customResourceStatus.{enabled (false), maxMessageLength (1024)}: evaluate the health of custom resources ( #8102 ).
  • artifacts.gitea.*: Gitea and Forgejo artifact accounts ( #8153 ).
  • urlRestrictions.allowedDomains per artifact account is now required when credentials are sent; rejectedIps matches resolved addresses ( #8171 , #8099 ).
  • The ecs-native cloud provider is opt-in ( #8210 ).
  • AWS launch templates accept connection-tracking timeouts ( #8104 ).
  • sql.agent.task-cleanup.failed-retryable-ttl-ms (7 days) ( #8172 ).

Orca

  • expression.dashedIdentifiers.enabled (false): rewrite dashed SpEL variable names ( #7983 ).
  • keiko.queue.redis.retry.{maxAttempts (3), backoffMs (100), exponentialBackoff (true)}: retry transient Redis connection errors in the queue ( #8002 ).
  • sql.enforceForeignPartition (true): when interlink is disabled, reject stage stores and deletes for executions owned by another partition. Set it to false only if every execution is local.
  • The GitlabCiStage stage, and extra metric tags on the stage execution context ( #8222 , #8005 ).

Fiat

  • auth.permissions.provider.artifact-account and auth.permissions.source.artifact-account.resource.enabled: Fiat permissions for artifact accounts ( #7892 ).
  • fiat.redis.repository.{skipUnchangedWrites (true), writeDigestTtl, writeDigestGeneration ("1")}: skip rewriting unchanged per-user permission keys ( #8137 ).

Kork (all services)

  • artifact-store.*, including artifact-store.type=sql which adds a table through the new 20260911-create-artifact-store-table migration ( #8000 ).
  • pubsub.redis.* from the new kork-pubsub-redis module ( #8031 ).

Gate

  • mcp.server.allowed-tools: allowlist for MCP tools ( #8184 ).
  • A branded sign-in page for basic auth and LDAP form login ( #8084 ).

Igor: GitLab CI triggers forward pipeline variables and the ref ( #8259 ).

Deck (settings.js): DEFAULT_THEME ( #8194 ), displayExecutionDeploymentTargets and providers.kubernetes.defaults.internalDNSNameTemplate ( #8094 ).

Fixes

Clouddriver: task store reliability

  • #8130 orders SQL task state by a per-task sequence and makes terminal states final, fixing invisible retries, completed tasks that looked running, and finished tasks being reopened. It adds nullable columns, indexes on tasks, and a unique tasks.request_id (existing duplicates are renamed, not deleted). Large Postgres installs can pre-create the indexes with CONCURRENTLY.
  • #8172 cleans up FAILED_RETRYABLE tasks (TTL sql.agent.task-cleanup.failed-retryable-ttl-ms, default 7 days) and no longer fails a successful operation when the final progress write fails.
  • #8173 bounds the operation executor (clouddriver.operations.executor.max-threads, default 500) and answers 503 with Retry-After when full; Orca retries a 503. Installs running more than about 500 concurrent operations per pod should raise the limit.
  • #8111 makes clouddriver-sql retries actually run, #8129 persists Redis task saga IDs and stops task key leaks, and #8110 reports an unreachable Redis task store as 503 instead of 500.
  • #8154 runs atomic operations with the caller’s security context.
  • #8141 and #8163 fix caching of AWS SDK v2 timestamps and named-image enums, #8196 reloads ECS account credentials when their backing AWS account changes, and #8052 stores ECS on-demand timestamps as epoch millis.

Fiat: GitHub App team role sync

#8224 and #8229 fix Fiat dropping every user’s GitHub roles with authMethod: GITHUB_APP: installation tokens are now renewed and cached memberships are kept when GitHub returns an error (only a 404 yields an empty result). New metrics include fiat.github.dataAgeSeconds (the one to alert on) and fiat.github.fetchFailures. An opt-in healthCheckEnabled (default false) adds the provider to /health, and can hold a starting replica DOWN while GitHub is unreachable.

Orca fixes

  • #8144 sends Clouddriver requests that the Retrofit2 migration left unexecuted.
  • #8174 stops a duplicate StartExecution from overwriting a newer execution status, and #8211 stops sharing the NO_TRIGGER instance across executions.
  • #8135 avoids loading the full execution for foreign partition checks.

Echo, Gate, Rosco and Igor

  • #8162 compares GitHub webhook signatures in constant time, and #8160 forwards SCM webhook headers and the raw body from Gate to Echo.
  • #8235 handles null type/schema when Echo hydrates pipelines.
  • #8126 lets Gate’s JsonHttpMessageConverter return raw JSON bodies as strings, and #8134 keeps Jackson 2-only HTTP serialization working on Spring Boot 4 for Clouddriver, Front50, Gate, Orca and Rosco.
  • #8217 keeps Rosco polling bakes after an error.
  • #8105 makes Igor accept Jenkins’ 303 already-queued redirect when submitting a build.
  • #8176 names the request in kork-web’s unhandled-error logs and logs them once, and #8051 ignores Spring Boot 4 empty-string placeholders in the plugin resolver.
  • #8181 updates image packages and shared Java dependencies.

Deck fixes

  • #8213 stores manifest selector changes in Formik manifest stages.
  • #8202 keeps pipeline editors in sync with pipeline changes, and #8128 reloads Run Pipeline stage parameters when switching stages.
  • #8003 hides SpEL expressions in execution deployment targets.

Security: CA trust and dependency bumps

  • #8242 rebuilds the service images against current CA packages and fails the build if emSign ECC Root CA - G3 is still trusted, removing that root from the JVM cacerts. Anything that relies on certificates chained to that root will stop validating.
  • #8267 bumps netty-bom to 4.1.137.Final (CVE-2026-75595) and #8268 bumps tomcat-embed to 10.1.59 (CVE-2026-65182).

More fixes

  • Fiat: #8261 makes MOST_SPECIFIC prefix permission resolution independent of the order of the entries in the configuration. Before, with foo* listed before foo, an application named exactly foo could be authorized with the wildcard’s roles. A full application name now always beats a wildcard, and among wildcards the longest prefix wins.
  • Orca: #8208 stops StartExecution’s rollback from undoing a cancellation, which could start a pipeline that had been canceled. #8236 reuses transaction connections in SQL execution persistence, cutting connection use on status updates and cancel, pause and resume.
  • Echo: #8221 keeps compensating missed cron triggers after an error (one unparseable cron expression used to stop it permanently), and #8220 keeps the SQS subscriber running when recreating its queue fails.
  • Front50: #8262 fixes the plugin binary cache, which looked up a literal key and so never hit; binaries were always re-fetched from storage.
  • Kayenta: #8252 excludes DataSourceAutoConfiguration in code, so a Kayenta config that still uses the Spring Boot 3 class name no longer fails startup with “Failed to configure a DataSource”. #8282 appends a trailing slash to the GCS rootFolder prefix when deleting objects, so deleting one key can’t match sibling keys sharing the prefix.
  • Google: #8280 makes updateBackendService failures actually retry (and retry on 500/503) instead of being swallowed and reported as success, and #8281 keeps one server group that fails to build from failing the whole region’s caching cycle. A skipped server group is evicted from the cache until a later cycle builds it.
  • Deck: #8263 revalidates index.html and settings*.js on reload, fixing stale bundles after an upgrade (such as useDeckRuntimeServices is not a function) that needed a hard refresh. #8273 speeds up stage editors and account selectors with thousands of accounts, and #8288 stops Apache gracefully on container stop, so pod termination no longer waits out the grace period.

Orca: zombie executions from a queue-ack race on looping/redirecting stages

#7919 fixes a race in the Redis queue’s message-acknowledgement path that could permanently drop a RunTask message for stages that loop or redirect between tasks (REDIRECT status), leaving the execution stuck. The check-then-delete acknowledgement is now a single atomic Lua script, matching how message delivery (poll()) already worked. The equivalent defect in RedisClusterQueue is a known, separate limitation not fixed by this change.

Orca: more robust handling of transient Redis connection errors

#8002 adds retry-with-backoff around Redis queue pushes, registers Jedis connection exceptions as retryable at the handler level, and preserves/restores stage or execution status around queue operations that fail after a status change — closing several paths that could leave a pipeline permanently stuck after a transient Redis read timeout.

#8026 fixes several bugs in /applications/{application}/pipelines/search: requests for a page beyond the first could return truncated or empty results, executions whose trigger time exactly matched a start/end boundary were silently dropped, pipelineName was ignored whenever application was "*", and a malformed trigger parameter returned a 500 instead of a 400.

Entity store: stored manifest references keep their kind, name, and namespace

#7999 restores metadata that was previously dropped when a deploy-manifest payload is swapped for a ref:// pointer in the execution context. Deck’s Deploy status now renders a “Kind namespace/name” label next to the details link instead of an opaque link-only fallback. References stored before this fix render as before.

Front50: staleCheck optimistic-concurrency check on pipeline saves

#8022 fixes ?staleCheck=true on pipeline saves, which has been a silent no-op since a 2022 refactor — Deck has sent this parameter on every save for years with no effect. The fix is gated behind a new, default-off flag (controller.pipeline.save.stale-check-enabled), so behavior is unchanged until an operator explicitly opts in for a later release.

Deck: Kubernetes manifest editor no longer clips the last line

#7920 replaces the long-unmaintained brace Ace editor bindings with current ace-builds, fixing long manifests being clipped behind the editor’s horizontal scrollbar.

#8004 fixes the manifest “Details” link not appearing for Deployment resources in some cases.

Deck and ECS/Lambda: assorted fixes

  • #7973 fixes a case-sensitivity bug in virtualizationType comparison that could under-populate available instance types.
  • #7960 fixes ECS’s Application.clusterNames to report actual Spinnaker cluster names instead of versioned ECS service names.

Echo: usage telemetry now reports the real service version

#7966 fixes stats.spinnaker-version in usage telemetry sent to stats.spinnaker.io, which previously always reported "unknown" because the version wasn’t wired up from the service’s own build metadata.

Gate MCP: fixed a startup failure

#7987 fixes gate-mcp failing to start with a BeanInstantiationException because its resource methods returned raw maps/lists, which the MCP annotations library doesn’t accept as a return type. Results are now serialized to JSON strings.

  • appengine: support full cache eviction to fix stale-cache bug (#8065) ( 5854ab91 )
  • aws: remove com.netflix.awsobjectmapper, the last real path to AWS SDK v1 (#8020) ( 3e1edb6d )
  • aws: support full cache eviction to fix stale-cache bug (#8069) ( eb2a1258 )
  • azure: support full cache eviction to fix stale-cache bug (#8062) ( 4ae0b02b )
  • builds: Prompt for whether to publish API specs, so backport releases do not override current APIs (#7979) ( 23bc5545 )
  • change: fix(clouddriver)!: require allowedDomains for artifact accounts that send credentials (#8171) ( 4d2819fc )
  • change: fix(gate)!: check the authenticated user’s membership of the GitHub organization (#8187) ( 30a9a333 )
  • ci: actually run spin’s go tests in CI (#8024) ( 11fe28f1 )
  • ci: bump pinned QEMU binfmt image from v7.0.0-28 to v10.2.3-68 (#7970) ( 0e51825a )
  • ci: index platform-specific SBOM for multi-platform image attestation (#8058) ( 96bb8abf )
  • ci: skip API docs PR when Gate’s OpenAPI spec is unchanged (#8089) ( e75d8c79 )
  • ci: split collapsed gradle-wrapper-validation steps (#8028) ( 962d231b )
  • ci: trim ubuntu image SPDX SBOM to fit attestation size limit (#8296) (#8297) ( 2e539b46 )
  • ci: use ghcr-cleanup-manager for GHCR image cleanup (#7985) ( 704ff3b4 )
  • clouddriver: bound the operation executor and answer 503 with Retry-After when full (#8173) ( 85ad3d8f )
  • clouddriver: cache AWS SDK v2 timestamps as epoch millis (#8141) ( 16ce2b03 )
  • clouddriver: cache named-image enums as their AWS wire values (#8163) ( 288bb252 )
  • clouddriver: clean up retryable task failures and keep successful operations successful (#8172) ( 63bf5ea3 )
  • clouddriver: make clouddriver-sql retries actually run (#8111) ( 10a54d1a )
  • clouddriver: order SQL task state by a per-task sequence and make terminal states final (#8130) ( 7935f064 )
  • clouddriver: persist Redis task saga IDs and stop Redis task keys leaking (#8129) ( 34e51801 )
  • clouddriver: remove broken ClusteredSortAgentScheduler and dead isAtomic/onDemand-lock machinery (#8073) ( 3a26f8ed )
  • clouddriver: report an unreachable Redis task store as 503, not 500 (#8110) ( 5c89a92d )
  • clouddriver: run atomic operations with the caller’s security context (#8154) ( 2bd4d06d )
  • cloudfoundry: support full cache eviction to fix stale-cache bug (#8064) ( 5c2c5832 )
  • cloudrun: support full cache eviction to fix stale-cache bug (#8066) ( f55e0816 )
  • deck/kubernetes: store manifest selector changes in Formik manifest stages (#8213) ( 07c75c08 )
  • deck: Case-insensitve on virtualizationType comparison (#7973) ( dfbdd89e )
  • deck: bump React from 16.14 to 17.0.2 across the workspace (#7981) ( 099f9e3a )
  • deck: bump rxjs from 6.6.7 to 7.8.2 across the workspace (#7980) ( 79a0562c )
  • deck: ensure kubernetes manifest deployment details link shows up in the UI (#8004) ( 6eebaa31 )
  • deck: hide SpEL expressions in execution deployment targets (#8003) ( 301ddaf1 )
  • deck: keep pipeline editors in sync with pipeline changes (#8202) ( ee17f942 )
  • deck: reload Run Pipeline stage parameters when switching stages (#8128) ( ff8e532f )
  • deck: revalidate entrypoint and runtime settings (#8263) ( 25aa6a54 )
  • deck: scope rxjs override so lerna publish doesn’t crash (#7972) ( 5d59f49c )
  • deck: speed up stage editors with many accounts (#8273) ( 266e16cd )
  • deck: stop apache gracefully when the container stops (#8288) ( d4ccf811 )
  • deck: upgrade react-ace/brace to fix Kubernetes manifest editor cutoff (#7920) ( dc3ad70e )
  • deck: use viteBuild in npm publish and keep webpack as deprecated alias (#8125) ( 3480e452 )
  • docker: support full cache eviction to fix stale-cache bug (#8067) ( a3e87f86 )
  • echo: compare GitHub webhook signatures in constant time (#8162) ( 6ecbc649 )
  • echo: handle null type/schema when hydrating pipelines (#8235) ( e0bb8cd6 )
  • echo: keep compensating missed cron triggers after an error (#8221) ( 2e882a89 )
  • echo: keep the SQS subscriber running when recreating its queue fails (#8220) ( 8ab95c5f )
  • echo: populate telemetry spinnakerVersion from resolved service version (#7966) ( 76d13b74 )
  • ecs: opt in to full cache eviction and delete redundant manual eviction (#8072) ( 57e4556f )
  • ecs: populate Application.clusterNames with real cluster names (#7960) ( 88422629 )
  • ecs: reload ECS account credentials when their backing AWS account changes (#8196) ( d42b9c91 )
  • ecs: store on-demand timestamps as epoch millis (#8052) ( 2f649765 )
  • entity-store: restore artifact name/kind/namespace on stored manifest references (#7999) ( 44935c40 )
  • entity-store: show real YAML for stored inline manifests in Deploy Manifest stage config (#8156) ( a7673db2 )
  • eureka: support full cache eviction to fix stale-cache bug (#8068) ( 61c74e66 )
  • fiat: deserialize extension resources in UserPermission.View (#8253) ( d32c418b )
  • fiat: harden GitHub App team role sync (follow-up to #8224) (#8229) ( cbf505d8 )
  • fiat: keep MOST_SPECIFIC prefix resolution order-independent (#8261) ( 423b7105 )
  • fiat: renew GitHub App installation tokens and keep cached memberships on errors (#8224) ( 37f1072c )
  • front50: read the plugin binary cache under the requested key (#8262) ( 79479631 )
  • front50: repair dormant pipeline staleCheck optimistic-concurrency check (#8022) ( 97296462 )
  • front50: serialize cache refresh and de-flake multi-threaded pipeline cache refresh specs (#8228) ( 464341f7 )
  • gate-mcp: serialize MCP resource results to JSON strings (#7987) ( 5656675c )
  • gate: forward SCM webhook headers and the raw body to echo (#8160) ( 57ccf10e )
  • gate: let JsonHttpMessageConverter hand back raw JSON bodies as String (#8126) ( 0d28842d )
  • gate: post the branded login form through gate’s context path (#8212) ( 43b9d65a )
  • gitlabci: strip GitLab log-line prefix before parsing build properties (#8278) ( 6803182a )
  • google: improve error handling and prevent NPE in AbstractGoogleServerGroupCachingAgent (#8281) ( 350121f4 )
  • google: retain empty cache entries for kinds with zero live resources (#8061) ( e418110c )
  • google: retry on updateBackendService (#8280) ( 5f550929 )
  • huaweicloud: opt in to full cache eviction and backfill authoritative keys (#8071) ( 1917403d )
  • igor: accept Jenkins 303 already-queued redirect when submitting a build (#7997) (#8105) ( 69ffa0b4 )
  • k8s: K8s caching is kind of broken with SQL (#8059) ( ef468788 )
  • kayenta-gcs: append trailing slash to rootFolder prefix to prevent GCS prefix collisions (#8282) ( ccf96eed )
  • kayenta: exclude DataSourceAutoConfiguration in code, not config (#8252) ( 71e027b9 )
  • kork-web: name the request in unhandled-error logs and log them once (#8176) ( 7d1c45b1 )
  • kork: ignore Boot 4 empty-string config placeholders in plugin resolver (#8051) ( 7704b9b8 )
  • kork: shared URL restrictions that check resolved addresses (#8099) ( 0705e3b0 )
  • kubernetes: retain empty cache entries for kinds with zero live resources (#8054) ( dbf9c0c1 )
  • kubernetes: show controller-written status text as plain text (#8101) ( 87526493 )
  • kubernetes: validate namespace allow-list when no namespace is set (#7998) ( c2661967 )
  • lambda: delete redundant manual eviction now that AwsProvider opts in (#8083) ( 8f996893 )
  • oracle: support full cache eviction to fix stale-cache bug (#8063) ( 447d7a69 )
  • orca: ack queue messages atomically so a concurrent push survives for stages that have looping tasks (#7919) ( 95b61248 )
  • orca: correct pagination, boundary, and filter bugs in pipeline trigger search (#8026) ( 6b1d59b1 )
  • orca: don’t let StartExecution’s rollback undo a cancellation (#8208) ( 90d58309 )
  • orca: don’t let a duplicate StartExecution overwrite a newer execution status (#8174) ( 1f568ed1 )
  • orca: don’t share the NO_TRIGGER instance across executions (#8211) ( 810e9d2e )
  • orca: reuse transaction connections in SQL execution persistence (#8236) ( 21694dfc )
  • orca: send Clouddriver requests that the Retrofit2 migration left unexecuted (#8144) ( 6114b31a )
  • rosco: close remaining helmfile RCE gaps and disable insecure helmfile features by default (#8034) ( 3039b0fe )
  • rosco: create writable home dir for spinnaker system user in Dockerfile.ubuntu (#7967) ( 3b926196 )
  • rosco: keep polling bakes after an error (#8217) ( 94418b20 )
  • rosco: reject helmfile hooks/postRenderers by default to prevent RCE via bake (#8015) ( 1dce54db )
  • security: bump netty-bom to 4.1.137.Final (CVE-2026-75595) (#8267) ( a583b535 )
  • security: bump tomcat-embed to 10.1.59 (CVE-2026-65182) (#8268) ( dfc385da )
  • security: drop emSign ECC Root CA - G3 from service images (#8242) ( 36c71ccc )
  • security: update image packages and shared Java dependencies (#8181) ( 1afea9c1 )
  • serialization: keep Jackson 2-only HTTP serialization working on Boot 4 for clouddriver,front50,gate,orca,rosco (#8134) ( 0a2b7eea )
  • spin: opt pipeline save/update into front50’s staleCheck (#8023) ( f1d65c36 )
  • tests: Tests using dockerhub images from minio which were removed. (#8001) ( 8b6bb186 )
  • yandex: opt in to full cache eviction and backfill authoritative keys (#8070) ( 8ab8335f )

Other

  • aws: Allow aws init calls to be made based on accounts region (#8132) ( ce64c593 )
  • aws: replace MinIO and LocalStack with MiniStack in AWS integration tests (#8010) ( ad69f46e )
  • aws: update AWS Java SDK v2 to latest version (#8038) ( 7bab5845 )
  • build: update pnpm and Node versions (#8161) ( 23c57518 )
  • change: Migrate jsch and agentproxy dependencies to com.github.mwiede versions (#8046) ( 2b3204df )
  • change: build: upgrade to Java 25 (#8014) ( 941369f8 )
  • change: chore: migrate to Spring Boot 4.1.1 (#7996) ( 8023f301 )
  • change: chore: upgrade springmockk and wiremock (#8040) ( 2f9a8c86 )
  • change: ci: publish libraries and deck npm packages only for full releases (#8266) ( 9ecc910f )
  • change: deps: update several libraries as easy-wins (#8039) ( 1ef54af3 )
  • change: docs: improve agent guidance for contributors and reviewers (#7986) ( 83d59408 )
  • change: make orca’s queue handling more robust (#8002) ( 94647a26 )
  • change: test: make vacuous assertThat calls actually assert (#8143) ( da92dc8b )
  • ci: restore deck trusted-publishing invocation and include deck SBOM in releases (#8042) ( dc6835e8 )
  • cleanup: REmove old subtree fork handling, update various readmes with current pointers, etc. Just cleanup a lot of old guides and docs references (#8041) ( f52af483 )
  • cleanup: Remove yandex as a clouddriver from the codebase (#8186) ( 0ba38000 )
  • cleanup: fix worklow and use Go binary instead of broken Docker image (#7982) ( a8282aed )
  • clouddriver/orca: use label selectors for kubernetes artifact lookups (#8045) ( 0b483736 )
  • clouddriver: remove ProviderCacheConfiguration full-eviction guard (#8106) ( 8eef4ea5 )
  • deck: migrate unit tests from Enzyme to React Testing Library (#8124) ( 64465bef )
  • deck: migrate unit tests from Karma to Vitest (#8121) ( cfe83a77 )
  • deck: remove leftover webpack tooling and dead Storybook config (#8122) ( 9de190ee )
  • deck: upgrade functional-test harness to Vite 7 (#8123) ( 1f1734e6 )
  • dependencies: update Google API dependencies (#8050) ( 462622cb )
  • deps-dev: bump vite from 7.3.6 to 7.3.7 in /deck/test/functional (#8260) ( 223e8561 )
  • deps-dev: bump vitest from 4.1.10 to 4.1.11 in /deck (#8159) ( 2a658e41 )
  • deps: bump actions/download-artifact from 4 to 8 (#8114) ( 778d966c )
  • deps: bump actions/github-script from 8 to 9 (#7663) ( 4e251179 )
  • deps: bump actions/setup-go from 5 to 7 (#8115) ( 28dae1a4 )
  • deps: bump actions/setup-java from 4 to 6 (#7946) ( 10e77349 )
  • deps: bump dompurify from 3.4.11 to 3.4.16 in /deck (#8158) ( de95a56c )
  • deps: bump fast-uri from 3.1.2 to 3.1.8 in /deck/test/functional (#7828) ( 5e70de28 )
  • deps: bump fast-uri from 3.1.8 to 3.1.9 in /deck/test/functional (#8275) ( e92c8ef7 )
  • deps: bump follow-redirects in /deck/test/functional (#8223) ( fd9dd054 )
  • deps: bump github/codeql-action from 4.37.3 to 4.37.9 (#7947) ( 1d4a5d0f )
  • deps: bump github/codeql-action from 4.37.9 to 4.38.2 (#8113) ( b9f6a1ee )
  • deps: bump postcss from 8.5.15 to 8.5.23 in /deck (#7838) ( e6031c62 )
  • deps: upgrade logstash-logback-encoder 4.11 -> 9.0 (#8047) ( 6750c511 )
  • fiat: Avoid copying role names when computing authorizations (#8093) ( 17fc95c3 )
  • fiat: index restricted resources by group and use sets for service account role checks (#8136) ( 5c3f4bb2 )
  • fiat: serialize resources once per sync and skip unchanged Redis writes (#8137) ( 523a127d )
  • front50: wire config into SqlPipelineControllerTck and add refresh diagnostics (#8138) ( 31cc0a2c )
  • kayenta-gcs: add fake-gcs-server integration test for prefix collisions (#8285) ( 2801e8b3 )
  • kork: remove the kork-stackdriver metrics push module (#8107) ( bf7add67 )
  • orca: rename Jenkins-specific CI tasks to generic build tasks (#8205) ( cc003a15 )
  • rfc: Pub sub plans (#8053) ( c56d297d )
  • sql: avoid loading the full execution for foreign partition checks (#8135) ( f3003b6c )
  • test: switch embedded/testcontainer Redis image to Valkey 8 (#8029) ( 7cebba93 )
  • tests: Remove deprecated tests from legacy versions (#7984) ( 31722c11 )
  • titus: remove the Titus cloud provider (#8095) ( 6d9f3c9e )