Skip to content

Conversation

@celebdor
Copy link

@celebdor celebdor commented Oct 3, 2025

Summary

• Extend the existing --auto-open-browser flag to support web login in addition to OIDC login
• Provides a consistent interface for controlling browser behavior across both authentication methods
• When --web is used with --auto-open-browser=false, the authorization URL is printed instead of being automatically opened
• Useful for environments where browser automation is not desired or possible (e.g., Konflux)

Changes

• Extended --auto-open-browser flag to work with both --web and --exec-plugin
• Updated flag documentation to clarify default behavior (true for --web, false for OIDC)
• Set default to true when using --web (unless explicitly overridden)
• Removed --auto-open-browser from OIDC-only validation checks
• Updated login examples to show --auto-open-browser=false usage
• Updated test coverage to reflect new behavior

Test plan

  • Test --web flag without --auto-open-browser (defaults to true, opens browser)
  • Test --web --auto-open-browser=false (prints URL without opening)
  • Test --auto-open-browser with OIDC login (existing behavior preserved)
  • Run all login tests to ensure no regression (all passing)
  • Verify successful build

Fixes: CNTRLPLANE-1538

🤖 Generated with Claude Code

@coderabbitai
Copy link

coderabbitai bot commented Oct 3, 2025

Walkthrough

Adds an --auto-open-browser flag behavior and runtime default for web OIDC login, removes that flag from required OIDC validation, and changes web login flow to optionally print the callback URL instead of launching a browser; tests for validation and URL handling added.

Changes

Cohort / File(s) Summary of changes
CLI flag help & validation
pkg/cli/login/login.go
Adds example showing --web --auto-open-browser=false --callback-port 8280; updates --auto-open-browser flag description to reflect nuanced defaults and contexts; removes OIDCAutoOpenBrowser from the set of required/checked OIDC options during validation.
Login options & runtime behavior
pkg/cli/login/loginoptions.go
Introduces runtime default: when using web login and flag not explicitly set, OIDCAutoOpenBrowser defaults to true. Modifies gatherAuthInfo/WebLogin path to either print instructions and not open a browser when OIDCAutoOpenBrowser is false, or print the URL and open the browser when true; non-web behavior unchanged.
Tests for auto-open behavior
pkg/cli/login/loginoptions_test.go
Adds TestValidateAutoOpenBrowser and TestAutoOpenBrowserURLHandling to cover --web/--auto-open-browser combinations and to verify URL handling/output for both enabled and disabled auto-open scenarios; adds test IO streams, a test loginURLHandler, and necessary imports.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feat(login): extend --auto-open-browser to work with --web" directly corresponds to the primary change in this pull request, which extends the existing --auto-open-browser flag to support web login mode in addition to OIDC login. The changes across login.go, loginoptions.go, and loginoptions_test.go all center on implementing this extension, with modifications to flag documentation, runtime defaults, validation logic, and test coverage. The title is concise, specific, and clearly communicates the main objective to someone reviewing the pull request history.
Description Check ✅ Passed The pull request description is clearly related to the changeset, providing a comprehensive overview of the extension to the --auto-open-browser flag for web login support. It includes a summary explaining the functionality, detailed changes (flag extension, documentation updates, default behavior, and test coverage), and a thorough test plan that aligns with the actual code modifications. The description uses specific, meaningful terms to convey the purpose and implementation details rather than generic language, making it informative and directly relevant to the changes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci openshift-ci bot requested review from ingvagabund and tchap October 3, 2025 10:32
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 3, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: celebdor
Once this PR has been reviewed and has the lgtm label, please assign atiratree for approval. For more information see the Code Review Process.

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

Needs approval from an approver in each of these files:

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

Copy link
Member

@ardaguclu ardaguclu left a comment

Choose a reason for hiding this comment

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

In my opinion, we don't need to introduce a flag for this.
/hold

cmds.Flags().Int32VarP(&o.CallbackPort, "callback-port", "c", o.CallbackPort, "Port for the callback server when using --web. Defaults to a random open port")

