Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
fee4e24
refactor(api): extract the shared chart catalog naming scheme
drey Sep 10, 2026
941c23e
feat(api): add the HelmApplicationRepository custom resource
drey Sep 10, 2026
f64f5bf
feat(api): add the HelmClusterApplicationRepository custom resource
drey Sep 10, 2026
bdf0800
feat(api): add the HelmApplicationChart custom resource
drey Sep 10, 2026
7cffbcd
feat(api): add the HelmClusterApplicationChart custom resource
drey Sep 10, 2026
5e3d6bd
feat(api): add the HelmApplication custom resource
drey Sep 10, 2026
09542a2
feat(api): bound the HelmApplication name and add status repository h…
drey Sep 10, 2026
b1d1072
internal: drop the permissions claim from the HelmApplication descrip…
drey Sep 10, 2026
c66105b
refactor(api): share one spec and status across the repository kinds
drey Sep 10, 2026
4064271
refactor(api): share one status across the chart catalog kinds
drey Sep 10, 2026
26f60e1
feat(controller): derive internal names for namespaced sources
drey Sep 10, 2026
403e83d
feat(controller): add the repository source contract and its adapters
drey Sep 10, 2026
0acc321
feat(controller): mirror repository catalogs through a kind-agnostic …
drey Sep 10, 2026
47c1bb3
refactor(controller): reconcile repository secrets and sources throug…
drey Sep 10, 2026
3eee116
refactor(controller): synchronize catalogs through the contract
drey Sep 10, 2026
dc92728
refactor(controller): reconcile every repository kind with one reconc…
drey Sep 10, 2026
570acf5
feat(controller): map internal resources back to a namespaced source
drey Sep 10, 2026
ee8a327
feat(controller): reconcile HelmApplicationRepository and HelmCluster…
drey Sep 10, 2026
2fc82f1
fix(controller): address the whole-branch review of the repository ge…
drey Sep 10, 2026
92501eb
feat(controller): add the release source contract
drey Sep 10, 2026
9ba96cf
feat(controller): adapt HelmClusterAddon to the release contract
drey Sep 10, 2026
53b7b2c
refactor(controller): drive the chart, release and maintenance servic…
drey Sep 10, 2026
36c538e
refactor(controller): reach a repository's consumers through a releas…
drey Sep 10, 2026
249c258
refactor(controller): claim charts and ensure namespaces through the …
drey Sep 10, 2026
b3bdf41
refactor(controller): reconcile every release kind with one reconciler
drey Sep 10, 2026
83369b5
feat(controller): adapt HelmApplication to the release contract
drey Sep 10, 2026
7761ce1
feat(controller): provide the identity an application release is appl…
drey Sep 10, 2026
06f24bc
feat(controller): map repositories and catalogs to the applications u…
drey Sep 10, 2026
b2adb96
feat(controller): reconcile HelmApplication
drey Sep 10, 2026
655511f
docs(api): state what creating a HelmApplication grants
drey Sep 10, 2026
cff7751
fix(controller): address the whole-branch review of the release gener…
drey Sep 10, 2026
e26ec01
refactor(chart-values): key auxiliary resources by the repository nam…
drey Sep 11, 2026
ca6016b
feat(chart-values): describe a repository kind by its family
drey Sep 11, 2026
a2e2e27
feat(chart-values): resolve charts of the application repositories
drey Sep 11, 2026
0e3b044
feat(chart-values): authorize a request by the resource its answer feeds
drey Sep 11, 2026
5340d21
fix(chart-values): let a namespace reach a cluster-scoped repository …
drey Sep 11, 2026
3b5f257
fix(chart-values): restore the released response contract
drey Sep 11, 2026
14f94fd
chore(chart-values): fix stale comments and a deprecated test helper
drey Sep 11, 2026
50ece84
test(chart-values): make two frozen assertions actually bite
drey Sep 11, 2026
a1a58a6
feat(chart-values): grant read access to the application repositories
drey Sep 11, 2026
5890851
test(e2e): add helpers for the application family
drey Sep 11, 2026
59ab93f
test(e2e): pin the derived service-account name against the operator
drey Sep 11, 2026
b21de1e
test(e2e): cover the namespaced repository lifecycle
drey Sep 11, 2026
a3c9812
test(e2e): cover the application lifecycle, identity and isolation
drey Sep 11, 2026
8ea9cb4
test(e2e): make the application spec discriminate
drey Sep 11, 2026
ba5ec4f
test(e2e): make the repository isolation spec discriminate
drey Sep 11, 2026
998821e
chore(controller): clear the lint findings this branch introduced
drey Sep 11, 2026
61bab9c
fix(rbac): narrow the controller's rights over the seeded role
drey Sep 11, 2026
5f41da4
fix(controller): name a cluster-scoped object without a leading slash
drey Sep 11, 2026
49c9db7
docs: document the namespace-scoped application family
drey Sep 11, 2026
a4aa50a
fix(rbac): grant bind on the role, not on the role binding
drey Sep 11, 2026
2f46ce0
chore: align the Go version of api with its consumers
drey Sep 11, 2026
389f01a
chore: add a unit-test task to every module
drey Sep 11, 2026
98b9d0a
ci: run the unit tests on every pull request
drey Sep 11, 2026
c6f07f5
ci: verify the generated files are committed
drey Sep 11, 2026
ffe72c0
chore: name the per-module test task after what it runs
drey Sep 11, 2026
e376870
fix(naming): drop a dot the truncation leaves behind
drey Sep 11, 2026
dc84304
fix(naming): make the application catalog name injective
drey Sep 11, 2026
aac1c8e
fix(chart-values): reject a namespace no cluster could have
drey Sep 11, 2026
85020f1
test(controller): pin that a cut release name stays distinct
drey Sep 11, 2026
730062f
feat(rbac): grant user-facing RBAC on the helm.deckhouse.io resources
drey Sep 11, 2026
1b336c3
fix(controller): don't delete or clobber a role binding we may not own
drey Sep 11, 2026
a61e821
fix(controller): stop caching service accounts and role bindings
drey Sep 11, 2026
46b40ad
fix(controller): stop namespace_service doc overclaiming its scope
drey Sep 11, 2026
39c4d64
test(webhook): cover ValidateCreate/ValidateUpdate for system namespaces
drey Sep 11, 2026
fbd0ead
fix(naming): make the addon chart catalog name injective too
drey Sep 11, 2026
9173ff6
feat(controller): migrate addon chart catalog objects to their new name
drey Sep 11, 2026
de8aa3d
fix(naming): hash the pair, not the ambiguous join
drey Sep 11, 2026
87772f9
chore: install golangci-lint with the toolchain we already have
drey Sep 11, 2026
de96ff9
docs(taskfile): say which image directories are not ours
drey Sep 11, 2026
cc9c85b
fix(controller): migrate every catalog object, not only the published…
drey Sep 11, 2026
b88baf2
fix(rbac): grant the manage roles a rule on their own ModuleConfig
drey Sep 11, 2026
f62feb6
fix(naming): trim a trailing dash or dot on an untruncated repository…
drey Sep 11, 2026
ebc24bf
docs(controller): explain why the service account delete needs no own…
drey Sep 11, 2026
a9f0121
chore: apply the formatting the current linter expects
drey Sep 11, 2026
db5ab50
fix: clear the static analysis findings the linter reports
drey Sep 11, 2026
6921cce
test(controller): keep the fixture parameters the linter would drop
drey Sep 11, 2026
fabf6f2
chore: keep prettier away from the chart-values werf template
drey Sep 11, 2026
c5b5ede
fix(controller): rename the catalog objects without waiting on the re…
drey Sep 11, 2026
215de04
chore: keep the linter binary out of the chart
drey Sep 11, 2026
1a86de8
fix(controller): report a failed rename instead of going silent
drey Sep 11, 2026
36c6945
docs(controller): give Sync back its own doc comment
drey Sep 11, 2026
54656c2
ci: run the linters again
drey Sep 11, 2026
ee2f838
chore: align the Go version of the hooks module too
drey Sep 11, 2026
5ff439a
fix(controller): report a failed rename on a pass that syncs nothing
drey Sep 11, 2026
883a3b4
fix(rbac): move repository read to the secrets-reading level
drey Sep 13, 2026
2d4f92e
fix(controller): do not synchronize over an unfinished rename
drey Sep 13, 2026
5076558
fix(release): requeue a release whose identity setup failed
drey Sep 13, 2026
077ab70
fix(release): mark a failed release-identity cleanup on the status
drey Sep 13, 2026
49be9b4
fix(api/naming): sanitize chart object name parts before assembly
drey Sep 13, 2026
1243296
fix(chart-values-controller): bound and validate the chart-values req…
drey Sep 13, 2026
2f99b5a
fix(controller): give an application a release name nothing else can …
drey Sep 13, 2026
8c0d5b2
fix(controller): keep applications out of default and every kube- nam…
drey Sep 13, 2026
ef20721
fix(api): bound HelmClusterAddonRepository name length via CEL
drey Sep 13, 2026
d2a39b4
chore(api): name the conditions the addon reads
drey Sep 13, 2026
06905fb
chore(rbac): close the remaining status subresources
drey Sep 13, 2026
225f1a9
test(e2e): clean up the namespace and wait for the uninstall
drey Sep 13, 2026
0007a0f
docs: describe the chart catalogs once, as the service objects they are
drey Sep 13, 2026
3e72584
fix(rbac): narrow the operator's rights over the seeded application role
drey Sep 13, 2026
bb1237a
fix(operator-helm-controller): read Namespaces through the API reader
drey Sep 13, 2026
30cb4a6
fix(chartartifact): bound the registry probe's transport and deadline
drey Sep 13, 2026
9f2ca01
fix(operator-helm-controller): scope the Secret informer to our names…
drey Sep 13, 2026
2751cd9
fix(webhook): say what the rule forbids, not how it was reached
drey Sep 13, 2026
d9e46bb
fix(rbac): authorize escalate without a resource name
drey Sep 13, 2026
78f08be
fix(controller): stop treating default as a system namespace
drey Sep 15, 2026
a682fae
feat(api): report how many charts a repository offers
drey Sep 15, 2026
cc134b5
feat(rbac): reach the module through Editor and Admin only
drey Sep 16, 2026
c611836
feat(rbac): move the application level to PrivilegedUser
drey Sep 16, 2026
ea803d0
feat(rbac): give ClusterAdmin the cluster-scoped kinds
drey Sep 16, 2026
dcf2eac
feat(rbac): fold the application rights into Admin
drey Sep 16, 2026
a1ab74d
feat(rbac): let Admin read the cluster-wide chart catalog
drey Sep 16, 2026
1c42753
feat(rbac): let every reader watch what it can list
drey Sep 16, 2026
57d414d
feat: migrate to upstream flux controllers (#78)
drey Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .dmtlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@ linters-settings:
enum:
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.sts.properties.provider"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.provider"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.provider"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.sts.properties.provider"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.upgrade.properties.remediation.properties.strategy.properties"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.uninstall.properties.deletionPropagation"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.driftDetection.properties.mode"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.upgrade.properties.remediation.properties.strategy"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.chart.properties.spec.properties.verify.properties.provider"
- "spec.versions[0].schema.openAPIV3Schema.properties.status.properties.lastAttemptedReleaseAction"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.chart.properties.spec.properties.verify.properties.provider"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.driftDetection.properties.mode"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.postRenderers.items.properties.kustomize.properties.patchesJson6902.items.properties.patch.items.properties.op"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.uninstall.properties.deletionPropagation"
- "spec.versions[1].schema.openAPIV3Schema.properties.spec.properties.upgrade.properties.remediation.properties.strategy"
- "spec.versions[1].schema.openAPIV3Schema.properties.status.properties.lastAttemptedReleaseAction"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.upgrade.properties.serverSideApply"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.rollback.properties.serverSideApply"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.waitStrategy.properties.name"
- "spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.postRenderStrategy"
- "properties.logLevel"
- "properties.logFormat"
rbac:
Expand Down
72 changes: 50 additions & 22 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,53 @@ jobs:
env:
DMT_METRICS_URL: ${{ secrets.DMT_METRICS_URL }}
DMT_METRICS_TOKEN: ${{ secrets.DMT_METRICS_TOKEN }}
# waiting for golangci-lint for go 1.26
# lint:
# runs-on: [self-hosted, large]
# name: Lint
# steps:
# - name: Set up Go ${{ vars.GO_VERSION }}
# uses: actions/setup-go@v6
# with:
# go-version: "${{ vars.GO_VERSION }}"

# - uses: actions/checkout@v6

# - name: Install Task
# uses: arduino/setup-task@v2
# with:
# repo-token: ${{ secrets.GITHUB_TOKEN }}

# - name: Install golangci-lint
# run: task --yes deps:install:golangci-lint

# - name: Run linters
# run: task --yes lint

generated_files:
runs-on: [self-hosted, large]
name: Generated files
steps:
- uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
cache: true
go-version-file: api/go.mod

- name: Install Task
uses: arduino/setup-task@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

# Regenerates the clients and the CRDs, then fails if anything moved. The
# prettier pass over the CRDs runs in a container, so the runner needs Docker.
- name: Verify the generated files are committed
run: task --yes ci:generate:api

- name: Verify the internal definitions are committed
run: task --yes ci:generate:internal-crds

lint:
runs-on: [self-hosted, large]
name: Lint
steps:
- uses: actions/checkout@v6

# The modules do not all declare the same Go version; the controllers ask
# for the newest one, and a toolchain that satisfies them satisfies the rest.
- name: Set up Go
uses: actions/setup-go@v6
with:
cache: true
go-version-file: images/operator-helm-controller/go.mod

- name: Install Task
uses: arduino/setup-task@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

# The linter is built from source by the lint task itself, so there is no
# separate install step: the shared one could not fetch a release new enough
# to read a module targeting this repository's Go version.
- name: Run linters
run: task --yes lint
36 changes: 36 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Unit tests

on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize, labeled, unlabeled]
push:
branches:
- main
- release-*

env:
TASK_X_REMOTE_TASKFILES: 1

jobs:
unit_tests:
runs-on: [self-hosted, large]
name: Unit tests
steps:
# The modules do not all declare the same Go version; the controllers ask
# for the newest one, and a toolchain that satisfies them satisfies the rest.
- uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
cache: true
go-version-file: images/operator-helm-controller/go.mod

- name: Install Task
uses: arduino/setup-task@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run unit tests
run: task --yes test:unit
1 change: 1 addition & 0 deletions .helmignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ LICENSE
tests/
Taskfile.yaml
CHANGELOG/
bin/
build/
requirements.lock
117 changes: 109 additions & 8 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ vars:
deckhouse_lib_helm_ver: 1.71.2
target: ""
VALIDATION_FILES: "tools/validation/{main,messages,diff,doc_changes}.go"
golangciLintVersion: "v2.8.0"

golangciLintVersion: "v2.13.2"

# Only the modules this repository authors are listed, including tools/internalcrds.
# images/kube-api-rewriter is a separate upstream module vendored in for the build, and
# images/helm-controller and images/source-controller carry nothing but their werf
# files, so none of them is ours to lint, format or test here. The one exception is
# the rewriter's operatornelm package, which is this module's own rule table: its
# tests run from test:rewrite-rules below.
includes:
api:
taskfile: ./api/Taskfile.dist.yaml
Expand All @@ -18,12 +24,15 @@ includes:
hooks:
taskfile: ./images/hooks/Taskfile.dist.yaml
dir: ./images/hooks
artifact:
operator-helm-controller:
taskfile: ./images/operator-helm-controller/Taskfile.dist.yaml
dir: ./images/operator-helm-controller
chart-values-artifact:
chart-values-controller:
taskfile: ./images/chart-values-controller/Taskfile.dist.yaml
dir: ./images/chart-values-controller
internalcrds:
taskfile: ./tools/internalcrds/Taskfile.dist.yaml
dir: ./tools/internalcrds

deps:
taskfile: https://raw.githubusercontent.com/werf/common-ci/refs/heads/main/Taskfile.deps.yml
Expand Down Expand Up @@ -55,6 +64,94 @@ tasks:
cmds:
- task: api:ci:generate

generate:internal-crds:
desc: "Regenerate the internal CustomResourceDefinitions from upstream flux."
cmds:
- |
set -eu
helmControllerTag=$(sed -n 's/^ *helm-controller: *//p' build/components/versions.yml)
sourceControllerTag=$(sed -n 's/^ *source-controller: *//p' build/components/versions.yml)
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
git clone --quiet --depth 1 --branch "$helmControllerTag" \
https://github.com/fluxcd/helm-controller "$work/helm-controller"
git clone --quiet --depth 1 --branch "$sourceControllerTag" \
https://github.com/fluxcd/source-controller "$work/source-controller"
cd tools/internalcrds
go run . -out ../../crds/embedded/helm-controller.yaml \
"$work/helm-controller/config/crd/bases"
go run . -out ../../crds/embedded/source-controller.yaml \
"$work/source-controller/config/crd/bases"

check-flux-tags:
desc: "Verify the upstream flux tags pinned in werf.inc.yaml match build/components/versions.yml."
cmds:
- |
set -eu
helmControllerTag=$(sed -n 's/^ *helm-controller: *//p' build/components/versions.yml)
sourceControllerTag=$(sed -n 's/^ *source-controller: *//p' build/components/versions.yml)
helmWerfTag=$(sed -n 's/.*\$helmControllerTag := "\(.*\)".*/\1/p' images/helm-controller/werf.inc.yaml)
sourceWerfTag=$(sed -n 's/.*\$sourceControllerTag := "\(.*\)".*/\1/p' images/source-controller/werf.inc.yaml)
for pin in "$helmControllerTag" "$sourceControllerTag" "$helmWerfTag" "$sourceWerfTag"; do
if [ -z "$pin" ]; then
echo "a version pin came out empty: build/components/versions.yml has '$helmControllerTag' and '$sourceControllerTag', the werf files have '$helmWerfTag' and '$sourceWerfTag'" >&2
exit 1
fi
done
if [ "$helmControllerTag" != "$helmWerfTag" ]; then
echo "images/helm-controller/werf.inc.yaml pins helm-controller $helmWerfTag but build/components/versions.yml pins $helmControllerTag" >&2
exit 1
fi
if [ "$sourceControllerTag" != "$sourceWerfTag" ]; then
echo "images/source-controller/werf.inc.yaml pins source-controller $sourceWerfTag but build/components/versions.yml pins $sourceControllerTag" >&2
exit 1
fi
silent: true

