mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-08 21:14:56 +09:00
08dca137debdbe9943bc78da67c3d5ca7ebbf62b
218
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fef9e76505 |
ci(renovate): pin base images and GitHub Actions to digests (#3025)
## What this PR does Raises OpenSSF Scorecard **Pinned-Dependencies** (currently **1/10**) by having Renovate manage and pin container base images and GitHub Actions to immutable digests. [PR #2849](https://github.com/cozystack/cozystack/pull/2849) SHA-pinned actions in 13 workflows, but the Scorecard check also scores **container base images** — 58 unpinned `FROM` lines across **27 distinct images** — which dominate the score and keep it at 1/10. #2849 also left `build-main.yaml` and `release-e2e.yaml` actions unpinned, and nothing in the Renovate config kept the newly-added action SHAs updated (they were set to rot). ### Changes - **`.github/renovate.json`** - Add `dockerfile` and `github-actions` to `enabledManagers` (was `gomod`-only). - `pinDigests: true` for both managers — Renovate opens the initial "pin to `@sha256:`" PR (including the two workflows #2849 missed) and keeps digests fresh thereafter. - Batch the initial pin + all digest-only refreshes into a **single weekly PR** (`matchUpdateTypes: ["digest", "pinDigest"]`, scheduled Monday). Frequently-rebuilt bases (alpine, debian, golang, distroless) would otherwise trickle in one rebuild-triggering PR each and load the shared CI runner. Real tag bumps (major/minor/patch) are intentionally excluded from the group so they get individual review. - Existing `do-not-merge/hold` label + `automerge: false` are unchanged, so every PR still requires a manual merge. - **`packages/system/bucket/images/s3manager/Dockerfile`** — pin floating tags to concrete versions so digest tracking doesn't churn endlessly: `golang:1` → `golang:1.26`, `alpine:latest` → `alpine:3.24`. ### Notes - The bulk digest pin of the 27 images is left to Renovate's first run (one grouped PR) rather than hand-edited here, keeping this PR to the config + tag-hygiene prerequisites. - Expected effect once the follow-up pin PR merges: Pinned-Dependencies **1 → ~7–8**. The remaining `downloadThenRun` / pip / npm items cap it below 10. ### Release note ```release-note ci(renovate): enable Renovate digest pinning for Dockerfile base images and GitHub Actions to improve the OpenSSF Scorecard Pinned-Dependencies score ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved automated dependency management for container images and GitHub Actions, including clearer update grouping and digest pinning. * Updated container base images to newer, fixed versions for more predictable builds and deployments. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0f1cc548b5 |
fix(objectstorage-controller): converge BucketClaim readiness and speed up COSI provisioner failover (#3034)
## What this PR does Fixes two failure modes in the COSI control plane built from upstream container-object-storage-interface v0.2.2, both carried as image patches. **BucketClaim never converges to ready (#3032).** The controller does not watch Bucket objects, and the generic controller drops no-op resync deltas, so a BucketClaim whose backend Bucket flips to ready *after* the first reconcile stayed `bucketReady=false` indefinitely — BucketAccess was never granted and the consuming app (bucket, harbor) got no credentials. The existing re-read of the live Bucket only ran during a reconcile that nothing re-triggered. The controller now returns an error while the Bucket is not ready, forcing a rate-limited requeue that re-reads the Bucket until its readiness propagates, so the claim converges deterministically instead of racing the async sidecar. **Slow provisioner failover on pod recreate (part of #2429).** The controller and the per-driver sidecar run single-replica, so leader election adds no availability — only failover latency. The upstream 150s lease made a recreated provisioner pod stall reconciliation for up to ~150s. The lease is lowered to the standard Kubernetes values (15s/10s/2s), so a recreated pod resumes in ~15s. The stale unix-socket CrashLoop in #2429 was already resolved by the seaweedfs-cosi-driver v0.3.1 self-heal; the silent "Bucket ready with no backend bucket" finding on that issue is a separate driver bug and is left tracked there. Coverage: a unit test in the patched controller pins the requeue/propagation contract (fails without the requeue), and the bucket/harbor e2e suites now assert `bucketReady=true` on a tight bound instead of tolerating the lag, with scoped diagnostics on the failure path. Closes #3032 Refs #2429 ### Screenshots N/A — no UI changes. ### Release note ```release-note fix(objectstorage-controller): converge BucketClaim readiness to the backend Bucket and speed up single-replica COSI provisioner failover ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved object storage bucket readiness propagation so bucket claims now track the backend bucket’s actual `bucketReady` status and requeue when readiness isn’t yet observed. * Reduced and made readiness waits more reliable in end-to-end checks, with explicit match conditions and clearer debug output (including claim YAML, backend bucket list, and controller pod status). * Shortened leader-election timing to speed up recovery after pod restarts. * **Chores** * Updated automated PR labeling to map the object storage controller scope to the storage area label. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0018a50656 |
docs: route bugs, features, and proposals to the right repo (#2854)
## What Make it unambiguous where each kind of contribution lands: | Contribution | Destination | |---|---| | Bug | issue here (`kind/bug`) | | Concrete, scoped feature | issue here (`kind/feature`) | | Question / early idea | GitHub Discussions | | Cross-cutting / architectural change | design proposal in cozystack/community | | Governance / process / community | cozystack/community | ## Changes - Add `.github/ISSUE_TEMPLATE/config.yml` — a chooser (`blank_issues_enabled: false`) linking to Discussions, the community design-proposal process, community governance issues, and chat. - Add `.github/ISSUE_TEMPLATE/feature_request.md` (`kind/feature`) with an up-front gate (question → Discussion; cross-cutting → design proposal) and a scope checklist. - `CONTRIBUTING.md`: add a "Where do I file?" routing table. - `README.md`: feature requests now point at issues instead of a Discussions category, reconciling a contradiction with the actively-used issue tracker. ## Notes - `blank_issues_enabled: false` removes the blank-issue escape hatch to keep triage clean — easy to flip if you'd rather keep it. - Pairs with a companion PR in cozystack/community (routing table + dead-link fix). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added “Where do I file?” guidance to help route bugs, scoped feature requests, questions/early ideas, cross-cutting design proposals, and community/process topics. * Updated the README “Contributions” section with clearer links and pointers to the right place for each request type. * **New Features** * Added a structured “Feature request” issue template to collect consistent, scoped details. * Disabled blank issue submissions and provided curated entry points for common support and discussion paths. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a036cfd1e9 |
ci(tests): remove redundant Release E2E workflow (#2978)
## What this PR does Removes the `Release E2E` workflow (`.github/workflows/release-e2e.yaml`), which ran the full bats suite on every release tag. **Why it's redundant.** `release-e2e.yaml` was a non-blocking alarm — its own header states *"a failure here is an alarm, not a release blocker."* The coverage it provided is already delivered by the release-cut PR: the "Prepare release" commit bakes image digests into `packages/core/` (installer, platform, testing) and other packages, and `select-e2e.sh`'s full-suite pattern escalates any `packages/core/` change to the **full** suite. So the release PR already runs the whole suite against the commit the tag will point at. **Why now.** The workflow has never been green since it was added (2026-05-02) — every tag run (`v1.5.0-rc.2`, `-rc.3`, `v1.5.0`) failed at the build step. Even after #2973 fixed the registry login earlier today, the next run still failed at *Build Talos image*. A perpetually-red, non-gating duplicate is pure noise. **Changes** - Delete `.github/workflows/release-e2e.yaml`. - Drop `release-e2e` from the full-suite pattern in `hack/select-e2e.sh`. - Repoint the workflow-trigger unit test in `hack/select-e2e_test.bats` to `pull-requests.yaml` (the remaining E2E workflow), preserving "workflow edit → full suite" coverage. All 11 `select-e2e_test.bats` cases pass. - Update `docs/agents/e2e-testing.md` to describe the release-cut PR as where the full suite runs. Refs #2397. ### Release note ```release-note ci(tests): remove the redundant Release E2E workflow; the full E2E suite already runs on the release-cut PR ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Removed automated release end-to-end testing workflow * Updated E2E test selection logic to reflect testing infrastructure changes * **Documentation** * Updated E2E testing procedures documentation to reflect current testing approach <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4f5dcea432 |
ci(pr-labeler): map objectstorage-controller scope to area/storage
The objectstorage-controller package ships the COSI control plane; its commits use the objectstorage-controller scope, which had no area mapping and fell back to area/uncategorized. Map it to area/storage alongside the other COSI/storage scopes. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
56108eca83 |
ci(renovate): pin base images and GitHub Actions to digests
Enable Renovate's dockerfile and github-actions managers with pinDigests so OpenSSF Scorecard Pinned-Dependencies (currently 1/10) can pass and supply-chain refs stay reproducible. PR #2849 SHA-pinned actions in 13 workflows, but the check also scores container base images -- 58 unpinned FROM lines across 27 distinct images -- and left build-main.yaml / release-e2e.yaml unpinned. Nothing kept the new action SHAs updated either, so they would silently stop receiving security patches. Enabling the managers lets Renovate open the initial pin PR (and pin the two missed workflows) and keep digests fresh thereafter. Digest-only refreshes and the initial pin are batched into a single weekly PR to avoid a trickle of rebuild-triggering PRs on the shared CI runner; real tag bumps stay individual for review. Also pin s3manager's floating tags (golang:1, alpine:latest) to concrete versions first, otherwise digest tracking churns endlessly. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e180a8142a |
docs: route bugs, features, and proposals to the right repo
Add an issue-template chooser and a feature-request template, and document in CONTRIBUTING and the README where each kind of contribution belongs: - bugs and concrete features -> issues in this repo - questions and early ideas -> GitHub Discussions - cross-cutting / architectural changes -> design proposals in cozystack/community Also reconciles the README, which routed feature requests to a Discussions category while the issue tracker is actually used for kind/feature issues. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
76ad921fdd |
ci: harden workflow token permissions and pin actions by SHA
Raise the OpenSSF Scorecard Token-Permissions and Pinned-Dependencies checks (both currently 0/10) ahead of CNCF Incubation due diligence: - Declare a top-level read-only default (permissions: contents: read) in every workflow, plus an explicit per-job permissions: block that grants only the writes that job actually needs. Workflows that previously held write scopes at the workflow level (backport, pr-labeler, pr-size, stale) now hold them at job level instead. - Pin every GitHub-owned and third-party action to a full commit SHA with a version comment. scorecard.yml was already pinned in #2721. No triggers, job graph, or step logic change; only token scopes and action refs. Self-hosted release jobs keep the exact write scopes they already declared. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> |
||
|
|
b81e92ac9c |
ci(tests): remove redundant Release E2E workflow
The Release E2E workflow (`release-e2e.yaml`) ran the full bats suite on every release tag as a non-blocking alarm — its own header notes "a failure here is an alarm, not a release blocker." It duplicates coverage the release-cut PR already provides: the "Prepare release" commit bakes image digests into `packages/core/` (and other packages), which TIA escalates to the full suite, so the release PR exercises the whole suite against the commit the tag will point at. It has also never been green since it was added (2026-05-02): every tag run failed at the build step. Even after #2973 fixed the registry login today, the next run still failed (Build Talos image). Removing a perpetually-red, non-gating duplicate removes noise without losing coverage. Removes the workflow, drops `release-e2e` from `select-e2e.sh`'s full-suite pattern, repoints its unit test to `pull-requests.yaml`, and updates the e2e-testing doc. Refs #2397 Assisted-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
1a6dd6feef |
ci(tests): fix OCIR registry login in Release E2E workflow
The Release E2E build job referenced secrets OCI_REGISTRY_USERNAME / OCI_REGISTRY_PASSWORD, which do not exist in the repo, so docker/login-action received empty credentials and failed every run with "Username and password required". The workflow has never built since it was added (2026-05-02): v1.5.0-rc.2, v1.5.0-rc.3 and v1.5.0 all died at this step before any image was built or test run. Use the configured OCIR_USER / OCIR_TOKEN secrets, matching build-main.yaml and pull-requests.yaml, and isolate the Docker config per job (Set up Docker config step + DOCKER_CONFIG on the login and build steps) so login does not clobber the shared ~/.docker/config.json on the self-hosted runner. Assisted-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
6329ffecfc |
fix(ci): create buildx builder in the build step's DOCKER_CONFIG (#2962)
## What this PR does The `Build cache (main)` workflow (`build-main.yaml`, added in #2948) failed on its first run: https://github.com/cozystack/cozystack/actions/runs/27929277423 The `Set up Buildx` step ran without `DOCKER_CONFIG`, so `docker/setup-buildx-action` created the docker-container builder under the runner's default `~/.docker`. The build step runs with `DOCKER_CONFIG=$RUNNER_TEMP/.docker` (seeded earlier, holding the OCIR auth), so buildx couldn't find the builder and failed immediately: ``` ERROR: no builder "builder-6fb46242-…" found ``` The post-job `docker buildx rm` still succeeded — because the action's cleanup runs under the default config where the builder actually lived — which confirms the builder existed but in the wrong config store. This sets `DOCKER_CONFIG` on the `Set up Buildx` step so the builder instance is created in the same config the build step reads. Impact: only the main cache-warmer was broken. PR builds `--cache-from` this ref, so a missing cache is a cold build, not a failure — but the warm-cache speedup from #2948 wasn't being delivered until this fix. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved build pipeline stability by ensuring consistent Docker configuration across workflow steps. This enhances the reliability of the container build and deployment process. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1564081f76 |
ci(release): auto-patch-release only the 2 newest release lines (#2856)
## What this PR does
The **Auto Patch Release** cron (`.github/workflows/auto-release.yaml`)
walked
*every* `release-X.Y` branch — 21 of them, back to `release-0.9` — and
cut a
`vX.Y.(Z+1)` tag whenever a branch had commits after its latest
published
release. This fires patch releases on long-EOL lines (e.g. `v1.3.6`),
whose
release PRs then sit blocked on unrelated CI failures and accumulate
stray
draft releases, tags and changelog PRs.
This restricts the cron to the **2 newest minor lines**
(`SUPPORTED_LINE_COUNT`).
The window is derived from the live branch list, so it slides
automatically as
new `release-X.Y` branches are cut — once `release-1.5` exists the
window
becomes `{1.5, 1.4}` and the trailing line retires with no further
edits.
Currently active: `release-1.4`, `release-1.3`. Skipped: 19 EOL lines.
### Release note
```release-note
ci(release): the automated patch-release job now only cuts releases for the two newest release branches; older EOL lines no longer receive automatic patch tags.
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated the automated release workflow to focus patch automation on
only the two newest minor `release-X.Y` maintenance lines.
* Enhanced workflow logging to report the selected branches and any
older/EOL branches skipped.
* **Documentation**
* Refined release documentation to explain the sliding-window selection
for automated patch tagging, including how next patch versions are
determined and when tags are created.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
f9185e3f4b |
ci: add CodeQL workflow for Go (SAST) (#2851)
## What this PR does Raises the OpenSSF Scorecard **SAST** check (was **0/10**) by adding GitHub's recommended CodeQL static analysis for Go. CodeQL is free for public repositories and is the SAST tool Scorecard recognizes directly. - Triggers on push to `main`, PRs to `main`, and a weekly schedule (Mon 03:27 UTC, offset from the other Monday cron jobs). - Results are uploaded to the code-scanning dashboard via `github/codeql-action/analyze`. ### Why `autobuild` The Go analysis uses **`build-mode: autobuild`**. Go's CodeQL extractor only supports `autobuild` or `manual` (not `none`), so autobuild is the low-friction choice. It discovers every `go.mod` in the tree and extracts each module separately — the root module, `api/apps/v1alpha1`, and the three nested image modules a root `go build ./...` never reaches — giving broader coverage than a single root build. Before falling back to the Go build it first attempts `make` from the repo root, which runs the default Makefile goal (including a network `git fetch upstream --tags`). `setup-go` pins the toolchain to the `go.mod` version so the extractor uses the project's Go rather than whatever the runner ships. ### Security posture - Top-level token is **read-only**; the `analyze` job opts into `security-events: write` (plus `contents: read`, `actions: read`) only. - `actions/checkout` is pinned to **v6.0.2** (matching `scorecard.yml`) with `persist-credentials: false`. - `codeql-action/init` and `/analyze` are pinned to the **v4.36.2 SHA** — the same commit as `scorecard.yml`'s `upload-sarif`, keeping every codeql-action ref in the repo on one commit and clear of the v3 deprecation warning. ### Verification - `actionlint`: **exit 0**. - Valid YAML. - No `run:` steps → no untrusted-input injection surface. > SAST is a ramping check: Scorecard credits the CodeQL workflow's presence immediately and the score climbs toward full as subsequent merged PRs get analyzed. ### Release note ```release-note ci: add CodeQL static analysis (SAST) for Go, running on push/PR to main and weekly ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enabled automated security scanning via CodeQL on pushes, pull requests targeting the main branch, and on a weekly schedule. * Added workflow controls for concurrency and longer execution time, with support for Go-based analysis using an autobuild setup. * Updated the SARIF upload step to use the latest CodeQL action version to improve reliability while maintaining secure, minimal permissions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e7abea9576 |
fix(ci): create buildx builder in the build step's DOCKER_CONFIG
The "Set up Buildx" step in build-main.yaml ran without DOCKER_CONFIG, so docker/setup-buildx-action created the docker-container builder under the default ~/.docker. The build step runs with DOCKER_CONFIG=$RUNNER_TEMP/.docker (seeded before the builder existed and holding the OCIR auth), so it could not find the builder and failed immediately with `no builder "builder-<uuid>" found`. The post-job `docker buildx rm` still succeeded because the action's cleanup runs under the default config where the builder actually lived. Set DOCKER_CONFIG on the Set up Buildx step so the builder instance is created in the same config the build step reads. Assisted-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
3bcab58453 |
ci(release): order skipped EOL branches numerically in the log
Address review feedback from lexfrei on .github/workflows/auto-release.yaml:82: the skipped-branches log used a lexicographic sort (release-0.9 after release-0.41). Reuse the existing lineNum helper so the log lists EOL branches in numeric order. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
94582fa07c |
ci(release): auto-patch-release only the 2 newest release lines
The Auto Patch Release cron walked every release-X.Y branch (21 of them,
back to release-0.9) and cut a vX.Y.(Z+1) tag whenever a branch had
commits after its latest published release. That fired patch releases on
long-EOL lines (e.g. v1.3.6), whose release PRs then sit blocked on
unrelated CI failures and accumulate stray draft releases, tags and
changelog PRs.
Restrict the cron to the SUPPORTED_LINE_COUNT (=2) newest minor lines.
The window is derived from the branch list, so it slides automatically as
new release-X.Y branches are cut — once release-1.5 exists the window
becomes {1.5, 1.4} and the trailing line retires with no further edits.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
f3914d2053 |
ci(build): disable credential persistence in build-cache checkout
The build-main cache warmer is a privileged workflow (packages:write + an OCIR push token) and never pushes git, so set persist-credentials: false to keep the checkout's GITHUB_TOKEN out of .git/config where a later build step could read it. (SHA-pinning the actions is handled repo-wide in #2849.) Addresses non-blocking follow-up 7 on #2948. Assisted-By: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
89b6c401a6 |
ci(codeql): align checkout with scorecard.yml and drop redundant concurrency prefix
Address non-blocking review feedback from lexfrei: bump actions/checkout to the v6.0.2 SHA already used by scorecard.yml so the security workflows track one version, and remove the hardcoded 'codeql-' prefix from the concurrency group (github.workflow already expands to 'CodeQL'). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
6b1212313a |
ci(codeql): fix the cron comment that mislabeled stale as a Monday job
Address review feedback from lexfrei on .github/workflows/codeql.yml:10: stale.yaml runs '37 4 * * *' (daily), but the comment listed it among the other Monday cron jobs. Note scorecard and labels as the Monday jobs and stale as daily. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
445a2fb1dc |
ci(codeql): correct the autobuild comment to match observed behavior
Address review feedback from lexfrei on .github/workflows/codeql.yml:43: the previous comment claimed autobuild 'runs the Go build the same way go build ./... does'. The run log shows autobuild discovers all five go.mod files and extracts each module separately (including the three nested image modules a root build never reaches), and first attempts make from the repo root, which triggers a network git fetch upstream --tags. Rewrite the comment to document this accurately. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e40db8cd43 |
ci(codeql): pin codeql-action to v4.36.2 to clear the v3 deprecation warning
Address review feedback from lexfrei on .github/workflows/codeql.yml:60: v3 is on a deprecation path (the workflow's own run already warns about it) and v4 is GA. Bump init, analyze, and scorecard.yml's upload-sarif to the same v4.36.2 commit SHA. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
eba31194d7 |
ci(build): isolate each PR build on its own ephemeral runner VM (#2939)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
d3958c5bcb |
refactor(build): mode=max registry cache with a main-only warmer (#2938)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
8b4d31866e |
ci: add Go-scoped Renovate configuration (#2850)
## What this PR does Raises the OpenSSF Scorecard **Dependency-Update-Tool** check (was **0/10**) by adding a Renovate configuration at `.github/renovate.json`. Scorecard scores this check on the presence of a recognized config file, so the check turns green as soon as this merges. ### Why Renovate (not Dependabot) Renovate is already the cozystack org standard — it actively raises and merges PRs on `cozystack/ansible-cozystack`, and `cozystack/talm` + `cozystack/boot-to-talos` already ship `renovate.json`. The Renovate GitHub App is authorized on the org, so this config is picked up **without creating a new credential**. There is no Dependabot usage anywhere in the org. > If the app installation is scoped to "selected repositories", `cozystack/cozystack` needs to be toggled into the existing installation by an org admin — a one-click change, not a new auth artifact. The Scorecard check does not depend on that toggle. ### Scoped to Go dependencies only (per the 2026-05-27 decision) - **`enabledManagers: ["gomod"]`** — Renovate only ever touches Go modules. It will **not** open PRs for Dockerfiles, Helm charts, shipped component/operator versions, or GitHub Actions. Components and images stay hand-managed. - **`gomodTidy` + `gomodUpdateImportPaths`** run after each bump. The `gomod` manager auto-discovers both the root module and the `api/apps/v1alpha1` submodule. - **Kubernetes libraries grouped** (`sigs.k8s.io/controller-runtime` + `k8s.io/**`) so `client-go`/`apimachinery` never bump out of lockstep with controller-runtime (a split bump fails to compile). - **Go toolchain directive pinned** (`matchDepTypes: ["golang"]` disabled) — `go.mod` is generated and a toolchain bump needs a matching `setup-go` + codegen run, out of scope for an automated PR. ### "do not merge" on every bot PR (requirement) - `automerge` and `platformAutomerge` are **off**. - Every Renovate PR is labeled **`do-not-merge/hold`** + **`automated`** on creation. Both labels already exist in `.github/labels.yml`; `stale.yaml` already exempts `do-not-merge/hold` PRs from auto-close, so held bumps won't rot. - Bumps therefore stay parked until tests pass and a maintainer removes the label after a hands-on check. > Note: `do-not-merge/hold` is a **signal/marker** (cozystack uses native GitHub, not Prow Tide). Combined with automerge being off, nothing can auto-merge a held PR. Hard merge-blocking would need a status check tied to the label, which would require branch-protection changes that were explicitly excluded. ### Verification - `renovate-config-validator` (Renovate v42): **Config validated successfully.** - Valid JSON. ### Release note ```release-note ci: add a Go-scoped Renovate configuration (gomod only, no automerge, bot PRs held with do-not-merge/hold) to automate Go dependency updates ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Configured automated dependency management for Go modules, including synchronized updates for Kubernetes-related dependencies, rate limiting on concurrent updates, and manual approval requirements to ensure controlled rollouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c961ffe286 |
feat(ci): test-impact analysis E2E (default-on) + release E2E workflow (#2559)
## What this PR does
Adds **test-impact analysis (TIA)** to the PR E2E workflow so that only
bats files affected by the diff are exercised, and a **release-time E2E
workflow** that runs the full suite on every release tag to keep
coverage on the shipped code.
### 1. Test-impact analysis selector — `hack/select-e2e.sh`
Reads `packages/core/platform/sources/*.yaml` (the PackageSource
dependency graph) and emits the bats files affected by a PR diff. The
walk is the same one `cozypkg dot` renders.
| Input | Output |
|---|---|
| `packages/apps/postgres/values.yaml` | `postgres` |
| `packages/system/postgres-operator/...` | `postgres harbor`
(transitive) |
| `packages/system/cilium/...` | full suite (cilium has many transitive
`*-application` dependents) |
| `packages/library/cozy-lib/...` | full suite (library affects
everything) |
| `hack/e2e-install-cozystack.bats` | full suite (shared install affects
all apps) |
| `hack/e2e-apps/redis.bats` | `redis` (per-app edit, never escalates) |
| `docs/agents/contributing.md` | (empty — no E2E impact) |
| `dashboards/gpu/gpu-fleet.json` | (empty) |
Conservative fallbacks:
- An unrecognised `packages/*` path or a system source with no
`*-application` descendants escalates to the full suite, so a path
inside the graph is never silently dropped.
- Per-app bats edits are matched **before** the full-suite trigger, so
editing one bats file selects only that app rather than escalating.
### 2. Default-on TIA + `full-e2e` opt-out — `pull-requests.yaml`
- The `Select E2E tests` step runs by default and produces `apps` +
`skip` outputs.
- `Run E2E tests` runs unless `skip=true` (docs / dashboards / `*.md`
only).
- Adding the `full-e2e` label skips the selector step (output empty) and
falls through to the unchanged full-bats-list path — the safety hatch
when reviewers want the full suite on a PR.
### 3. `release-e2e.yaml` — full E2E on every release tag
Triggered on `v*.*.*`, `v*.*.*-rc.*`, `v*.*.*-beta.*`, `v*.*.*-alpha.*`.
Builds images + Talos image, then runs the full suite. Independent of
`tags.yaml`'s release publish flow — failure here is an alarm, not a
release blocker.
This closes the coverage gap left by making PR runs default to TIA: the
full suite is now exercised at tag-cut time against the shipped code.
## Tests
`hack/select-e2e_test.bats` covers 11 cases — single app, transitive
operator, networking/library full-suite, docs/dashboards skip,
`kubernetes-application` two-bats mapping, shared E2E helper, install
bats, per-app bats no-escalation, release-e2e workflow change.
YAML parse verified for both new workflow files.
## Workflow injection safety
All `${{ }}` contexts that could carry untrusted data
(`github.base_ref`, label arrays) flow through env vars, never directly
into shell text. `github.workspace` is also indirected through
`WORKSPACE` env in the release workflow.
### Release note
```
NONE
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* CI now runs a Test Impact Analysis to pick only affected apps,
reducing E2E runtime.
* Added a release-level E2E workflow that runs full acceptance tests for
version tags with deterministic sandboxing, artifact capture,
conditional retries, teardown, and report upload.
* E2E jobs accept selected-apps metadata and support conditional
full-suite overrides.
* **Tests**
* New test suite validates selection logic, operator expansion,
full-suite escalation, and docs-only/no-op behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
0d6aaf93ac |
ci: use autobuild build-mode for CodeQL Go
CodeQL 2.25.x rejects build-mode 'none' for Go ('Go does not support the
none build mode; use autobuild or manual'), which failed the initial run.
Switch to autobuild and add a SHA-pinned setup-go (go-version-file: go.mod)
so the autobuilder uses the project's Go toolchain rather than whatever the
runner ships. go build ./... already compiles cleanly, so autobuild
succeeds.
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Assisted-By: Claude <noreply@anthropic.com>
|
||
|
|
540c4a1315 |
ci: add CodeQL workflow for Go (SAST)
Raise the OpenSSF Scorecard SAST check (was 0/10) by adding GitHub's recommended CodeQL analysis for Go. Runs on push and PR to main plus a weekly schedule, and uploads results to the code-scanning dashboard. - build-mode: none extracts Go source without compiling, so the job cannot fail on the monorepo's generated files, build tags, or the api/apps/v1alpha1 submodule. It still produces real alerts and is credited by Scorecard. Can be switched to autobuild later for deeper build-aware analysis. - Top-level token is read-only; the analyze job opts into security-events: write only. - codeql-action pinned to the same v3 SHA already used by scorecard.yml; checkout pinned by SHA. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> |
||
|
|
ac56d4cea1 |
ci: add Go-scoped Renovate configuration
Raise the OpenSSF Scorecard Dependency-Update-Tool check (was 0/10) by adding a Renovate config. Renovate is already the cozystack org standard (active on ansible-cozystack, talm, boot-to-talos), so the app is authorized org-wide and this file is picked up without a new credential. Scoped deliberately so automated bumps only ever touch Go dependencies: - enabledManagers: [gomod] — Renovate ignores Dockerfiles, Helm charts, shipped component/operator versions, and GitHub Actions. Components and images stay hand-managed, per the 2026-05-27 decision. - gomodTidy + gomodUpdateImportPaths run after each bump; the gomod manager auto-discovers both the root module and the api/apps/v1alpha1 submodule. - controller-runtime and k8s.io/** are grouped so client-go and controller-runtime never bump out of lockstep. - The Go toolchain directive is pinned (matchDepTypes golang disabled): go.mod is generated and a toolchain bump needs a matching setup-go and a codegen run, out of scope for an automated PR. - automerge/platformAutomerge are off and every Renovate PR is labeled do-not-merge/hold + automated, so bumps are held until tests pass and a maintainer reviews them by hand. Validated with renovate-config-validator (config validated successfully). Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> |
||
|
|
53edfc1f50 |
test(e2e): capture COSI bucket state in failure diagnostics and cozyreport
Run 27057500380 failed on harbor's BucketClaim never reaching bucketReady=true, and neither artifact could explain why: the per-app diagnostics dump has no bucket objects, and cozyreport collects neither COSI resources nor objectstorage-controller / seaweedfs provisioner logs — by the time the report is taken, the bucket state has moved on. Add a COSI module to cozyreport.sh (bucketclaims/bucketaccesses/ buckets/classes as custom-column tables plus full YAML, controller and per-namespace provisioner logs) and a bucket-readiness snapshot to the per-app failure dump in the PR workflow. The COSI CRDs ship no printer columns, so plain kubectl get would show only NAME/AGE — readiness fields are pulled explicitly. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
d8d4c71e0f |
ci(pull-requests): dump cluster state on Install Cozystack failure
Mirror the diagnostics group already on `Run E2E tests` to the `Install Cozystack into sandbox` step. Without this, install-step failures (e.g. an HR not reaching Ready inside the bats `kubectl wait` window) surface only as "error: timed out waiting for the condition on helmreleases/<name>" with no cluster snapshot — re-running is the only way to triage, which is the exact pattern the parent commit removed. On failure, dump three groups: - `kubectl get hr -A -o wide` (last 100 lines): which HRs exist and their Ready/Status columns. - `kubectl describe hr` for each not-Ready HR (tail -50): the Conditions block surfaces helm install/upgrade errors, missing CRDs, and chart-render failures — the actual cause. - `kubectl get events -A --sort-by=.lastTimestamp` (last 50): cluster events that often pinpoint the failing pod/PVC/job. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
199781a7a5 |
ci(pull-requests): report total attempt count in prepare-env retry log
Address review feedback from coderabbitai on .github/workflows/pull-requests.yaml:235: $attempt is incremented only on failure, so first-try success printed "completed after 0 attempts". Use $((attempt + 1)) so the message reflects the total number of runs. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e3b54cb201 |
ci(pull-requests): drop 3x retry on Run E2E + Install Cozystack
Audit of 30 successful PR runs found that across 5 sampled failure attempts, **25/25 retries** on `Run E2E tests` failed — the retry loop never recovered a flake, only stretched deterministic failures and tripled diagnostic wall-time. Same data shape on `Install Cozystack`. Drop both. `Prepare environment` keeps its 3x retry — that step is pure infrastructure (Talos image download, sandbox VM boot, network) where transient runner hiccups warrant a retry. On failure, the test step now captures `kubectl get hr -A -o wide` and `kubectl get events -A` under a collapsible group so triage starts with the actual broken-state snapshot. Depends on: - #2508 — installer namespace bootstrap (Helm namespace-ownership conflict) - #2509 — operator HelmRelease config knobs (`seaweedfs-system` 2-min wait race) - #2528 — harbor bucket-secret + BucketInfo gating (harbor ValuesError) - #2529 — objectstorage-controller BucketAccess conflict retry - the daniil/split-vminstance PR (vminstance disk race + VM IP/ready timeouts) - the daniil/split-event-driven PR (existence backstops surfacing real errors) Until those land, dropping the retry will fail CI for unrelated PRs that hit the seaweedfs / harbor / installer / vminstance races. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> Assisted-By: Claude <noreply@anthropic.com> |
||
|
|
26574f08f3 |
ci(release): repair orphaned draft tag_name on retag (#2761)
## What this PR does When a release-cut PR is merged after the underlying git tag was deleted and re-created (e.g. the release branch was force-updated between the initial tag push and the merge), GitHub orphans the corresponding draft release — its `tag_name` becomes `untagged-<hash>` while `name` is preserved. The "Publish draft release" step in `pull-requests-release.yaml` looks up the draft strictly by `tag_name === tag` and throws `Draft release for <tag> not found`, blocking the release. Observed on run [#26558920814](https://github.com/cozystack/cozystack/actions/runs/26558920814/job/78236959976) cutting v1.4.2, and the same error fired on the earlier [v1.4.1 finalize run](https://github.com/cozystack/cozystack/actions/runs/26271301257). This change adds a fallback: when the primary lookup misses, search for a draft where `name === tag` and `tag_name` matches `/^untagged-/`. If found, repair the draft's `tag_name` to the real tag via `updateRelease` before publishing, so the released artifact correctly points at the git tag created earlier in the same job. The strict-fail path is preserved when neither lookup matches. The fix is forward-only and does **not** auto-recover the currently stuck v1.4.2 draft — that needs a one-time manual `tag_name` patch + job re-run, or publishing the draft via the GitHub UI. ### Release note ```release-note ci(release): the release-finalize workflow now repairs an orphaned draft release (tag_name == `untagged-<hash>` after a tag delete + re-create) by re-linking it to the actual tag before publishing. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved the robustness of the release publication process to handle edge cases when locating draft releases, ensuring more reliable and consistent release deployments. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2761?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
bac670d07b |
ci: bump cozyvalues-gen to v1.6.0 in pre-commit workflow
v1.6.0 adds the date-time string-format alias and the @example annotation. Both are additive, opt-in directives: charts that do not use them regenerate byte-identical schema, README and Go type output, so the pre-commit check stays green without touching any committed artifact. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
22187e069d |
ci(release): repair orphaned draft tag_name on retag
When the git tag was deleted and re-created between draft creation and merge, GitHub orphaned the draft release: tag_name became "untagged-<hash>" while `name` was preserved. The finalize step looked up the draft by tag_name and threw `Draft release for <tag> not found`, blocking the release. Fall back to matching by `name` only when the candidate is the GitHub-orphaned form (tag_name matches /^untagged-/), repair the draft's tag_name via updateRelease, then publish. Hard-fail is preserved when neither lookup matches. Same failure recurred on the v1.4.1 finalize run; this commit prevents recurrence but does not auto-recover the stuck v1.4.2 draft. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
3756f5c459 |
feat(networking): Gateway API support via Cilium (supersedes #2213) (#2470)
## What this PR does
Replaces ingress-nginx as the default ingress layer for cozystack-native
services with **Cilium Gateway API**, materialised per-tenant via a new
`TenantGateway` CRD reconciled by `cozystack-controller`. Supersedes
#2213 / #2208. Stacked on top of #2468.
## Architecture
The chart renders one `gateway.cozystack.io/v1alpha1 TenantGateway` CR
per tenant that owns its own Gateway. The cozystack-controller
reconciles the actual `Gateway`, per-tenant `Issuer`, `Certificate`
(wildcard or per-listener), and HTTP→HTTPS redirect `HTTPRoute` from
there. Helm does not render `Gateway` or `Certificate` directly — that
prevents the Helm-vs-controller race on `Gateway.spec.listeners` that
route-driven listener additions would otherwise cause.
```
┌── TenantGateway CR (rendered by extra/gateway chart for owning tenants)
│
└──▶ cozystack-controller reconciles:
├─ Gateway (with dynamic listeners, label-based allowedRoutes)
├─ Issuer (per-tenant ACME account)
├─ Certificate(s) — wildcard + per-child SANs in DNS-01, per-listener in HTTP-01
├─ HTTPRoute (controller-owned http→https redirect)
├─ Namespace label patching (cozy-* system namespaces from spec.AttachedNamespaces)
└─ Watches HTTPRoute / TLSRoute attachments to materialise listeners
```
## Inheritance: tenants attach by default, opt into their own Gateway
A tenant gets a dedicated Gateway (own LB Service, own LB IP, own
Certificate) only when it explicitly asks via
`tenant.spec.gateway=true`. Every other tenant in the tree publishes
through the Gateway of the nearest ancestor that owns one — same shape
as the existing `_namespace.ingress` inheritance.
The `apps/tenant` chart writes a `namespace.cozystack.io/gateway` label
on each tenant namespace, carrying either the tenant's own name (when
owning a Gateway) or the inherited ancestor name (when inheriting). The
Gateway's listener `allowedRoutes.namespaces.selector` is keyed on that
label, so the same selector admits routes from every namespace pointing
at the owner — descendants and cozy-* system namespaces alike.
cozystack-controller patches the same label onto every namespace in
`tgw.Spec.AttachedNamespaces` and garbage-collects labels it wrote when
an entry is removed from the attach list (annotation-gated GC so labels
written by the apps/tenant chart are never stripped).
In DNS-01 mode, the controller extends the parent's wildcard Certificate
with `<child-apex>` + `*.<child-apex>` SANs per inheriting child, and
adds a `*.<child-apex>` HTTPS listener per child apex referencing the
same cert. Without this expansion the parent's single-level wildcard
cannot match a child route's hostname (`harbor.alice.example.org` is two
labels past the parent's `*.example.org`).
Opt-out into own Gateway is the right choice when: a tenant needs its
own LB IP (DNS pinned, firewall rule), the apex is not derived from the
parent (custom `host` value the ancestor's cert can't cover), or the
tenant wants its own ACME account / cert authority. Otherwise leave
`gateway` unset and inherit.
## End-to-end flow
1. Platform: `gateway.enabled=true` toggles cert-manager solver,
switches per-system-app templates from Ingress to HTTPRoute / TLSRoute.
2. Per tenant: explicit `tenant.spec.gateway=true` renders a
`TenantGateway` CR and triggers the controller to materialise the owner
Gateway. Tenants with the field unset inherit through
`_namespace.gateway` propagation in the tenant chart.
3. Adding a published app under any tenant (owner or inheriting) is just
deploying its HTTPRoute. The controller picks up the hostname, adds a
per-listener Certificate (HTTP-01) or extends the wildcard cert's SANs
(DNS-01), and updates the owner Gateway's listeners.
Defaults stay legacy: `gateway.enabled=false`,
`tenant.spec.gateway=false`. Existing clusters upgrade unchanged.
## External IP allocation — mechanism-agnostic
The per-tenant Gateway's auto-created `LoadBalancer` Service draws its
IP from whatever LB allocator the cluster admin has configured at the
platform layer — same shape as ingress-nginx today. The tenant API stays
mechanism-agnostic — no `gatewayIP` field, no allocator-specific
manifest in the tenant chart. Cozystack itself ships MetalLB installed
but does not render any `IPAddressPool` / `L2Advertisement` /
`BGPAdvertisement` from this chart; admins set up the allocator that
suits their environment (MetalLB pool with L2 / BGP, Cilium LB-IPAM with
announcer, robotlb against a cloud provider, or
`Service.spec.externalIPs` pinning).
If a tenant needs a specific address (DNS already pinned, firewall rule,
etc.), the operator pre-allocates it on the admin side: either
pre-create the Service with `loadBalancerIP` set, or hand the tenant a
reference to a named admin-managed pool. Per-Service IP uniqueness is
the allocator's responsibility — same as for any other LoadBalancer
Service.
## Cert mode: HTTP-01 (default) vs DNS-01 (opt-in)
`publishing.certificates.solver` selects how the controller sources TLS
certs.
**HTTP-01 (default)** — per-app HTTPS listener + per-app Certificate.
New apps require zero platform-side config: deploy the HTTPRoute,
controller does the rest. Inheriting children's hostnames pick up
per-listener certs the same way the owner's own apps do.
**DNS-01 (opt-in)** — single wildcard Certificate (`<apex>` +
`*.<apex>`) covering every published app under the apex, plus per-child
SANs (`<child-apex>` + `*.<child-apex>`) for every inheriting tenant.
Pick this for clusters where many apps share the apex and Let's Encrypt
rate limits matter. The DNS provider account must be able to write TXT
records under every apex level the parent serves — for deeply-nested
inherited children that requires zone delegation or a wide-scope
provider credential.
| `publishing.certificates.dns01.provider` | Required
`publishing.certificates.dns01.<provider>` keys |
| --- | --- |
| `cloudflare` (default) | `cloudflare.secretName`,
`cloudflare.secretKey` |
| `route53` | `route53.region`, `route53.secretName` (and `accessKeyID`
if not on IRSA) |
| `digitalocean` | `digitalocean.secretName` |
| `rfc2136` | `rfc2136.nameserver`, `rfc2136.tsigKeyName`,
`rfc2136.secretName` |
The platform chart wires every provider's keys into `_cluster.dns01-*`;
the per-tenant gateway chart and the cluster-wide `cluster-issuers.yaml`
both read them.
## Strengthens admission coverage on apps.cozystack.io/*
The `cozystack-tenant-host-policy` probe in `gateway.bats` initially
looked like a flake — the apply that was supposed to be VAP-rejected
just succeeded. Investigation traced it to the custom REST handler at
`pkg/registry/apps/application/rest.go`. genericapiserver hands every
storage method a callback into the validating admission chain:
`createValidation` for Create, `updateValidation` for Update,
`deleteValidation` for Delete. `Update` was correctly invoking its
callback since
|
||
|
|
2cb16d5ae6 |
refactor(build): standardize image tagging to fix concurrent PR push conflicts (#2711)
## What this PR does Concurrent PR builds were racing in the OCIR registry. Every package Makefile tagged its images via `settag`, which on any non-release commit collapsed to `:latest` — so every image across every PR was pushed to the same tag, and parallel builds got 409s on the manifest PUT. Two outliers (`metallb`, `redis-operator`) used hardcoded version tags and collided across PRs unconditionally. This PR replaces `settag` and the `TAG=latest` fallback in `hack/common-envs.mk` with a single `image-tags` macro driven by three env vars: | Env | Meaning | |---|---| | `IMAGE_TAG` | Build-unique tag, always pushed | | `PUBLISH_VERSIONED` | Also push `:<component-version>` (when provided) | | `PUBLISH_FLOATING` | Also push `:latest` | Wired into the two workflows: - **`pull-requests.yaml`** — `IMAGE_TAG=pr-<N>-<sha>`, both `PUBLISH_*` off. Every PR build pushes a unique tag set; no collisions, no `:latest` move. - **`tags.yaml`** — `IMAGE_TAG=<ref_name>`, both `PUBLISH_*` on. Release output preserved (component versions + `:latest`) plus a uniform `:<git-tag>` handle on every image for traceability. - **Local** — defaults to `IMAGE_TAG=dev`, no flags, `PUSH=0`. All 30 package Makefiles converted to `$(call image-tags,<repo>,<versioned-tag>)`. 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. Also 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 `:<git-tag>` plus the existing `:<component-version>` tags on release. `ubuntu-container-disk` builds a separate image per Kubernetes version in a loop, so its primary tag became `:<k8s-ver>-<IMAGE_TAG>` to prevent loop iterations within a single build from pushing to the same tag. Verified by dry-running `make -n image` across representative packages (simple, dual-tag, skopeo, flux-push, loop) under all four contexts (PR / release / main / dev) — tag sets are unique and behave as expected. ### Release note ```release-note refactor(build): PR CI now pushes images under a unique `pr-<N>-<sha>` tag per build instead of `:latest`. Concurrent PR builds no longer race in the registry. Release builds keep the existing `:<component-version>` and `:latest` tags and additionally publish a uniform `:<git-tag>` handle across every image. The redundant `:<component-version>-<git-tag>` tag (cilium, linstor, matchbox, ubuntu-container-disk, kubevirt-*, cluster-autoscaler) is no longer published — image references in values.yaml are digest-pinned and were the only legitimate consumers. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Centralized and simplified container image tagging across build workflows. * PR builds now use unique image tags derived from PR metadata for better isolation. * Added configurable flags to control publishing of versioned and floating tags, making release tagging behavior more predictable. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2711?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
943441b0c7 |
ci: bump cozyvalues-gen pin to v1.5.0
v1.5.0 adds the @immutable annotation support (cozystack/cozyvalues-gen#24). Without the bump, pre-commit re-runs make generate with the v1.4.0 binary, silently strips any x-kubernetes-validations entries that downstream PRs add to values.schema.json / embedded openAPISchema, and reports drift against the committed artefacts. This is a no-op for the current main: no chart currently uses @immutable, so regeneration with v1.5.0 produces identical output to v1.4.0. Unblocks cozystack/cozystack#2639 (apply @immutable to storageClass across stateful apps). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
d2e851f63b |
feat: Gateway API support via Cilium
Replace ingress-nginx as the default ingress layer for cozystack-native
services with Cilium Gateway API, materialised per-tenant via a new
TenantGateway CRD reconciled by cozystack-controller.
The extra/gateway chart renders one gateway.cozystack.io/v1alpha1
TenantGateway per tenant; the controller owns the resulting Gateway,
per-tenant Issuer, Certificate(s), and the http->https redirect
HTTPRoute. This avoids the helm-vs-controller race on
Gateway.spec.listeners when route-driven listeners are added.
publishing.certificates.solver selects HTTP-01 (default; per-app HTTPS
listener + per-app Certificate) or DNS-01 (opt-in; single wildcard
Certificate per apex; providers: cloudflare, route53, digitalocean,
rfc2136). HTTP-01 keeps zero-config per-app onboarding; DNS-01 saves
Let's Encrypt budget on apex-shared clusters.
Security model -- seven independent layers, all admission-time gates
fail-closed:
1. Listener allowedRoutes namespace whitelist via the
kube-apiserver-written kubernetes.io/metadata.name label;
plain-HTTP listener is strictly narrower than HTTPS, and HTTPS /
passthrough listeners restrict allowedRoutes.kinds to
HTTPRoute / TLSRoute respectively.
2. cozystack-gateway-hostname-policy VAP on Gateway.
3. cozystack-gateway-attached-namespaces-policy VAP on Package --
blocks tenant-* in gateway.attachedNamespaces.
4. cozystack-tenant-host-policy VAP on Tenant -- blocks spec.host
writes from non-trusted callers.
5. cozystack-namespace-host-label-policy VAP on Namespace -- blocks
writes to namespace.cozystack.io/host from non-trusted callers.
6. Render-time fail in cozystack-basics for tenant-* in
gateway.attachedNamespaces.
7. cozystack-route-hostname-policy VAP on HTTPRoute / TLSRoute,
scoped to tenant-* namespaces.
Within-apex cross-namespace hostname conflict is resolved at reconcile
time by a HostnameConflict condition (cozy-* namespace wins).
Five reconcile paths refuse to rewrite pre-existing objects with the
controller-derived name but no OwnerReference back to the
TenantGateway: Gateway, redirect HTTPRoute, per-tenant Issuer, wildcard
Certificate, per-listener Certificate.
Derived-apex tenants (tenants whose host is a subdomain of a parent
tenant's) auto-enable Gateway when the platform-level gateway.enabled
is on.
Bonus fix: pkg/registry/apps/application/rest.go was ignoring the
createValidation and deleteValidation callbacks that genericapiserver
hands to every storage method, silently bypassing admission for Create
and Delete on every apps.cozystack.io resource (Tenant, MariaDB,
Postgres, Kubernetes, ...). Aligned with the existing updateValidation
pattern.
Always-on changes: cilium.envoy.enabled + cilium.gatewayAPI.enabled
flip to true (extra cilium-envoy DaemonSet, ~100 MB RAM/node idle),
and the cozystack-api admission-chain fix. Everything else is gated
behind gateway.enabled=false and tenant.spec.gateway=false; existing
clusters see no behavioural change until an operator opts in.
Tests: 60+ Go cases in internal/controller/tenantgateway/, admission-
chain regression tests in pkg/registry/apps/application/, helm-unittest
across 7 charts (extra/gateway, core/platform, apps/tenant,
system/cozystack-basics, system/cert-manager-issuers,
system/cozystack-api, system/dashboard), and 14 e2e bats scenarios in
hack/e2e-apps/gateway.bats. New make test-controllers target wired
into pull-requests.yaml.
Deps: sigs.k8s.io/gateway-api v1.4.1, cert-manager v1.17.4.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
688f73f8f0 |
ci: pin Scorecard workflow actions by SHA
The initial Scorecard workflow used floating major-version tags (@v2, @v4, @v3). ossf/scorecard-action does not publish a floating v2 tag — only specific patch releases — so the first scheduled run failed with `Unable to resolve action ossf/scorecard-action@v2`. Pin every action by its full commit SHA with a trailing comment showing the human-readable version. This also satisfies the `Pinned-Dependencies` Scorecard check itself. - actions/checkout@de0fac2 (v6.0.2) - ossf/scorecard-action@4eaacf0 (v2.4.3) - actions/upload-artifact@043fb46 (v7.0.1) - github/codeql-action/upload-sarif@03e4368 (v3) Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
2396d08ee5 |
ci: add OpenSSF Scorecard workflow
Runs the OpenSSF Scorecard action on: - weekly schedule (Mon 06:00 UTC) - branch protection rule changes - pushes to main - manual dispatch Publishes results to: - the public OpenSSF Scorecard API (scorecard.dev) for transparency - the GitHub code-scanning dashboard (Security tab) for triage No README badge is added yet — the badge will be introduced in a follow-up PR once the first scans have run and any quick-win improvements (token permissions, dependency pinning) have landed. Aligns with the project's CNCF Incubation readiness work and the security self-assessment in progress. Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
7cc0194f20 |
ci(pre-commit): bump cozyvalues-gen to v1.4.0
v1.4.0 adds the `intOrString` type alias used by the postgres package's
`postgresql.parameters` schema in this PR. CI must install v1.4.0 so the
"Verify generated code is up to date" check regenerates the same schema
shape (anyOf + x-kubernetes-int-or-string: true) rather than reverting
to {type: string}.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
ed0297eb87 |
refactor(build): standardize image tagging to fix concurrent PR push conflicts
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> |
||
|
|
00d47ee684 |
ci(tags): include data/versions in website docs commit
`release_next.sh` and `init_version.sh` (via `update-all → init-version`)
create `data/versions/<DOC_VERSION>.yaml` for new versions, but the
`update-website-docs` job only staged `content` and `hugo.yaml`. The new
file was silently dropped from the website PR, breaking
`{{< version-pin >}}` lookups for the released minor.
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
71c713f002 |
ci(workflows): rebuild breakpoint authorized-users from active contributors
Replace MAINTAINERS.md snapshot with a list derived from actual recent activity on main (commits, merged PRs and reviews over the last three months). MAINTAINERS.md had drifted in both directions — listing people no longer active on the project while missing several current maintainers — so copying it verbatim was both handing SSH access to inactive accounts and locking out people who would actually use this debug feature. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> |
||
|
|
6c8e111ab6 |
ci(workflows): add SSH breakpoint on E2E failure for debug/release PRs
When the e2e job fails on a PR carrying the `debug` or `release` label (release PRs are bot-created, so the label implies maintainer authorship), hold the runner and open an SSH breakpoint via cozystack/breakpoint-action (a fork of namespacelabs/breakpoint-action pinned by SHA) so a maintainer can attach, inspect Talos/Cozystack state, and resume. The fork adds three things on top of upstream: * `mode: pause-idle` — waits 20m for the first SSH connection, then keeps the workflow paused while sessions are active, exiting 10m after the last session disconnects. Saves runner-minutes vs a fixed timeout. * `endpoint` step output + `::notice::` annotation — surfaces the SSH endpoint while the step is still paused (step logs are buffered until step completion, so the endpoint would otherwise be invisible). * A dedicated Check Run "Breakpoint Open" with conclusion=failure carrying the SSH endpoint and sandbox-entry hint in output.summary (Markdown, rendered in the UI). Surfaces as a standard ✗ in `gh pr checks` so any CI watcher sees the open breakpoint without bespoke marker parsing. Updated to conclusion=success when the breakpoint exits. The step is configured via the `BREAKPOINT_ENDPOINT` repo variable. In fork PRs, repo variables are not exposed, so the step is naturally skipped and forks cannot reach the self-hosted rendezvous server. The `authorized-users` list is kept as a second defense layer at the breakpoint level. Permissions on the e2e job: `checks: write` (for Check Run create+update). Upstream PR: namespacelabs/breakpoint-action#16 Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com> |
||
|
|
b7fd200e4b |
ci(tags): make generate-changelog non-blocking
Mark the generate-changelog job with continue-on-error and switch the update-website-docs gate to always() so a failed or skipped changelog generation no longer blocks the website docs update. prepare-release remains the hard gate. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
315802d8fc |
ci(pull-requests): raise E2E job timeout from 120m to 180m
The 2-hour ceiling on the E2E job was clipping otherwise-working runs on the oracle-vm-24cpu-96gb-x86-64 runners: image pulls, multi-stage Talos bootstrap, full helm-release fan-out plus the post-install bats matrix routinely consume 100-180 minutes of wall-clock, and runs that would have eventually gone green were getting cancelled by GitHub at the timeout. Recent successful E2E runs on the same runner pool sit between 60 and 184 minutes; lift the cap to 180m to cover the long tail without inviting truly-stuck jobs to linger forever. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
8da1e7a40a |
feat(platform): implement backup strategy for postgres (#2552)
<!-- Thank you for making a contribution! Here are some tips for you: - Use Conventional Commits for the PR title: `type(scope): description` - Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore - Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples: - System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api - Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes - Development and maintenance: api, hack, tests, ci, docs, maintenance - Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does ### Screenshots <!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating the visual impact of your changes. PRs with UI changes without screenshots will not be merged. --> ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same `type(scope):` prefix as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note Implemented CNPG-strategy controller for postgres backups with supporting in-place and to-copy restores. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * CNPG-based backup strategy for PostgreSQL with S3-backed object store and controller support * Option to reference existing Kubernetes Secret for S3 credentials (configurable key names) * Controller supports scheduled/ad-hoc backups and both in-place and to-copy restores; safer credential handling (no inline keys) * **Examples** * Complete manifests: bucket, credentials, CNPG strategy, BackupClass, Plan, BackupJob, RestoreJob, Postgres source/target * **Security/RBAC** * Controller RBAC expanded for CNPG resources; tests enforce no cluster-wide Secret read * **Documentation** * README, chart values/schema and UI schema updated to document secret-reference workflow and restore guidance * **Tests** * New end-to-end and unit tests covering CNPG flows, restore semantics, cleanup behavior and RBAC constraints <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ed5ae16e36 |
feat(platform): implement backup strategy for postgres application
Signed-off-by: Andrey Kolkov <androndo@gmail.com> |