Skip to content

Conversation

@ktrysmt
Copy link
Owner

@ktrysmt ktrysmt commented Dec 5, 2025

Summary

This PR addresses issue #326 by replacing all log.Fatal calls in client constructor functions with proper error returns. This allows library users to handle errors gracefully instead of having the entire application crash on authentication errors.

Changes

Modified Functions

  • NewOAuthClientCredentials: Now returns (*Client, error) instead of *Client
  • NewOAuth: Now returns (*Client, error) instead of *Client
  • NewOAuthWithCode: Now returns (*Client, string, error) instead of (*Client, string)
  • NewOAuthWithRefreshToken: Now returns (*Client, string, error) instead of (*Client, string)
  • NewOAuthbearerToken: Now returns (*Client, error) instead of *Client
  • NewBasicAuth: Now returns (*Client, error) instead of *Client
  • injectClient (internal): Now returns (*Client, error) instead of *Client

Additional Changes

  • Removed unused log import from client.go
  • Updated all test files to properly handle the new error returns
  • All errors now include context using fmt.Errorf with %w for error wrapping

Impact

This is a breaking change for existing users of this library. Any code that calls these constructor functions will need to be updated to handle the returned error.

Migration Example

Before:

client := bitbucket.NewBasicAuth(username, password)

After:

client, err := bitbucket.NewBasicAuth(username, password)
if err != nil {
    // Handle error appropriately
    return err
}

Testing

  • All existing tests have been updated and pass
  • Build completes successfully without warnings
  • Code is properly formatted with go fmt

Benefits

  • Library now behaves as a proper Go library
  • Calling applications can handle authentication errors gracefully
  • No more forced application exits on error conditions
  • Better error messages with context

Fixes #326

Replace all log.Fatal calls in client constructor functions with proper
error returns to allow library users to handle errors gracefully instead
of crashing the entire application.

Changes:
- Updated NewOAuthClientCredentials to return (*Client, error)
- Updated NewOAuth to return (*Client, error)
- Updated NewOAuthWithCode to return (*Client, string, error)
- Updated NewOAuthWithRefreshToken to return (*Client, string, error)
- Updated NewOAuthbearerToken to return (*Client, error)
- Updated NewBasicAuth to return (*Client, error)
- Updated injectClient to return (*Client, error)
- Removed unused log import
- Updated all test files to handle the new error returns

This ensures the library behaves as a proper library and doesn't force
the calling application to exit on authentication errors.

Fixes #326

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

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 5, 2025 12:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes log.Fatal calls from client constructor functions and replaces them with proper error returns, allowing library users to handle authentication errors gracefully instead of experiencing forced application exits.

Key Changes:

  • Modified all client constructor functions to return errors alongside client instances
  • Removed the log package import from client.go
  • Updated all test files to handle the new error return values

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
client.go Modified 7 constructor functions to return (*Client, error) and replaced log.Fatal with fmt.Errorf; removed unused log import
tests/workspace_test.go Updated getBitbucketClient helper to handle error return from NewBasicAuth
tests/webhooks_test.go Added error handling for NewBasicAuth call
tests/variable_test.go Added error handling for NewBasicAuth call and reordered imports
tests/user_test.go Added error handling for NewBasicAuth call
tests/ssh_test.go Added error handling for NewBasicAuth call
tests/repository_test.go Added error handling for all NewBasicAuth calls across multiple test functions
tests/repositories_test.go Added error handling for NewBasicAuth calls
tests/project_test.go Updated getClient helper to handle error return from NewBasicAuth
tests/list_test.go Added error handling for NewBasicAuth call
tests/environment_test.go Added error handling for NewBasicAuth calls
tests/diff_test.go Added error handling for NewBasicAuth calls
tests/deploykeys_test.go Added error handling for NewBasicAuth calls
tests/client_test.go Added error handling for NewBasicAuth call
tests/branchrestrictions_test.go Updated setup helper to handle error return from NewBasicAuth
teams.go Removed trailing newline

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ktrysmt, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and usability of the library by transitioning from abrupt application termination via log.Fatal to a more idiomatic Go error handling approach. By returning errors from client constructors, it empowers calling applications to implement custom error recovery strategies, preventing unexpected crashes and providing clearer diagnostic information. This change aligns the library with best practices for Go error management, making it more predictable and easier to integrate into larger systems.

