feat: Implement support for Atlassian Scoped User Tokens#928
feat: Implement support for Atlassian Scoped User Tokens#928adrian-gierakowski wants to merge 1 commit intoankitpokhrel:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements support for Atlassian Scoped User Tokens by automatically detecting cloud instances during initialization and converting the server URL to use the Atlassian API gateway endpoint format.
Key changes:
- Adds tenant info fetching during
jira initto retrieve cloudId - Automatically converts cloud instance URLs to the API gateway format (
https://api.atlassian.com/ex/jira/<cloudId>) - Maintains backward compatibility by falling back to the user-provided URL if tenant info cannot be fetched
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| pkg/jira/types.go | Adds TenantInfo struct to hold cloudId from tenant info endpoint |
| internal/cmd/init/init.go | Implements fetchTenantInfo function and integrates it into the initialization flow to automatically detect and configure cloud instances |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
pkg/jira/types.go
Outdated
|
|
||
| // TenantInfo holds tenant info. | ||
| type TenantInfo struct { | ||
| CloudId string `json:"cloudId"` |
There was a problem hiding this comment.
The field name "CloudId" should follow Go naming conventions for acronyms and be "CloudID" instead. In Go, acronyms like ID, URL, HTTP, etc. should be all uppercase when used in identifier names.
| CloudId string `json:"cloudId"` | |
| CloudID string `json:"cloudId"` |
internal/cmd/init/init.go
Outdated
| if err := json.NewDecoder(res.Body).Decode(&info); err != nil { | ||
| return nil, nil // Also okay if this fails. | ||
| } | ||
| if info.CloudId == "" { |
There was a problem hiding this comment.
The field reference "info.CloudId" should be "info.CloudID" to match Go naming conventions for acronyms. This needs to be updated once the struct field name is corrected.
| if info.CloudId == "" { | |
| if info.CloudID == "" { |
internal/cmd/init/init.go
Outdated
| params := parseFlags(cmd.Flags()) | ||
|
|
||
| if info, err := fetchTenantInfo(params.server); err == nil && info != nil { | ||
| params.server = "https://api.atlassian.com/ex/jira/" + info.CloudId |
There was a problem hiding this comment.
The field reference "info.CloudId" should be "info.CloudID" to match Go naming conventions for acronyms. This needs to be updated once the struct field name is corrected.
| func fetchTenantInfo(server string) (*jira.TenantInfo, error) { | ||
| server = strings.TrimSuffix(server, "/") | ||
| req, err := http.NewRequest(http.MethodGet, server+"/_edge/tenant_info", nil) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| res, err := http.DefaultClient.Do(req) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| defer func() { _ = res.Body.Close() }() | ||
|
|
||
| if res.StatusCode != http.StatusOK { | ||
| return nil, nil // It's okay if this fails. | ||
| } | ||
|
|
||
| var info jira.TenantInfo | ||
| if err := json.NewDecoder(res.Body).Decode(&info); err != nil { | ||
| return nil, nil // Also okay if this fails. | ||
| } | ||
| if info.CloudId == "" { | ||
| return nil, nil | ||
| } | ||
|
|
||
| return &info, nil | ||
| } |
There was a problem hiding this comment.
The new fetchTenantInfo function lacks test coverage. Given that this repository has comprehensive test coverage for other functions (as seen in pkg/jira/*_test.go files), this function should have tests covering:
- Successful tenant info retrieval with valid cloudId
- Non-200 status code responses
- Invalid JSON response handling
- Empty cloudId handling
- Network errors
|
converted to draft as it broken issue urls for opening in browser |
835344f to
b19ddb0
Compare
This commit introduces support for Atlassian Scoped User Tokens in jira-cli. Previously, the CLI used Basic Authentication against the instance domain, which resulted in `401 Unauthorized` for scoped tokens. This change modifies the `jira init` command to fetch the `CloudID` from the `/_edge/tenant_info` endpoint (if installation == Cloud). If a `CloudID` is found, the server URL in the configuration is updated to `https://api.atlassian.com/ex/jira/<CloudID>`, which is the correct endpoint for scoped tokens, while the originally provided server url is stored as `browse_server` (as this is used to generate urls for viewing issues etc in the browser). This approach ensures that the `CloudID` is fetched only once during the initialization process. The change is also backward-compatible, as it falls back to the user-provided server URL if the `CloudID` cannot be fetched. Non-scoped tokes also work with this approach since they can be used to fetch CloudID and to call api.atlassian.com. fixes ankitpokhrel#850
b19ddb0 to
6bd820b
Compare
|
@adrian-gierakowski out of curiosity is this work done/ready now? This is a feature gap I just spent a couple hours debugging before noticing 😔 |
I do have this working on my fork. Not sure if this branch is up to date. Will check tomorrow. |
|
@tayydev this is the branch I'm currently using https://github.com/adrian-gierakowski/jira-cli/commits/all-new-features-2 It's got a few other features I've implemented, |
This PR introduces support for Atlassian Scoped User Tokens in jira-cli.
Previously, the CLI used Basic Authentication against the instance domain, which resulted in
401 Unauthorizedfor scoped tokens.This change modifies the
jira initcommand to fetch thecloudIdfrom the/_edge/tenant_infoendpoint. If acloudIdis found, the server URL in the configuration is updated tohttps://api.atlassian.com/ex/jira/<cloudId>, which is the correct endpoint for scoped tokens.This approach ensures that the
cloudIdis fetched only once during the initialization process, making the implementation more efficient. The change is also backward-compatible, as it falls back to the user-provided server URL if thecloudIdcannot be fetched.fixes #850