`--cache-to type=inline` only exports the final stage. 25 of 38 Dockerfiles are multistage, so the expensive `builder` stages (Go/Node compiles) were never cached even with a warm tag. Switch every image to a shared mode=max registry cache.
- New `cache-args` macro (hack/common-envs.mk) emits `--cache-from` always and `--cache-to … mode=max` only when WRITE_CACHE=1, so PR builds stay read-only and concurrent PRs never race on the cache ref (the 409 class #2711 fixed for tags). oci-mediatypes/image-manifest keep the cache manifest portable across registries.
- Cache ref is CACHE_REGISTRY/<img>:buildcache, co-located with the build registry (CACHE_REGISTRY now defaults to $(REGISTRY)).
- New build-main.yaml warms :buildcache on every push to main (WRITE_CACHE=1), serialized via concurrency.
All 31 package image recipes converted from the inline cache-from/cache-to pair to `$(call cache-args,…)`; ubuntu-container-disk keeps a per-k8s-version cache tag. Verified with `make -n image` across all packages in both PR (read-only) and main (mode=max write) contexts.
Part of #2937.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
PR #2711 switched PR builds to push only :pr-<N>-<sha> tags (PUBLISH_FLOATING=0) to stop concurrent-push 409 conflicts, but left --cache-from pointing at $(REGISTRY)/<img>:latest. PR builds set REGISTRY to the per-CI registry (iad.ocir.io) and never publish :latest there, so every PR build's registry cache lookup 404s and rebuilds cold.
Add a CACHE_REGISTRY knob (default ghcr.io/cozystack/cozystack, where release builds do publish :latest) and point every --cache-from at it. Push targets ($(REGISTRY)) and the unique per-PR tags are unchanged, so the #2711 anti-conflict behaviour is preserved while PR builds regain a warm cache from the last release.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
The vendored COSI controller (v0.2.2) sets only BucketClaim.status.bucketName
in the dynamic-provisioning path and hardcodes bucketReady=false, never
re-reading the Bucket afterwards. The controller does not watch Buckets, so the
readiness transition the sidecar performs (false->true) is never reflected on
the BucketClaim: bucketReady stays false forever and BucketAccess is never
granted, leaving provisioned buckets without credentials.
Re-read the live Bucket after create and propagate its readiness, so the
periodic resync converges the BucketClaim to ready. This matches the behavior
the rewritten upstream controller already has on its main branch.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Every package Makefile tagged images via `settag` which, on a non-release
commit, collapsed to `:latest`. Concurrent PR builds therefore raced on every
image's `:latest` manifest in the OCIR registry. Two outliers (metallb,
redis-operator) used hardcoded version tags and collided across PRs even when
`settag` would not have.
Replace `settag` and the `TAG=latest` fallback with an `image-tags` macro
driven by three env vars:
- IMAGE_TAG — build-unique tag, always pushed
- PUBLISH_VERSIONED — also push :<component-version>
- PUBLISH_FLOATING — also push :latest
PR CI sets IMAGE_TAG=pr-<N>-<sha> with both PUBLISH_* off, so every push is
unique across runs. Release CI sets IMAGE_TAG=<git-tag> with both PUBLISH_*
on, preserving the previous release output and adding a uniform :<git-tag>
tag across every image. Local builds default to IMAGE_TAG=dev with PUSH=0
already off.
Image consumers reference digests pinned into values.yaml by each Makefile,
so the tag is decorative for cluster-side pulls; the build-unique tag is
sufficient for E2E.
Drops the redundant `:<component-version>-<git-tag>` form (cilium, linstor,
matchbox, ubuntu-container-disk, kubevirt-*, cluster-autoscaler) — nothing
in the repo or downstream values.yaml consumed it. The same information is
preserved via the new uniform `:<git-tag>` plus the existing
`:<component-version>` on release.
ubuntu-container-disk builds a separate image per Kubernetes version in a
loop. Switched its primary tag to `:<k8s-ver>-<IMAGE_TAG>` so loop
iterations within a single build do not push to the same tag.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
## What this PR does
Carries an upstream-bound patch against COSI v0.2.2's BucketAccess
sidecar reconciler so it survives the optimistic-concurrency race with
the central Bucket reconciler running in the same process.
In `sidecar/pkg/bucketaccess/bucketaccess_controller.go`, the `Add` path
does:
```go
bucket, _ := buckets().Get(...)
// ...
if controllerutil.AddFinalizer(bucket, BABucketFinalizer) {
buckets().Update(ctx, bucket, ...) // <-- 409 here
}
```
Between `Get` and `Update` the Bucket reconciler in the same binary can
mutate the object and bump `resourceVersion`, producing:
```
Operation cannot be fulfilled on buckets.objectstorage.k8s.io "bucket-...":
the object has been modified; please apply your changes to the latest
version and try again
```
surfaced to users as a `FailedGrantAccess` event on the BucketAccess.
This patch wraps the Bucket finalizer add in
`retry.RetryOnConflict(retry.DefaultRetry, ...)` and re-`Get`s the
Bucket inside the closure so each retry mutates the freshest version.
Patch is held as `91-bucketaccess-conflict-retry.diff` and consumed at
image build time (re-introduces `git` to the source stage and the `COPY
patches /patches` + `git apply /patches/*.diff` steps that existed
before `c29d501b` dropped them when 89/90 were upstreamed). The
convention is identical: drop the local patch the moment the upstream PR
merges and ships in a tagged release.
### Release note
~~~release-note
[objectstorage-controller] Carry a patch that retries on Bucket update
conflict during BucketAccess reconcile, eliminating the "object has been
modified" FailedGrantAccess event seen in CI.
~~~
## Test plan
- [x] `make image` for `system/objectstorage-controller` and verify
`values.yaml` picks up the new digest.
- [x] Re-run the cozystack-e2e suite that emitted the
`FailedGrantAccess: ... object has been modified` event on
`tenant-test/BucketAccess/bucket-test-admin` and confirm it no longer
fires.
- [ ] Verify `kubectl describe bucketaccess` reports
`AccessGranted=true` on first reconcile, no requeue from the conflict
path.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced bucket access update reliability with improved conflict
handling during concurrent operations. The system now automatically
retries operations and refetches data to prevent update conflicts.
* **Chores**
* Improved Docker build process with automatic patch application support
for source customization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Upstream COSI v0.2.2's BucketAccess reconciler does a Get->mutate->Update
on the parent Bucket and surfaces "Operation cannot be fulfilled ... the
object has been modified" as a FailedGrantAccess event when it races
against the Bucket reconciler in the same controller process. Wrap the
mutation in retry.RetryOnConflict so the reconcile loop refreshes and
retries instead of leaking the conflict to users.
Carried as 91-bucketaccess-conflict-retry.diff until upstreamed
(cf. 89-reconciliation.diff and 90-bucket-name.diff, both dropped
in c29d501b once merged upstream).
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Replace commit hash with v0.2.2 tag for better readability.
GitHub archive URLs work with tags identically.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Update COSI controller/sidecar from commit c2f6e65 to v0.2.2
(f75d475) and remove two patches that have been merged upstream:
- 89-reconciliation.diff: fix reconciliation logic for existing
and deleted objects (PR #89)
- 90-bucket-name.diff: prefix bucket names with bucket- using
UID only (PR #90)
Both patches were contributed by kvaps and included in the
upstream v0.2.2 release (2025-12-08).
Also remove git from Dockerfile dependencies as it was only
needed for applying patches.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Move common-envs.mk and package.mk from scripts/ to hack/ directory.
Update all Makefile includes to use new paths. Remove unused
issue-flux-certificates.sh script.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Many resources created as part of managed apps in cozystack (pods,
secrets, etc) do not carry predictable labels that unambiguously
indicate which app originally triggered their creation. Some resources
are managed by controllers and other custom resources and this
indirection can lead to loss of information. Other controllers sometimes
simply do not allow setting labels on controlled resources and the
latter do not inherit labels from the owner. This patch implements a
webhook that sidesteps this problem with a universal solution. On
creation of a pod/secret/PVC etc it walks through the owner references
until a HelmRelease is found that can be matched with a managed app
dynamically registered in the Cozystack API server. The pod is mutated
with labels identifying the managed app.
```release-note
[cozystack-controller] Add a mutating webhook to identify the Cozystack
managed app that ultimately owns low-level resources created in the
cluster and label these resources with a reference to said app.
```
Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>