Skip to content

refactor(build): mode=max registry cache with a main-only warmer - #2938

Closed
myasnikovdaniil wants to merge 3 commits into
fix/cilium-endpoint-leak-e2e-healerfrom
ci/build-cache-mode-max
Closed

refactor(build): mode=max registry cache with a main-only warmer#2938
myasnikovdaniil wants to merge 3 commits into
fix/cilium-endpoint-leak-e2e-healerfrom
ci/build-cache-mode-max

Conversation

@myasnikovdaniil

@myasnikovdaniil myasnikovdaniil commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What this PR does

--cache-to type=inline only exports the final stage, so the expensive builder stages of our 25 multistage Dockerfiles (Go/Node compiles) were never cached even with a warm tag. This switches all images to a shared mode=max registry cache:

  • New cache-args macro (hack/common-envs.mk): emits --cache-from always; --cache-to … mode=max only when WRITE_CACHE=1 → PR builds stay read-only, so concurrent PRs never race on the cache ref (the 409 class refactor(build): standardize image tagging to fix concurrent PR push conflicts #2711 fixed for image tags). oci-mediatypes=true,image-manifest=true keep the cache manifest portable across registries.
  • Cache ref is CACHE_REGISTRY/<img>:buildcache, co-located with the build registry (CACHE_REGISTRY defaults to $(REGISTRY)).
  • New build-main.yaml warms :buildcache on every push to main (serialized via concurrency), so PR builds start hot.
  • All 31 package image recipes converted from the --cache-from/--cache-to type=inline pair to $(call cache-args,…). ubuntu-container-disk keeps a per-k8s-version cache tag (:<ver>-buildcache).

Verified with make -n image across all 31 packages in both PR (WRITE_CACHE=0, read-only) and main (WRITE_CACHE=1, mode=max write) contexts — push --tag targets are unchanged. CI itself validates that OCIR accepts the mode=max cache manifest.

Note: the first build-main run is fully cold (no :buildcache yet) and seeds the cache; subsequent PR builds warm-start from it.

Release note

refactor(build): CI image builds now use a mode=max registry cache (caching all multistage stages, not just the final one), warmed by a serialized build-on-main workflow. PR builds read the cache and never write it, so concurrent builds no longer race or rebuild cold.

Part of #2937.

Summary by CodeRabbit

  • New Features

    • Added a self-healing e2e mechanism for Cilium endpoint leaks via an in-cluster loop/job and test-time wiring.
    • Extended SeaweedFS COSI chart to support separate lock buckets and read/write access classes.
  • Bug Fixes / Improvements

    • Updated Kubernetes health probing for core components with a dedicated startup probe.
    • Adjusted e2e bucket port-forward readiness to use loopback and aligned client traffic accordingly.
    • Reduced SeaweedFS master volume size limit to improve test stability.
  • Chores

    • Added a main-branch cache-warming workflow and standardized Docker Buildx cache argument generation, including configurable cache writing.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request optimizes the CI build process by upgrading the Docker build cache strategy. By switching to a mode=max registry cache, the system can now cache intermediate stages of multistage Dockerfiles, which were previously ignored. The implementation introduces a centralized macro for cache management and enforces read-only cache access for PR builds to eliminate concurrency issues, while main branch builds handle the cache warming process.

Highlights

  • Registry Cache Refactor: Migrated from --cache-to type=inline to a shared mode=max registry cache, enabling caching of all multistage build layers.
  • Build Performance: Introduced a cache-args macro to standardize cache configuration across all 31 package image recipes, ensuring consistent cache usage.
  • Concurrency and Race Conditions: Implemented a WRITE_CACHE flag to make PR builds read-only, preventing race conditions on the cache manifest during concurrent builds.
  • Cache Warming: Added a serialized build-main.yaml workflow to warm the :buildcache on the main branch, significantly speeding up PR build start times.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/build-main.yaml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot Bot added area/build Issues or PRs related to image build infrastructure, multi-arch support area/ci Issues or PRs related to CI workflows, GitHub Actions, automation labels Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a shared build cache macro and WRITE_CACHE toggle to hack/common-envs.mk, introduces a build-main.yaml workflow that warms registry cache on pushes to main, refactors ~30 package Makefiles to use the centralized cache macro, deploys in-cluster Cilium endpoint leak self-healing, and adjusts SeaweedFS and e2e test configurations.

Changes

Build cache centralization and CI warming

Layer / File(s) Summary
cache-args macro and WRITE_CACHE variable in hack/common-envs.mk
hack/common-envs.mk
Updates CACHE_REGISTRY to default to $(REGISTRY), adds WRITE_CACHE ?= 0, and defines cache-args macro to emit --cache-from registry reads always and conditional --cache-to with mode=max only when writes are enabled.
build-main.yaml workflow for cache warming
.github/workflows/build-main.yaml
Adds GitHub Actions workflow for main-branch pushes that authenticates to OCIR, sets up Buildx, and runs make build with WRITE_CACHE=1 to write registry cache while disabling image publishing.
Package Makefiles refactored to use cache-args
packages/apps/*/Makefile, packages/core/*/Makefile, packages/extra/*/Makefile, packages/system/*/Makefile
Updates ~30 image build targets to replace explicit --cache-from and --cache-to type=inline flags with $(call cache-args,<image>) macro; flux-plunger and kubeovn-plunger also add conditional --builder support.

E2E test resilience and self-healing

Layer / File(s) Summary
Bucket e2e test port-forwarding fix
hack/e2e-apps/bucket.bats
Refactors SeaweedFS S3 port-forward to start directly in test shell (backgrounded) instead of via bash -c, and changes readiness probe and mc aliases from localhost to 127.0.0.1 loopback address.
Cilium endpoint leak self-healing shell script
hack/e2e-cilium-endpoint-leak-healer.sh
Introduces continuous in-cluster loop detecting FailedCreatePodSandBox events with "IP already in use" errors, identifying orphaned Cilium endpoints via cilium-dbg endpoint get, verifying ownership to avoid false evictions, and disconnecting confirmed orphans with configurable polling interval and safety gates.
Cilium healer Job and e2e install integration
hack/e2e-cilium-leak-healer.yaml, hack/e2e-install-cozystack.bats
Adds Kubernetes Job manifest with ServiceAccount and RBAC for event/pod/exec access; integrates healer into e2e install via setup_file() hook creating ConfigMap and applying Job, and teardown_file() hook logging healer activity.

Application and test configuration updates

Layer / File(s) Summary
CAPI provider component startup probe
packages/system/capi-providers-core/files/core-components.yaml
Adds startupProbe with HTTP GET to /healthz on healthz port, failureThreshold: 30, and periodSeconds: 10 for graceful initialization handling.
SeaweedFS Helm COSI and S3 template updates
packages/system/seaweedfs/charts/seaweedfs/templates/cosi/cosi-bucket-class.yaml, packages/system/seaweedfs/charts/seaweedfs/templates/s3/s3-service.yaml, packages/system/seaweedfs/values.yaml
Adds COSI BucketClass for object lock bucket, extends BucketAccessClass with read-only variant, changes S3 Service name template to {{ .Values.seaweedfs.name }}-s3, and reduces master volumeSizeLimitMB from 30000 to 1000.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • cozystack/cozystack#2834: Overlaps on SeaweedFS Helm template changes in charts/seaweedfs/templates/cosi/cosi-bucket-class.yaml, templates/s3/s3-service.yaml, and values.yaml.
  • cozystack/cozystack#2855: Also modifies hack/common-envs.mk CACHE_REGISTRY and related Makefile cache behavior, though main PR further refactors into centralized cache-args macro with WRITE_CACHE toggle.

Suggested labels

size/XL, area/ci, area/infrastructure

Suggested reviewers

  • kvaps
  • lllamnyp
  • lexfrei
  • androndo
  • IvanHunters

Poem

🐇 Behold! A cache warmer hops upon the main branch's stage,
With registry glow and make-driven gauge.
And lo, a healer script guards the Cilium pen,
Preventing pod sandbox sorrows again and again.
One macro to rule them all—hooray for unified build-time zen! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: refactoring the build caching strategy to use mode=max registry cache with a dedicated main-branch warmer workflow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/build-cache-mode-max

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Trivy (0.69.3)

Trivy execution timed out


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Docker buildx caching mechanism across all packages by introducing a centralized cache-args macro in hack/common-envs.mk to dynamically generate cache flags, replacing hardcoded inline cache configurations in various package Makefiles. It also introduces a WRITE_CACHE variable to control cache writes. The feedback suggests simplifying the macro definition in hack/common-envs.mk by using the GNU Make $(or ...) function instead of nested $(if ...) statements to improve readability.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread hack/common-envs.mk
# $(comma) escapes the literal commas in the --cache-to value so make does not
# mis-parse them as $(if ...) argument separators.
comma := ,
cache-args = --cache-from type=registry,ref=$(CACHE_REGISTRY)/$(1):$(if $(2),$(2),buildcache)$(if $(filter 1,$(WRITE_CACHE)), --cache-to type=registry$(comma)ref=$(CACHE_REGISTRY)/$(1):$(if $(2),$(2),buildcache)$(comma)mode=max$(comma)oci-mediatypes=true$(comma)image-manifest=true)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The '$(if $(2),$(2),buildcache)' expression is repeated twice in the macro definition. We can simplify this and improve readability by using the built-in GNU Make '$(or ...)' function, which returns the first non-empty argument.

cache-args = --cache-from type=registry,ref=$(CACHE_REGISTRY)/$(1):$(or $(2),buildcache)$(if $(filter 1,$(WRITE_CACHE)), --cache-to type=registry$(comma)ref=$(CACHE_REGISTRY)/$(1):$(or $(2),buildcache)$(comma)mode=max$(comma)oci-mediatypes=true$(comma)image-manifest=true)

@github-actions github-actions Bot added kind/cleanup Categorizes issue or PR as related to cleanup of code, process, or technical debt size/L This PR changes 100-499 lines, ignoring generated files labels Jun 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/build-main.yaml (1)

37-41: ⚡ Quick win

Consider pinning action to SHA and disabling credential persistence.

The checkout action uses a version tag (v4) which can be moved. Pinning to a specific commit SHA provides stronger supply-chain security. Additionally, setting persist-credentials: false is good security hygiene to prevent Git credentials from being left in the workspace.

🔒 Suggested changes
       - name: Checkout code
-        uses: actions/checkout@v4
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-main.yaml around lines 37 - 41, The checkout action
in the workflow file is using a version tag (v4) which can be moved, reducing
supply chain security. Replace the `actions/checkout@v4` reference with a pin to
a specific commit SHA (for example, the full SHA of the v4 release).
Additionally, add `persist-credentials: false` to the `with:` section to prevent
Git credentials from being left in the workspace after the action completes,
which is a security best practice.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build-main.yaml:
- Around line 49-54: In the "Login to OCIR" step in the workflow file, replace
the `docker/login-action@v3` version reference with a specific commit SHA to
provide stronger supply-chain guarantees. Pin the action to the latest available
release (v4.2.0 or newer) by updating the `uses` field to reference the exact
commit SHA corresponding to that release instead of the major version tag.

---

Nitpick comments:
In @.github/workflows/build-main.yaml:
- Around line 37-41: The checkout action in the workflow file is using a version
tag (v4) which can be moved, reducing supply chain security. Replace the
`actions/checkout@v4` reference with a pin to a specific commit SHA (for
example, the full SHA of the v4 release). Additionally, add
`persist-credentials: false` to the `with:` section to prevent Git credentials
from being left in the workspace after the action completes, which is a security
best practice.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6fb888db-8bbd-47eb-bef7-185311702590

📥 Commits

Reviewing files that changed from the base of the PR and between 39f3ac7 and 11843de.

📒 Files selected for processing (33)
  • .github/workflows/build-main.yaml
  • hack/common-envs.mk
  • packages/apps/clickhouse/Makefile
  • packages/apps/http-cache/Makefile
  • packages/apps/kubernetes/Makefile
  • packages/apps/mariadb/Makefile
  • packages/core/installer/Makefile
  • packages/core/platform/Makefile
  • packages/core/talos/Makefile
  • packages/core/testing/Makefile
  • packages/extra/monitoring/Makefile
  • packages/system/backup-controller/Makefile
  • packages/system/backupstrategy-controller/Makefile
  • packages/system/bucket/Makefile
  • packages/system/cilium/Makefile
  • packages/system/cozystack-api/Makefile
  • packages/system/cozystack-controller/Makefile
  • packages/system/dashboard/Makefile
  • packages/system/flux-plunger/Makefile
  • packages/system/grafana-operator/Makefile
  • packages/system/kamaji/Makefile
  • packages/system/keycloak-operator/Makefile
  • packages/system/kilo/Makefile
  • packages/system/kubeovn-plunger/Makefile
  • packages/system/kubeovn-webhook/Makefile
  • packages/system/lineage-controller-webhook/Makefile
  • packages/system/linstor-gui/Makefile
  • packages/system/linstor/Makefile
  • packages/system/metallb/Makefile
  • packages/system/monitoring/Makefile
  • packages/system/multus/Makefile
  • packages/system/objectstorage-controller/Makefile
  • packages/system/redis-operator/Makefile

Comment on lines +49 to +54
- name: Login to OCIR
uses: docker/login-action@v3
with:
username: ${{ secrets.OCIR_USER }}
password: ${{ secrets.OCIR_TOKEN }}
registry: iad.ocir.io

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

docker/login-action latest release version 2025

💡 Result:

In 2025, the docker/login-action project released several versions [1]. The versions released during that calendar year included: - v3.4.0 (released March 14, 2025) [2] - v3.5.0 (released August 4, 2025) [3] Following these, the project continued development into 2026, with version v4.1.0 released on April 2, 2026 [4], and v4.2.0 released on May 22, 2026 [5]. Version 4.x represents the latest major release branch as of June 2026 [6].

Citations:


🏁 Script executed:

#!/bin/bash
# Fetch docker/login-action releases to get exact SHAs for specific versions
curl -s https://api.github.com/repos/docker/login-action/releases | \
  python3 - <<'PY'
import json
import sys

data = json.load(sys.stdin)

# Extract relevant versions
versions = {}
for release in data:
    tag = release['tag_name']
    if tag in ['v3.4.0', 'v3.5.0', 'v4.1.0', 'v4.2.0']:
        versions[tag] = {
            'sha': release.get('target_commitish', 'N/A'),
            'published': release['published_at']
        }

# Print in order
for version in ['v3.4.0', 'v3.5.0', 'v4.1.0', 'v4.2.0']:
    if version in versions:
        print(f"{version}: SHA={versions[version]['sha']}, Published={versions[version]['published']}")
PY

Repository: cozystack/cozystack

Length of output: 784


🌐 Web query:

docker/login-action v3.4.0 commit SHA github

💡 Result:

The GitHub Action docker/login-action version v3.4.0 is associated with the commit SHA 74a5d14 [1][2]. This release was published on March 14, 2025 [3][1].

Citations:


🌐 Web query:

docker/login-action v4.2.0 latest version 2026

💡 Result:

As of June 16, 2026, the latest version of the docker/login-action is v4.2.0, which was released on May 22, 2026 [1]. This release included several dependency updates, such as bumping @actions/core to 3.0.1, @docker/actions-toolkit to 0.90.0, and various AWS SDK packages [1].

Citations:


Pin docker/login-action to a specific SHA.

Similar to the checkout action, pinning to a commit SHA provides stronger supply-chain guarantees.

Update the suggested version to the latest available release (v4.2.0 or newer) rather than the outdated v3.4.0 referenced in the diff.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 50-50: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-main.yaml around lines 49 - 54, In the "Login to
OCIR" step in the workflow file, replace the `docker/login-action@v3` version
reference with a specific commit SHA to provide stronger supply-chain
guarantees. Pin the action to the latest available release (v4.2.0 or newer) by
updating the `uses` field to reference the exact commit SHA corresponding to
that release instead of the major version tag.

Source: Linters/SAST tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/build-main.yaml (1)

39-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Drop the unused packages: write permission.

This workflow authenticates to OCIR with OCIR_USER/OCIR_TOKEN and sets REGISTRY to iad.ocir.io, so the GitHub token does not need package write access. Keep it to contents: read to reduce blast radius on the self-hosted runner.

🛡️ Proposed permission tightening
     permissions:
       contents: read
-      packages: write
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-main.yaml around lines 39 - 41, In the permissions
block of the build-main.yaml workflow, remove the line containing `packages:
write` since the workflow authenticates directly to OCIR using OCIR_USER and
OCIR_TOKEN environment variables with REGISTRY set to iad.ocir.io. The GitHub
token only needs `contents: read` permission for this workflow, which reduces
the potential blast radius on the self-hosted runner. Keep only the `contents:
read` permission line and delete the `packages: write` line.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/build-main.yaml:
- Line 70: Replace the mutable version tag `@v3` with a pinned commit SHA in the
docker/setup-buildx-action action usage on line 70. Change `uses:
docker/setup-buildx-action@v3` to use a specific commit SHA (e.g., `uses:
docker/setup-buildx-action@<commit-sha>`) to align with the repository's
unpinned-action policy, matching the pattern already applied to the
docker/login-action step elsewhere in the workflow file.

---

Outside diff comments:
In @.github/workflows/build-main.yaml:
- Around line 39-41: In the permissions block of the build-main.yaml workflow,
remove the line containing `packages: write` since the workflow authenticates
directly to OCIR using OCIR_USER and OCIR_TOKEN environment variables with
REGISTRY set to iad.ocir.io. The GitHub token only needs `contents: read`
permission for this workflow, which reduces the potential blast radius on the
self-hosted runner. Keep only the `contents: read` permission line and delete
the `packages: write` line.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e4efb632-7943-4573-bc60-356892d385e5

📥 Commits

Reviewing files that changed from the base of the PR and between 11843de and 478509d.

📒 Files selected for processing (3)
  • .github/workflows/build-main.yaml
  • packages/system/flux-plunger/Makefile
  • packages/system/kubeovn-plunger/Makefile
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/system/flux-plunger/Makefile

# isolated buildkit so it never contends with PR builds on the shared one.
- name: Set up Buildx (docker-container driver)
id: buildx
uses: docker/setup-buildx-action@v3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find docker/setup-buildx-action references that are still pinned by mutable tags.
# Expectation after the fix: no matches.
rg -nP 'uses:\s+docker/setup-buildx-action@v[0-9]+(\b|$)' .github/workflows/build-main.yaml

Repository: cozystack/cozystack

Length of output: 110


🏁 Script executed:

cat -n .github/workflows/build-main.yaml | sed -n '60,80p'

Repository: cozystack/cozystack

Length of output: 1155


🏁 Script executed:

rg -nP 'uses:\s+docker/\w+@v[0-9]+(\b|$)' .github/workflows/build-main.yaml

Repository: cozystack/cozystack

Length of output: 45


🏁 Script executed:

rg -n 'uses:\s+docker/' .github/workflows/build-main.yaml

Repository: cozystack/cozystack

Length of output: 150


Pin docker/setup-buildx-action to a commit SHA.

Line 70 uses a mutable version tag @v3. Pin this action to a vetted commit SHA, matching the repository's unpinned-action policy; the existing prior comment already covers the docker/login-action step.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 70-70: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-main.yaml at line 70, Replace the mutable version
tag `@v3` with a pinned commit SHA in the docker/setup-buildx-action action
usage on line 70. Change `uses: docker/setup-buildx-action@v3` to use a specific
commit SHA (e.g., `uses: docker/setup-buildx-action@<commit-sha>`) to align with
the repository's unpinned-action policy, matching the pattern already applied to
the docker/login-action step elsewhere in the workflow file.

Source: Linters/SAST tools

`--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>
`--cache-to type=registry,mode=max` is unsupported on the host's default embedded docker driver unless the daemon runs the containerd image store, so on a classic store the warmer would fail to export any cache. Build the warmer on a docker-container buildx builder, which supports mode=max regardless of the host image store.

It also gives the warmer its own buildkit (separate bbolt), so it never contends with PR builds on the shared embedded buildkit.

Part of #2937.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
These two recipes spell out their buildx flags instead of using $(BUILDX_ARGS), so they never received --builder and ran on the default docker driver. After the mode=max migration that became a hard failure -- "Cache export is not supported for the docker driver" -- since the embedded docker driver cannot export a registry cache. Add the same conditional --builder flag $(BUILDX_ARGS) carries, so WRITE_CACHE=1 builds route to the docker-container builder; an empty BUILDER still emits no flag for local builds.

Part of #2937.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@myasnikovdaniil
myasnikovdaniil force-pushed the ci/build-cache-mode-max branch from 478509d to e1781ac Compare June 17, 2026 16:03
myasnikovdaniil added a commit that referenced this pull request Jun 17, 2026
The shared self-hosted runner runs 4 agents against one dockerd-embedded buildkit; concurrent build jobs serialize on buildkit's single-writer bbolt cache lock + exporter mutex and stall to the 30-min timeout (proven via a live SIGUSR1 goroutine dump of a hung build). Run the Build job on a small ephemeral oracle-vm shape (4cpu/16gb x86-64) instead, so each build gets its own VM and its own buildkit -- the cross-job contention is severed by construction.

make build is serial (one image at a time), so the small shape suffices; it relies on the warm mode=max cache (#2938) to stay under the 30-min wall. The `debug` label still routes to self-hosted for the breakpoint path.

Phase 0.5 of #2937.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@github-actions github-actions Bot added size/XL This PR changes 500-999 lines, ignoring generated files and removed size/L This PR changes 100-499 lines, ignoring generated files labels Jun 17, 2026
@myasnikovdaniil
myasnikovdaniil changed the base branch from main to fix/cilium-endpoint-leak-e2e-healer June 17, 2026 16:03
@myasnikovdaniil
myasnikovdaniil marked this pull request as draft June 19, 2026 08:46
myasnikovdaniil added a commit that referenced this pull request Jun 22, 2026
## What

Consolidated landing branch for a set of interdependent platform/CI
stabilization fixes. It began as the source PRs in the table below (in
dependency order) and has since grown with review-driven fixes and a few
production-behavior changes — the full current inventory is under
**Scope** below. Landing them as one unit lets CI run against the real
combined state instead of a fragile bottom-up merge train.

## Source PRs (dependency order)

| # | Commit | Source PR | Addresses |
|---|--------|-----------|-----------|
| 1 | fix(capi): startupProbe on capi-controller-manager | #2946 | capi
crashloop during cert provisioning |
| 2 | test(e2e): bucket.bats port-forward + S3 client reliability |
#2944 | flaky bucket test |
| 3 | fix(seaweedfs): restore -lock BucketClass, s3 svc name, drop
volumeSizeLimitMB | #2943 | missing bucket/access classes |
| 4 | test(e2e): in-cluster Cilium endpoint-leak healer (install + apps)
| #2874 | cilium "IP already in use" leak |
| 5 | refactor(build): mode=max registry cache + main-only warmer |
#2938 | build cache |
| 6 | ci(build): isolate each PR build on its own ephemeral runner VM |
#2939 | shared-buildkit contention |
| 7 | fix(e2e): LINSTOR post-install waits on a single 15m deadline |
#2928 | LINSTOR provisioning timeouts |
| 8 | test(metallb): assert digest-pinned image form, not version
literal | #2873 | brittle metallb assertion |

## Why consolidated

These form a dependency DAG (verified from CI logs): e.g. 2943 needs
2946, 2938 needs 2874, 2928 needs 2938/2939, 2873 needs 2928. Tested
bottom-up, each lower PR runs with none of the fixes above it and can't
go green alone. This branch carries all of them, so CI runs against the
real combined state.

## Verification status

CI is green on the latest head (`5653c30`): full-suite E2E passes
end-to-end and is reproducible (2 of 3 runs on this SHA green). The one
red run was a LINSTOR tie-breaker / DRBD-metadata infra flake on the
sandbox, unrelated to the diff — a different environmental subsystem
failed each run (details in the comments below). The earlier 3-hour
crust-gather snapshot hang is fixed in `5653c30`.

## Scope beyond the original 8

The branch has grown past the 8 source PRs above with review-driven
fixes and a few production-behavior changes. For reviewer transparency,
the full set:

**Review fixes (@lexfrei review):**
- **B1 (blocker)** — `8f41910` converts the SeaweedFS
`-lock`/`-readonly` BucketClasses and the s3 service-name override into
`patches/`, wired into `make update`, so a re-vendor no longer drops
them.
- **FU1** — `cc99230` grants the cilium leak-healer `delete` on pods
(both delete remedies were RBAC-forbidden).
- **FU3** — `014de3f` adds a unit test for the HelmRelease update
conflict-retry path.
- **FU4** — `6deddc6` makes the leak-healer refuse a disconnect for any
non-terminal owner phase, not just `Running`.
- **FU7** — `f3914d2` sets `persist-credentials: false` on the
build-cache checkout (SHA-pinning is handled repo-wide in #2849).

**Production-behavior changes (not in the table above):**
- VPA `updateMode: Auto → Initial` for etcd (`6e9ff90`) and monitoring
(`0997105`), plus `vmselect`/`vmstorage` `minAllowed` floors — stops
install-time eviction churn.
- cozystack-api: `retry.RetryOnConflict` on the Application→HelmRelease
update path (`728f676`).

**E2E robustness follow-ups:** per-test crust-gather snapshots
(`50e5f94`), EtcdBackupSchedule wait (`763b85e`), tenant-node
single-deadline wait (`9e43d45`), harbor BucketClaim 10m budget
(`d7f244f`), tenant API via LoadBalancer (`9beda4e`), crust-gather pin
(`95f42aa`).

**Not addressed (by decision):** FU2 — the s3 Service keeps
`seaweedfs.name`-based naming via patch (rendered output unchanged;
cozystack renders `fullname == seaweedfs`, so it matches the
`componentName`/`fullname` siblings in practice). FU6 — fork PR build
push is handled by the existing mirror-to-same-repo-branch workflow.

## Relates to

#2946 #2944 #2943 #2874 #2938 #2939 #2928 #2873 — if this lands, those
can be closed; otherwise they remain the granular per-PR review path.


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

* **New Features**
  * Added CI build cache warming for main branch builds.
* Added a best-effort in-cluster Cilium endpoint self-heal watchdog for
e2e installs.
* Extended SeaweedFS COSI with object-lock support plus separate
readonly access.

* **Improvements**
* Reduced e2e install flakiness with a shared readiness deadline, safer
waits, and improved cleanup/diagnostics capture.
* Prevented install-time churn by switching VPA update mode to
**Initial**.
  * Added container startup probes and updated SeaweedFS volume sizing.

* **Tests**
* Improved e2e robustness (etcd backup schedule waiting, digest-pinned
image checks, and corrected S3 port-forwarding).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
pull Bot pushed a commit to medampudi/cozystack that referenced this pull request Jun 22, 2026
…ystack#2938)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@myasnikovdaniil

Copy link
Copy Markdown
Contributor Author

Landed on main via #2948 (commit d3958c5b, merged 2026-06-22) — the consolidation batch carried this PR's commit verbatim, so the cache-args macro in hack/common-envs.mk (:buildcache + mode=max, write-gated on WRITE_CACHE=1) and .github/workflows/build-main.yaml (the main-only warmer) are now on main. Closing as superseded; Phase 1 of #2937 is checked off there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build Issues or PRs related to image build infrastructure, multi-arch support area/ci Issues or PRs related to CI workflows, GitHub Actions, automation kind/cleanup Categorizes issue or PR as related to cleanup of code, process, or technical debt size/XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant