Skip to content

feat: handle usersignup rejected state#1267

Open
mfrancisc wants to merge 5 commits into
codeready-toolchain:masterfrom
mfrancisc:handlerejected
Open

feat: handle usersignup rejected state#1267
mfrancisc wants to merge 5 commits into
codeready-toolchain:masterfrom
mfrancisc:handlerejected

Conversation

@mfrancisc
Copy link
Copy Markdown
Contributor

@mfrancisc mfrancisc commented May 29, 2026

Add setStatusRejected status updater and wire it into the reconcile loop so users with the Rejected state are labelled and their status is set to Complete/Rejected instead of falling through to provisioning.

related PRs:

Summary by CodeRabbit

  • New Features

    • Rejected user signups now transition to a "rejected" state, update the signup completion condition with a rejection reason and message, and halt downstream provisioning.
  • Tests

    • Added test coverage verifying rejected signups do not create downstream resources, do not increment related metrics, and that rejection status and notification conditions are set as expected.

mfrancisc and others added 2 commits May 29, 2026 11:01
Add setStatusRejected status updater and wire it into the reconcile
loop so users with the Rejected state are labelled and their status
is set to Complete/Rejected instead of falling through to provisioning.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cover the reconcile path where a UserSignup has the Rejected state set,
asserting the state label is updated to "rejected" and the Complete
condition is set to True with reason Rejected.

Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci openshift-ci Bot requested review from jrosental and metlos May 29, 2026 09:10
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 2828013c-f679-40b6-be5c-c4bcd379fd83

📥 Commits

Reviewing files that changed from the base of the PR and between 134de0c and 7e57744.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • go.mod
💤 Files with no reviewable changes (1)
  • go.mod
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: GolangCI Lint
  • GitHub Check: govulncheck
  • GitHub Check: test
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
🧰 Additional context used
🔀 Multi-repo context codeready-toolchain/registration-service, codeready-toolchain/toolchain-e2e, codeready-toolchain/api, codeready-toolchain/toolchain-common, codeready-toolchain/member-operator

codeready-toolchain/registration-service

  • Reads/checks the UserSignup Complete condition and gates behavior via checkUserSignupCompleted:
    • pkg/signup/service/signup_service.go:330, 442, 456-458 — FindConditionByType(..., UserSignupComplete) and if completeCondition.Status != ConditionTrue && checkUserSignupCompleted { ... } [::codeready-toolchain/registration-service::pkg/signup/service/signup_service.go:330]
    • GetSignup/DoGetSignup signatures include checkUserSignupCompleted flag used by proxy handlers and services [::codeready-toolchain/registration-service::pkg/signup/service/signup_service.go:382-386]
  • Tests & fakes rely on constructing a Complete condition:
    • pkg/signup/service/signup_service_test.go:703 and related helpers newUserSignupComplete() [::codeready-toolchain/registration-service::pkg/signup/service/signup_service_test.go:703]
    • test/fake/conditions.go:11 builds UserSignupComplete for fakes [::codeready-toolchain/registration-service::test/fake/conditions.go:11]
  • Proxy/metrics reference Rejected label:
    • pkg/proxy/metrics/proxy_metrics.go:8 — MetricLabelRejected = "Rejected" [::codeready-toolchain/registration-service::pkg/proxy/metrics/proxy_metrics.go:8]
  • Impact: registration-service behavior/tests that depend on whether UserSignupComplete is true (and its Reason) may be affected when host-operator sets Complete=True with Reason=Rejected.

codeready-toolchain/toolchain-e2e

  • Multiple wait helpers block on UserSignupComplete:
    • testsupport/wait/conditions.go:71,87,103,117,136,146,157,168,178,262,282,302,322,350,375,411 — references to toolchainv1alpha1.UserSignupComplete used in test waits [::codeready-toolchain/toolchain-e2e::testsupport/wait/conditions.go:71]
  • Impact: e2e tests may need updates to expect Complete=True with Reason=Rejected (or to handle rejected semantics) for rejected UserSignup resources.

codeready-toolchain/api

  • Declares the rejected label/state/reason/constants used by host-operator:
    • api/v1alpha1/usersignup_types.go:12 — UserSignupComplete ConditionType = "Complete" [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:12]
    • api/v1alpha1/usersignup_types.go:80-81 — UserSignupStateLabelValueRejected = "rejected" [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:80]
    • api/v1alpha1/usersignup_types.go:110 — UserSignupUserRejectedReason = "Rejected" [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:110]
    • api/v1alpha1/usersignup_types.go:171-173 — UserSignupStateRejected = UserSignupState("rejected") [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:171]

