Skip to content

Tags: cozystack/cozystack

Tags

v1.6.5

Toggle v1.6.5's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(release): promote v1.6.5-rc.3 -> v1.6.5 (#4937)

Promotes `v1.6.5-rc.3` to stable `v1.6.5` without rebuilding containers.
Their digests remain bit-for-bit what passed rc e2e; the tag-rewritten
packages tree is re-serialized as a temporary OCI candidate and pinned
here by digest. On merge, pull-requests-release.yaml verifies that
candidate against this tree before creating the write-once `v1.6.5` tag,
retagging the candidate and container digests to `v1.6.5` (+`:latest`
when this is the newest stable), publishing the stable cozy-installer
chart, and publishing the release. Do NOT squash-merge (decision B): the
stable tag must attach to a real merge commit.

✅ RC full e2e was verified for `v1.6.5-rc.3` before promotion.

ℹ️ E2E already ran against the immutable rc, so this promote PR does not
run E2E by default. A maintainer may add the `full-e2e` label to run the
full suite again.

✅ Includes `docs/changelogs/v1.6.5.md`, which finalize uses verbatim as
the published release body.

✅ Website docs PR opened/refreshed on `cozystack/website` (branch
`update-docs-v1.6.5`), generated from the `release-1.6.5` staging
branch. **Do NOT merge that PR until `v1.6.5` is published** — merging
it early flips the site's latest-version pointer to an unpublished
version and 404s its docs/API links (see the PR body).

v1.6.5-rc.3

Toggle v1.6.5-rc.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
[Backport release-1.6] fix(tcp-balancer): rename backends and pin HAP…