Highlights

  • Error Handling Improvement: Replaced all log.Fatal calls in client constructor functions with proper error returns, allowing library users to handle authentication and client initialization errors gracefully.
  • Function Signature Changes: Modified the signatures of NewOAuthClientCredentials, NewOAuth, NewOAuthWithCode, NewOAuthWithRefreshToken, NewOAuthbearerToken, NewBasicAuth, and injectClient to include an error return type.
  • Error Wrapping: Implemented fmt.Errorf with %w for error wrapping, providing more context to returned errors.
  • Breaking Change: This is a breaking change for existing users, as calls to the modified constructor functions will now require handling the new error return.
  • Test Updates: All existing test files have been updated to correctly handle the new error returns from client constructors.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This is an excellent pull request that significantly improves the library's robustness by replacing log.Fatal calls with proper error returns in client constructors. This change allows consumers of the library to handle authentication and setup errors gracefully. The modifications are thorough, and all tests have been updated accordingly, which is great to see. I have a few minor suggestions to further enhance error handling by adding more context to returned errors and a design recommendation for the NewOAuth function to improve its usability as a library component.

}

func NewOAuth(i, s string) *Client {
func NewOAuth(i, s string) (*Client, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This function NewOAuth interacts directly with stdin and stdout (fmt.Printf and fmt.Scan). This is generally considered an anti-pattern for a library function as it makes it difficult to use in non-interactive environments (e.g., web servers, background jobs) and also makes the function hard to test.

I recommend refactoring this to improve modularity and usability. You could split the logic:

  1. Provide a function that generates and returns the authentication URL.
  2. The library user can then display this URL, obtain the authorization code through their own UI/CLI, and use the existing NewOAuthWithCode function.

This approach would make the library more flexible. The current NewOAuth implementation could be moved to an example file or a separate CLI tool package to demonstrate interactive usage.

Comment on lines 140 to 142
if err != nil {
return nil, "", err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To improve error diagnostics, it's a good practice to wrap the error returned from injectClient to provide more context. This creates a chain of errors that is easier for the caller to inspect and understand.

Suggested change
if err != nil {
return nil, "", err
}
if err != nil {
return nil, "", fmt.Errorf("failed to create client: %w", err)
}

Copy link
Owner Author

Choose a reason for hiding this comment

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

Thank you for the feedback! I've updated the code to wrap the error from injectClient with additional context. This has been addressed in commit bf2edad.

Comment on lines 166 to 168
if err != nil {
return nil, "", err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the comment in NewOAuthWithCode, it would be beneficial to wrap the error returned from injectClient here as well. This will provide more context to the caller, making debugging easier.

Suggested change
if err != nil {
return nil, "", err
}
if err != nil {
return nil, "", fmt.Errorf("failed to create client: %w", err)
}

Improve error diagnostics by wrapping errors returned from injectClient
with additional context in NewOAuthWithCode and NewOAuthWithRefreshToken.
This creates a clearer error chain for callers to inspect and debug.

Changes:
- Wrap injectClient error in NewOAuthWithCode with "failed to create client"
- Wrap injectClient error in NewOAuthWithRefreshToken with "failed to create client"

This addresses review feedback from @gemini-code-assist.
The NewOAuth function uses stdin/stdout directly, making it unsuitable
for non-interactive environments such as web servers and background jobs.

This marks the function as deprecated and recommends using NewOAuthWithCode
instead, where users can obtain the authorization code through their own
UI/CLI implementation.

This addresses the design concern raised in review feedback from
@gemini-code-assist.
@ktrysmt ktrysmt merged commit c7bddf1 into master Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

log.Fatal in constructor? WTF???

2 participants