if kcmdutil.FeatureGate("OC_ENABLE_WEB_LOGIN_NO_BROWSER").IsEnabled() {
cmds.Flags().BoolVar(&o.NoBrowser, "no-browser", o.NoBrowser, "Print the authorization URL instead of opening it in a browser. Only valid with --web.")
Copy link
Member

@ardaguclu ardaguclu Oct 3, 2025

Choose a reason for hiding this comment

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

I think we need some info about why do we need it.

Because If we talk about standard login in OCP; I'm not sure this can be achieved. If yes, we can either re-use the one that was introduced for OIDC login

cmds.Flags().BoolVar(&o.OIDCAutoOpenBrowser, "auto-open-browser", o.OIDCAutoOpenBrowser, "Experimental: Specify browser is automatically opened or not for external OIDC issuer. Disabled by default.")
or introduce an environment variable to disable this. cc'ing @liouk.

If we talk about OIDC login, it exists

cmds.Flags().BoolVar(&o.OIDCAutoOpenBrowser, "auto-open-browser", o.OIDCAutoOpenBrowser, "Experimental: Specify browser is automatically opened or not for external OIDC issuer. Disabled by default.")
already.

Copy link
Author

Choose a reason for hiding this comment

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

I'm using it mostly for Konflux

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 3, 2025
# Log in to the given server through a browser
oc login localhost:8443 --web --callback-port 8280
oc login localhost:8443 --web --callback-port 8280`
Copy link
Member

Choose a reason for hiding this comment

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

We don't need changes in here.

oc login localhost:8443 --web --callback-port 8280
oc login localhost:8443 --web --callback-port 8280`

if kcmdutil.FeatureGate("OC_ENABLE_WEB_LOGIN_NO_BROWSER").IsEnabled() {
Copy link
Member

Choose a reason for hiding this comment

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

We don't need a feature gate for this.

# Log in to the external OIDC issuer through Auth Code + PKCE by starting a local server listening on port 8080
oc login localhost:8443 --exec-plugin=oc-oidc --client-id=client-id --extra-scopes=email,profile --callback-port=8080
`)
oc login localhost:8443 --exec-plugin=oc-oidc --client-id=client-id --extra-scopes=email,profile --callback-port=8080`
Copy link
Member

Choose a reason for hiding this comment

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

The changes in here is not related.

`)

loginExample = templates.Examples(`
loginExample = func() string {
Copy link
Member

Choose a reason for hiding this comment

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

unrelated change

@celebdor celebdor force-pushed the feat/cntrlplane-1538-no-browser-flag branch from e2e29d8 to 7ca31bb Compare October 17, 2025 10:08
@celebdor celebdor changed the title feat(login): add --no-browser flag for web login feat(login): extend --auto-open-browser to work with --web Oct 17, 2025
Copy link

@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: 0

🧹 Nitpick comments (1)
pkg/cli/login/login.go (1)

107-110: Address past reviewer feedback about the feature gate.

A previous reviewer (ardaguclu) commented that "We don't need a feature gate for this" on the earlier version. The current implementation still uses the feature gate OC_ENABLE_WEB_LOGIN_NO_BROWSER. If there's a specific reason to keep the feature gate (e.g., for staged rollout or experimental status), please clarify this in the PR discussion or consider removing the gate if it's no longer needed.

Additionally, the feature gate string "OC_ENABLE_WEB_LOGIN_NO_BROWSER" is repeated three times (lines 51, 107, 239), which creates maintenance risk.

Consider extracting the feature gate name to a package-level constant:

+const webLoginNoBrowserFeatureGate = "OC_ENABLE_WEB_LOGIN_NO_BROWSER"
+
 var (
 	loginLong = templates.LongDesc(`

Then use it consistently:

-	if kcmdutil.FeatureGate("OC_ENABLE_WEB_LOGIN_NO_BROWSER").IsEnabled() {
+	if kcmdutil.FeatureGate(webLoginNoBrowserFeatureGate).IsEnabled() {

Based on past review comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between e2e29d8 and 7ca31bb.

📒 Files selected for processing (3)
  • pkg/cli/login/login.go (4 hunks)
  • pkg/cli/login/loginoptions.go (2 hunks)
  • pkg/cli/login/loginoptions_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/cli/login/loginoptions.go
  • pkg/cli/login/loginoptions_test.go
🔇 Additional comments (2)
pkg/cli/login/login.go (2)

37-64: LGTM: Clean conditional example generation.

The IIFE pattern appropriately generates examples with conditional content based on the feature gate. Since examples are static and evaluated at package initialization, checking the feature gate once at init time is correct.


239-241: LGTM: Validation logic is correct.

The validation appropriately enforces that --no-browser can only be used with --web, and the feature gate check is consistent with the flag registration. The error message is clear and follows the pattern of other validation errors in this function.

@celebdor celebdor force-pushed the feat/cntrlplane-1538-no-browser-flag branch from 7ca31bb to 6cfbd76 Compare October 17, 2025 10:13
Extend the existing --auto-open-browser flag to support web login
in addition to OIDC login. This provides a consistent interface for
controlling browser behavior across both authentication methods.

Changes:
- Extend --auto-open-browser flag to work with both --web and --exec-plugin
- Update flag documentation to clarify default behavior (true for --web, false for OIDC)
- Set default to true when using --web (unless explicitly overridden)
- Remove --auto-open-browser from OIDC-only validation checks
- Update login examples to show --auto-open-browser=false usage
- Update test coverage to reflect new behavior

When --web is used with --auto-open-browser=false, the authorization
URL is printed instead of being automatically opened in a browser.
This is useful for environments where browser automation is not
desired or possible.

Fixes: CNTRLPLANE-1538

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@celebdor celebdor force-pushed the feat/cntrlplane-1538-no-browser-flag branch from 6cfbd76 to b6d05d7 Compare October 17, 2025 10:14
Copy link

@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

🧹 Nitpick comments (1)
pkg/cli/login/loginoptions_test.go (1)

491-547: Consider adding negative test cases and clarify test case naming.

The validation tests cover valid flag combinations well, but consider:

  1. Missing negative tests: All cases expect no error. If certain flag combinations should be invalid (e.g., --auto-open-browser without --web and without OIDC flags), add tests for those.

  2. Misleading test case name (line 511): The comment says "will default to true" but explicitly sets autoOpenBrowser: false. This test case appears to verify that validation passes when the flag isn't set (which would default at runtime). Consider clarifying the name to reflect what's actually being tested, e.g., "valid: --web when auto-open-browser will use runtime default".

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 6cfbd76 and b6d05d7.

📒 Files selected for processing (3)
  • pkg/cli/login/login.go (4 hunks)
  • pkg/cli/login/loginoptions.go (1 hunks)
  • pkg/cli/login/loginoptions_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/cli/login/login.go
  • pkg/cli/login/loginoptions.go
🔇 Additional comments (1)
pkg/cli/login/loginoptions_test.go (1)

4-4: LGTM!

The new imports (bytes, net/url, strings) are appropriately used in the test functions added below.

Also applies to: 11-11, 13-13

Comment on lines +549 to +625
func TestAutoOpenBrowserURLHandling(t *testing.T) {
testCases := []struct {
name string
autoOpenBrowser bool
expectedOutputRegex string
shouldNotContain string
}{
{
name: "with --auto-open-browser=false prints URL without opening",
autoOpenBrowser: false,
expectedOutputRegex: "Please visit the following URL in your browser: https://example.com/oauth/authorize\\?test=1\nThe callback server is listening and will receive the authentication response.\n",
shouldNotContain: "Opening login URL in the default browser",
},
{
name: "with --auto-open-browser=true shows opening message",
autoOpenBrowser: true,
expectedOutputRegex: "Opening login URL in the default browser: https://example.com/oauth/authorize\\?test=1\n",
shouldNotContain: "Please visit the following URL",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Capture output
outBuf := &bytes.Buffer{}
streams := genericiooptions.IOStreams{
In: strings.NewReader(""),
Out: outBuf,
ErrOut: &bytes.Buffer{},
}

options := &LoginOptions{
WebLogin: true,
OIDCAutoOpenBrowser: tc.autoOpenBrowser,
IOStreams: streams,
}

// Create a test login URL handler that matches the actual implementation
loginURLHandler := func(u *url.URL) error {
loginURL := u.String()
if !options.OIDCAutoOpenBrowser {
fmt.Fprintf(options.Out, "Please visit the following URL in your browser: %s\n", loginURL)
fmt.Fprintf(options.Out, "The callback server is listening and will receive the authentication response.\n")
return nil
} else {
fmt.Fprintf(options.Out, "Opening login URL in the default browser: %s\n", loginURL)
// Don't actually call browser.OpenURL in tests
return nil
}
}

// Test the handler with a test URL
testURL, _ := url.Parse("https://example.com/oauth/authorize?test=1")
err := loginURLHandler(testURL)

if err != nil {
t.Errorf("unexpected error: %v", err)
}

output := outBuf.String()

// Check expected output using regex
matched, regexErr := regexp.MatchString(tc.expectedOutputRegex, output)
if regexErr != nil {
t.Fatalf("regex error: %v", regexErr)
}
if !matched {
t.Errorf("output did not match expected pattern.\nExpected pattern: %s\nActual output: %s", tc.expectedOutputRegex, output)
}

// Check that certain strings are not present
if tc.shouldNotContain != "" && strings.Contains(output, tc.shouldNotContain) {
t.Errorf("output should not contain '%s', but got: %s", tc.shouldNotContain, output)
}
})
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Refactor test to verify actual implementation rather than a mock.

This test defines a local loginURLHandler function (lines 587-598) that duplicates the expected implementation logic, then tests that mock function instead of the actual LoginOptions methods. This approach has significant limitations:

  • If the real implementation in loginoptions.go changes, this test won't catch regressions
  • The test validates its own mock logic, not production code
  • Provides false confidence since it doesn't exercise actual code paths

Consider restructuring to:

  1. Call the actual LoginOptions method that handles web login
  2. Mock the browser-opening dependency (e.g., inject a test browser.OpenURL implementation)
  3. Verify behavior through the actual code path rather than reimplementing the logic in the test

Example approach:

-// Create a test login URL handler that matches the actual implementation
-loginURLHandler := func(u *url.URL) error {
-    loginURL := u.String()
-    if !options.OIDCAutoOpenBrowser {
-        fmt.Fprintf(options.Out, "Please visit the following URL in your browser: %s\n", loginURL)
-        fmt.Fprintf(options.Out, "The callback server is listening and will receive the authentication response.\n")
-        return nil
-    } else {
-        fmt.Fprintf(options.Out, "Opening login URL in the default browser: %s\n", loginURL)
-        // Don't actually call browser.OpenURL in tests
-        return nil
-    }
-}
-
-// Test the handler with a test URL
-testURL, _ := url.Parse("https://example.com/oauth/authorize?test=1")
-err := loginURLHandler(testURL)
+// Mock the browser opener to avoid actually opening a browser
+options.browserOpener = func(url string) error {
+    return nil // no-op in tests
+}
+
+// Call the actual method that handles web login URL
+// (adjust based on actual method name in LoginOptions)
+err := options.handleWebLoginURL("https://example.com/oauth/authorize?test=1")

This ensures the test validates actual production behavior.

Committable suggestion skipped: line range outside the PR's diff.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 17, 2025

@celebdor: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/verify b6d05d7 link true /test verify

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Copy link
Member

@ardaguclu ardaguclu left a comment

Choose a reason for hiding this comment

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

Overall looks good to me. I dropped a comment about test case removal. But verify failure needs to be fixed.

Thanks

}
}

func TestAutoOpenBrowserURLHandling(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

We can remove this test function. Because it seems that it does not exercise the behavior of oc command (it exercises its own custom loginhandler).

Copy link
Author

Choose a reason for hiding this comment

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

Thanks. I'll do that!

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

Labels

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants