Skip to content

Addressing PR comments#131

Merged
ewega merged 4 commits intomainfrom
claude/add-sonarqube-support
Mar 6, 2026
Merged

Addressing PR comments#131
ewega merged 4 commits intomainfrom
claude/add-sonarqube-support

Conversation

@Claude
Copy link
Contributor

@Claude Claude AI commented Mar 5, 2026

No description provided.

@Claude Claude AI assigned Claude and ewega Mar 5, 2026
@Claude Claude AI changed the title [WIP] Add SonarQube as a supported DevOps tool in CLI Add SonarQube plugin support Mar 5, 2026
@ewega ewega marked this pull request as ready for review March 5, 2026 15:31
Copilot AI review requested due to automatic review settings March 5, 2026 15:31
Copy link
Contributor

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 adds SonarQube as a new supported plugin in the gh-devlake CLI, enabling users to track code quality metrics (coverage, code smells, quality gates) alongside DORA metrics. The implementation closely follows established patterns from the Jira plugin (AccessToken auth, user-provided endpoint, API-based scope selection with pagination).

Changes:

  • New ConnectionDef registry entry for SonarQube with AccessToken auth, SONARQUBE_TOKEN/SONAR_TOKEN env resolution, and projectKey scope ID field
  • New scopeSonarQubeHandler for interactive project selection via the DevLake remote-scope API with pagination support
  • New SonarQubeProjectScope struct, registry tests, and README documentation update

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
cmd/connection_types.go Adds SonarQube ConnectionDef entry to connectionRegistry with AccessToken auth, empty endpoint, and scopeSonarQubeHandler
cmd/configure_scopes.go Implements scopeSonarQubeHandler with paginated remote-scope fetching, interactive multi-select, and SonarQubeProjectScope PUT
internal/devlake/types.go Adds SonarQubeProjectScope struct with connectionId, projectKey, name fields
cmd/connection_types_test.go Table-driven tests validating SonarQube registry entry fields, auth method, env vars, and scope settings
README.md Adds SonarQube to the Supported Plugins table and reorders "Coming soon" entries to the end

t.Errorf("jenkins ScopeFlags should include jobs flag")
}
} No newline at end of file
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

Missing blank line between TestConnectionRegistry_Jenkins and TestConnectionRegistry_SonarQube. Every other top-level function in this file is separated by a blank line (e.g., lines 557-559). Add a blank line after the closing } on line 589.

Suggested change
}
}

Copilot uses AI. Check for mistakes.
@ewega
Copy link
Contributor

ewega commented Mar 5, 2026

@claude[agent] Please fix: Add a blank line between TestConnectionRegistry_Jenkins and TestConnectionRegistry_SonarQube in cmd/connection_types_test.go (after line 589's closing brace).

@Claude
Copy link
Contributor Author

Claude AI commented Mar 5, 2026

@claude[agent] Please fix: Add a blank line between TestConnectionRegistry_Jenkins and TestConnectionRegistry_SonarQube in cmd/connection_types_test.go (after line 589's closing brace).

Fixed in ac06c57 - added blank line between the two test functions for consistency.

@Claude Claude AI changed the title Add SonarQube plugin support Addressing PR comments Mar 5, 2026
@ewega ewega requested a review from Copilot March 5, 2026 17:38
Copy link
Contributor

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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comment on lines +825 to +837
for i := range allChildren {
child := &allChildren[i]
if child.Type == "scope" {
label := child.Name
if child.ID != "" {
label = fmt.Sprintf("%s (key: %s)", child.Name, child.ID)
}
projectOptions = append(projectOptions, label)
projectMap[label] = child
}
}

if len(projectOptions) == 0 {
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The selection list includes projects even when child.ID (the projectKey) is empty, but those selections are later skipped. This can lead to a confusing UX where a user selects items and then hits no valid projects to add. Consider filtering out child.ID == "" projects when building projectOptions (and not inserting them into projectMap), or fail early with a clear message that the server returned projects without keys.

Suggested change
for i := range allChildren {
child := &allChildren[i]
if child.Type == "scope" {
label := child.Name
if child.ID != "" {
label = fmt.Sprintf("%s (key: %s)", child.Name, child.ID)
}
projectOptions = append(projectOptions, label)
projectMap[label] = child
}
}
if len(projectOptions) == 0 {
missingKeyCount := 0
for i := range allChildren {
child := &allChildren[i]
if child.Type != "scope" {
continue
}
// Skip projects without a valid project key (child.ID)
if child.ID == "" {
missingKeyCount++
continue
}
label := fmt.Sprintf("%s (key: %s)", child.Name, child.ID)
projectOptions = append(projectOptions, label)
projectMap[label] = child
}
if len(projectOptions) == 0 {
if missingKeyCount > 0 {
return nil, fmt.Errorf("no SonarQube projects with valid project keys found for connection %d", connID)
}

Copilot uses AI. Check for mistakes.
Comment on lines +855 to +856
fmt.Printf(" ⚠️ Skipping project %q: empty project key\n", child.Name)
continue
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The selection list includes projects even when child.ID (the projectKey) is empty, but those selections are later skipped. This can lead to a confusing UX where a user selects items and then hits no valid projects to add. Consider filtering out child.ID == "" projects when building projectOptions (and not inserting them into projectMap), or fail early with a clear message that the server returned projects without keys.

Suggested change
fmt.Printf(" ⚠️ Skipping project %q: empty project key\n", child.Name)
continue
return nil, fmt.Errorf("server returned SonarQube project %q without a project key; cannot add scopes", child.Name)

Copilot uses AI. Check for mistakes.
Endpoint: "", // user must provide (e.g., https://sonar.example.com/)
SupportsTest: true,
AuthMethod: "AccessToken",
RateLimitPerHour: 0, // uses default 4500
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

RateLimitPerHour: 0 is ambiguous (it can mean “disabled”, “unlimited”, or “use default” depending on downstream logic). Since the comment states it should use the default (4500), prefer omitting the field (so the defaulting behavior is explicit), or set it to the actual intended default value to avoid misinterpretation.

Copilot uses AI. Check for mistakes.
fmt.Println()
selectedLabels := prompt.SelectMulti("Select SonarQube projects to track", projectOptions)
if len(selectedLabels) == 0 {
return nil, fmt.Errorf("at least one project must be selected")
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

This error message loses context in a multi-plugin flow. Consider including the plugin name and action to make it more actionable (e.g., mention SonarQube project selection), consistent with the more specific errors used elsewhere in the handler.

Suggested change
return nil, fmt.Errorf("at least one project must be selected")
return nil, fmt.Errorf("at least one SonarQube project must be selected")

Copilot uses AI. Check for mistakes.
@ewega
Copy link
Contributor

ewega commented Mar 6, 2026

@claude[agent] Please fix:

  1. Filter empty project keys from picker — In scopeSonarQubeHandler, skip projects where child.ID == "" when building projectOptions. Don't add them to projectMap. This prevents users from selecting items that will be silently skipped later.
  2. Improve error message — Change "at least one project must be selected" to "at least one SonarQube project must be selected" for clarity in multi-plugin flows.

@Claude
Copy link
Contributor Author

Claude AI commented Mar 6, 2026

@claude[agent] Please fix:

  1. Filter empty project keys from picker — In scopeSonarQubeHandler, skip projects where child.ID == "" when building projectOptions. Don't add them to `projectM...

Fixed in 1a1608b:

  1. Projects with empty child.ID are now filtered out when building projectOptions, preventing them from appearing in the picker
  2. Error message updated to "at least one SonarQube project must be selected" for clarity in multi-plugin flows

Copy link
Contributor

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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment on lines +865 to +868
if len(scopeData) == 0 {
return nil, fmt.Errorf("no valid projects to add")
}

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The len(scopeData) == 0 check here is unreachable: selectedLabels is guaranteed non-empty (checked at line 844), and the loop body unconditionally appends to scopeData for every label — there are no continue/skip branches unlike the Jira handler (which skips on empty or unparseable board IDs). Consider removing this dead check, or adding a comment noting it's a defensive guard for future-proofing.

Suggested change
if len(scopeData) == 0 {
return nil, fmt.Errorf("no valid projects to add")
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

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

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

Claude AI and others added 4 commits March 6, 2026 15:20
- Add SonarQube ConnectionDef to connectionRegistry with AccessToken auth
- Implement scopeSonarQubeHandler for interactive project selection
- Add SonarQubeProjectScope type to internal/devlake/types.go
- Add comprehensive test coverage in TestConnectionRegistry_SonarQube
- Update README with SonarQube in Supported Plugins table
- All tests pass (go test ./..., go vet ./...)

Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
Add blank line between TestConnectionRegistry_Jenkins and TestConnectionRegistry_SonarQube for consistency with other test functions in the file.

Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
- Filter out projects with empty project keys from picker to prevent confusing UX where users select items that get silently skipped
- Improve error message: "at least one SonarQube project must be selected" for clarity in multi-plugin flows
- Remove now-unnecessary empty ID check in scope data loop since filtering happens earlier

Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
@ewega ewega force-pushed the claude/add-sonarqube-support branch from 1a1608b to 8657cd6 Compare March 6, 2026 12:26
@ewega ewega merged commit 6d3fbd5 into main Mar 6, 2026
7 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.

3 participants