ci:generate:internal-crds:
desc: "Regenerate the internal CustomResourceDefinitions and verify they are committed."
cmds:
- task: check-flux-tags
- task: generate:internal-crds
- |
git diff --exit-code crds/embedded || (echo "Please run task generate:internal-crds and commit changes" && exit 1)

# The shared deps task installs golangci-lint through the upstream install.sh,
# whose checksum lookup is an unanchored grep: releases now ship an SBOM entry
# next to the archive, both lines match, and the verification fails for every
# version past v2.8.0. Building the binary with the toolchain already present
# sidesteps the download and keeps the linter new enough to read a module that
# targets this repository's Go version.
install:golangci-lint:
desc: "Install golangci-lint binary to bin/golangci-lint-<version>."
status:
- test -x bin/golangci-lint-{{.golangciLintVersion}}
cmds:
- mkdir -p bin
- GOBIN="$(pwd)/bin" go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@{{.golangciLintVersion}}
- mv bin/golangci-lint bin/golangci-lint-{{.golangciLintVersion}}

test:unit:
desc: "Run the unit tests of every module."
cmds:
- task: api:test:unit
- task: hooks:test:unit
- task: operator-helm-controller:test:unit
- task: chart-values-controller:test:unit
- task: e2e:test:unit
- task: internalcrds:test:unit
- task: test:rewrite-rules

