[WIP] Add Amazon Q Developer plugin support in CLI#150
Open
Claude wants to merge 3 commits into
Open
Conversation
4 tasks
Add support for Amazon Q Developer as a DevOps tool plugin with AWS credential authentication and S3-based scope configuration. - Add QDevS3Slice type for S3 time-sliced scope entries - Extend ConnectionParams, ConnectionCreateRequest, and ConnectionTestRequest with AWS-specific fields (AccessKeyID, SecretAccessKey, Region, Bucket, IdentityStoreID, IdentityStoreRegion) - Add ConnectionDef for q_dev plugin with AwsCredentials auth method - Implement scopeQDevHandler for interactive S3 scope selection (account-based or prefix-based) - Add comprehensive tests for q_dev connection and AWS credential handling - Support both account-based scopes (recommended) and legacy explicit prefix scopes Agent-Logs-Url: https://github.com/DevExpGbb/gh-devlake/sessions/cce9936b-4e70-4bbc-93b6-c92b8c407c20 Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds initial Amazon Q Developer (q_dev) plugin wiring to the gh-devlake GitHub CLI extension by extending connection payload types, registering the plugin in the connection registry, and adding a first-pass scope configuration handler.
Changes:
- Added
QDevS3Slicescope payload type forPUT /scopes. - Extended DevLake client connection create/test request payloads with AWS-specific fields.
- Registered
q_devinconnectionRegistry, added tests for the registry entry and AWS-field request building, and introduced an interactivescopeQDevHandler.
Show a summary per file
| File | Description |
|---|---|
| internal/devlake/types.go | Adds QDevS3Slice struct for Q Developer S3 slice scope upserts. |
| internal/devlake/client.go | Extends connection create/test request payloads with AWS credential + bucket/region fields. |
| cmd/connection_types.go | Adds AWS fields to ConnectionParams, maps them into create/test requests, and registers the q_dev plugin definition. |
| cmd/connection_types_test.go | Adds coverage for the q_dev registry entry and AWS-specific request field mapping. |
| cmd/configure_scopes.go | Adds scopeQDevHandler to create and upsert a Q Developer S3 slice scope. |
Copilot's findings
- Files reviewed: 5/5 changed files
- Comments generated: 6
Comment on lines
126
to
173
| // BuildCreateRequest constructs the API payload for creating this connection. | ||
| func (d *ConnectionDef) BuildCreateRequest(name string, params ConnectionParams) *devlake.ConnectionCreateRequest { | ||
| endpoint := d.Endpoint | ||
| if params.Endpoint != "" { | ||
| endpoint = params.Endpoint | ||
| } | ||
| req := &devlake.ConnectionCreateRequest{ | ||
| Name: name, | ||
| Endpoint: endpoint, | ||
| Proxy: params.Proxy, | ||
| AuthMethod: d.authMethod(), | ||
| RateLimitPerHour: d.rateLimitOrDefault(), | ||
| EnableGraphql: d.EnableGraphql, | ||
| } | ||
| if d.NeedsUsername && params.Username != "" { | ||
| // BasicAuth-style plugins (e.g., Jenkins, Bitbucket, Jira) expect credentials | ||
| // in username/password fields, not in the token field. | ||
| req.Username = params.Username | ||
| req.Password = params.Token | ||
| } else { | ||
| req.Token = params.Token | ||
| } | ||
| if (d.NeedsOrg || d.NeedsOrgOrEnt) && params.Org != "" { | ||
| req.Organization = params.Org | ||
| } | ||
| if (d.NeedsEnterprise || d.NeedsOrgOrEnt) && params.Enterprise != "" { | ||
| req.Enterprise = params.Enterprise | ||
| } | ||
| // AWS-specific fields (for Amazon Q Developer) | ||
| if params.AccessKeyID != "" { | ||
| req.AccessKeyID = params.AccessKeyID | ||
| } | ||
| if params.SecretAccessKey != "" { | ||
| req.SecretAccessKey = params.SecretAccessKey | ||
| } | ||
| if params.Region != "" { | ||
| req.Region = params.Region | ||
| } | ||
| if params.Bucket != "" { | ||
| req.Bucket = params.Bucket | ||
| } | ||
| if params.IdentityStoreID != "" { | ||
| req.IdentityStoreID = params.IdentityStoreID | ||
| } | ||
| if params.IdentityStoreRegion != "" { | ||
| req.IdentityStoreRegion = params.IdentityStoreRegion | ||
| } | ||
| return req |
Comment on lines
+463
to
+477
| ConnectionFlags: []FlagDef{ | ||
| {Name: "access-key-id", Description: "AWS Access Key ID"}, | ||
| {Name: "secret-access-key", Description: "AWS Secret Access Key"}, | ||
| {Name: "region", Description: "AWS region (e.g., us-east-1)"}, | ||
| {Name: "bucket", Description: "S3 bucket name containing Q Developer data"}, | ||
| {Name: "identity-store-id", Description: "IAM Identity Center store ID (optional)"}, | ||
| {Name: "identity-store-region", Description: "IAM Identity Center region (optional)"}, | ||
| }, | ||
| ScopeFlags: []FlagDef{ | ||
| {Name: "account-id", Description: "AWS account ID for scope generation"}, | ||
| {Name: "year", Description: "Year for data collection (e.g., 2024)"}, | ||
| {Name: "month", Description: "Month for data collection (1-12, optional)"}, | ||
| {Name: "base-path", Description: "S3 base path prefix (optional)"}, | ||
| {Name: "prefix", Description: "Explicit S3 prefix (alternative to account-id)"}, | ||
| }, |
Comment on lines
+448
to
+460
| Plugin: "q_dev", | ||
| DisplayName: "Amazon Q Developer", | ||
| Available: true, | ||
| Endpoint: "", // S3-based, no REST endpoint | ||
| SupportsTest: false, | ||
| AuthMethod: "AwsCredentials", | ||
| RateLimitPerHour: 20000, | ||
| RequiredScopes: []string{}, | ||
| ScopeHint: "", | ||
| TokenPrompt: "AWS Secret Access Key", | ||
| EnvVarNames: []string{"AWS_SECRET_ACCESS_KEY"}, | ||
| EnvFileKeys: []string{"AWS_SECRET_ACCESS_KEY"}, | ||
| ScopeFunc: scopeQDevHandler, |
Comment on lines
+1636
to
+1653
| // scopeQDevHandler configures S3-based scopes for Amazon Q Developer. | ||
| // Scopes are time-sliced S3 prefixes (year/month) for Q Developer data collection. | ||
| func scopeQDevHandler(client *devlake.Client, connID int, org, enterprise string, opts *ScopeOpts) (*devlake.BlueprintConnection, error) { | ||
| // Determine scope creation mode | ||
| var accountID, prefix, basePath string | ||
| var year, month int | ||
|
|
||
| fmt.Println("\n📝 Configuring Amazon Q Developer scope...") | ||
| fmt.Println(" Scopes represent S3 data slices for Q Developer metrics.") | ||
| fmt.Println() | ||
|
|
||
| // Prompt for account ID (recommended) or explicit prefix (legacy) | ||
| accountID = prompt.ReadLine("AWS Account ID (leave empty for explicit prefix)") | ||
| if accountID != "" { | ||
| // Account-based scope (new style) | ||
| basePath = prompt.ReadLine("S3 base path [leave empty for default]") | ||
| yearStr := prompt.ReadLine("Year for data collection (e.g., 2024)") | ||
| if yearStr == "" { |
Comment on lines
+435
to
+443
| t.Run("AWS fields populated correctly", func(t *testing.T) { | ||
| req := def.BuildCreateRequest("test-q-dev", ConnectionParams{ | ||
| AccessKeyID: "AKIAIOSFODNN7EXAMPLE", | ||
| SecretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", | ||
| Region: "us-east-1", | ||
| Bucket: "my-q-developer-bucket", | ||
| IdentityStoreID: "d-1234567890", | ||
| IdentityStoreRegion: "us-east-1", | ||
| }) |
Comment on lines
+1647
to
+1663
| // Prompt for account ID (recommended) or explicit prefix (legacy) | ||
| accountID = prompt.ReadLine("AWS Account ID (leave empty for explicit prefix)") | ||
| if accountID != "" { | ||
| // Account-based scope (new style) | ||
| basePath = prompt.ReadLine("S3 base path [leave empty for default]") | ||
| yearStr := prompt.ReadLine("Year for data collection (e.g., 2024)") | ||
| if yearStr == "" { | ||
| return nil, fmt.Errorf("year is required") | ||
| } | ||
| var err error | ||
| year, err = strconv.Atoi(yearStr) | ||
| if err != nil || year < 2020 || year > 2100 { | ||
| return nil, fmt.Errorf("invalid year: %s", yearStr) | ||
| } | ||
|
|
||
| monthStr := prompt.ReadLine("Month (1-12, leave empty for full year)") | ||
| if monthStr != "" { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.