codeready-toolchain/toolchain-common

  • Provides state helpers and test helpers used by the change:
    • pkg/states/state_manager.go:53-57 — Rejected(...) and SetRejected(...) operate on UserSignupStateRejected [::codeready-toolchain/toolchain-common::pkg/states/state_manager.go:53]
    • pkg/test/usersignup/usersignup.go:95,110,123,164,176 — test user signup builders include UserSignupComplete condition usage [::codeready-toolchain/toolchain-common::pkg/test/usersignup/usersignup.go:95]

codeready-toolchain/member-operator

  • No matches found for UserSignupComplete, rejected, or SetRejected in broad search — no direct references observed in this scan [::codeready-toolchain/member-operator::]

Overall conclusion

  • Relevant cross-repo consumers found: registration-service and toolchain-e2e both read/wait on UserSignupComplete; registration-service additionally uses a checkUserSignupCompleted flag to skip checking completion in some contexts. Because the PR sets rejected UserSignup to Complete=True with Reason=Rejected and labels state=rejected, tests and runtime logic in registration-service and e2e suites may need updates to handle or expect this behavior. The api and toolchain-common repos already declare the needed constants/helpers.

Walkthrough

This PR implements a Rejected state for UserSignup by adding a status updater method, inserting a Reconcile branch that sets the Rejected label and status and returns early, adding a controller test verifying no provisioning occurs for rejected users, and updating go.mod dependency versions.

Changes

User signup rejected state

Layer / File(s) Summary
Rejected status condition method
controllers/usersignup/status_updater.go
New setStatusRejected method sets the UserSignupComplete condition to True with UserSignupUserRejectedReason and an optional message; minor import formatting change.
Rejected state reconciliation logic
controllers/usersignup/usersignup_controller.go
Reconcile now checks for the rejected state immediately after the banned branch, updates the state label to Rejected, calls the rejected status updater, and returns early before deactivation/provisioning.
Test coverage for rejected state
controllers/usersignup/usersignup_controller_test.go
TestUserSignupRejected verifies a rejected UserSignup does not create MasterUserRecord, Space, or SpaceBinding; has rejected state label and UserSignupUserRejectedReason; and does not increment banned/deactivated/approved/unique metrics.
API dependency updates
go.mod
Updates pseudo-versions for github.com/codeready-toolchain/api and github.com/codeready-toolchain/toolchain-common.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

feature, test, dependencies

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding functionality to handle the rejected state for UserSignup resources.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added dependencies Pull requests that update a dependency file feature New feature or request test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness) labels May 29, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
controllers/usersignup/usersignup_controller.go (1)

170-172: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Rejected-state check is ordered too late in reconcile flow.

At Line 170, checkIfMurAlreadyExists(...) can return early before the new rejected branch (Line 185), so rejected signups with an existing MUR can bypass rejected handling and continue the non-rejected path.

Proposed fix
-	if exists, err := r.checkIfMurAlreadyExists(ctx, config, userSignup, banned); err != nil || exists {
-		return reconcile.Result{}, err
-	}
-
 	// If there is no MasterUserRecord created, yet the UserSignup is Banned, simply set the status
 	// and return
 	if banned {
 		// if the UserSignup doesn't have the state=banned label set, then update it
 		if err := r.setStateLabel(ctx, config, userSignup, toolchainv1alpha1.UserSignupStateLabelValueBanned); err != nil {
 			return reconcile.Result{}, err
 		}
 
 		return reconcile.Result{}, r.updateStatus(ctx, userSignup, r.setStatusBanned)
 	}
 
 	// Check if the user has been rejected
 	if states.Rejected(userSignup) {
 		if err := r.setStateLabel(ctx, config, userSignup, toolchainv1alpha1.UserSignupStateLabelValueRejected); err != nil {
 			return reconcile.Result{}, err
 		}
 		return reconcile.Result{}, r.updateStatus(ctx, userSignup, r.setStatusRejected)
 	}
+
+	if exists, err := r.checkIfMurAlreadyExists(ctx, config, userSignup, banned); err != nil || exists {
+		return reconcile.Result{}, err
+	}

Also applies to: 185-191

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controllers/usersignup/usersignup_controller.go` around lines 170 - 172, The
current reconcile flow calls checkIfMurAlreadyExists(ctx, config, userSignup,
banned) before handling the "rejected" branch, which allows rejected userSignups
with existing MURs to bypass rejected handling; fix by moving the rejected-state
check so that the code inspects userSignup's rejected state (the branch
currently at lines ~185-191) and executes the rejected handling path before
calling checkIfMurAlreadyExists, or alternatively adjust the conditional around
checkIfMurAlreadyExists to skip/return if userSignup.IsRejected() so
checkIfMurAlreadyExists never short-circuits a rejected signup; reference
checkIfMurAlreadyExists, userSignup (the rejected branch currently after it),
and the reconcile return path to locate and reorder/update the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Around line 160-163: Remove the local path replace directives from go.mod that
reference github.com/codeready-toolchain/api and
github.com/codeready-toolchain/toolchain-common; instead revert to canonical
module versions (or move those local overrides into a developer-only go.work) so
module resolution is deterministic in CI. Locate the replace block containing
"github.com/codeready-toolchain/api => ../api" and
"github.com/codeready-toolchain/toolchain-common => ../toolchain-common" and
delete those lines (or relocate them to a go.work used only for local
development).

---

Outside diff comments:
In `@controllers/usersignup/usersignup_controller.go`:
- Around line 170-172: The current reconcile flow calls
checkIfMurAlreadyExists(ctx, config, userSignup, banned) before handling the
"rejected" branch, which allows rejected userSignups with existing MURs to
bypass rejected handling; fix by moving the rejected-state check so that the
code inspects userSignup's rejected state (the branch currently at lines
~185-191) and executes the rejected handling path before calling
checkIfMurAlreadyExists, or alternatively adjust the conditional around
checkIfMurAlreadyExists to skip/return if userSignup.IsRejected() so
checkIfMurAlreadyExists never short-circuits a rejected signup; reference
checkIfMurAlreadyExists, userSignup (the rejected branch currently after it),
and the reconcile return path to locate and reorder/update the logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 81e07af2-48dd-457d-b66b-1eb516e5b3c7

📥 Commits

Reviewing files that changed from the base of the PR and between e74ff80 and f295528.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (4)
  • controllers/usersignup/status_updater.go
  • controllers/usersignup/usersignup_controller.go
  • controllers/usersignup/usersignup_controller_test.go
  • go.mod
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: GolangCI Lint
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • controllers/usersignup/usersignup_controller.go
  • controllers/usersignup/usersignup_controller_test.go
  • go.mod
  • controllers/usersignup/status_updater.go
🔀 Multi-repo context codeready-toolchain/api, codeready-toolchain/toolchain-common, codeready-toolchain/registration-service, codeready-toolchain/member-operator, codeready-toolchain/toolchain-e2e

Linked repositories findings

  • [::codeready-toolchain/api::]

    • Contains UserSignupComplete condition type (api/v1alpha1/usersignup_types.go:12-13). The host-operator PR introduces a new status reason constant (UserSignupUserRejectedReason) which is not present in this file — API repo likely needs an update to add that reason. [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:12-13]
  • [::codeready-toolchain/toolchain-common::]

    • Tests/helpers reference UserSignupComplete (pkg/test/usersignup/usersignup.go lines ~95,110,123,164,176). I did not find an existing SetRejected helper or a 'rejected' state constant in the scanned locations; the host-operator PR calls states.SetRejected, so toolchain-common must provide the new state constant/helper (PR #531 referenced). [::codeready-toolchain/toolchain-common::pkg/test/usersignup/usersignup.go:95,110,123,164,176]
  • [::codeready-toolchain/registration-service::]

    • Many locations read the UserSignupComplete condition (tests and service code), e.g. pkg/signup/service/signup_service.go lines referencing condition.FindConditionByType(..., UserSignupComplete). If host-operator sets the Complete condition with reason Rejected, registration-service behavior that checks Complete may be affected; consider whether registration-service expects particular reasons. [::codeready-toolchain/registration-service::pkg/signup/service/signup_service.go:330,442 and test/fake/conditions.go:11]
  • [::codeready-toolchain/member-operator::]

    • No matches for rejected-state/status changes found in the scan; no direct impact observed.
  • [::codeready-toolchain/toolchain-e2e::]

    • Tests wait on UserSignupComplete condition in many helpers (testsupport/wait/conditions.go). Changing Complete reason to Rejected should be visible to e2e checks that inspect condition reason/status; review tests that assert specific reasons if any. [::codeready-toolchain/toolchain-e2e::testsupport/wait/conditions.go:multiple]

Summary / action items:

  • codeready-toolchain/api: add the new status reason constant (UserSignupUserRejectedReason) so host-operator builds against API types.
  • codeready-toolchain/toolchain-common: add 'rejected' state constant and states.SetRejected helper used by host-operator.
  • Review registration-service and e2e tests for any logic that inspects the UserSignup Complete condition reason (they already inspect Complete); ensure they accept the new Rejected reason where appropriate.
🔇 Additional comments (1)
controllers/usersignup/status_updater.go (1)

5-5: LGTM!

Also applies to: 186-198

Comment thread go.mod Outdated
@MatousJobanek
Copy link
Copy Markdown
Contributor

btw, it would be nice to update also e2e tests

@openshift-ci
Copy link
Copy Markdown

openshift-ci Bot commented Jun 1, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: MatousJobanek, metlos, mfrancisc

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [MatousJobanek,metlos,mfrancisc]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot removed dependencies Pull requests that update a dependency file feature New feature or request test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness) labels Jun 3, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@go.mod`:
- Line 67: The go.mod lists an indirect dependency
"github.com/go-bindata/go-bindata v3.1.2+incompatible" that likely isn't
required; run "go mod why github.com/go-bindata/go-bindata" and search the repo
for any imports referencing "github.com/go-bindata/go-bindata" (or a /v3
variant) to confirm usage, then either remove the stale indirect entry by
running "go mod tidy" (if unused) or update imports and the go.mod to the
canonical "/v3" module if the v3 API is actually required; ensure the final
change updates the go.mod entry accordingly and re-runs tests/build.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 8735911f-2110-4ca3-ad95-d267c10fb0fc

📥 Commits

Reviewing files that changed from the base of the PR and between f295528 and 2aa5167.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • go.mod
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: GolangCI Lint
  • GitHub Check: Build & push operator bundles & dashboard image for e2e tests
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • go.mod
🔀 Multi-repo context codeready-toolchain/api, codeready-toolchain/toolchain-common, codeready-toolchain/registration-service, codeready-toolchain/toolchain-e2e, codeready-toolchain/member-operator

codeready-toolchain/api

  • Defines the new rejected state/value and reason:
    • api/v1alpha1/usersignup_types.go:80 — UserSignupStateLabelValueRejected = "rejected" [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:80]
    • api/v1alpha1/usersignup_types.go:171-173 — UserSignupStateRejected = UserSignupState("rejected") [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:171-173]
    • api/v1alpha1/usersignup_types.go:110 — UserSignupUserRejectedReason = "Rejected" [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:110]
  • Confirms UserSignupComplete ConditionType exists (Complete) [::codeready-toolchain/api::api/v1alpha1/usersignup_types.go:12-13]

codeready-toolchain/toolchain-common

  • Provides state helpers for rejected:
    • pkg/states/state_manager.go:52-57 — Rejected(...) and SetRejected(...) implementations that operate on UserSignupStateRejected [::codeready-toolchain/toolchain-common::pkg/states/state_manager.go:52-57]
  • Test helpers reference UserSignupComplete condition in multiple locations (tests/usersignup helper) [::codeready-toolchain/toolchain-common::pkg/test/usersignup/usersignup.go:95,110,123,164,176]

codeready-toolchain/registration-service

  • Reads/checks UserSignupComplete condition in service logic:
    • pkg/signup/service/signup_service.go:330,442,456-458 — finds/uses UserSignupComplete and checks its Status before proceeding (uses checkUserSignupCompleted flag) [::codeready-toolchain/registration-service::pkg/signup/service/signup_service.go:330,442,456-458]
  • Tests and test fakes reference UserSignupComplete:
    • test/fake/conditions.go:11 — builds condition of type UserSignupComplete [::codeready-toolchain/registration-service::test/fake/conditions.go:11]
  • Also uses a "Rejected" metric label in proxy metrics/tests:
    • pkg/proxy/metrics/proxy_metrics.go:8 — MetricLabelRejected = "Rejected" and multiple test files reference rejected headers/behaviour [::codeready-toolchain/registration-service::pkg/proxy/metrics/proxy_metrics.go:8]

codeready-toolchain/toolchain-e2e

  • Many e2e helpers wait on UserSignupComplete condition (testsupport/wait/conditions.go multiple lines) — tests may observe the Complete condition and its Reason/Status [::codeready-toolchain/toolchain-e2e::testsupport/wait/conditions.go:multiple]

codeready-toolchain/member-operator

  • No matches found for rejected/state changes or UserSignupComplete in search results (no stdout) [::codeready-toolchain/member-operator::]

Conclusion: The API and toolchain-common already contain the 'rejected' state and UserSignupUserRejectedReason and a SetRejected helper; registration-service and e2e reference UserSignupComplete (and registration-service checks condition Status). These repositories are relevant consumers of the status change introduced in the PR.

🔇 Additional comments (2)
go.mod (2)

161-164: Local replace directives are already flagged.

This concern has been raised in a previous review.


5-6: LGTM!

Comment thread go.mod Outdated
@mfrancisc
Copy link
Copy Markdown
Contributor Author

btw, it would be nice to update also e2e tests

@MatousJobanek see codeready-toolchain/toolchain-e2e#1283

@coderabbitai coderabbitai Bot added dependencies Pull requests that update a dependency file feature New feature or request test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness) labels Jun 3, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 3, 2026

@coderabbitai coderabbitai Bot removed dependencies Pull requests that update a dependency file feature New feature or request labels Jun 3, 2026
@coderabbitai coderabbitai Bot removed the test Work that adds, fixes, or maintains automated tests or coverage (unit, integration, e2e, flakiness) label Jun 3, 2026
@mfrancisc
Copy link
Copy Markdown
Contributor Author

/retest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants