From 39434f911e5e2e9b627cea3afdb270d91a4f6733 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Thu, 11 Jun 2026 11:51:47 +0200 Subject: [PATCH 01/13] Upgrade golang.org/x/net to v0.55.0 Bumps golang.org/x/net from v0.48.0 to v0.55.0. Signed-off-by: Thomas Maas --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 353dbb5..a7f5dea 100644 --- a/go.mod +++ b/go.mod @@ -82,14 +82,14 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect - golang.org/x/net v0.48.0 // indirect + golang.org/x/net v0.55.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools v0.44.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect diff --git a/go.sum b/go.sum index 0a7d7ab..109339e 100644 --- a/go.sum +++ b/go.sum @@ -199,35 +199,35 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 76f1f446d12158d39c1ef7c6db6a399370ffee08 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Mon, 22 Jun 2026 10:52:34 +0200 Subject: [PATCH 02/13] Bump golangci-lint to v2.12 for Go 1.26 support Signed-off-by: Thomas Maas --- .github/workflows/lint.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 339202b..41aef48 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,4 +20,4 @@ jobs: - name: Run linter uses: golangci/golangci-lint-action@v9 with: - version: v2.6 + version: v2.12 diff --git a/Makefile b/Makefile index 925efff..8c5b815 100644 --- a/Makefile +++ b/Makefile @@ -261,7 +261,7 @@ CONTROLLER_TOOLS_VERSION ?= v0.18.0 ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}') #ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31) ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}') -GOLANGCI_LINT_VERSION ?= v2.1.0 +GOLANGCI_LINT_VERSION ?= v2.12.2 .PHONY: kustomize kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. From 26ba671e2e576415eb0c4844cf1f5387a329bf22 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Mon, 22 Jun 2026 12:30:17 +0200 Subject: [PATCH 03/13] Exclude goconst from test files Signed-off-by: Thomas Maas --- .golangci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index e5b21b0..fbac0d4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -36,6 +36,9 @@ linters: - dupl - lll path: internal/* + - linters: + - goconst + path: _test\.go paths: - third_party$ - builtin$ From 84a8dfdd78aa7b11934ade1d72542968000d5cb1 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Mon, 22 Jun 2026 13:46:07 +0200 Subject: [PATCH 04/13] Disable goconst linter Signed-off-by: Thomas Maas --- .golangci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index fbac0d4..389995b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,7 +8,6 @@ linters: - dupl - errcheck - ginkgolinter - - goconst - gocyclo - govet - ineffassign @@ -36,9 +35,6 @@ linters: - dupl - lll path: internal/* - - linters: - - goconst - path: _test\.go paths: - third_party$ - builtin$ From 6d116b6cbd957e6f1fe35600fcd7ae2865e3dc74 Mon Sep 17 00:00:00 2001 From: R-Lawton Date: Mon, 29 Jun 2026 16:23:38 +0100 Subject: [PATCH 05/13] chore: add contributor governance workflow Adds the thin caller workflow for the centralized contributor governance automation from Kuadrant/.github#3. Signed-off-by: R-Lawton Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Thomas Maas --- .github/workflows/contributor-governance.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/contributor-governance.yml diff --git a/.github/workflows/contributor-governance.yml b/.github/workflows/contributor-governance.yml new file mode 100644 index 0000000..67b99b3 --- /dev/null +++ b/.github/workflows/contributor-governance.yml @@ -0,0 +1,12 @@ +name: Contributor Governance + +on: + issues: + types: [opened, labeled, unlabeled] + pull_request_target: + types: [opened, reopened] + +jobs: + governance: + uses: Kuadrant/.github/.github/workflows/contributor-governance.yml@main + secrets: inherit From 3b61d9682fff7193d3aa67aa2575c1d24448a334 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Mon, 29 Jun 2026 18:02:35 +0200 Subject: [PATCH 06/13] contribution guidelines Signed-off-by: Eguzki Astiz Lezaun Signed-off-by: Thomas Maas --- CONTRIBUTING.md | 28 ++++++++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ed8eec2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing + +For general Kuadrant contribution guidance, see the [Kuadrant contributing guide](https://kuadrant.io/contributing/). + +This document covers the automated governance rules enforced in this repository and the project-specific workflow for getting a contribution merged. + +## Issue Triage + +All new issues are automatically labelled `triage/needs-triage`. A maintainer will review and move the issue to `triage/accepted` once it has been discussed and prioritised. + +| Label | Meaning | +|---|---| +| `triage/needs-triage` | New issue, awaiting maintainer review | +| `triage/accepted` | Reviewed, prioritised, and ready for work | + +Only Kuadrant org members can change triage labels. If a non-member attempts to add or remove a triage label, the change is automatically reverted. + +## Pull Request Requirements + +Every PR from an external contributor must: + +1. **Link to an issue** — use `Fixes #123` or `Closes #123` in the PR description, or link it via the GitHub sidebar. +2. **Link to a triaged issue** — the linked issue must carry the `triage/accepted` label before the PR is opened. +3. **Not duplicate existing work** — if another contributor already has an open PR for the same issue, your PR will be auto-drafted until that one is resolved. + +PRs that do not meet these requirements are automatically closed with an explanatory comment. Your branch is kept intact, so you can reopen once the requirements are satisfied. + +This enforcement is implemented by the [Kuadrant contributor governance workflow](https://github.com/Kuadrant/.github/blob/main/.github/workflows/contributor-governance.yml), called from [`.github/workflows/contributor-governance.yml`](.github/workflows/contributor-governance.yml) in this repo. diff --git a/README.md b/README.md index 569011a..31b8560 100644 --- a/README.md +++ b/README.md @@ -630,6 +630,10 @@ spec: EOF ``` +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. + ## License Copyright 2025. From 7e97208a80d27754c90c4355690e5fefcd7083f8 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Mon, 22 Jun 2026 10:21:53 +0200 Subject: [PATCH 07/13] Upgrade Go to 1.26.3 Signed-off-by: Thomas Maas --- Dockerfile | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index b8e0c29..6205c41 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM --platform=$BUILDPLATFORM golang:1.25 AS builder +FROM --platform=$BUILDPLATFORM golang:1.26 AS builder ARG TARGETOS ARG TARGETARCH ARG GIT_SHA diff --git a/go.mod b/go.mod index a7f5dea..2f93544 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kuadrant/developer-portal-controller -go 1.25.9 +go 1.26.3 require ( github.com/go-logr/logr v1.4.3 From aa75f654fd0b6897c7582c9792bdfc984c375d4e Mon Sep 17 00:00:00 2001 From: R-Lawton Date: Thu, 2 Jul 2026 17:08:01 +0100 Subject: [PATCH 08/13] docs: add contributing guide with issue policy Link to the centralised Kuadrant contributing guide and add a repo-specific issue policy requiring assignment before work begins. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: R-Lawton Signed-off-by: Thomas Maas --- CONTRIBUTING.md | 130 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 16 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed8eec2..781dc97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,28 +1,126 @@ # Contributing -For general Kuadrant contribution guidance, see the [Kuadrant contributing guide](https://kuadrant.io/contributing/). +For general contribution guidelines, PR requirements, and issue triage rules, see the [Kuadrant contributing guide](https://github.com/Kuadrant/.github/blob/main/CONTRIBUTING.md). -This document covers the automated governance rules enforced in this repository and the project-specific workflow for getting a contribution merged. +## Issue Policy -## Issue Triage +**Do not start work on an issue unless it has been assigned to you by a maintainer.** -All new issues are automatically labelled `triage/needs-triage`. A maintainer will review and move the issue to `triage/accepted` once it has been discussed and prioritised. +Issues go through a triage and planning process before they are ready for contribution. Working on unassigned issues — whether manually or via AI coding agents — wastes your time and ours. -| Label | Meaning | -|---|---| -| `triage/needs-triage` | New issue, awaiting maintainer review | -| `triage/accepted` | Reviewed, prioritised, and ready for work | +**Pull requests submitted against unassigned issues will be automatically closed and will not be reopened.** -Only Kuadrant org members can change triage labels. If a non-member attempts to add or remove a triage label, the change is automatically reverted. +If you're interested in contributing to an issue, leave a comment and wait for a maintainer to assign it to you before starting any work. -## Pull Request Requirements +## Contributions -Every PR from an external contributor must: +We welcome code and non-code contributions to our project. Non-code contributions can come in the form of documentation updates, bug reports, enhancement requests, and feature requests. -1. **Link to an issue** — use `Fixes #123` or `Closes #123` in the PR description, or link it via the GitHub sidebar. -2. **Link to a triaged issue** — the linked issue must carry the `triage/accepted` label before the PR is opened. -3. **Not duplicate existing work** — if another contributor already has an open PR for the same issue, your PR will be auto-drafted until that one is resolved. +### Finding Issues to Work On -PRs that do not meet these requirements are automatically closed with an explanatory comment. Your branch is kept intact, so you can reopen once the requirements are satisfied. +The best place to start is to look through our issues for [bugs](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3Akind%2Fbug), [good first issues](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22), and [help wanted](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). These are a great starting point for new contributors. -This enforcement is implemented by the [Kuadrant contributor governance workflow](https://github.com/Kuadrant/.github/blob/main/.github/workflows/contributor-governance.yml), called from [`.github/workflows/contributor-governance.yml`](.github/workflows/contributor-governance.yml) in this repo. +Remember: only work on issues that are `triage/accepted` and assigned to you. + +### Bug Reporting + +If you found a bug, please submit an [issue](https://github.com/Kuadrant/developer-portal-controller/issues/new) describing the problem. Include: + +- Steps to reproduce the bug +- The Kubernetes/OpenShift version you are running +- CRD versions installed +- Any relevant logs + +### Enhancement Requests + +If you want an enhancement of a feature or workflow, submit an [issue](https://github.com/Kuadrant/developer-portal-controller/issues/new) describing the enhancement. Include: + +- What you are wanting to see improved +- The current behavior +- The new behavior you wish to see + +### Feature Requests + +If you want to see a new feature, file an [issue](https://github.com/Kuadrant/developer-portal-controller/issues/new) detailing the new feature. Include: + +- What you are trying to achieve with the new feature +- What you will need +- Any relevant documentation or information on the new feature + +### Documentation + +If there is documentation that is unclear or could use some improvements, please raise an issue or submit a pull request. + +### Pull Requests + +If you want to submit code changes to the project, here are some guidelines: + +1. **Create a Branch** + + ```bash + git checkout -b your-feature-branch + ``` + +2. **Implement Your Changes** + + Make your code changes, ensuring that you follow the project's coding standards and best practices. + + If you modify API types in `api/v1alpha1/*_types.go`, regenerate code and CRDs: + + ```bash + make manifests generate + ``` + +3. **Testing** + + Ensure all tests pass before committing. + + ```bash + make test # run unit tests with coverage + make test-e2e # run e2e tests (creates/deletes Kind cluster) + go test ./internal/controller -v # run controller tests only + ``` + +4. **Linting and Formatting** + + Ensure your code passes linting and formatting checks. + + ```bash + make fmt # run go fmt + make vet # run go vet + make lint # run golangci-lint + ``` + +5. **Ensure CI Passes** + + Your contributions will need to pass the Continuous Integration (CI) tests for pull requests. + +6. **Commit Changes** + + Use meaningful commit messages following the [Conventional Commits](https://www.conventionalcommits.org/) specification. + + ```bash + git commit -m "feat: add new feature" + ``` + +7. **Push to Your Fork** + + ```bash + git push origin your-feature-branch + ``` + +8. **Open a Pull Request** + + Go to the original repository and click on **New Pull Request**. Provide a clear description of your changes, including any issues your PR fixes, acceptance criteria, and any special notes to the reviewers. + +## Commit Messages + +Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification: + +- `feat`: A new feature. +- `fix`: A bug fix. +- `docs`: Documentation changes. +- `style`: Code style changes (formatting, missing semi-colons, etc.). +- `refactor`: Code changes that neither fix a bug nor add a feature. +- `test`: Adding or correcting tests. +- `chore`: Changes to the build process or auxiliary tools. From 7bd475d41dd11bcad44a9bca62fa45b66704f913 Mon Sep 17 00:00:00 2001 From: Rachel Lawton Date: Fri, 3 Jul 2026 15:57:37 +0100 Subject: [PATCH 09/13] docs: add maintainers-only issue policy to contributing guide Signed-off-by: Rachel Lawton Signed-off-by: R-Lawton Signed-off-by: Thomas Maas --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 781dc97..4ce2b1f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,6 +12,8 @@ Issues go through a triage and planning process before they are ready for contri If you're interested in contributing to an issue, leave a comment and wait for a maintainer to assign it to you before starting any work. +Issues labelled `maintainers-only` are reserved for the maintainer team and are not available for external contribution. + ## Contributions We welcome code and non-code contributions to our project. Non-code contributions can come in the form of documentation updates, bug reports, enhancement requests, and feature requests. From 0d7375ca76419a658c8bdbf88603a6af38241d04 Mon Sep 17 00:00:00 2001 From: Rachel Lawton Date: Fri, 3 Jul 2026 16:17:04 +0100 Subject: [PATCH 10/13] docs: remove help wanted label reference from contributing guide Signed-off-by: Rachel Lawton Signed-off-by: R-Lawton Signed-off-by: Thomas Maas --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ce2b1f..2a2e3ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ We welcome code and non-code contributions to our project. Non-code contribution ### Finding Issues to Work On -The best place to start is to look through our issues for [bugs](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3Akind%2Fbug), [good first issues](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22), and [help wanted](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). These are a great starting point for new contributors. +The best place to start is to look through our issues for [bugs](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3Akind%2Fbug) and [good first issues](https://github.com/Kuadrant/developer-portal-controller/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22). These are a great starting point for new contributors. Remember: only work on issues that are `triage/accepted` and assigned to you. From d0d1de99ffcee374150b9d35fbafae251d85cae2 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Mon, 6 Jul 2026 18:04:12 +0200 Subject: [PATCH 11/13] Upgrade Go to 1.26.4 Signed-off-by: Thomas Maas --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2f93544..297e06c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kuadrant/developer-portal-controller -go 1.26.3 +go 1.26.4 require ( github.com/go-logr/logr v1.4.3 From 1c772951084d1e429b8eb42c534c43576435ab6e Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Fri, 10 Jul 2026 13:39:18 +0200 Subject: [PATCH 12/13] fix: watch Secrets to clear transient APIKey failures The APIKey status controller sets SecretNotFound when the referenced Secret does not exist yet. However, no watched resource changes when the Secret is subsequently created, so the APIKey stays stuck in Failed state permanently. Add a Secret watch so creation/updates trigger re-reconciliation. The existing calculateFailedCondition logic already re-evaluates and clears the failure when the Secret appears. Fixes #78 Signed-off-by: Thomas Maas --- internal/controller/apikey_status_controller.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/controller/apikey_status_controller.go b/internal/controller/apikey_status_controller.go index b1bfa0f..d011e9a 100644 --- a/internal/controller/apikey_status_controller.go +++ b/internal/controller/apikey_status_controller.go @@ -53,7 +53,7 @@ type APIKeyStatusReconciler struct { // +kubebuilder:rbac:groups=devportal.kuadrant.io,resources=apiproducts,verbs=get;list;watch // +kubebuilder:rbac:groups=devportal.kuadrant.io,resources=apikeyapprovals,verbs=get;list;watch // +kubebuilder:rbac:groups=devportal.kuadrant.io,resources=apikeyrequests,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=secrets,verbs=get +// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch // +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=httproutes,verbs=get;list;watch // +kubebuilder:rbac:groups=kuadrant.io,resources=kuadrants,verbs=get;list;watch @@ -557,6 +557,7 @@ func (r *APIKeyStatusReconciler) SetupWithManager(mgr ctrl.Manager) error { Watches(&devportalv1alpha1.APIKeyRequest{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass)). Watches(&devportalv1alpha1.APIKeyApproval{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass)). Watches(&gwapiv1.HTTPRoute{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass)). + Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass)). Named("apikey-status"). Complete(r) } From 76d49eac1b7dc1ee17080b64ba144531cb9a98d7 Mon Sep 17 00:00:00 2001 From: Thomas Maas Date: Fri, 10 Jul 2026 13:45:57 +0200 Subject: [PATCH 13/13] test: add regression test for Secret-after-APIKey recovery Verify that an APIKey in SecretNotFound state recovers when the referenced Secret is subsequently created. This is the scenario triggered by the console-plugin's ownerReference flow (PR #541) where the APIKey is created before its Secret. Ref #78 Signed-off-by: Thomas Maas --- .../apikey_status_controller_test.go | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/internal/controller/apikey_status_controller_test.go b/internal/controller/apikey_status_controller_test.go index 4169540..06aa279 100644 --- a/internal/controller/apikey_status_controller_test.go +++ b/internal/controller/apikey_status_controller_test.go @@ -313,6 +313,91 @@ var _ = Describe("APIKey Status Controller", func() { }, time.Second*10, time.Millisecond*250).Should(Succeed()) }) + // Regression test for https://github.com/Kuadrant/developer-portal-controller/issues/78 + // + // When the console-plugin creates an APIKey before its Secret (to set + // an ownerReference for garbage collection), the status controller + // sets SecretNotFound on the first reconciliation. Without a Secret + // watch, no subsequent event triggers re-reconciliation, so the + // APIKey stays stuck in Failed permanently even after the Secret + // appears. This test verifies that creating the Secret clears the + // failure. + It("should clear Failed condition when Secret is created after the APIKey", func() { + controllerReconciler := &APIKeyStatusReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + + secretName := "late-arriving-secret" + + By("Creating an APIKey that references a Secret that does not exist yet") + apiKeyObj := &devportalv1alpha1.APIKey{ + ObjectMeta: metav1.ObjectMeta{ + Name: "apikey-late-secret", + Namespace: consumerNamespace, + }, + Spec: devportalv1alpha1.APIKeySpec{ + APIProductRef: devportalv1alpha1.APIProductReference{ + Name: apiProductName, + Namespace: apiProductNamespace, + }, + SecretRef: corev1.LocalObjectReference{ + Name: secretName, + }, + PlanTier: "premium", + UseCase: "Testing secret recovery", + RequestedBy: devportalv1alpha1.RequestedBy{ + UserID: "test-user", + Email: "test@example.com", + }, + }, + } + Expect(k8sClient.Create(ctx, apiKeyObj)).To(Succeed()) + + By("Running reconciliation — should set SecretNotFound") + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{}) + Expect(err).NotTo(HaveOccurred()) + + updatedAPIKey := &devportalv1alpha1.APIKey{} + Eventually(func(g Gomega) { + err := k8sClient.Get(ctx, types.NamespacedName{ + Name: "apikey-late-secret", + Namespace: consumerNamespace, + }, updatedAPIKey) + g.Expect(err).NotTo(HaveOccurred()) + failedCondition := meta.FindStatusCondition(updatedAPIKey.Status.Conditions, devportalv1alpha1.APIKeyConditionFailed) + g.Expect(failedCondition).NotTo(BeNil()) + g.Expect(failedCondition.Reason).To(Equal("SecretNotFound")) + }, time.Second*10, time.Millisecond*250).Should(Succeed()) + + By("Creating the Secret that the APIKey references") + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: consumerNamespace, + }, + Type: corev1.SecretTypeOpaque, + Data: map[string][]byte{ + "api_key": []byte("test-key-value"), + }, + } + Expect(k8sClient.Create(ctx, secret)).To(Succeed()) + + By("Running reconciliation — should clear the Failed condition") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{}) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func(g Gomega) { + err := k8sClient.Get(ctx, types.NamespacedName{ + Name: "apikey-late-secret", + Namespace: consumerNamespace, + }, updatedAPIKey) + g.Expect(err).NotTo(HaveOccurred()) + failedCondition := meta.FindStatusCondition(updatedAPIKey.Status.Conditions, devportalv1alpha1.APIKeyConditionFailed) + g.Expect(failedCondition).To(BeNil(), "Failed condition should be cleared after Secret is created") + }, time.Second*10, time.Millisecond*250).Should(Succeed()) + }) + It("should set Pending condition when no approval exists", func() { controllerReconciler := &APIKeyStatusReconciler{ Client: k8sClient,