Skip to content

Fix TestingBot credential resolution and Test Connection#40

Merged
jochen-testingbot merged 2 commits into
masterfrom
fix-credential-resolution
Jul 17, 2026
Merged

Fix TestingBot credential resolution and Test Connection#40
jochen-testingbot merged 2 commits into
masterfrom
fix-credential-resolution

Conversation

@jochen-testingbot

@jochen-testingbot jochen-testingbot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Two correctness fixes surfaced by an end-to-end run against a real TestingBot account.

1. Credentials never resolved at build time

TestingBotCredentials extended BaseCredentials (implementing StandardCredentials). CredentialsProvider.lookupCredentialsInItem(TestingBotCredentials.class, …) — used by the build wrapper's getCredentials(), availableCredentials() and every credential dropdown — returned an empty list for it, even though the stored objects are instances of the class:

  • a StandardCredentials.class lookup returns them;
  • a control UsernamePasswordCredentialsImpl (which extends BaseStandardCredentials) is found by its concrete class.

So the freestyle wrapper silently resolved null credentials — TB_KEY/TB_SECRET/TESTINGBOT_BUILD were never injected, and the credential dropdowns were empty.

Fix: make TestingBotCredentials extend BaseStandardCredentials, which owns id/description (and the id-based equals/hashCode), so concrete-type lookups resolve it. Verified old-format credentials.xml (scope/id/description/key/secret) still deserializes unchanged — the field names are identical.

2. Test Connection failed for accounts without an email

doVerifyCredentials required a non-null user email. A valid account can return HTTP 200 with a null email (e.g. sub-accounts), producing a false 'Could not verify these credentials' for working key/secret. Now any authenticated user is treated as success, preferring the email and falling back to the account first name.

Both verified live: credential now injects into the build; Test Connection returns 'Connection successful — signed in as … (… plan)' for a null-email account and still reports auth failures for bad secrets.

Summary by CodeRabbit

  • Bug Fixes

    • Improved credential verification messaging when email isn’t available, including more accurate “signed in as” display and handling for missing identity fields.
    • Updated verification success criteria to treat a non-null authenticated user as successful even when email is absent.
  • Refactor

    • Streamlined credential implementation while continuing to securely use the TestingBot API key and secret.
  • Tests

    • Added automated coverage for verification message formatting across multiple missing-data scenarios.

Two correctness fixes surfaced by an end-to-end run against a real account.

1. Credentials never resolved at build time.
   TestingBotCredentials extended BaseCredentials (implements StandardCredentials).
   CredentialsProvider.lookupCredentialsInItem(TestingBotCredentials.class, ...) —
   used by the build wrapper's getCredentials(), availableCredentials() and every
   credential dropdown — returned an empty list for it, even though the stored
   objects are instances of the class (a StandardCredentials.class lookup found
   them; a UsernamePasswordCredentialsImpl, which extends BaseStandardCredentials,
   is found by concrete class). As a result the freestyle wrapper silently
   resolved null credentials, so TB_KEY/TB_SECRET/TESTINGBOT_BUILD were never
   injected and the dropdowns were empty.

   Make TestingBotCredentials extend BaseStandardCredentials, which owns id and
   description (and the id-based equals/hashCode), so concrete-type lookups work.
   Old-format credentials.xml (scope/id/description/key/secret) still deserializes
   unchanged — field names are identical.

2. Test Connection failed for accounts without an email.
   doVerifyCredentials required a non-null user email; a valid account can return
   200 with a null email (e.g. sub-accounts), which produced a false 'Could not
   verify these credentials' for working key/secret. Treat any authenticated user
   as success, preferring the email and falling back to the account first name.
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

TestingBotCredentials now delegates identity metadata and equality to `BaseStandardCredentials. Verification succeeds for any non-null user and formats optional email, first-name, and plan details.

Changes

Credential updates

Layer / File(s) Summary
Standard credential contract
src/main/java/testingbot/TestingBotCredentials.java
TestingBotCredentials extends BaseStandardCredentials, stores the TestingBot key and secret, and delegates credential identity, description, and equality behavior to the base class.
Credential verification formatting and coverage
src/main/java/testingbot/TestingBotCredentials.java, src/test/java/testingbot/TestingBotCredentialsVerificationTest.java
Verification fails only for a null user, prefers email over first name, treats plan details as optional, and adds tests for the supported field combinations.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main changes: TestingBot credential resolution and Test Connection behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@src/main/java/testingbot/TestingBotCredentials.java`:
- Around line 305-318: Add regression tests for the credential verification
logic around the null-user failure and success-message branches, covering users
with an email, users without an email but with a first name, and users missing
optional identity and plan fields. Assert the expected validation status and
message for each case, including that missing fields still produce successful
verification.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 64ed1f3c-b4e2-499b-bf8b-6c096c8ff6e6

📥 Commits

Reviewing files that changed from the base of the PR and between 6c594a9 and a6f8dc4.

📒 Files selected for processing (1)
  • src/main/java/testingbot/TestingBotCredentials.java

Comment on lines +305 to +318
if (user == null) {
return FormValidation.error("Could not verify these credentials with TestingBot.");
}
// A valid TestingBot account may not expose an email (e.g. sub-accounts); the
// authenticated user object itself is proof the key/secret work. Prefer the email,
// fall back to the account's first name, so verification never fails on a null email.
String who = Util.fixEmptyAndTrim(user.getEmail());
if (who == null) {
who = Util.fixEmptyAndTrim(user.getFirstName());
}
String plan = Util.fixEmptyAndTrim(user.getPlan());
return FormValidation.ok("Connection successful — signed in as %s%s",
user.getEmail(), plan != null ? " (" + plan + " plan)" : "");
return FormValidation.ok("Connection successful%s%s",
who != null ? " — signed in as " + who : "",
plan != null ? " (" + plan + " plan)" : "");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the new verification branches.

Cover null-user failure, email-present success, email-absent/first-name fallback, and success when optional identity or plan fields are missing.

🤖 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 `@src/main/java/testingbot/TestingBotCredentials.java` around lines 305 - 318,
Add regression tests for the credential verification logic around the null-user
failure and success-message branches, covering users with an email, users
without an email but with a first name, and users missing optional identity and
plan fields. Assert the expected validation status and message for each case,
including that missing fields still produce successful verification.

Extract the user-facing result building of doVerifyCredentials into a pure,
package-private verificationResult(TestingbotUser) helper (behavior unchanged) so
it can be unit-tested without the network call or the Jenkins permission check
(a JenkinsRule test is not viable here — see the harness/Jetty conflict).

Cover: null user -> error; user with email -> success naming the email; user
without email but with a first name -> success naming the first name; user
missing email, first name and plan -> still success, with no identity or plan
fragment in the message.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@src/main/java/testingbot/TestingBotCredentials.java`:
- Around line 305-308: Update the exception handling around the TestingBot
credential validation to catch TestingbotUnauthorizedException separately and
retain the authentication-failed message only for that exception. Handle
TestingbotApiException in its own branch with a connection/API failure message,
preserving the existing exception details in both responses.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e536193e-d8d3-4c8e-8471-a41d592713ea

📥 Commits

Reviewing files that changed from the base of the PR and between a6f8dc4 and f9e5f94.

📒 Files selected for processing (2)
  • src/main/java/testingbot/TestingBotCredentials.java
  • src/test/java/testingbot/TestingBotCredentialsVerificationTest.java

Comment on lines 305 to 308
} catch (TestingbotUnauthorizedException | TestingbotApiException e) {
// The REST client's typed failures: bad key/secret, and network/parse errors (it wraps
// IOException into TestingbotApiException). Unexpected runtime exceptions propagate.
return FormValidation.error("TestingBot authentication failed: " + e.getMessage());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Distinguish API/connectivity failures from invalid credentials.

TestingbotApiException also covers network/parse errors, but this branch labels all of them as authentication failures. Catch it separately and return a connection/API error; retain the authentication message for TestingbotUnauthorizedException.

🤖 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 `@src/main/java/testingbot/TestingBotCredentials.java` around lines 305 - 308,
Update the exception handling around the TestingBot credential validation to
catch TestingbotUnauthorizedException separately and retain the
authentication-failed message only for that exception. Handle
TestingbotApiException in its own branch with a connection/API failure message,
preserving the existing exception details in both responses.

@jochen-testingbot
jochen-testingbot merged commit b8923cb into master Jul 17, 2026
5 checks passed
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.

1 participant