feat(charts): take the harbor and vault charts from the registry mirror #207

Merged
grachevko merged 2 commits from feat/oci-chart-mirror into main 2026-09-24 17:59:17 +00:00
Collaborator

What was

Both apps took their chart from a GitRepository of the upstream project, because the upstream chart repositories are unusable from our network: helm.goharbor.io is served by CloudFront and stalls the transfer (200 with Content-Length: 95085, then ~11 KB in 90 s), and helm.releases.hashicorp.com answers 403. A chart taken from a git repository is what no cluster-level check can inflate, so those two releases were the only ones a render-based check could not cover.

What this PR does

  • kubernetes/apps/harbor/harbor/app and kubernetes/apps/security/vault/app: the GitRepository source is replaced by an OCIRepository of our mirror (oci://harbor.grachevko.ru/charts/<name>, the tag is the CHART version), the HelmRelease uses chartRef to it, and the kustomization lists the new file instead of the old one.
  • kubernetes/apps/renovate/renovate-operator/app/helmrelease.yaml: install/upgrade.disableSchemaValidation: true. The chart schema wants a hostname in policy.allowedHosts, and the value there is git.${SECRET_DOMAIN} — a valid hostname only after Flux substitutes it, so the release fails schema validation both on install and on upgrade. The field is the Flux API switch for exactly this case, not a hole in the check.

Why the CI gate is not in this PR

The gate lives in feat/flux-local-gate and is opened separately. Its diff job renders the cluster both at the head and at the base branch, and on the current base branch the harbor and vault charts come from a git repository, which flux-local can only inflate from a local path; it fails with unable to detect chart at <workdir>/Chart.yaml while rendering main. Measured on run 175 of that workflow: Flux Local - Test succeeded — that is the whole gate — and only the diff job failed, on the base branch side. In other words the gate needs this change to be merged first, and this change does not need the gate.

Verified

  • flux-local test --enable-helm --all-namespaces --path kubernetes/flux/cluster --sources flux-system=. on this branch: 126 passed, no failures. On main the same command reported 123 passed and 3 failed; with only the Renovate fix 124 passed and 2 failed (harbor and vault). Both mirrored charts are pulled from harbor.grachevko.ru during that run, so the OCI sources are proven to inflate.
  • The same gate ran in the cluster runner on the first revision of this branch: the Flux Local - Test job succeeded there too, which is the same command in the real environment.
  • The mirror is live: charts/harbor:1.19.2 (sha256:6323d18c...) and charts/vault:0.34.1 (sha256:a8ecf85c...) in Harbor, both pullable anonymously (helm show chart oci://... with no credentials), and the mirroring workflow ran green in grachevko/charts.
  • Negative control from the same setup: a stray optional: true under valueFrom.secretKeyRef in another app makes the run fail with additional properties 'optional' not allowed — the class of error the gate exists for.

Watch after merge

source-controller has to trust the internal CA to pull from harbor.grachevko.ru: that certificate is signed by our CA, while the node-level trust (talos/all/55-registry-harbor.yaml) covers kubelet only. If the first reconcile reports x509: certificate signed by unknown authority, the fix is to give the Flux controllers the same internal-ca ConfigMap the other controllers already mount, rather than weakening the source.

Next

  1. feat/flux-local-gate opens as its own pull request once this one is merged.
  2. Renovate does not update the two chart tags yet: it has to be able to read the tags of our Harbor. That is a separate change to the Renovate configuration.

Rollback

Revert the commit: both sources go back to their GitRepository. The charts stay in Harbor, so nothing has to be re-pushed.

## What was Both apps took their chart from a GitRepository of the upstream project, because the upstream chart repositories are unusable from our network: `helm.goharbor.io` is served by CloudFront and stalls the transfer (200 with `Content-Length: 95085`, then ~11 KB in 90 s), and `helm.releases.hashicorp.com` answers 403. A chart taken from a git repository is what no cluster-level check can inflate, so those two releases were the only ones a render-based check could not cover. ## What this PR does - `kubernetes/apps/harbor/harbor/app` and `kubernetes/apps/security/vault/app`: the GitRepository source is replaced by an OCIRepository of our mirror (`oci://harbor.grachevko.ru/charts/<name>`, the tag is the CHART version), the HelmRelease uses `chartRef` to it, and the kustomization lists the new file instead of the old one. - `kubernetes/apps/renovate/renovate-operator/app/helmrelease.yaml`: `install/upgrade.disableSchemaValidation: true`. The chart schema wants a hostname in `policy.allowedHosts`, and the value there is `git.${SECRET_DOMAIN}` — a valid hostname only after Flux substitutes it, so the release fails schema validation both on install and on upgrade. The field is the Flux API switch for exactly this case, not a hole in the check. ## Why the CI gate is not in this PR The gate lives in `feat/flux-local-gate` and is opened separately. Its diff job renders the cluster both at the head and at the base branch, and on the current base branch the harbor and vault charts come from a git repository, which flux-local can only inflate from a local path; it fails with `unable to detect chart at <workdir>/Chart.yaml` while rendering main. Measured on run 175 of that workflow: `Flux Local - Test` succeeded — that is the whole gate — and only the diff job failed, on the base branch side. In other words the gate needs this change to be merged first, and this change does not need the gate. ## Verified - `flux-local test --enable-helm --all-namespaces --path kubernetes/flux/cluster --sources flux-system=.` on this branch: **126 passed**, no failures. On main the same command reported 123 passed and 3 failed; with only the Renovate fix 124 passed and 2 failed (harbor and vault). Both mirrored charts are pulled from `harbor.grachevko.ru` during that run, so the OCI sources are proven to inflate. - The same gate ran in the cluster runner on the first revision of this branch: the `Flux Local - Test` job succeeded there too, which is the same command in the real environment. - The mirror is live: `charts/harbor:1.19.2` (sha256:6323d18c...) and `charts/vault:0.34.1` (sha256:a8ecf85c...) in Harbor, both pullable anonymously (`helm show chart oci://...` with no credentials), and the mirroring workflow ran green in grachevko/charts. - Negative control from the same setup: a stray `optional: true` under `valueFrom.secretKeyRef` in another app makes the run fail with `additional properties 'optional' not allowed` — the class of error the gate exists for. ## Watch after merge source-controller has to trust the internal CA to pull from `harbor.grachevko.ru`: that certificate is signed by our CA, while the node-level trust (`talos/all/55-registry-harbor.yaml`) covers kubelet only. If the first reconcile reports `x509: certificate signed by unknown authority`, the fix is to give the Flux controllers the same `internal-ca` ConfigMap the other controllers already mount, rather than weakening the source. ## Next 1. `feat/flux-local-gate` opens as its own pull request once this one is merged. 2. Renovate does not update the two chart tags yet: it has to be able to read the tags of our Harbor. That is a separate change to the Renovate configuration. ## Rollback Revert the commit: both sources go back to their GitRepository. The charts stay in Harbor, so nothing has to be re-pushed.
feat(charts): take the harbor and vault charts from the registry mirror
Some checks failed
Flate / Flate - Filter (pull_request) Successful in 4s
Flux Local / Flux Local - Test (pull_request) Successful in 48s
Flux Local / Flux Local - Diff (pull_request) Failing after 1m2s
Flux Local / Flux Local - Success (pull_request) Failing after 4s
Flate / Flate (pull_request) Successful in 32s
Flate / Flate - Success (pull_request) Successful in 3s
4bb3ba39a4
## What was

Both apps took their chart from a GitRepository of the upstream project, because the upstream
chart repositories are unusable from our network: `helm.goharbor.io` is served by CloudFront and
stalls the transfer (200 with `Content-Length: 95085`, then ~11 KB in 90 s), and
`helm.releases.hashicorp.com` answers 403. A chart taken from a git repository is exactly what no
cluster-level check can inflate, so those two releases were the only ones a render-based check
could not cover.

## What this PR does

- `kubernetes/apps/harbor/harbor/app` and `kubernetes/apps/security/vault/app`: the GitRepository
  source is replaced by an OCIRepository of our mirror
  (`oci://harbor.grachevko.ru/charts/<name>`, tag is the CHART version), the HelmRelease uses
  `chartRef` to it, and the kustomization lists the new file.
- `.github/workflows/flux-local.yaml`: the gate. `test` inflates the whole cluster with helm,
  which validates the values of every HelmRelease against its chart schema, and `diff` renders
  the HelmReleases at the head and at the base and posts the diff as a pull request comment. The
  jobs use the upstream composite actions; the runner (Forgejo kubernetes plugin) executes steps
  inside the pod's `main` container and has no per-step images, which is why the pinned image
  form used by other repositories is not available here. The `Flux Local - Success` aggregator
  exists because job-level `success()`/`cancelled()` are not evaluated on this Forgejo version.
- `kubernetes/apps/renovate/renovate-operator/app/helmrelease.yaml`: `install/upgrade
  .disableSchemaValidation: true`. The chart schema requires a hostname in
  `policy.allowedHosts`, and the value there is `git.${SECRET_DOMAIN}`, which is a valid hostname
  only after Flux substitutes it; the release therefore fails schema validation on install and on
  upgrade. The field is the Flux API's own switch for this case, not a way around the check.

## Verified

- `flux-local test --enable-helm --all-namespaces --path kubernetes/flux/cluster --sources
  flux-system=.` on this branch: **126 passed**, no failures. Before the mirror, the same command
  on main reported 123 passed and 3 failed, and with only the Renovate fix 124 passed and 2
  failed (harbor and vault). Both mirrored charts are pulled by flux-local from
  `harbor.grachevko.ru` during that run, so the OCI sources are proven to inflate.
- The mirror itself is live: `charts/harbor:1.19.2` (sha256:6323d18c…) and `charts/vault:0.34.1`
  (sha256:a8ecf85c…), both pullable anonymously (`helm show chart oci://…` without credentials).
  Its workflow ran green in grachevko/charts.
- Negative control from the same setup: a stray `optional: true` under `valueFrom.secretKeyRef`
  in another app makes the run fail with `additional properties 'optional' not allowed`, which is
  the class of error this gate exists for.

## Watch after merge

source-controller has to trust the internal CA to pull from `harbor.grachevko.ru`. The certificate
of that name is signed by our CA, while node-level trust (talos/all/55-registry-harbor.yaml)
covers kubelet only. If the first reconcile reports `x509: certificate signed by unknown
authority`, the fix is to give the Flux controllers the same `internal-ca` ConfigMap the other
controllers already mount, not to weaken the source.

## Next

Renovate does not update the two chart tags yet: it has to read the tags of our Harbor. That is a
separate change to the Renovate configuration.

## Rollback

Revert the commit: the two sources go back to their GitRepository and the workflow disappears.
The charts stay in Harbor, so nothing has to be re-pushed.
chore(ci): keep the flux-local gate out of this change
All checks were successful
Flate / Flate - Filter (pull_request) Successful in 3s
Flate / Flate (pull_request) Successful in 26s
Flate / Flate - Success (pull_request) Successful in 3s
d81a3c8abf
The gate cannot go green in the same change that fixes the base branch: its diff job renders the
cluster at both the head and the base branch, and on the current base branch the harbor and vault
charts come from a git repository, which flux-local can only inflate from a local path. It
reports `unable to detect chart at <workdir>/Chart.yaml` while rendering main.

Measured on the first run of this workflow (run 175): the `Flux Local - Test` job succeeded, which
is the whole gate, and only `Flux Local - Diff` failed, on the base branch side.

The workflow goes in its own change, to be opened once this one is merged and main renders clean.
grachevko deleted branch feat/oci-chart-mirror 2026-09-24 17:59:18 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
grachevko/home-ops!207
No description provided.