…roxy so the chart starts on 3.3+ (#4516)

## What this PR does

Backports #4366 to release-1.6. All three original commits applied
without conflicts and retain their cherry-pick references.

HAProxy is pinned to 3.4.4 and backend names no longer collide with
frontend names. An empty whitelist leaves Kubernetes and Talos frontends
unfiltered. Enabling whitelistHTTP without a whitelist fails rendering.

Validation passed with 9 Helm tests, five rendered configurations
checked by HAProxy 3.4.4, and package generation without changes. The
old chart reproduces the name collision. Removing only the HTTP reject
rule makes the regression test fail.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(tcp-balancer): backport HAProxy 3.4.4, distinct backend names and whitelist validation to 1.6.
```

api/apps/v1alpha1/v1.6.5

Toggle api/apps/v1alpha1/v1.6.5's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(release): promote v1.6.5-rc.3 -> v1.6.5 (#4937)

Promotes `v1.6.5-rc.3` to stable `v1.6.5` without rebuilding containers.
Their digests remain bit-for-bit what passed rc e2e; the tag-rewritten
packages tree is re-serialized as a temporary OCI candidate and pinned
here by digest. On merge, pull-requests-release.yaml verifies that
candidate against this tree before creating the write-once `v1.6.5` tag,
retagging the candidate and container digests to `v1.6.5` (+`:latest`
when this is the newest stable), publishing the stable cozy-installer
chart, and publishing the release. Do NOT squash-merge (decision B): the
stable tag must attach to a real merge commit.

✅ RC full e2e was verified for `v1.6.5-rc.3` before promotion.

ℹ️ E2E already ran against the immutable rc, so this promote PR does not
run E2E by default. A maintainer may add the `full-e2e` label to run the
full suite again.

✅ Includes `docs/changelogs/v1.6.5.md`, which finalize uses verbatim as
the published release body.

✅ Website docs PR opened/refreshed on `cozystack/website` (branch
`update-docs-v1.6.5`), generated from the `release-1.6.5` staging
branch. **Do NOT merge that PR until `v1.6.5` is published** — merging
it early flips the site's latest-version pointer to an unpublished
version and 404s its docs/API links (see the PR body).

v1.6.5-rc.2

Toggle v1.6.5-rc.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
[Backport release-1.6] fix(api): keep a suspended HelmRelease suspend…

…ed across an app update (#4928)

## What this PR does

Backport of #4411 to `release-1.6`.

`REST.Update` rebuilds the HelmRelease from the Application and writes
it back whole, and Application has no suspension, so every edit through
the API resumes a release that an operator or a controller suspended.
The CNPG restore driver depends on it: it suspends the target release,
patches the Postgres app through this API, purges the Cluster and
resumes only after the purge, so the next render lands
`bootstrap.recovery` on an empty namespace. When the patch resumes the
release, helm-controller upgrades right away, the Cluster gets rendered
while the purge still runs, the driver deletes it, and nothing renders
it again because the values don't change anymore. RestoreJob stays
`Running` until its deadline.

Why it is needed on this line now. The race was hidden by timing: Update
dropped `finalizers.fluxcd.io`, helm-controller spent its first pass
putting it back and requeued, and that delay usually let the purge
finish first. #4683 and #4919 keep the finalizer across the write, so
the delay is gone. After they landed, `postgres-2-backup-roundtrip`
failed on v1.6.5-rc.1
(https://github.com/cozystack/cozystack/actions/runs/38583543706) and in
two earlier PR runs, each time stuck at `TargetPurged: Cluster ...
deleted; awaiting chart-rendered re-bootstrap`. In the snapshot of the
rc run the HelmRelease of the restore target upgraded to v2 at
16:16:13Z, the Cluster was deleted at 16:16:22Z, and no Cluster of the
target exists afterwards.

The cherry-pick conflicted only in comments of `REST.Update`, where this
branch already has the metadata carry-over. The two `Spec.Suspend`
assignments merged unchanged and the comments read as they do on main.

### Validation

- `go build ./...` is clean, `go vet ./pkg/registry/...` is clean, `go
test ./pkg/registry/... ./internal/backupcontroller/...` passes.
- Removing either `Spec.Suspend` assignment turns its test red:
`TestUpdate_PreservesSuspend` for the first write,
`TestUpdate_RefreshesSuspendOnConflictRetry` for the conflict retry.
- Not run here: the restore round trip on a live cluster, the E2E of
this PR covers it.

### Downstream repositories

It changes how the aggregated API writes the HelmRelease back, no
downstream repository restates that.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

```release-note
fix(api): app edit through cozystack API no longer resumes a suspended HelmRelease, so postgres restore waits for its purge before the cluster is rendered again.
```

v1.6.5-rc.1

Toggle v1.6.5-rc.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
[Backport release-1.6] fix(cilium)!: take cilium's own addresses from…

… a block kube-ovn does not hand out (#4918)

## What this PR does

Backport of #4778 to `release-1.6`, fixes #3740 on the 1.6 line.

On the kube-ovn variants (`isp-full`, `isp-full-generic`) cilium
allocates no pod IPs, but it still takes its router IP and the Gateway
API ingress IP from `Node.spec.podCIDR`, a /24 out of the same range
kube-ovn hands pods from, so sooner or later kube-ovn gives a pod an
address cilium already holds. With this change cilium runs `ipam.mode:
cluster-pool` with a /29 per node out of the last /21 of
`networking.podCIDR`, platform passes the same range to kube-ovn as
`--default-exclude-ips`, and a post-upgrade hook in the cilium chart
moves existing clusters. Mechanism and hook steps are the same as in
#4778, its description has the details.

This is breaking for a patch release, please read before merging:

- `networking.podCIDR` has to be /20 or wider on the kube-ovn variants,
otherwise platform refuses to render and the upgrade stops before
anything changes. Widening the value later doesn't help, the hook
refuses a block outside the subnet the cluster was installed with.
- A /21 of /29s caps these variants at 256 nodes.
- Every cilium agent restarts twice, once for the config change and once
in the hook. While the cilium release is failed, packages that depend on
networking wait for it.
- If kube-ovn already handed out an address from the last /21, the hook
names that address and stops before it moves any node. Recreate the pods
holding it and the next retry goes through.
- Rolling back to 1.6.4 brings `ipam.mode: kubernetes` back, agents take
their /24 again, and the exclusions stay in `ovn-default`.

### Differences from #4778

- No slim variants on release-1.6, so the `cozystack.platform.slim` gate
is gone and the pool is wired in the `isp-full` and `isp-full-generic`
branches only. `isp-hosted` renders `noop` and is not touched.
- The code around the wiring in `system.yaml` is release-1.6's (no
`gateway.http2`, no `networking.encryption`, the older
`cozystack.platform.package` call).
- The wiring test for `isp-slim` is left out of the cherry-pick, the
second commit adds one for `isp-hosted` with a /24 pod CIDR, which has
to keep rendering without the /20 requirement.
- `packages/system/cilium` has no `make test` target here, so
`hack/helm-unit-tests.sh` would skip the new suite without a word. The
third commit adds it.
- The follow-up from main that loads `test_helper` in
`hack/cilium-ipam-migration.bats` is not applied. release-1.6 has no
`hack/test_helper.bash` and runs `hack/*.bats` through
`hack/cozytest.sh`, with that line the file doesn't load.
- release-1.6 ships kube-ovn v1.15.10, #4778 was written against
v1.15.26.

### Validation

- `helm unittest`: cilium 11/11, platform 113/113 with #4808 merged.
`hack/cilium-ipam-migration.bats` passes 27/27 through
`hack/cozytest.sh`.
- Live hook run on a three-node Talos cluster with kube-ovn v1.15.10. I
put cilium on the release-1.6 chart first, then upgraded to this branch
with `helm upgrade` (operator stopped, HelmRelease suspended). A pod
pinned to `10.244.250.10` made the hook add the block and the old
ingress IPs to `excludeIps` of `ovn-default`, name that address and stop
before moving any node. After deleting the pod the same upgrade moved
all three nodes to /29s from `10.244.248.0/21`, router and ingress IPs
inside. The available range of the subnet ends at `10.244.247.255`, no
pod IP is duplicated, and pod to pod across nodes, DNS and a ping to a
VM pod IP work. A third run of the same upgrade restarted nothing and
left the CIDRs as they were.
- Rolling the release back on that cluster returned the agents to their
/24s with new ingress IPs, and `excludeIps` stayed until I patched it by
hand.
- Not run: the upgrade through the operator, the generic variant,
Gateway API traffic (no gateway on that cluster). kube-ovn still admits
a pod with a static `ovn.kubernetes.io/ip_address` inside the block
after the migration, the hook looks at it only while migrating.

### Downstream repositories

The website note for this change is cozystack/website#739, merged for
`docs/next`. The v1.6 docs need the same note, not opened yet, so the
box stays empty.

- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

```release-note
fix(cilium)!: on the kube-ovn variants cilium now takes its router and gateway api ingress ips from the last /21 of networking.podCIDR, which kube-ovn no longer hands out, so pods stop landing on addresses cilium holds. existing clusters move on upgrade through a post-upgrade hook, and each cilium agent restarts twice, once for the config change and once in the hook. networking.podCIDR needs /20 or wider on these variants, and a /21 of /29s caps them at 256 nodes.
```

v1.7.0-rc.1

Toggle v1.7.0-rc.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(redis): expose min-replicas-to-write and min-replicas-max-lag (#…

…4848)

## What this PR does

Adds two optional values to the Redis app, `minReplicasToWrite` and
`minReplicasMaxLag`, rendered as `min-replicas-to-write` and
`min-replicas-max-lag` in the RedisFailover `spec.redis.customConfig`.
Both are unset by default, so the rendered config and behaviour are
unchanged for existing instances.
Replication is asynchronous, so a master that is isolated from its
replicas keeps accepting writes until Sentinel fails over, and those
writes are lost. With `minReplicasToWrite: 1` the isolated master stops
accepting them after `minReplicasMaxLag` seconds, which bounds the loss.
Trade-off: with the default `replicas: 2` there is a single replica, so
the master also refuses writes whenever that replica is down (node
drain, restart, upgrade). Users who turn this on accept lower write
availability for a bounded loss window.
Includes helm-unittest cases and the regenerated schema, README, Go
types and ApplicationDefinition.


### Screenshots


### Downstream repositories


- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [x]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
cozystack/terraform-provider-cozystack#68
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note


```release-note
feat(redis): add optional minReplicasToWrite and minReplicasMaxLag values to bound writes lost on failover; unset by default
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added optional Redis settings to require a minimum number of replicas
to acknowledge writes and to set the maximum age of those
acknowledgements.
* Invalid settings are rejected: the required replica count must be
nonnegative and below the configured replica count, and the
acknowledgement age must be at least 1 when a replica requirement is
set. Replication remains asynchronous, so these settings do not
eliminate potential write loss during failover.
* **Documentation**
* Documented the settings, defaults, validation, and behavior in Redis
configuration guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

v1.7.0-alpha.3

Toggle v1.7.0-alpha.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(linstor): build piraeus-server's protobuf code on an arm64 builder (

#4576)

## What this PR does

The arm64 half of a release fails to build piraeus-server.
linstor-server's build always downloads the `linux-x86_64` protoc, and
the builder stage runs on the build platform. Since the release builds
arm64 on a native arm64 runner, that protoc cannot execute there, and
`./gradlew generateJava` fails with `Syntax error: ")" unexpected`. The
first multi-arch pre-release run, v1.7.0-alpha.2, stopped on it.

A new patch to linstor-server picks the protoc build for the host's
architecture. An amd64 builder still gets the same x86_64 protoc as
before. The generated code is Java, so one native builder serves both
target platforms.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
NONE
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Builds on ARM-based hosts now select a compatible Protocol Buffers
compiler download, avoiding failures caused by using an x86_64-only
build. Builds on other supported hosts continue to use the x86_64
compiler. This improves compatibility across build architectures without
changing the resulting application behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

v1.7.0-alpha.2

Toggle v1.7.0-alpha.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
ci(release): build pre-release images for amd64 and arm64 and gate re…

…leases on it (#4505)

## What this PR does

Pre-release builds now publish every image as an amd64 and arm64 index,
and a release fails if anything it ships is single-arch. Main, release
lines and pull requests keep building amd64 only. It builds on #4498,
which made every image buildable for both architectures. Part of #1961.

**This PR is on hold until everything under "Merge after" has landed.**
Merged earlier, the new gate fails the next rc on the images those PRs
fix.

### How a pre-release is built

A pre-release tag gets a second job, for arm64, next to the existing
release job. That covers `-rc.N`, `-beta.N` and `-alpha.N` tags. It runs
on the CNCF arm64 pool (`oracle-vm-24cpu-96gb-arm64`), builds the same
images with `PLATFORM=linux/arm64`, and pushes them as `<tag>-arm64`.
`prepare-release` waits for it, and if the arm64 job fails the rc fails
with it. There is no amd64-only fallback. Stable tags do not run it:
promotion copies the rc digests with `skopeo copy --multi-arch all`, so
a stable release inherits the indexes.

After the amd64 build, the stitch joins each amd64 image with its arm64
twin into one index. It lives in `hack/stitch-multiarch.sh`. Every tag
of the amd64 image moves to the index, the component-versioned ones
included. The script then rewrites the digests in the tree and
republishes the packages artifact and the installer chart pinned on
them. It reads refs through `hack/lib/image-refs.sh`, and it fails if an
old digest survives anywhere outside `charts/`.

### The gate

A new check fails the rc when a pinned digest in the tree is not an
index with both linux/amd64 and linux/arm64. It lives in
`hack/verify-multiarch.sh`. It checks first-party and third-party refs
alike. Images that are amd64 by nature go into
`hack/multiarch-allowlist`, one repository per line, each with a
mandatory reason. Today that is only the e2e sandbox. An entry that
matches nothing is reported as stale.

The static gate only sees digest-pinned refs in the tree. A tag-only
ref, an image from a vendored chart default, or one an operator starts
at runtime is invisible to it. So the rc e2e also audits every image its
nodes pulled, with the same check and the same allowlist. Neither covers
a package the e2e never installs.

### Nightly

A new nightly workflow builds main for arm64. It keeps the arm64 build
cache warm, since the rc job only reads it. It also prints the
single-arch refs that would block the next rc. Nothing it builds is
published.

### Smaller changes

- `CACHE_TAG` in `hack/common-envs.mk` moves the default cache ref, so
the arm64 build keeps a cache of its own.
- `MATRIX_ARCH=arm64` makes `hack/build-matrix.sh` leave out the
amd64-only e2e sandbox.
- The kamaji provider image is pushed under the build's `IMAGE_TAG` like
every other image. Its Makefile set `IMAGE_TAG` itself, so concurrent
builds overwrote each other's component tag. Closes #4503.
- `hack/nightly-mirror.sh` verifies a copy against the raw manifest
digest. Plain `skopeo inspect` resolves an index to one platform's
child.
- matchbox is rebuilt for both platforms in the amd64 release job. The
arm64 leg skips the talos package, so there is no arm64 half to stitch,
and its Dockerfile only copies files, so no QEMU is needed. Releases
then network-boot arm64 machines too. Closes #4524.

The stitch also rewrites the kamaji ref inside `files/components.gz`,
recompressed with `gzip -n` so the bytes are reproducible, so the kamaji
control-plane provider ships multi-arch too. keda and kuberture now name
the repository next to their pinned digest, so the gate can resolve
them; their rendered manifests do not change.

### Merge after

- #4552 builds the Talos installer, matchbox, Harbor and the Velero
KubeVirt plugin for arm64, and adds flux-plunger, keycloak-operator,
kilo and migration-controller to the root `build:` list. It replaces
#4507, #4515, #4525 and #4528.
- #4549 moves ingress-nginx, cozy-proxy, cozystack-scheduler and
keycloak-kms-proxy to their multi-arch releases, which are already
published.

The rest of the stack is merged: #4485, #4498, #4512, #4517, #4521 and
#4522 here, and the multi-arch PRs in
ingress-nginx-with-protobuf-exporter, cozy-proxy, cozystack-scheduler
and keycloak-kms-proxy.

### Verification

The bats suites pass: stitch, verify-multiarch, build-matrix,
common-envs, nightly-mirror and the release contracts. The first three
also pass under `hack/cozytest.sh` with dash. Each new test was red
before its implementation, and the verify-multiarch and stitch tests
each have a mutation that turns them red. I ran `verify-multiarch
--report` against main. It lists the first-party refs the stitch will
fix, plus the third-party and special cases above. The workflows have
not run yet. The arm64 job's tools and duration, the stitch against real
registries, and the audit are checked for the first time on the nightly
and on the next rc.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

Nothing under `hack/` is moved or renamed, and no make target changes
its default behaviour: `CACHE_TAG` and `MATRIX_ARCH` are opt-in. The
satellite repositories listed under "Merge after" are prerequisites, not
follow-ups this change forces on them.

### Release note

```release-note
ci(release): pre-release builds publish every image as an amd64 and arm64 multi-arch index, and a release fails if any image it ships or pulls in e2e lacks either architecture. Stable releases inherit the indexes through promotion.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Release candidates now build amd64 and arm64 images in parallel and
combine eligible images into verified multi-architecture indexes before
publication.
* A nightly arm64 image build is available for testing and supplies a
build cache for release-candidate builds.
* **Bug Fixes**
* End-to-end checks audit whether pulled images support both
architectures. Audit failures block prerelease checks, while stable
releases continue with a warning.
* End-to-end test artifacts now include collected image references and
multi-architecture audit results.
* **Documentation**
* Updated release and image guidance covers multi-architecture builds,
verification checks, and troubleshooting, including arm64 build and
stitching failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

v1.6.4

Toggle v1.6.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(release): promote v1.6.4-rc.1 -> v1.6.4 (#4533)

Promotes `v1.6.4-rc.1` to stable `v1.6.4` without rebuilding containers.
Their digests remain bit-for-bit what passed rc e2e; the tag-rewritten
packages tree is re-serialized as a temporary OCI candidate and pinned
here by digest. On merge, pull-requests-release.yaml verifies that
candidate against this tree before creating the write-once `v1.6.4` tag,
retagging the candidate and container digests to `v1.6.4` (+`:latest`
when this is the newest stable), publishing the stable cozy-installer
chart, and publishing the release. Do NOT squash-merge (decision B): the
stable tag must attach to a real merge commit.

⚠️ **RC e2e gate bypassed** — this promotion did not verify green full
e2e evidence for `v1.6.4-rc.1`.

ℹ️ E2E already ran against the immutable rc, so this promote PR does not
run E2E by default. A maintainer may add the `full-e2e` label to run the
full suite again.

✅ Includes `docs/changelogs/v1.6.4.md`, which finalize uses verbatim as
the published release body.

✅ Website docs PR opened/refreshed on `cozystack/website` (branch
`update-docs-v1.6.4`), generated from the `release-1.6.4` staging
branch. **Do NOT merge that PR until `v1.6.4` is published** — merging
it early flips the site's latest-version pointer to an unpublished
version and 404s its docs/API links (see the PR body).

api/apps/v1alpha1/v1.6.4

Toggle api/apps/v1alpha1/v1.6.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(release): promote v1.6.4-rc.1 -> v1.6.4 (#4533)

Promotes `v1.6.4-rc.1` to stable `v1.6.4` without rebuilding containers.
Their digests remain bit-for-bit what passed rc e2e; the tag-rewritten
packages tree is re-serialized as a temporary OCI candidate and pinned
here by digest. On merge, pull-requests-release.yaml verifies that
candidate against this tree before creating the write-once `v1.6.4` tag,
retagging the candidate and container digests to `v1.6.4` (+`:latest`
when this is the newest stable), publishing the stable cozy-installer
chart, and publishing the release. Do NOT squash-merge (decision B): the
stable tag must attach to a real merge commit.

⚠️ **RC e2e gate bypassed** — this promotion did not verify green full
e2e evidence for `v1.6.4-rc.1`.

ℹ️ E2E already ran against the immutable rc, so this promote PR does not
run E2E by default. A maintainer may add the `full-e2e` label to run the
full suite again.

✅ Includes `docs/changelogs/v1.6.4.md`, which finalize uses verbatim as
the published release body.

✅ Website docs PR opened/refreshed on `cozystack/website` (branch
`update-docs-v1.6.4`), generated from the `release-1.6.4` staging
branch. **Do NOT merge that PR until `v1.6.4` is published** — merging
it early flips the site's latest-version pointer to an unpublished
version and 404s its docs/API links (see the PR body).