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
githubclient registration requests theread:orgscope. - 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:
- 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 - Delete
rollup.config.js, then runcheck-plugin --fixto restore the scaffold’svite.config.jsand update thebuildandwatchscripts:Afterwardsrm rollup.config.js npx check-plugin --fixpackage.jsonhas"build": "NODE_ENV=production spinnaker-scripts build"and"watch": "spinnaker-scripts start", andvite.config.jscontains:module.exports = require('@spinnaker/pluginsdk/pluginconfig/vite.config'); - Remove
rollup,@rollup/*androllup-plugin-*fromdevDependencies, unless your own code still uses them. - If you customised
rollup.config.js, move the changes intovite.config.jsby 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
templatepopulated from anycustomFilterTemplatethey 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-leveltemplatesmap no longer affect that metric.customFilterTemplateand thetemplatesmap are left in place, so nothing is lost on rollback. - A
customFilterTemplatethat 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 guidedmetricNameplus 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
githubaccounts default togithub.com,api.github.com,codeload.github.com,raw.githubusercontent.com,media.githubusercontent.comandobjects.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) andTitusPreconfiguredJobPropertiesfrom theorca-apiplugin API. - #8186 removes the Yandex provider from Clouddriver.
-
#8107
removes
kork-stackdriver.spectator.stackdriver.enabled=trueis 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
ProviderCacheConfigurationclass fromclouddriver-api, now that full cache eviction is always on. Plugins or forks that implement it, or call the two-argumentNamedCacheFactory.getCache/SqlCacheconstructor, 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.
Gate MCP tool allowlist and deleted-pipeline search
-
#8184
adds
mcp.server.allowed-toolsso operators can limit which MCP tools Gate exposes. If unset, all tools stay enabled. -
#8027
adds an opt-in
includeDeletedPipelinesparameter (defaultfalse) to Orca’s pipeline search andGET /applications/{application}/pipelines, passed through Gate and thesearch_executionsMCP 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/Readyconditions,status.phase) instead of always reporting them healthy. It is off by default:kubernetes: customResourceStatus: enabled: true -
#8045
passes label selectors to the
kubectl getcalls used for artifact lookups, avoiding large memory spikes in busy namespaces, and fixes Orca’sCleanupArtifactsTasknot 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,udpStreamTimeoutandudpTimeout(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 theRetry-Afterhint 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.allowedDomainsper artifact account is now required when credentials are sent;rejectedIpsmatches resolved addresses ( #8171 , #8099 ).- The
ecs-nativecloud 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 tofalseonly if every execution is local.- The
GitlabCiStagestage, and extra metric tags on the stage execution context ( #8222 , #8005 ).
Fiat
auth.permissions.provider.artifact-accountandauth.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.*, includingartifact-store.type=sqlwhich adds a table through the new20260911-create-artifact-store-tablemigration ( #8000 ).pubsub.redis.*from the newkork-pubsub-redismodule ( #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 uniquetasks.request_id(existing duplicates are renamed, not deleted). Large Postgres installs can pre-create the indexes withCONCURRENTLY. -
#8172
cleans up
FAILED_RETRYABLEtasks (TTLsql.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 answers503withRetry-Afterwhen 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
StartExecutionfrom overwriting a newer execution status, and #8211 stops sharing theNO_TRIGGERinstance 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
JsonHttpMessageConverterreturn 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 - G3is still trusted, removing that root from the JVMcacerts. Anything that relies on certificates chained to that root will stop validating. -
#8267
bumps
netty-bomto 4.1.137.Final (CVE-2026-75595) and #8268 bumpstomcat-embedto 10.1.59 (CVE-2026-65182).
More fixes
- Fiat:
#8261
makes
MOST_SPECIFICprefix permission resolution independent of the order of the entries in the configuration. Before, withfoo*listed beforefoo, an application named exactlyfoocould 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
keyand so never hit; binaries were always re-fetched from storage. - Kayenta:
#8252
excludes
DataSourceAutoConfigurationin 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 GCSrootFolderprefix when deleting objects, so deleting one key can’t match sibling keys sharing the prefix. - Google:
#8280
makes
updateBackendServicefailures 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.htmlandsettings*.json reload, fixing stale bundles after an upgrade (such asuseDeckRuntimeServices 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.
Orca: pagination, boundary, and filter bugs in pipeline trigger search
#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.
Deck: Kubernetes Deployment details link
#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
virtualizationTypecomparison that could under-populate available instance types. -
#7960
fixes ECS’s
Application.clusterNamesto 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 )