# The rule table and the generated definitions are two halves of one
# agreement, and only a live cluster reports a disagreement: a request the
# proxy renames to a group, kind or resource type no definition declares is
# answered "not found". The test compares the two, and reads the definitions
# from outside its own module, which the test cache does not track.
test:rewrite-rules:
desc: "Check the proxy rewrite rules against the generated definitions."
cmds:
- cd images/kube-api-rewriter && go test -count=1 ./pkg/operatornelm/...

test:e2e:setup:
desc: "Setup environment for e2e tests."
cmds:
Expand Down Expand Up @@ -116,17 +213,21 @@ tasks:
cmds:
- task: api:format
- task: hooks:format
- task: artifact:format
- task: chart-values-artifact:format
- task: operator-helm-controller:format
- task: chart-values-controller:format
- task: e2e:format
- task: internalcrds:format

lint:
deps:
- install:golangci-lint
cmds:
- task: api:lint
- task: hooks:lint
- task: artifact:lint
- task: chart-values-artifact:lint
- task: operator-helm-controller:lint
- task: chart-values-controller:lint
- task: e2e:lint
- task: internalcrds:lint
- task: lint:doc-ru

lint:doc-ru:
Expand Down
7 changes: 6 additions & 1 deletion api/Taskfile.dist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ includes:
gciPrefix: '{{.gciPrefix | default "github.com/deckhouse/"}}'
golangciConfigPath: '{{.golangciConfigPath | default "./.golangci.yaml"}}'
golangciLintBinDir: '{{.golangciLintBinDir | default "../bin"}}'
golangciLintVersion: '{{.golangciLintVersion | default "v2.8.0"}}'
golangciLintVersion: '{{.golangciLintVersion | default "v2.13.2"}}'
golangciPaths: '{{.golangciPaths | default "./..."}}'
paths: '{{.paths | default "."}}'
prettierPattern: '../crds/*.yaml'

tasks:
test:unit:
desc: "Run the unit tests of this module."
cmds:
- go test ./...

generate:
desc: "Regenerate all"
cmds:
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading