Compare commits

..

38 commits
v2.8.3 ... main

Author SHA1 Message Date
Stefan Prodan
125464ed72
Merge pull request #5833 from Iam-Karan-Suresh/fix/resolve-symlinks
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
ossf / scorecard (push) Waiting to run
scan / analyze (push) Waiting to run
update / update-components (push) Waiting to run
fix: handle multiple symlinks to same target in build artifact
2026-04-10 14:03:51 +03:00
iam-karan-suresh
69e2c6bc7d fix: handle multiple symlinks to same target in build artifact
Signed-off-by: iam-karan-suresh <karansuresh.info@gmail.com>
2026-04-10 16:15:11 +05:30
Stefan Prodan
7c9810ea3b
Merge pull request #5835 from fluxcd/create-secret-receiver
Add `flux create secret receiver` command
2026-04-10 13:12:31 +03:00
Stefan Prodan
c601a212f6
Add --audience-claim for GCR Receivers
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2026-04-10 12:34:26 +03:00
Stefan Prodan
02734f28ba
Add flux create secret receiver command
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2026-04-10 12:09:42 +03:00
Stefan Prodan
3d4eec61fe
Merge pull request #5828 from rafaelperoco/feat/show-source-get-kustomization
Add `--show-source` to `flux get ks` and `flux get hr`
2026-04-10 10:48:03 +03:00
Rafael Peroco
8a777bdd0f feat: add --show-source flag to flux get helmrelease
Signed-off-by: Rafael Peroco <rafaelperoco@gmail.com>
2026-04-09 18:20:43 -03:00
Rafael Peroco
e2af45aee4 feat: add --show-source flag to flux get kustomization
Fixes #2692

Signed-off-by: Rafael Peroco <rafaelperoco@gmail.com>
2026-04-08 21:49:15 -03:00
Stefan Prodan
befe53a722
Merge pull request #5821 from fluxcd/update-components-main
Some checks failed
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
Update toolkit components
2026-04-07 20:27:35 +03:00
fluxcdbot
241d703e7f Update toolkit components
- kustomize-controller to v1.8.3
  https://github.com/fluxcd/kustomize-controller/blob/v1.8.3/CHANGELOG.md
- source-controller to v1.8.2
  https://github.com/fluxcd/source-controller/blob/v1.8.2/CHANGELOG.md
- notification-controller to v1.8.3
  https://github.com/fluxcd/notification-controller/blob/v1.8.3/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2026-04-07 17:12:55 +00:00
Matheus Pimenta
c432d380dd
Merge pull request #5798 from gma1k/fix/create-kustomization-source-validation
Some checks failed
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
fix: validate --source flag in create kustomization command
2026-03-30 12:41:13 +01:00
Ghassan Malke
457abed9f9
fix: validate --source flag in create kustomization command
Signed-off-by: Ghassan Malke <gmalke@shiftbase.com>
2026-03-30 13:20:31 +02:00
Stefan Prodan
5fc8afcaaf
Merge pull request #5724 from rohansood10/feat/resolve-symlinks-5055
Some checks failed
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
Add --resolve-symlinks flag to build and push artifact commands
2026-03-28 10:46:53 +02:00
Rohan Sood
7bf0bda689 Add --resolve-symlinks flag to build and push artifact commands
This adds a --resolve-symlinks flag to the flux build artifact and flux push artifact
commands. When enabled, symlinks in the source directory are resolved (copied as regular
files/directories) before building the artifact. This includes:

- Recursive symlink resolution with cycle detection
- File permission preservation
- Proper handling of both single-file and directory symlink targets
- Comprehensive test coverage

Fixes #5055

Signed-off-by: Rohan Sood <56945243+rohansood10@users.noreply.github.com>
2026-03-20 11:47:27 -07:00
Matheus Pimenta
d9f51d047d
Merge pull request #5780 from fluxcd/update-components-main
Some checks failed
e2e / e2e-amd64-kubernetes (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
Update toolkit components
2026-03-16 13:39:39 +00:00
fluxcdbot
dc5631f12b Update toolkit components
- helm-controller to v1.5.3
  https://github.com/fluxcd/helm-controller/blob/v1.5.3/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2026-03-16 13:23:43 +00:00
Matheus Pimenta
3f9d5bdc3d
Merge pull request #5776 from fluxcd/rfcs-implemented
Some checks failed
e2e / e2e-amd64-kubernetes (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
Mark RFC 0010, 0011 and 0012 as implemented
2026-03-13 20:38:50 +00:00
Stefan Prodan
64e18014c3
Mark RFC 0010, 0011 and 0012 as implemented
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2026-03-13 22:08:38 +02:00
Matheus Pimenta
e9226713e8
Merge pull request #5701 from Aman-Cool/fix/resume-exit-code
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
ossf / scorecard (push) Waiting to run
scan / analyze (push) Waiting to run
update / update-components (push) Waiting to run
Fix/resume exit code
2026-03-13 10:37:23 +00:00
Aman-Cool
6a5e644798 fix: return error immediately on failed reconciliation status
Co-authored-by: Matheus Pimenta <matheuscscp@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
2026-03-13 15:34:12 +05:30
Matheus Pimenta
0b0be7c1b6
Merge pull request #5773 from fluxcd/update-branch-name
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
ossf / scorecard (push) Waiting to run
scan / analyze (push) Waiting to run
update / update-components (push) Waiting to run
Add target branch name to update branch
2026-03-12 16:37:04 +00:00
Matheus Pimenta
484346ffcc
Add target branch name to update branch
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2026-03-12 16:34:49 +00:00
Matheus Pimenta
5b3acbfcb5
Merge pull request #5769 from fluxcd/update-components
Some checks failed
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
ossf / scorecard (push) Waiting to run
scan / analyze (push) Waiting to run
update / update-components (push) Waiting to run
e2e-azure / e2e-aks (push) Has been cancelled
e2e-gcp / e2e-gcp (push) Has been cancelled
Update toolkit components
2026-03-12 14:15:28 +00:00
fluxcdbot
2288dd90d6 Update toolkit components
- helm-controller to v1.5.2
  https://github.com/fluxcd/helm-controller/blob/v1.5.2/CHANGELOG.md
- kustomize-controller to v1.8.2
  https://github.com/fluxcd/kustomize-controller/blob/v1.8.2/CHANGELOG.md
- source-controller to v1.8.1
  https://github.com/fluxcd/source-controller/blob/v1.8.1/CHANGELOG.md
- notification-controller to v1.8.2
  https://github.com/fluxcd/notification-controller/blob/v1.8.2/CHANGELOG.md
- image-reflector-controller to v1.1.1
  https://github.com/fluxcd/image-reflector-controller/blob/v1.1.1/CHANGELOG.md
- image-automation-controller to v1.1.1
  https://github.com/fluxcd/image-automation-controller/blob/v1.1.1/CHANGELOG.md
- source-watcher to v2.1.1
  https://github.com/fluxcd/source-watcher/blob/v2.1.1/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2026-03-12 14:01:48 +00:00
Matheus Pimenta
af05357a62
Merge pull request #5766 from fluxcd/update-pkg-deps/main
Update fluxcd/pkg dependencies
2026-03-12 10:46:05 +00:00
matheuscscp
64808a0eac Update fluxcd/pkg dependencies
Signed-off-by: GitHub <noreply@github.com>
2026-03-12 10:23:07 +00:00
Stefan Prodan
2ead4fb31c
Merge pull request #5764 from fluxcd/dependabot/github_actions/ci-c90743e802
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-azure / e2e-aks (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
e2e-gcp / e2e-gcp (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
ossf / scorecard (push) Waiting to run
scan / analyze (push) Waiting to run
update / update-components (push) Waiting to run
build(deps): bump the ci group across 1 directory with 11 updates
2026-03-11 19:02:08 +02:00
dependabot[bot]
b60dfbe970
build(deps): bump the ci group across 1 directory with 11 updates
Bumps the ci group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/setup-go](https://github.com/actions/setup-go) | `6.2.0` | `6.3.0` |
| [replicatedhq/replicated-actions](https://github.com/replicatedhq/replicated-actions) | `1.19.0` | `1.20.0` |
| [hashicorp/setup-terraform](https://github.com/hashicorp/setup-terraform) | `3.1.2` | `4.0.0` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3.7.0` | `4.0.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3.12.0` | `4.0.0` |
| [docker/login-action](https://github.com/docker/login-action) | `3.7.0` | `4.0.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `6.0.0` | `7.0.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `4.32.4` | `4.32.6` |
| [anchore/sbom-action](https://github.com/anchore/sbom-action) | `0.22.2` | `0.23.1` |
| [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `4.0.0` | `4.1.0` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `6.4.0` | `7.0.0` |



Updates `actions/setup-go` from 6.2.0 to 6.3.0
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](7a3fe6cf4c...4b73464bb3)

Updates `replicatedhq/replicated-actions` from 1.19.0 to 1.20.0
- [Release notes](https://github.com/replicatedhq/replicated-actions/releases)
- [Commits](49b440dabd...1abb33f527)

Updates `hashicorp/setup-terraform` from 3.1.2 to 4.0.0
- [Release notes](https://github.com/hashicorp/setup-terraform/releases)
- [Changelog](https://github.com/hashicorp/setup-terraform/blob/main/CHANGELOG.md)
- [Commits](b9cd54a3c3...5e8dbf3c6d)

Updates `docker/setup-qemu-action` from 3.7.0 to 4.0.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](c7c5346462...ce360397dd)

Updates `docker/setup-buildx-action` from 3.12.0 to 4.0.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](8d2750c68a...4d04d5d948)

Updates `docker/login-action` from 3.7.0 to 4.0.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](c94ce9fb46...b45d80f862)

Updates `actions/upload-artifact` from 6.0.0 to 7.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](b7c566a772...bbbca2ddaa)

Updates `github/codeql-action` from 4.32.4 to 4.32.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](89a39a4e59...0d579ffd05)

Updates `anchore/sbom-action` from 0.22.2 to 0.23.1
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](28d71544de...57aae52805)

Updates `sigstore/cosign-installer` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](faadad0cce...ba7bc0a3fe)

Updates `goreleaser/goreleaser-action` from 6.4.0 to 7.0.0
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](e435ccd777...ec59f474b9)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: replicatedhq/replicated-actions
  dependency-version: 1.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: hashicorp/setup-terraform
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: docker/login-action
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
- dependency-name: github/codeql-action
  dependency-version: 4.32.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ci
- dependency-name: anchore/sbom-action
  dependency-version: 0.23.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: goreleaser/goreleaser-action
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-11 16:46:48 +00:00
Stefan Prodan
ee8bb8d8a0
Merge pull request #5763 from gaganhr94/fix/token-permissions
ci: add top-level permissions to upgrade-fluxcd-pkg workflow
2026-03-11 18:42:27 +02:00
Gagan H R
5f3098477e ci: add top-level permissions to upgrade-fluxcd-pkg workflow
Add explicit top-level `permissions: contents: read` to the
upgrade-fluxcd-pkg workflow to follow the principle of least privilege
and fix the OpenSSF Scorecard Token-Permissions warning.

Signed-off-by: Gagan H R <hrgagan4@gmail.com>
2026-03-11 21:40:14 +05:30
Matheus Pimenta
4c79a76e94
Merge pull request #5743 from fluxcd/rn-template
Some checks failed
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
Add missing things to release notes template
2026-02-27 12:56:46 +00:00
Matheus Pimenta
1516761fc8
Add missing things to release notes template
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2026-02-27 12:38:51 +00:00
Matheus Pimenta
52b1c1152b
Merge pull request #5740 from fluxcd/update-components
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
scan / analyze (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
ossf / scorecard (push) Waiting to run
update / update-components (push) Waiting to run
Update toolkit components
2026-02-27 09:28:07 +00:00
fluxcdbot
ab4bbffa5b Update toolkit components
- helm-controller to v1.5.1
  https://github.com/fluxcd/helm-controller/blob/v1.5.1/CHANGELOG.md
- kustomize-controller to v1.8.1
  https://github.com/fluxcd/kustomize-controller/blob/v1.8.1/CHANGELOG.md
- notification-controller to v1.8.1
  https://github.com/fluxcd/notification-controller/blob/v1.8.1/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2026-02-27 09:08:54 +00:00
Matheus Pimenta
e7314e8926
Merge pull request #5733 from fluxcd/remove-workaround
Some checks failed
scan / analyze (push) Has been cancelled
update / update-components (push) Has been cancelled
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
Remove no longer needed workaround for Flux 2.8
2026-02-25 11:00:16 +00:00
Matheus Pimenta
2666eaf8fc
Remove no longer needed workaround for Flux 2.8
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2026-02-25 10:48:35 +00:00
Matheus Pimenta
8262f8099e
Merge pull request #5732 from fluxcd/label-2.8
Some checks failed
conformance / conform-kubernetes (1.35.0) (push) Has been cancelled
ossf / scorecard (push) Has been cancelled
e2e-azure / e2e-aks (push) Has been cancelled
e2e-bootstrap / e2e-boostrap-github (push) Has been cancelled
e2e-gcp / e2e-gcp (push) Has been cancelled
e2e / e2e-amd64-kubernetes (push) Has been cancelled
scan / analyze (push) Has been cancelled
conformance / conform-openshift (4.20.0-okd) (push) Has been cancelled
update / update-components (push) Has been cancelled
sync-labels / sync-labels (push) Has been cancelled
conformance / conform-k3s (1.33.7) (push) Has been cancelled
conformance / conform-k3s (1.34.3) (push) Has been cancelled
conformance / conform-kubernetes (1.33.0) (push) Has been cancelled
conformance / conform-kubernetes (1.34.1) (push) Has been cancelled
conformance / conform-k3s (1.35.0) (push) Has been cancelled
Add backport label for Flux 2.8
2026-02-24 13:30:57 +00:00
Matheus Pimenta
cbc5c736f4
Add backport label for Flux 2.8
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
2026-02-24 13:24:55 +00:00
34 changed files with 960 additions and 136 deletions

6
.github/labels.yaml vendored
View file

@ -44,12 +44,12 @@
description: Feature request proposals in the RFC format description: Feature request proposals in the RFC format
color: '#D621C3' color: '#D621C3'
aliases: ['area/RFC'] aliases: ['area/RFC']
- name: backport:release/v2.5.x
description: To be backported to release/v2.5.x
color: '#ffd700'
- name: backport:release/v2.6.x - name: backport:release/v2.6.x
description: To be backported to release/v2.6.x description: To be backported to release/v2.6.x
color: '#ffd700' color: '#ffd700'
- name: backport:release/v2.7.x - name: backport:release/v2.7.x
description: To be backported to release/v2.7.x description: To be backported to release/v2.7.x
color: '#ffd700' color: '#ffd700'
- name: backport:release/v2.8.x
description: To be backported to release/v2.8.x
color: '#ffd700'

View file

@ -3,6 +3,9 @@ name: upgrade-fluxcd-pkg
on: on:
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
upgrade-fluxcd-pkg: upgrade-fluxcd-pkg:
uses: fluxcd/gha-workflows/.github/workflows/upgrade-fluxcd-pkg.yaml@v0.9.0 uses: fluxcd/gha-workflows/.github/workflows/upgrade-fluxcd-pkg.yaml@v0.9.0

View file

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path/filepath"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -48,9 +49,10 @@ from the given directory or a single manifest file.`,
} }
type buildArtifactFlags struct { type buildArtifactFlags struct {
output string output string
path string path string
ignorePaths []string ignorePaths []string
resolveSymlinks bool
} }
var excludeOCI = append(strings.Split(sourceignore.ExcludeVCS, ","), strings.Split(sourceignore.ExcludeExt, ",")...) var excludeOCI = append(strings.Split(sourceignore.ExcludeVCS, ","), strings.Split(sourceignore.ExcludeExt, ",")...)
@ -61,6 +63,7 @@ func init() {
buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.path, "path", "p", "", "Path to the directory where the Kubernetes manifests are located.") buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.path, "path", "p", "", "Path to the directory where the Kubernetes manifests are located.")
buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "o", "artifact.tgz", "Path to where the artifact tgz file should be written.") buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "o", "artifact.tgz", "Path to where the artifact tgz file should be written.")
buildArtifactCmd.Flags().StringSliceVar(&buildArtifactArgs.ignorePaths, "ignore-paths", excludeOCI, "set paths to ignore in .gitignore format") buildArtifactCmd.Flags().StringSliceVar(&buildArtifactArgs.ignorePaths, "ignore-paths", excludeOCI, "set paths to ignore in .gitignore format")
buildArtifactCmd.Flags().BoolVar(&buildArtifactArgs.resolveSymlinks, "resolve-symlinks", false, "resolve symlinks by copying their targets into the artifact")
buildCmd.AddCommand(buildArtifactCmd) buildCmd.AddCommand(buildArtifactCmd)
} }
@ -85,6 +88,15 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("invalid path '%s', must point to an existing directory or file", path) return fmt.Errorf("invalid path '%s', must point to an existing directory or file", path)
} }
if buildArtifactArgs.resolveSymlinks {
resolved, cleanupDir, err := resolveSymlinks(path)
if err != nil {
return fmt.Errorf("resolving symlinks failed: %w", err)
}
defer os.RemoveAll(cleanupDir)
path = resolved
}
logger.Actionf("building artifact from %s", path) logger.Actionf("building artifact from %s", path)
ociClient := oci.NewClient(oci.DefaultOptions()) ociClient := oci.NewClient(oci.DefaultOptions())
@ -96,6 +108,141 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error {
return nil return nil
} }
// resolveSymlinks creates a temporary directory with symlinks resolved to their
// real file contents. This allows building artifacts from symlink trees (e.g.,
// those created by Nix) where the actual files live outside the source directory.
// It returns the resolved path and the temporary directory path for cleanup.
func resolveSymlinks(srcPath string) (string, string, error) {
absPath, err := filepath.Abs(srcPath)
if err != nil {
return "", "", err
}
info, err := os.Stat(absPath)
if err != nil {
return "", "", err
}
// For a single file, resolve the symlink and return the path to the
// copied file within the temp dir, preserving file semantics for callers.
if !info.IsDir() {
resolved, err := filepath.EvalSymlinks(absPath)
if err != nil {
return "", "", fmt.Errorf("resolving symlink for %s: %w", absPath, err)
}
tmpDir, err := os.MkdirTemp("", "flux-artifact-*")
if err != nil {
return "", "", err
}
dst := filepath.Join(tmpDir, filepath.Base(absPath))
if err := copyFile(resolved, dst); err != nil {
os.RemoveAll(tmpDir)
return "", "", err
}
return dst, tmpDir, nil
}
tmpDir, err := os.MkdirTemp("", "flux-artifact-*")
if err != nil {
return "", "", err
}
visited := make(map[string]bool)
if err := copyDir(absPath, tmpDir, visited); err != nil {
os.RemoveAll(tmpDir)
return "", "", err
}
return tmpDir, tmpDir, nil
}
// copyDir recursively copies the contents of srcDir to dstDir, resolving any
// symlinks encountered along the way. The visited map tracks resolved real
// directory paths to detect and break symlink cycles.
func copyDir(srcDir, dstDir string, visited map[string]bool) error {
real, err := filepath.EvalSymlinks(srcDir)
if err != nil {
return fmt.Errorf("resolving symlink %s: %w", srcDir, err)
}
abs, err := filepath.Abs(real)
if err != nil {
return fmt.Errorf("getting absolute path for %s: %w", real, err)
}
if visited[abs] {
return nil // break the cycle
}
visited[abs] = true
defer delete(visited, abs)
entries, err := os.ReadDir(srcDir)
if err != nil {
return err
}
for _, entry := range entries {
srcPath := filepath.Join(srcDir, entry.Name())
dstPath := filepath.Join(dstDir, entry.Name())
// Resolve symlinks to get the real path and info.
realPath, err := filepath.EvalSymlinks(srcPath)
if err != nil {
return fmt.Errorf("resolving symlink %s: %w", srcPath, err)
}
realInfo, err := os.Stat(realPath)
if err != nil {
return fmt.Errorf("stat resolved path %s: %w", realPath, err)
}
if realInfo.IsDir() {
if err := os.MkdirAll(dstPath, realInfo.Mode()); err != nil {
return err
}
// Recursively copy the resolved directory contents.
if err := copyDir(realPath, dstPath, visited); err != nil {
return err
}
continue
}
if !realInfo.Mode().IsRegular() {
continue
}
if err := copyFile(realPath, dstPath); err != nil {
return err
}
}
return nil
}
func copyFile(src, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
return err
}
out, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, srcInfo.Mode())
if err != nil {
return err
}
defer out.Close()
if _, err := io.Copy(out, in); err != nil {
return err
}
return out.Close()
}
func saveReaderToFile(reader io.Reader) (string, error) { func saveReaderToFile(reader io.Reader) (string, error) {
b, err := io.ReadAll(bufio.NewReader(reader)) b, err := io.ReadAll(bufio.NewReader(reader))
if err != nil { if err != nil {

View file

@ -18,6 +18,7 @@ package main
import ( import (
"os" "os"
"path/filepath"
"strings" "strings"
"testing" "testing"
@ -68,3 +69,149 @@ data:
} }
} }
func Test_resolveSymlinks(t *testing.T) {
g := NewWithT(t)
// Create source directory with a real file
srcDir := t.TempDir()
realFile := filepath.Join(srcDir, "real.yaml")
g.Expect(os.WriteFile(realFile, []byte("apiVersion: v1\nkind: Namespace\nmetadata:\n name: test\n"), 0o644)).To(Succeed())
// Create a directory with symlinks pointing to files outside it
symlinkDir := t.TempDir()
symlinkFile := filepath.Join(symlinkDir, "linked.yaml")
g.Expect(os.Symlink(realFile, symlinkFile)).To(Succeed())
// Also add a regular file in the symlink dir
regularFile := filepath.Join(symlinkDir, "regular.yaml")
g.Expect(os.WriteFile(regularFile, []byte("apiVersion: v1\nkind: ConfigMap\n"), 0o644)).To(Succeed())
// Create a symlinked subdirectory
subDir := filepath.Join(srcDir, "subdir")
g.Expect(os.MkdirAll(subDir, 0o755)).To(Succeed())
g.Expect(os.WriteFile(filepath.Join(subDir, "nested.yaml"), []byte("nested"), 0o644)).To(Succeed())
g.Expect(os.Symlink(subDir, filepath.Join(symlinkDir, "linkeddir"))).To(Succeed())
// Resolve symlinks
resolved, cleanupDir, err := resolveSymlinks(symlinkDir)
g.Expect(err).To(BeNil())
t.Cleanup(func() { os.RemoveAll(cleanupDir) })
// Verify the regular file was copied
content, err := os.ReadFile(filepath.Join(resolved, "regular.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(Equal("apiVersion: v1\nkind: ConfigMap\n"))
// Verify the symlinked file was resolved and copied
content, err = os.ReadFile(filepath.Join(resolved, "linked.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(ContainSubstring("kind: Namespace"))
// Verify that the resolved file is a regular file, not a symlink
info, err := os.Lstat(filepath.Join(resolved, "linked.yaml"))
g.Expect(err).To(BeNil())
g.Expect(info.Mode().IsRegular()).To(BeTrue())
// Verify that the symlinked directory was resolved and its contents were copied
content, err = os.ReadFile(filepath.Join(resolved, "linkeddir", "nested.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(Equal("nested"))
// Verify that the file inside the symlinked directory is a regular file
info, err = os.Lstat(filepath.Join(resolved, "linkeddir", "nested.yaml"))
g.Expect(err).To(BeNil())
g.Expect(info.Mode().IsRegular()).To(BeTrue())
}
func Test_resolveSymlinks_singleFile(t *testing.T) {
g := NewWithT(t)
// Create a real file
srcDir := t.TempDir()
realFile := filepath.Join(srcDir, "manifest.yaml")
g.Expect(os.WriteFile(realFile, []byte("kind: ConfigMap"), 0o644)).To(Succeed())
// Create a symlink to the real file
linkDir := t.TempDir()
linkFile := filepath.Join(linkDir, "link.yaml")
g.Expect(os.Symlink(realFile, linkFile)).To(Succeed())
// Resolve the single symlinked file
resolved, cleanupDir, err := resolveSymlinks(linkFile)
g.Expect(err).To(BeNil())
t.Cleanup(func() { os.RemoveAll(cleanupDir) })
// The returned path should be a file, not a directory
info, err := os.Stat(resolved)
g.Expect(err).To(BeNil())
g.Expect(info.IsDir()).To(BeFalse())
// Verify contents
content, err := os.ReadFile(resolved)
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(Equal("kind: ConfigMap"))
}
func Test_resolveSymlinks_cycle(t *testing.T) {
g := NewWithT(t)
// Create a directory with a symlink cycle: dir/link -> dir
dir := t.TempDir()
g.Expect(os.WriteFile(filepath.Join(dir, "file.yaml"), []byte("data"), 0o644)).To(Succeed())
g.Expect(os.Symlink(dir, filepath.Join(dir, "cycle"))).To(Succeed())
// resolveSymlinks should not infinite-loop
resolved, cleanupDir, err := resolveSymlinks(dir)
g.Expect(err).To(BeNil())
t.Cleanup(func() { os.RemoveAll(cleanupDir) })
// The file should be copied
content, err := os.ReadFile(filepath.Join(resolved, "file.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(Equal("data"))
// The cycle directory should exist but not cause infinite nesting
_, err = os.Stat(filepath.Join(resolved, "cycle"))
g.Expect(err).To(BeNil())
// There should NOT be deeply nested cycle/cycle/cycle/... paths
_, err = os.Stat(filepath.Join(resolved, "cycle", "cycle", "cycle"))
g.Expect(os.IsNotExist(err)).To(BeTrue())
}
func Test_resolveSymlinks_multipleLinksSameTarget(t *testing.T) {
g := NewWithT(t)
// Create source directory with a real file inside a dir
srcDir := t.TempDir()
targetDir := filepath.Join(srcDir, "target")
g.Expect(os.MkdirAll(targetDir, 0o755)).To(Succeed())
g.Expect(os.WriteFile(filepath.Join(targetDir, "file.yaml"), []byte("data"), 0o644)).To(Succeed())
// Create a directory with multiple symlinks pointing to targetDir
symlinkDir := t.TempDir()
// Link 1
link1 := filepath.Join(symlinkDir, "link1")
g.Expect(os.Symlink(targetDir, link1)).To(Succeed())
// Link 2
link2 := filepath.Join(symlinkDir, "link2")
g.Expect(os.Symlink(targetDir, link2)).To(Succeed())
// Resolve symlinks
resolved, cleanupDir, err := resolveSymlinks(symlinkDir)
g.Expect(err).To(BeNil())
t.Cleanup(func() { os.RemoveAll(cleanupDir) })
// Verify link1 has the file
content, err := os.ReadFile(filepath.Join(resolved, "link1", "file.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content)).To(Equal("data"))
// Verify link2 ALSO has the file
content2, err := os.ReadFile(filepath.Join(resolved, "link2", "file.yaml"))
g.Expect(err).To(BeNil())
g.Expect(string(content2)).To(Equal("data"))
}

View file

@ -136,6 +136,9 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
if !strings.HasPrefix(kustomizationArgs.path.String(), "./") { if !strings.HasPrefix(kustomizationArgs.path.String(), "./") {
return fmt.Errorf("path must begin with ./") return fmt.Errorf("path must begin with ./")
} }
if kustomizationArgs.source.Name == "" {
return fmt.Errorf("source is required")
}
if !createArgs.export { if !createArgs.export {
logger.Generatef("generating Kustomization") logger.Generatef("generating Kustomization")

View file

@ -0,0 +1,48 @@
//go:build unit
// +build unit
/*
Copyright 2026 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import "testing"
func TestCreateKustomization(t *testing.T) {
tests := []struct {
name string
args string
assert assertFunc
}{
{
// A user creating a kustomization without --source gets a confusing
// API-level error about spec.sourceRef.kind instead of a clear message.
name: "missing source",
args: "create kustomization my-app --path=./deploy --export",
assert: assertError("source is required"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.args,
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}

View file

@ -30,6 +30,7 @@ import (
notificationv1 "github.com/fluxcd/notification-controller/api/v1" notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
) )
@ -49,7 +50,7 @@ var createReceiverCmd = &cobra.Command{
} }
type receiverFlags struct { type receiverFlags struct {
receiverType string receiverType flags.ReceiverType
secretRef string secretRef string
events []string events []string
resources []string resources []string
@ -58,7 +59,7 @@ type receiverFlags struct {
var receiverArgs receiverFlags var receiverArgs receiverFlags
func init() { func init() {
createReceiverCmd.Flags().StringVar(&receiverArgs.receiverType, "type", "", "") createReceiverCmd.Flags().Var(&receiverArgs.receiverType, "type", receiverArgs.receiverType.Description())
createReceiverCmd.Flags().StringVar(&receiverArgs.secretRef, "secret-ref", "", "") createReceiverCmd.Flags().StringVar(&receiverArgs.secretRef, "secret-ref", "", "")
createReceiverCmd.Flags().StringSliceVar(&receiverArgs.events, "event", []string{}, "also accepts comma-separated values") createReceiverCmd.Flags().StringSliceVar(&receiverArgs.events, "event", []string{}, "also accepts comma-separated values")
createReceiverCmd.Flags().StringSliceVar(&receiverArgs.resources, "resource", []string{}, "also accepts comma-separated values") createReceiverCmd.Flags().StringSliceVar(&receiverArgs.resources, "resource", []string{}, "also accepts comma-separated values")
@ -109,7 +110,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.ReceiverSpec{ Spec: notificationv1.ReceiverSpec{
Type: receiverArgs.receiverType, Type: receiverArgs.receiverType.String(),
Events: receiverArgs.events, Events: receiverArgs.events,
Resources: resources, Resources: resources,
SecretRef: meta.LocalObjectReference{ SecretRef: meta.LocalObjectReference{

View file

@ -56,6 +56,22 @@ func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.S
} }
existing.StringData = secret.StringData existing.StringData = secret.StringData
if secret.Annotations != nil {
if existing.Annotations == nil {
existing.Annotations = make(map[string]string)
}
for k, v := range secret.Annotations {
existing.Annotations[k] = v
}
}
if secret.Labels != nil {
if existing.Labels == nil {
existing.Labels = make(map[string]string)
}
for k, v := range secret.Labels {
existing.Labels[k] = v
}
}
if err := kubeClient.Update(ctx, &existing); err != nil { if err := kubeClient.Update(ctx, &existing); err != nil {
return err return err
} }

View file

@ -0,0 +1,134 @@
/*
Copyright 2026 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
)
var createSecretReceiverCmd = &cobra.Command{
Use: "receiver [name]",
Short: "Create or update a Kubernetes secret for a Receiver webhook",
Long: `The create secret receiver command generates a Kubernetes secret with
the token used for webhook payload validation and an annotation with the
computed webhook URL.`,
Example: ` # Create a receiver secret for a GitHub webhook
flux create secret receiver github-receiver \
--namespace=my-namespace \
--type=github \
--hostname=flux.example.com \
--export
# Create a receiver secret for GCR with email claim
flux create secret receiver gcr-receiver \
--namespace=my-namespace \
--type=gcr \
--hostname=flux.example.com \
--email-claim=sa@project.iam.gserviceaccount.com \
--export`,
RunE: createSecretReceiverCmdRun,
}
type secretReceiverFlags struct {
receiverType flags.ReceiverType
token string
hostname string
emailClaim string
audienceClaim string
}
var secretReceiverArgs secretReceiverFlags
func init() {
createSecretReceiverCmd.Flags().Var(&secretReceiverArgs.receiverType, "type", secretReceiverArgs.receiverType.Description())
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.token, "token", "", "webhook token used for payload validation and URL computation, auto-generated if not specified")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.hostname, "hostname", "", "hostname for the webhook URL e.g. flux.example.com")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.emailClaim, "email-claim", "", "IAM service account email, required for gcr type")
createSecretReceiverCmd.Flags().StringVar(&secretReceiverArgs.audienceClaim, "audience-claim", "", "custom OIDC token audience for gcr type, defaults to the webhook URL")
createSecretCmd.AddCommand(createSecretReceiverCmd)
}
func createSecretReceiverCmdRun(cmd *cobra.Command, args []string) error {
name := args[0]
if secretReceiverArgs.receiverType == "" {
return fmt.Errorf("--type is required")
}
if secretReceiverArgs.hostname == "" {
return fmt.Errorf("--hostname is required")
}
if secretReceiverArgs.receiverType.String() == notificationv1.GCRReceiver && secretReceiverArgs.emailClaim == "" {
return fmt.Errorf("--email-claim is required for gcr receiver type")
}
labels, err := parseLabels()
if err != nil {
return err
}
opts := sourcesecret.Options{
Name: name,
Namespace: *kubeconfigArgs.Namespace,
Labels: labels,
ReceiverType: secretReceiverArgs.receiverType.String(),
Token: secretReceiverArgs.token,
Hostname: secretReceiverArgs.hostname,
EmailClaim: secretReceiverArgs.emailClaim,
AudienceClaim: secretReceiverArgs.audienceClaim,
}
secret, err := sourcesecret.GenerateReceiver(opts)
if err != nil {
return err
}
if createArgs.export {
rootCmd.Println(secret.Content)
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}
var s corev1.Secret
if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil {
return err
}
if err := upsertSecret(ctx, kubeClient, s); err != nil {
return err
}
logger.Actionf("receiver secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace)
return nil
}

View file

@ -0,0 +1,74 @@
/*
Copyright 2026 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"testing"
)
func TestCreateReceiverSecret(t *testing.T) {
tests := []struct {
name string
args string
assert assertFunc
}{
{
name: "missing type",
args: "create secret receiver test-secret --token=t --hostname=h",
assert: assertError("--type is required"),
},
{
name: "invalid type",
args: "create secret receiver test-secret --type=invalid --token=t --hostname=h",
assert: assertError("invalid argument \"invalid\" for \"--type\" flag: receiver type 'invalid' is not supported, must be one of: generic, generic-hmac, github, gitlab, bitbucket, harbor, dockerhub, quay, gcr, nexus, acr, cdevents"),
},
{
name: "missing hostname",
args: "create secret receiver test-secret --type=github --token=t",
assert: assertError("--hostname is required"),
},
{
name: "gcr missing email-claim",
args: "create secret receiver test-secret --type=gcr --token=t --hostname=h",
assert: assertError("--email-claim is required for gcr receiver type"),
},
{
name: "github receiver secret",
args: "create secret receiver receiver-secret --type=github --token=test-token --hostname=flux.example.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver.yaml"),
},
{
name: "gcr receiver secret",
args: "create secret receiver gcr-secret --type=gcr --token=test-token --hostname=flux.example.com --email-claim=sa@project.iam.gserviceaccount.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver-gcr.yaml"),
},
{
name: "gcr receiver secret with custom audience",
args: "create secret receiver gcr-secret --type=gcr --token=test-token --hostname=flux.example.com --email-claim=sa@project.iam.gserviceaccount.com --audience-claim=https://custom.audience.example.com --namespace=my-namespace --export",
assert: assertGoldenFile("testdata/create_secret/receiver/secret-receiver-gcr-audience.yaml"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.args,
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}

View file

@ -28,13 +28,22 @@ import (
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2"
) )
type getHelmReleaseFlags struct {
showSource bool
}
var getHrArgs getHelmReleaseFlags
var getHelmReleaseCmd = &cobra.Command{ var getHelmReleaseCmd = &cobra.Command{
Use: "helmreleases", Use: "helmreleases",
Aliases: []string{"hr", "helmrelease"}, Aliases: []string{"hr", "helmrelease"},
Short: "Get HelmRelease statuses", Short: "Get HelmRelease statuses",
Long: "The get helmreleases command prints the statuses of the resources.", Long: "The get helmreleases command prints the statuses of the resources.",
Example: ` # List all Helm releases and their status Example: ` # List all Helm releases and their status
flux get helmreleases`, flux get helmreleases
# List all Helm releases with source information
flux get helmreleases --show-source`,
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)), ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{ get := getCommand{
@ -69,6 +78,7 @@ var getHelmReleaseCmd = &cobra.Command{
} }
func init() { func init() {
getHelmReleaseCmd.Flags().BoolVar(&getHrArgs.showSource, "show-source", false, "show the source reference for each helmrelease")
getCmd.AddCommand(getHelmReleaseCmd) getCmd.AddCommand(getHelmReleaseCmd)
} }
@ -79,16 +89,45 @@ func getHelmReleaseRevision(helmRelease helmv2.HelmRelease) string {
return helmRelease.Status.LastAttemptedRevision return helmRelease.Status.LastAttemptedRevision
} }
func getHelmReleaseSource(item helmv2.HelmRelease) string {
if item.Spec.ChartRef != nil {
ns := item.Spec.ChartRef.Namespace
if ns == "" {
ns = item.GetNamespace()
}
return fmt.Sprintf("%s/%s/%s",
item.Spec.ChartRef.Kind,
ns,
item.Spec.ChartRef.Name)
}
ns := item.Spec.Chart.Spec.SourceRef.Namespace
if ns == "" {
ns = item.GetNamespace()
}
return fmt.Sprintf("%s/%s/%s",
item.Spec.Chart.Spec.SourceRef.Kind,
ns,
item.Spec.Chart.Spec.SourceRef.Name)
}
func (a helmReleaseListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string { func (a helmReleaseListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
item := a.Items[i] item := a.Items[i]
revision := getHelmReleaseRevision(item) revision := getHelmReleaseRevision(item)
status, msg := statusAndMessage(item.Status.Conditions) status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), row := nameColumns(&item, includeNamespace, includeKind)
if getHrArgs.showSource {
row = append(row, getHelmReleaseSource(item))
}
return append(row,
revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg) revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg)
} }
func (a helmReleaseListAdapter) headers(includeNamespace bool) []string { func (a helmReleaseListAdapter) headers(includeNamespace bool) []string {
headers := []string{"Name", "Revision", "Suspended", "Ready", "Message"} headers := []string{"Name"}
if getHrArgs.showSource {
headers = append(headers, "Source")
}
headers = append(headers, "Revision", "Suspended", "Ready", "Message")
if includeNamespace { if includeNamespace {
headers = append([]string{"Namespace"}, headers...) headers = append([]string{"Namespace"}, headers...)
} }

View file

@ -30,13 +30,22 @@ import (
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
) )
type getKustomizationFlags struct {
showSource bool
}
var getKsArgs getKustomizationFlags
var getKsCmd = &cobra.Command{ var getKsCmd = &cobra.Command{
Use: "kustomizations", Use: "kustomizations",
Aliases: []string{"ks", "kustomization"}, Aliases: []string{"ks", "kustomization"},
Short: "Get Kustomization statuses", Short: "Get Kustomization statuses",
Long: `The get kustomizations command prints the statuses of the resources.`, Long: `The get kustomizations command prints the statuses of the resources.`,
Example: ` # List all kustomizations and their status Example: ` # List all kustomizations and their status
flux get kustomizations`, flux get kustomizations
# List all kustomizations with source information
flux get kustomizations --show-source`,
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)), ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{ get := getCommand{
@ -74,6 +83,7 @@ var getKsCmd = &cobra.Command{
} }
func init() { func init() {
getKsCmd.Flags().BoolVar(&getKsArgs.showSource, "show-source", false, "show the source reference for each kustomization")
getCmd.AddCommand(getKsCmd) getCmd.AddCommand(getKsCmd)
} }
@ -83,12 +93,27 @@ func (a kustomizationListAdapter) summariseItem(i int, includeNamespace bool, in
status, msg := statusAndMessage(item.Status.Conditions) status, msg := statusAndMessage(item.Status.Conditions)
revision = utils.TruncateHex(revision) revision = utils.TruncateHex(revision)
msg = utils.TruncateHex(msg) msg = utils.TruncateHex(msg)
return append(nameColumns(&item, includeNamespace, includeKind), row := nameColumns(&item, includeNamespace, includeKind)
if getKsArgs.showSource {
sourceNs := item.Spec.SourceRef.Namespace
if sourceNs == "" {
sourceNs = item.GetNamespace()
}
row = append(row, fmt.Sprintf("%s/%s/%s",
item.Spec.SourceRef.Kind,
sourceNs,
item.Spec.SourceRef.Name))
}
return append(row,
revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg) revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg)
} }
func (a kustomizationListAdapter) headers(includeNamespace bool) []string { func (a kustomizationListAdapter) headers(includeNamespace bool) []string {
headers := []string{"Name", "Revision", "Suspended", "Ready", "Message"} headers := []string{"Name"}
if getKsArgs.showSource {
headers = append(headers, "Source")
}
headers = append(headers, "Revision", "Suspended", "Ready", "Message")
if includeNamespace { if includeNamespace {
headers = append([]string{"Namespace"}, headers...) headers = append([]string{"Namespace"}, headers...)
} }

View file

@ -456,6 +456,7 @@ func resetCmdArgs() {
secretGitArgs = NewSecretGitFlags() secretGitArgs = NewSecretGitFlags()
secretGitHubAppArgs = secretGitHubAppFlags{} secretGitHubAppArgs = secretGitHubAppFlags{}
secretProxyArgs = secretProxyFlags{} secretProxyArgs = secretProxyFlags{}
secretReceiverArgs = secretReceiverFlags{}
secretHelmArgs = secretHelmFlags{} secretHelmArgs = secretHelmFlags{}
secretTLSArgs = secretTLSFlags{} secretTLSArgs = secretTLSFlags{}
sourceBucketArgs = sourceBucketFlags{} sourceBucketArgs = sourceBucketFlags{}

View file

@ -103,17 +103,18 @@ The command can read the credentials from '~/.docker/config.json' but they can a
} }
type pushArtifactFlags struct { type pushArtifactFlags struct {
path string path string
source string source string
revision string revision string
creds string creds string
provider flags.SourceOCIProvider provider flags.SourceOCIProvider
ignorePaths []string ignorePaths []string
annotations []string annotations []string
output string output string
debug bool debug bool
reproducible bool reproducible bool
insecure bool insecure bool
resolveSymlinks bool
} }
var pushArtifactArgs = newPushArtifactFlags() var pushArtifactArgs = newPushArtifactFlags()
@ -137,6 +138,7 @@ func init() {
pushArtifactCmd.Flags().BoolVarP(&pushArtifactArgs.debug, "debug", "", false, "display logs from underlying library") pushArtifactCmd.Flags().BoolVarP(&pushArtifactArgs.debug, "debug", "", false, "display logs from underlying library")
pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.reproducible, "reproducible", false, "ensure reproducible image digests by setting the created timestamp to '1970-01-01T00:00:00Z'") pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.reproducible, "reproducible", false, "ensure reproducible image digests by setting the created timestamp to '1970-01-01T00:00:00Z'")
pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.insecure, "insecure-registry", false, "allows artifacts to be pushed without TLS") pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.insecure, "insecure-registry", false, "allows artifacts to be pushed without TLS")
pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.resolveSymlinks, "resolve-symlinks", false, "resolve symlinks by copying their targets into the artifact")
pushCmd.AddCommand(pushArtifactCmd) pushCmd.AddCommand(pushArtifactCmd)
} }
@ -183,6 +185,15 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("invalid path '%s', must point to an existing directory or file: %w", path, err) return fmt.Errorf("invalid path '%s', must point to an existing directory or file: %w", path, err)
} }
if pushArtifactArgs.resolveSymlinks {
resolved, cleanupDir, err := resolveSymlinks(path)
if err != nil {
return fmt.Errorf("resolving symlinks failed: %w", err)
}
defer os.RemoveAll(cleanupDir)
path = resolved
}
annotations := map[string]string{} annotations := map[string]string{}
for _, annotation := range pushArtifactArgs.annotations { for _, annotation := range pushArtifactArgs.annotations {
kv := strings.Split(annotation, "=") kv := strings.Split(annotation, "=")

View file

@ -152,7 +152,14 @@ func reconciliationHandled(kubeClient client.Client, namespacedName types.Namesp
return false, err return false, err
} }
return result.Status == kstatus.CurrentStatus, nil switch result.Status {
case kstatus.CurrentStatus:
return true, nil
case kstatus.InProgressStatus:
return false, nil
default:
return false, fmt.Errorf("%s", result.Message)
}
} }
} }

View file

@ -126,6 +126,17 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
resume.printMessage(reconcileResps) resume.printMessage(reconcileResps)
// Return an error if any reconciliation failed
var failedCount int
for _, r := range reconcileResps {
if r.resumable != nil && r.err != nil {
failedCount++
}
}
if failedCount > 0 {
return fmt.Errorf("reconciliation failed for %d %s(s)", failedCount, resume.kind)
}
return nil return nil
} }

View file

@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
name: gcr-secret
namespace: my-namespace
stringData:
audience: https://custom.audience.example.com
email: sa@project.iam.gserviceaccount.com
token: test-token

View file

@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
name: gcr-secret
namespace: my-namespace
stringData:
audience: https://flux.example.com/hook/6d6c55e9affb9d1e0d101ce604ae4270880ec1ff24d1bd2d928fcd64243d21a4
email: sa@project.iam.gserviceaccount.com
token: test-token

View file

@ -0,0 +1,11 @@
---
apiVersion: v1
kind: Secret
metadata:
annotations:
notification.toolkit.fluxcd.io/webhook: https://flux.example.com/hook/106120121d366c2f67e93200f6c1dbe938235eb588daa5e8c0516d3a77ac1dee
name: receiver-secret
namespace: my-namespace
stringData:
token: test-token

View file

@ -26,6 +26,8 @@ The following template can be used for the GitHub release page:
<!-- Text describing the most important changes in this release --> <!-- Text describing the most important changes in this release -->
ℹ️ Please follow the [Upgrade Procedure for Flux v2.7+](https://github.com/fluxcd/flux2/discussions/5572) for a smooth upgrade from Flux v2.6 to the latest version.
### Fixes and improvements ### Fixes and improvements
<!-- List of fixes and improvements to the controllers and CLI --> <!-- List of fixes and improvements to the controllers and CLI -->
@ -36,7 +38,7 @@ The following template can be used for the GitHub release page:
## Components changelog ## Components changelog
- <name>-controller [v<version>](https://github.com/fluxcd/<name>-controller/blob/<version>/CHANGELOG.md - <name>-controller [v<version>](https://github.com/fluxcd/<name>-controller/blob/<version>/CHANGELOG.md)
## CLI changelog ## CLI changelog

28
go.mod
View file

@ -15,23 +15,23 @@ require (
github.com/fluxcd/helm-controller/api v1.5.3 github.com/fluxcd/helm-controller/api v1.5.3
github.com/fluxcd/image-automation-controller/api v1.1.1 github.com/fluxcd/image-automation-controller/api v1.1.1
github.com/fluxcd/image-reflector-controller/api v1.1.1 github.com/fluxcd/image-reflector-controller/api v1.1.1
github.com/fluxcd/kustomize-controller/api v1.8.2 github.com/fluxcd/kustomize-controller/api v1.8.3
github.com/fluxcd/notification-controller/api v1.8.2 github.com/fluxcd/notification-controller/api v1.8.3
github.com/fluxcd/pkg/apis/event v0.24.1 github.com/fluxcd/pkg/apis/event v0.25.0
github.com/fluxcd/pkg/apis/meta v1.25.1 github.com/fluxcd/pkg/apis/meta v1.26.0
github.com/fluxcd/pkg/auth v0.38.4 github.com/fluxcd/pkg/auth v0.40.0
github.com/fluxcd/pkg/chartutil v1.22.1 github.com/fluxcd/pkg/chartutil v1.23.0
github.com/fluxcd/pkg/envsubst v1.5.0 github.com/fluxcd/pkg/envsubst v1.5.0
github.com/fluxcd/pkg/git v0.43.1 github.com/fluxcd/pkg/git v0.46.0
github.com/fluxcd/pkg/kustomize v1.27.1 github.com/fluxcd/pkg/kustomize v1.28.0
github.com/fluxcd/pkg/oci v0.60.1 github.com/fluxcd/pkg/oci v0.63.0
github.com/fluxcd/pkg/runtime v0.100.4 github.com/fluxcd/pkg/runtime v0.103.0
github.com/fluxcd/pkg/sourceignore v0.17.0 github.com/fluxcd/pkg/sourceignore v0.17.0
github.com/fluxcd/pkg/ssa v0.67.3 github.com/fluxcd/pkg/ssa v0.70.0
github.com/fluxcd/pkg/ssh v0.24.0 github.com/fluxcd/pkg/ssh v0.24.0
github.com/fluxcd/pkg/tar v0.17.0 github.com/fluxcd/pkg/tar v0.17.0
github.com/fluxcd/pkg/version v0.12.0 github.com/fluxcd/pkg/version v0.14.0
github.com/fluxcd/source-controller/api v1.8.1 github.com/fluxcd/source-controller/api v1.8.2
github.com/fluxcd/source-watcher/api/v2 v2.1.1 github.com/fluxcd/source-watcher/api/v2 v2.1.1
github.com/go-git/go-git/v5 v5.16.5 github.com/go-git/go-git/v5 v5.16.5
github.com/go-logr/logr v1.4.3 github.com/go-logr/logr v1.4.3
@ -128,7 +128,7 @@ require (
github.com/fatih/color v1.18.0 // indirect github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fluxcd/pkg/apis/acl v0.9.0 // indirect github.com/fluxcd/pkg/apis/acl v0.9.0 // indirect
github.com/fluxcd/pkg/apis/kustomize v1.15.1 // indirect github.com/fluxcd/pkg/apis/kustomize v1.16.0 // indirect
github.com/fluxcd/pkg/cache v0.13.0 // indirect github.com/fluxcd/pkg/cache v0.13.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect

60
go.sum
View file

@ -180,48 +180,48 @@ github.com/fluxcd/image-automation-controller/api v1.1.1 h1:uiu7kjdVoW8/461HOemX
github.com/fluxcd/image-automation-controller/api v1.1.1/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660= github.com/fluxcd/image-automation-controller/api v1.1.1/go.mod h1:lkD/drkD6Wc+2SDjVj5KqfozEucTLFexWgby/5ft660=
github.com/fluxcd/image-reflector-controller/api v1.1.1 h1:4Bj1abzVnjj8+b/293kNeFMRJc+y2wO8Z12ReZ/gA0w= github.com/fluxcd/image-reflector-controller/api v1.1.1 h1:4Bj1abzVnjj8+b/293kNeFMRJc+y2wO8Z12ReZ/gA0w=
github.com/fluxcd/image-reflector-controller/api v1.1.1/go.mod h1:j4JSIocL42HQ77Veg1t60sApOy+lng8/cbXHXGSnfi0= github.com/fluxcd/image-reflector-controller/api v1.1.1/go.mod h1:j4JSIocL42HQ77Veg1t60sApOy+lng8/cbXHXGSnfi0=
github.com/fluxcd/kustomize-controller/api v1.8.2 h1:LcFUjJccwNrhCo7pQBBneLAlHfZZcb58bWB2LnyFwag= github.com/fluxcd/kustomize-controller/api v1.8.3 h1:Ux9AAOY0lkP6FgRg5/b/ITvRSy8lz6VBBaZ9bXmTLmI=
github.com/fluxcd/kustomize-controller/api v1.8.2/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc= github.com/fluxcd/kustomize-controller/api v1.8.3/go.mod h1:c/mUPIffDDLg1EicXCJtX4N/rc+z5Zh0e/CXjhd7Dyc=
github.com/fluxcd/notification-controller/api v1.8.2 h1:TDrXohUC5Gh3BF+v2ux9/zEG1Ax8u49WDW+3Y6GiIEc= github.com/fluxcd/notification-controller/api v1.8.3 h1:edYpC/t4pNw/KQur189SRC1XtFNU597ooDTCrW90Xmw=
github.com/fluxcd/notification-controller/api v1.8.2/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA= github.com/fluxcd/notification-controller/api v1.8.3/go.mod h1:ozgJGQPy0dG5eOsLZlwAr6n0q/y6+TWd1fGOtavlXJA=
github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA= github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA=
github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4= github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4=
github.com/fluxcd/pkg/apis/event v0.24.1 h1:TClVdn02aiq3sAl9BuzLjjTIxm3JJ83fJ9nchtBa4qg= github.com/fluxcd/pkg/apis/event v0.25.0 h1:zdwytvDhG+fk+Ywl5DOtv7TklkrVgM21WHm1f+YhleE=
github.com/fluxcd/pkg/apis/event v0.24.1/go.mod h1:TlK8HWYrTwl0raqBRC+ROoNpYW5fdVnwcwOBOx5Kzw8= github.com/fluxcd/pkg/apis/event v0.25.0/go.mod h1:TlK8HWYrTwl0raqBRC+ROoNpYW5fdVnwcwOBOx5Kzw8=
github.com/fluxcd/pkg/apis/kustomize v1.15.1 h1:t9QZh+3ZS8EKmlxrnnbcKZcGTrg8FDvMF1T8BHMCuqI= github.com/fluxcd/pkg/apis/kustomize v1.16.0 h1:PhWXEhqQqsisIpwp1/wHvTvo+MO+GGzsBPoN0ZnRE3Y=
github.com/fluxcd/pkg/apis/kustomize v1.15.1/go.mod h1:IZOy4CCtR/hxMGb7erK1RfbGnczVv4/dRBoVD37AywI= github.com/fluxcd/pkg/apis/kustomize v1.16.0/go.mod h1:IZOy4CCtR/hxMGb7erK1RfbGnczVv4/dRBoVD37AywI=
github.com/fluxcd/pkg/apis/meta v1.25.1 h1:WG1GIC/SOz0GjxT0uVuO6AMicQ3yFsk6bDozCnq+fto= github.com/fluxcd/pkg/apis/meta v1.26.0 h1:dxP1FfBpTCYso6odzRcltVnnRuBb2VyhhgV0VX9YbUE=
github.com/fluxcd/pkg/apis/meta v1.25.1/go.mod h1:c7o6mJGLCMvNrfdinGZehkrdZuFT9vZdZNrn66DtVD0= github.com/fluxcd/pkg/apis/meta v1.26.0/go.mod h1:c7o6mJGLCMvNrfdinGZehkrdZuFT9vZdZNrn66DtVD0=
github.com/fluxcd/pkg/auth v0.38.4 h1:xVsJ1rakUm5zS2tOKguZOQc5g6wLgCNxW2a9exidd4M= github.com/fluxcd/pkg/auth v0.40.0 h1:p6Kw6KH+z8oRqngKhmTt8ILKD/rC+8tP87a//kLZhi8=
github.com/fluxcd/pkg/auth v0.38.4/go.mod h1:KTXOh770ukcyQfC8NavEFzm110ORSQRan0v/kjzgFXs= github.com/fluxcd/pkg/auth v0.40.0/go.mod h1:Oq/hIEKUMTbL2bv5blf+EhC/jXXJLsOjIMtJj/AtG3Y=
github.com/fluxcd/pkg/cache v0.13.0 h1:MqtlgOwIVcGKKgV422e39O+KFSVMWuExKeRaMDBjJlk= github.com/fluxcd/pkg/cache v0.13.0 h1:MqtlgOwIVcGKKgV422e39O+KFSVMWuExKeRaMDBjJlk=
github.com/fluxcd/pkg/cache v0.13.0/go.mod h1:0xRZ1hitrIFQ6pl68ke2wZLbIqA2VLzY78HpDo9DVxs= github.com/fluxcd/pkg/cache v0.13.0/go.mod h1:0xRZ1hitrIFQ6pl68ke2wZLbIqA2VLzY78HpDo9DVxs=
github.com/fluxcd/pkg/chartutil v1.22.1 h1:ufI9LJ4d5T79h9ruBQRoRcSmuI/KkcwEqWdxu/9Xub8= github.com/fluxcd/pkg/chartutil v1.23.0 h1:ohstQEVnrBIbN85FGu83hnmAohLl0PdOoPlsM6+cjyI=
github.com/fluxcd/pkg/chartutil v1.22.1/go.mod h1:4/2mpNLyfox3uey++hG21AePPsMWekdhSWAtSdDiubQ= github.com/fluxcd/pkg/chartutil v1.23.0/go.mod h1:kFhmD6DwBgRsvC1ilINsomargMi2WbqvSndWQLikkLc=
github.com/fluxcd/pkg/envsubst v1.5.0 h1:S07mo+MkGhptdHA4pRze5HPKlc8tHxKswNdcMZi1WDY= github.com/fluxcd/pkg/envsubst v1.5.0 h1:S07mo+MkGhptdHA4pRze5HPKlc8tHxKswNdcMZi1WDY=
github.com/fluxcd/pkg/envsubst v1.5.0/go.mod h1:c3a8DYI855sZUubHFYQbjfjop6Wu4/zg1cLyf7SnCes= github.com/fluxcd/pkg/envsubst v1.5.0/go.mod h1:c3a8DYI855sZUubHFYQbjfjop6Wu4/zg1cLyf7SnCes=
github.com/fluxcd/pkg/git v0.43.1 h1:lw29P44wueKzQk79KnYyvisfw//cxg0S4cDeTYx+Slo= github.com/fluxcd/pkg/git v0.46.0 h1:QMh0+ZzQ2jO6rIGj4ffR5trZ8g/cxvt8cVajReJ8Iyw=
github.com/fluxcd/pkg/git v0.43.1/go.mod h1:3R/AjCe7ee7FqWcAG+2IiuJPOCxrGHF4SCGkuvKS6OQ= github.com/fluxcd/pkg/git v0.46.0/go.mod h1:iHcIjx9c8zye3PQiajTJYxgOMRiy7WCs+hfLKDswpfI=
github.com/fluxcd/pkg/gittestserver v0.25.1 h1:40Ridmy1xKxBM9ItDn012R4VKmaoDqzvGaC5g7xv+mw= github.com/fluxcd/pkg/gittestserver v0.26.0 h1:+RZrCzFRsE+d5WaqAoqaPCEgcgv/jZp6+f7DS0+Ynb8=
github.com/fluxcd/pkg/gittestserver v0.25.1/go.mod h1:7fybYb0yej1fFNiF1ohs0Jr0XzyaZQ/cRh3AFEoCtuc= github.com/fluxcd/pkg/gittestserver v0.26.0/go.mod h1:7fybYb0yej1fFNiF1ohs0Jr0XzyaZQ/cRh3AFEoCtuc=
github.com/fluxcd/pkg/kustomize v1.27.1 h1:BLOBNLb2N5ObttZA8XJhZ2NqNY1ZjBqQtTpNlIx8/L4= github.com/fluxcd/pkg/kustomize v1.28.0 h1:0RuFVczJRabbt8frHZ/ql8aqte6BOOKk274O09l6/hE=
github.com/fluxcd/pkg/kustomize v1.27.1/go.mod h1:A2RQTe9woDPiwJDWFlkoP4oF9eX9DeXr89FEkKnSObk= github.com/fluxcd/pkg/kustomize v1.28.0/go.mod h1:cW08mnngSP8MJYb6mDmMvxH8YjNATdiML0udb37dk+M=
github.com/fluxcd/pkg/oci v0.60.1 h1:mT6WBX+MBIcczzEnw/W4cfXyt5JSRNhRoB/UnJ72K6M= github.com/fluxcd/pkg/oci v0.63.0 h1:ZPKTT2C+gWYjhP63xC76iTPdYE9w3ABcsDq77uhAgwo=
github.com/fluxcd/pkg/oci v0.60.1/go.mod h1:w2FGseUl3WGjwRMH/3h6MTI4gKahcBQtnGbn/TQVA34= github.com/fluxcd/pkg/oci v0.63.0/go.mod h1:qMPz4njvm6hJzdyGSb8ydSqrapXxTQwJonxHIsdeXSQ=
github.com/fluxcd/pkg/runtime v0.100.4 h1:rwvbeoeWN0BTJORJBISJJEkWn6DVfmWwynFl2GseWns= github.com/fluxcd/pkg/runtime v0.103.0 h1:J5y5GPhWdkyqIUBlaI1FP2N02TtZmsjbWhhZubuTSFk=
github.com/fluxcd/pkg/runtime v0.100.4/go.mod h1:M6LjRJ1hIe2s6E2ykFfae1Xy/rLvOFQf2QquMKmN350= github.com/fluxcd/pkg/runtime v0.103.0/go.mod h1:mbo2f3azo3yVQgm7XZGxQB6/2zvzQ5Wgtd8TjRRwwAw=
github.com/fluxcd/pkg/sourceignore v0.17.0 h1:Z72nruRMhC15zIEpWoDrAcJcJ1El6QDnP/aRDfE4WOA= github.com/fluxcd/pkg/sourceignore v0.17.0 h1:Z72nruRMhC15zIEpWoDrAcJcJ1El6QDnP/aRDfE4WOA=
github.com/fluxcd/pkg/sourceignore v0.17.0/go.mod h1:3e/VmYLId0pI/H5sK7W9Ibif+j0Ahns9RxNjDMtTTfY= github.com/fluxcd/pkg/sourceignore v0.17.0/go.mod h1:3e/VmYLId0pI/H5sK7W9Ibif+j0Ahns9RxNjDMtTTfY=
github.com/fluxcd/pkg/ssa v0.67.3 h1:mjuhH5fNOYstkF6jB7EeaWmfnt5T272Cup8ZD9O8YBQ= github.com/fluxcd/pkg/ssa v0.70.0 h1:IBylYPiTK1IEdCC2DvjKXIhwQcbd5VufXA9WS3zO+tE=
github.com/fluxcd/pkg/ssa v0.67.3/go.mod h1:6igtlt7/zF+nNFQpa5ZAkkvtpL6o36NRU39/PqqC+Bg= github.com/fluxcd/pkg/ssa v0.70.0/go.mod h1:6igtlt7/zF+nNFQpa5ZAkkvtpL6o36NRU39/PqqC+Bg=
github.com/fluxcd/pkg/ssh v0.24.0 h1:hrPlxs0hhXf32DRqs68VbsXs0XfQMphyRVIk0rYYJa4= github.com/fluxcd/pkg/ssh v0.24.0 h1:hrPlxs0hhXf32DRqs68VbsXs0XfQMphyRVIk0rYYJa4=
github.com/fluxcd/pkg/ssh v0.24.0/go.mod h1:xWammEqalrpurpcMiixJRXtynRQtBEoqheyU5F/vWrg= github.com/fluxcd/pkg/ssh v0.24.0/go.mod h1:xWammEqalrpurpcMiixJRXtynRQtBEoqheyU5F/vWrg=
github.com/fluxcd/pkg/tar v0.17.0 h1:uNxbFXy8ly8C7fJ8D7w3rjTNJFrb4Hp1aY/30XkfvxY= github.com/fluxcd/pkg/tar v0.17.0 h1:uNxbFXy8ly8C7fJ8D7w3rjTNJFrb4Hp1aY/30XkfvxY=
github.com/fluxcd/pkg/tar v0.17.0/go.mod h1:b1xyIRYDD0ket4SV5u0UXYv+ZdN/O/HmIO5jZQdHQls= github.com/fluxcd/pkg/tar v0.17.0/go.mod h1:b1xyIRYDD0ket4SV5u0UXYv+ZdN/O/HmIO5jZQdHQls=
github.com/fluxcd/pkg/version v0.12.0 h1:MGbdbNf2D5wazMqAkNPn+Lh5j+oY0gxQJFTGyet5Hfc= github.com/fluxcd/pkg/version v0.14.0 h1:T3llSc8sUnsuFrW5ng2ePSfXwGXUKv0YG9QXf0ErhWw=
github.com/fluxcd/pkg/version v0.12.0/go.mod h1:YHdg/78kzf+kCqS+SqSOiUxum5AjxlixiqwpX6AUZB8= github.com/fluxcd/pkg/version v0.14.0/go.mod h1:YHdg/78kzf+kCqS+SqSOiUxum5AjxlixiqwpX6AUZB8=
github.com/fluxcd/source-controller/api v1.8.1 h1:49HiJF5mNEdZTwueQMRahTVts35B+xhN5CsuOAL9gQ0= github.com/fluxcd/source-controller/api v1.8.2 h1:i0/6BeNCn+zRfX+gKh4PsFF2NBzBhwXt0wPImVlZObg=
github.com/fluxcd/source-controller/api v1.8.1/go.mod h1:HgZ6NSH1cyOE2jRoNwln1xEwr9ETvrLeiy1o4O04vQM= github.com/fluxcd/source-controller/api v1.8.2/go.mod h1:HgZ6NSH1cyOE2jRoNwln1xEwr9ETvrLeiy1o4O04vQM=
github.com/fluxcd/source-watcher/api/v2 v2.1.1 h1:1LfT50ty+78MKKbschAZl28QbVqIyjaNq17KmW5wPJI= github.com/fluxcd/source-watcher/api/v2 v2.1.1 h1:1LfT50ty+78MKKbschAZl28QbVqIyjaNq17KmW5wPJI=
github.com/fluxcd/source-watcher/api/v2 v2.1.1/go.mod h1:6M1BzBGQRoIuSenSQlfJHwMVVobFPiNPxXqfN0IILc4= github.com/fluxcd/source-watcher/api/v2 v2.1.1/go.mod h1:6M1BzBGQRoIuSenSQlfJHwMVVobFPiNPxXqfN0IILc4=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=

View file

@ -0,0 +1,68 @@
/*
Copyright 2026 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"fmt"
"strings"
notificationv1 "github.com/fluxcd/notification-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/utils"
)
var supportedReceiverTypes = []string{
notificationv1.GenericReceiver,
notificationv1.GenericHMACReceiver,
notificationv1.GitHubReceiver,
notificationv1.GitLabReceiver,
notificationv1.BitbucketReceiver,
notificationv1.HarborReceiver,
notificationv1.DockerHubReceiver,
notificationv1.QuayReceiver,
notificationv1.GCRReceiver,
notificationv1.NexusReceiver,
notificationv1.ACRReceiver,
notificationv1.CDEventsReceiver,
}
type ReceiverType string
func (r *ReceiverType) String() string {
return string(*r)
}
func (r *ReceiverType) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no receiver type given, please specify %s",
r.Description())
}
if !utils.ContainsItemString(supportedReceiverTypes, str) {
return fmt.Errorf("receiver type '%s' is not supported, must be one of: %s",
str, strings.Join(supportedReceiverTypes, ", "))
}
*r = ReceiverType(str)
return nil
}
func (r *ReceiverType) Type() string {
return strings.Join(supportedReceiverTypes, "|")
}
func (r *ReceiverType) Description() string {
return "the receiver type"
}

View file

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.2/kustomize-controller.crds.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.2/kustomize-controller.deployment.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.deployment.yaml
- account.yaml - account.yaml
transformers: transformers:
- labels.yaml - labels.yaml

View file

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.2/notification-controller.crds.yaml - https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.2/notification-controller.deployment.yaml - https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.deployment.yaml
- account.yaml - account.yaml
transformers: transformers:
- labels.yaml - labels.yaml

View file

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/source-controller/releases/download/v1.8.1/source-controller.crds.yaml - https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v1.8.1/source-controller.deployment.yaml - https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.deployment.yaml
- account.yaml - account.yaml
transformers: transformers:
- labels.yaml - labels.yaml

View file

@ -1,10 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/source-controller/releases/download/v1.8.1/source-controller.crds.yaml - https://github.com/fluxcd/source-controller/releases/download/v1.8.2/source-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.2/kustomize-controller.crds.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v1.8.3/kustomize-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v1.5.3/helm-controller.crds.yaml - https://github.com/fluxcd/helm-controller/releases/download/v1.5.3/helm-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v1.8.2/notification-controller.crds.yaml - https://github.com/fluxcd/notification-controller/releases/download/v1.8.3/notification-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.1/image-reflector-controller.crds.yaml - https://github.com/fluxcd/image-reflector-controller/releases/download/v1.1.1/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.1/image-automation-controller.crds.yaml - https://github.com/fluxcd/image-automation-controller/releases/download/v1.1.1/image-automation-controller.crds.yaml
- https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.crds.yaml - https://github.com/fluxcd/source-watcher/releases/download/v2.1.1/source-watcher.crds.yaml

View file

@ -42,6 +42,12 @@ const (
KnownHostsSecretKey = "known_hosts" KnownHostsSecretKey = "known_hosts"
BearerTokenKey = "bearerToken" BearerTokenKey = "bearerToken"
TrustPolicyKey = "trustpolicy.json" TrustPolicyKey = "trustpolicy.json"
TokenSecretKey = "token"
EmailSecretKey = "email"
AudienceSecretKey = "audience"
// WebhookURLAnnotation is the annotation key for the computed webhook URL.
WebhookURLAnnotation = "notification.toolkit.fluxcd.io/webhook"
// Deprecated: Replaced by CACrtSecretKey, but kept for backwards // Deprecated: Replaced by CACrtSecretKey, but kept for backwards
// compatibility with deprecated TLS flags. // compatibility with deprecated TLS flags.
@ -82,6 +88,13 @@ type Options struct {
GitHubAppInstallationID string GitHubAppInstallationID string
GitHubAppPrivateKey string GitHubAppPrivateKey string
GitHubAppBaseURL string GitHubAppBaseURL string
// Receiver options
ReceiverType string
Token string
Hostname string
EmailClaim string
AudienceClaim string
} }
type VerificationCrt struct { type VerificationCrt struct {

View file

@ -18,7 +18,10 @@ package sourcesecret
import ( import (
"bytes" "bytes"
"crypto/rand"
"crypto/sha256"
"encoding/base64" "encoding/base64"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
@ -260,6 +263,59 @@ func GenerateGitHubApp(options Options) (*manifestgen.Manifest, error) {
return secretToManifest(secret, options) return secretToManifest(secret, options)
} }
func GenerateReceiver(options Options) (*manifestgen.Manifest, error) {
token := options.Token
if token == "" {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
return nil, fmt.Errorf("failed to generate random token: %w", err)
}
token = hex.EncodeToString(b)
}
if options.Hostname == "" {
return nil, fmt.Errorf("hostname is required")
}
// Compute the webhook path using the same algorithm as notification-controller.
// See: github.com/fluxcd/notification-controller/api/v1.Receiver.GetWebhookPath
digest := sha256.Sum256([]byte(token + options.Name + options.Namespace))
webhookPath := fmt.Sprintf("/hook/%x", digest)
webhookURL := fmt.Sprintf("https://%s%s", options.Hostname, webhookPath)
secret := &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: options.Name,
Namespace: options.Namespace,
Labels: options.Labels,
Annotations: map[string]string{
WebhookURLAnnotation: webhookURL,
},
},
StringData: map[string]string{
TokenSecretKey: token,
},
}
if options.ReceiverType == "gcr" {
if options.EmailClaim == "" {
return nil, fmt.Errorf("email-claim is required for gcr receiver type")
}
secret.StringData[EmailSecretKey] = options.EmailClaim
if options.AudienceClaim != "" {
secret.StringData[AudienceSecretKey] = options.AudienceClaim
} else {
secret.StringData[AudienceSecretKey] = webhookURL
}
}
return secretToManifest(secret, options)
}
func LoadKeyPairFromPath(path, password string) (*ssh.KeyPair, error) { func LoadKeyPairFromPath(path, password string) (*ssh.KeyPair, error) {
if path == "" { if path == "" {
return nil, nil return nil, nil

View file

@ -1,15 +1,10 @@
# RFC-0010 Multi-Tenant Workload Identity # RFC-0010 Multi-Tenant Workload Identity
**Status:** implementable **Status:** implemented
<!--
Status represents the current state of the RFC.
Must be one of `provisional`, `implementable`, `implemented`, `deferred`, `rejected`, `withdrawn`, or `replaced`.
-->
**Creation date:** 2025-02-22 **Creation date:** 2025-02-22
**Last update:** 2025-04-29 **Last update:** 2026-03-13
## Summary ## Summary
@ -1420,10 +1415,11 @@ options to call `gcp.NewTokenSource()` and feed this token source to the
`HelmRepository` and `HelmChart`, as well as for SOPS decryption `HelmRepository` and `HelmChart`, as well as for SOPS decryption
in the `Kustomization` API and Azure Event Hubs in the in the `Kustomization` API and Azure Event Hubs in the
`Provider` API. `Provider` API.
* In Flux 2.7 object-level workload identity was introduced for all
<!-- the remaining APIs that support cloud providers, i.e. `Bucket`,
Major milestones in the lifecycle of the RFC such as: `GitRepository` and `ImageUpdateAutomation`, and also all the
- The first Flux release where an initial version of the RFC was available. remaining types for the `Provider` API, i.e. `azuredevops` and
- The version of Flux where the RFC graduated to general availability. `googlepubsub`. In addition, support for controller and
- The version of Flux where the RFC was retired or superseded. object-level workload identity was introduced for the
--> `Kustomization` and `HelmRelease` APIs for remote cluster
access.

View file

@ -1,15 +1,10 @@
# RFC-0011: OpenTelemetry Tracing # RFC-0011: OpenTelemetry Tracing
**Status:** provisional **Status:** implemented
<!--
Status represents the current state of the RFC.
Must be one of `provisional`, `implementable`, `implemented`, `deferred`, `rejected`, `withdrawn`, or `replaced`.
-->
**Creation date:** 2025-04-24 **Creation date:** 2025-04-24
**Last update:** 2025-08-13 **Last update:** 2026-03-13
## Summary ## Summary
The aim is to be able to collect traces via OpenTelemetry (OTel) across all Flux related objects, such as HelmReleases, Kustomizations and among others. These may be sent towards a tracing provider where may be potentially stored and visualized. Flux does not have any responsibility on storing and visualizing those, it keeps being completely stateless. Thereby, being seamless for the user, the implementation is going to be part of the already existing `Alert` API Type. Therefore, `EventSources` is going to discriminate the events belonging to the specific sources, which are going to be looked up to and send them out towards the `Provider` set. In this way, it could facilitate the observability and monitoring of Flux related objects. The aim is to be able to collect traces via OpenTelemetry (OTel) across all Flux related objects, such as HelmReleases, Kustomizations and among others. These may be sent towards a tracing provider where may be potentially stored and visualized. Flux does not have any responsibility on storing and visualizing those, it keeps being completely stateless. Thereby, being seamless for the user, the implementation is going to be part of the already existing `Alert` API Type. Therefore, `EventSources` is going to discriminate the events belonging to the specific sources, which are going to be looked up to and send them out towards the `Provider` set. In this way, it could facilitate the observability and monitoring of Flux related objects.
@ -210,9 +205,4 @@ This design ensures trace continuity even in challenging distributed environment
## Implementation History ## Implementation History
<!-- * RFC implemented and generally available in Flux [v2.7.0](https://github.com/fluxcd/flux2/releases/tag/v2.7.0)
Major milestones in the lifecycle of the RFC such as:
- The first Flux release where an initial version of the RFC was available.
- The version of Flux where the RFC graduated to general availability.
- The version of Flux where the RFC was retired or superseded.
-->

View file

@ -1,10 +1,10 @@
# RFC-0012 External Artifact # RFC-0012 External Artifact
**Status:** provisional **Status:** implemented
**Creation date:** 2025-04-08 **Creation date:** 2025-04-08
**Last update:** 2025-09-03 **Last update:** 2026-03-13
## Summary ## Summary
@ -319,9 +319,4 @@ control the adoption of the `ExternalArtifact` feature in their clusters.
## Implementation History ## Implementation History
<!-- * RFC implemented and generally available in Flux [v2.7.0](https://github.com/fluxcd/flux2/releases/tag/v2.7.0)
Major milestones in the lifecycle of the RFC such as:
- The first Flux release where an initial version of the RFC was available.
- The version of Flux where the RFC graduated to general availability.
- The version of Flux where the RFC was retired or superseded.
-->

View file

@ -11,10 +11,10 @@ require (
github.com/fluxcd/image-reflector-controller/api v1.0.4 github.com/fluxcd/image-reflector-controller/api v1.0.4
github.com/fluxcd/kustomize-controller/api v1.7.3 github.com/fluxcd/kustomize-controller/api v1.7.3
github.com/fluxcd/notification-controller/api v1.7.5 github.com/fluxcd/notification-controller/api v1.7.5
github.com/fluxcd/pkg/apis/event v0.24.1 github.com/fluxcd/pkg/apis/event v0.25.0
github.com/fluxcd/pkg/apis/meta v1.25.1 github.com/fluxcd/pkg/apis/meta v1.26.0
github.com/fluxcd/pkg/git v0.43.1 github.com/fluxcd/pkg/git v0.46.0
github.com/fluxcd/pkg/runtime v0.100.4 github.com/fluxcd/pkg/runtime v0.103.0
github.com/fluxcd/source-controller/api v1.7.4 github.com/fluxcd/source-controller/api v1.7.4
github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b
github.com/go-git/go-git/v5 v5.16.5 github.com/go-git/go-git/v5 v5.16.5
@ -66,9 +66,9 @@ require (
github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fluxcd/pkg/apis/acl v0.9.0 // indirect github.com/fluxcd/pkg/apis/acl v0.9.0 // indirect
github.com/fluxcd/pkg/apis/kustomize v1.15.1 // indirect github.com/fluxcd/pkg/apis/kustomize v1.16.0 // indirect
github.com/fluxcd/pkg/ssh v0.24.0 // indirect github.com/fluxcd/pkg/ssh v0.24.0 // indirect
github.com/fluxcd/pkg/version v0.12.0 // indirect github.com/fluxcd/pkg/version v0.14.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.7.0 // indirect github.com/go-git/go-billy/v5 v5.7.0 // indirect

View file

@ -136,22 +136,22 @@ github.com/fluxcd/notification-controller/api v1.7.5 h1:6CO5bKyjodiK9exQFOdBcz0X
github.com/fluxcd/notification-controller/api v1.7.5/go.mod h1:IciwSg8Q0pVtdbsyDyEXx/MxBKWeagxAazpm64C8oCE= github.com/fluxcd/notification-controller/api v1.7.5/go.mod h1:IciwSg8Q0pVtdbsyDyEXx/MxBKWeagxAazpm64C8oCE=
github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA= github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA=
github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4= github.com/fluxcd/pkg/apis/acl v0.9.0/go.mod h1:TttNS+gocsGLwnvmgVi3/Yscwqrjc17+vhgYfqkfrV4=
github.com/fluxcd/pkg/apis/event v0.24.1 h1:TClVdn02aiq3sAl9BuzLjjTIxm3JJ83fJ9nchtBa4qg= github.com/fluxcd/pkg/apis/event v0.25.0 h1:zdwytvDhG+fk+Ywl5DOtv7TklkrVgM21WHm1f+YhleE=
github.com/fluxcd/pkg/apis/event v0.24.1/go.mod h1:TlK8HWYrTwl0raqBRC+ROoNpYW5fdVnwcwOBOx5Kzw8= github.com/fluxcd/pkg/apis/event v0.25.0/go.mod h1:TlK8HWYrTwl0raqBRC+ROoNpYW5fdVnwcwOBOx5Kzw8=
github.com/fluxcd/pkg/apis/kustomize v1.15.1 h1:t9QZh+3ZS8EKmlxrnnbcKZcGTrg8FDvMF1T8BHMCuqI= github.com/fluxcd/pkg/apis/kustomize v1.16.0 h1:PhWXEhqQqsisIpwp1/wHvTvo+MO+GGzsBPoN0ZnRE3Y=
github.com/fluxcd/pkg/apis/kustomize v1.15.1/go.mod h1:IZOy4CCtR/hxMGb7erK1RfbGnczVv4/dRBoVD37AywI= github.com/fluxcd/pkg/apis/kustomize v1.16.0/go.mod h1:IZOy4CCtR/hxMGb7erK1RfbGnczVv4/dRBoVD37AywI=
github.com/fluxcd/pkg/apis/meta v1.25.1 h1:WG1GIC/SOz0GjxT0uVuO6AMicQ3yFsk6bDozCnq+fto= github.com/fluxcd/pkg/apis/meta v1.26.0 h1:dxP1FfBpTCYso6odzRcltVnnRuBb2VyhhgV0VX9YbUE=
github.com/fluxcd/pkg/apis/meta v1.25.1/go.mod h1:c7o6mJGLCMvNrfdinGZehkrdZuFT9vZdZNrn66DtVD0= github.com/fluxcd/pkg/apis/meta v1.26.0/go.mod h1:c7o6mJGLCMvNrfdinGZehkrdZuFT9vZdZNrn66DtVD0=
github.com/fluxcd/pkg/git v0.43.1 h1:lw29P44wueKzQk79KnYyvisfw//cxg0S4cDeTYx+Slo= github.com/fluxcd/pkg/git v0.46.0 h1:QMh0+ZzQ2jO6rIGj4ffR5trZ8g/cxvt8cVajReJ8Iyw=
github.com/fluxcd/pkg/git v0.43.1/go.mod h1:3R/AjCe7ee7FqWcAG+2IiuJPOCxrGHF4SCGkuvKS6OQ= github.com/fluxcd/pkg/git v0.46.0/go.mod h1:iHcIjx9c8zye3PQiajTJYxgOMRiy7WCs+hfLKDswpfI=
github.com/fluxcd/pkg/gittestserver v0.25.1 h1:40Ridmy1xKxBM9ItDn012R4VKmaoDqzvGaC5g7xv+mw= github.com/fluxcd/pkg/gittestserver v0.26.0 h1:+RZrCzFRsE+d5WaqAoqaPCEgcgv/jZp6+f7DS0+Ynb8=
github.com/fluxcd/pkg/gittestserver v0.25.1/go.mod h1:7fybYb0yej1fFNiF1ohs0Jr0XzyaZQ/cRh3AFEoCtuc= github.com/fluxcd/pkg/gittestserver v0.26.0/go.mod h1:7fybYb0yej1fFNiF1ohs0Jr0XzyaZQ/cRh3AFEoCtuc=
github.com/fluxcd/pkg/runtime v0.100.4 h1:rwvbeoeWN0BTJORJBISJJEkWn6DVfmWwynFl2GseWns= github.com/fluxcd/pkg/runtime v0.103.0 h1:J5y5GPhWdkyqIUBlaI1FP2N02TtZmsjbWhhZubuTSFk=
github.com/fluxcd/pkg/runtime v0.100.4/go.mod h1:M6LjRJ1hIe2s6E2ykFfae1Xy/rLvOFQf2QquMKmN350= github.com/fluxcd/pkg/runtime v0.103.0/go.mod h1:mbo2f3azo3yVQgm7XZGxQB6/2zvzQ5Wgtd8TjRRwwAw=
github.com/fluxcd/pkg/ssh v0.24.0 h1:hrPlxs0hhXf32DRqs68VbsXs0XfQMphyRVIk0rYYJa4= github.com/fluxcd/pkg/ssh v0.24.0 h1:hrPlxs0hhXf32DRqs68VbsXs0XfQMphyRVIk0rYYJa4=
github.com/fluxcd/pkg/ssh v0.24.0/go.mod h1:xWammEqalrpurpcMiixJRXtynRQtBEoqheyU5F/vWrg= github.com/fluxcd/pkg/ssh v0.24.0/go.mod h1:xWammEqalrpurpcMiixJRXtynRQtBEoqheyU5F/vWrg=
github.com/fluxcd/pkg/version v0.12.0 h1:MGbdbNf2D5wazMqAkNPn+Lh5j+oY0gxQJFTGyet5Hfc= github.com/fluxcd/pkg/version v0.14.0 h1:T3llSc8sUnsuFrW5ng2ePSfXwGXUKv0YG9QXf0ErhWw=
github.com/fluxcd/pkg/version v0.12.0/go.mod h1:YHdg/78kzf+kCqS+SqSOiUxum5AjxlixiqwpX6AUZB8= github.com/fluxcd/pkg/version v0.14.0/go.mod h1:YHdg/78kzf+kCqS+SqSOiUxum5AjxlixiqwpX6AUZB8=
github.com/fluxcd/source-controller/api v1.7.4 h1:+EOVnRA9LmLxOx7J273l7IOEU39m+Slt/nQGBy69ygs= github.com/fluxcd/source-controller/api v1.7.4 h1:+EOVnRA9LmLxOx7J273l7IOEU39m+Slt/nQGBy69ygs=
github.com/fluxcd/source-controller/api v1.7.4/go.mod h1:ruf49LEgZRBfcP+eshl2n9SX1MfHayCcViAIGnZcaDY= github.com/fluxcd/source-controller/api v1.7.4/go.mod h1:ruf49LEgZRBfcP+eshl2n9SX1MfHayCcViAIGnZcaDY=
github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b h1:FSPtvaVgL8azcyweqLmD71elAw4vozuXH/QvsJQ7tg0= github.com/fluxcd/test-infra/tftestenv v0.0.0-20250626232827-e0ca9c3f8d7b h1:FSPtvaVgL8azcyweqLmD71elAw4vozuXH/QvsJQ7tg0=