go-jira
go-jira copied to clipboard
Some APIs used will be shutdown on May 1st 2025
https://developer.atlassian.com/changelog/#CHANGE-2046
It looks like v1 and v2 both use deprecated search APIs that will be shutdown on May 1st. There is a partial replacement available.
Does anyone know when this might get merged?
those old JIRA search API just closed. 😭
Also got hit by this 😢
Facing the same issue.
Facing this as well, any quick fix for this ?
I will look into https://github.com/andygrunwald/go-jira/pull/717 today or in the next days to get it into main.
If anyone needs some temporary workaround you can try doing something like this using NewRequestWithContext from jira client:
// Use the new Jira API v3 search endpoint
searchURL := "/rest/api/3/search/jql"
queryParams := url.Values{}
queryParams.Set("jql", query)
queryParams.Set("maxResults", "50")
queryParams.Set("fields", "key,summary")
req, err := c.client.NewRequestWithContext(ctx, "GET", searchURL+"?"+queryParams.Encode(), nil)
if err != nil {
return nil, errorlib.Wrap(err, "failed to create jira search request")
}
var searchResult struct {
Issues []struct {
Key string `json:"key"`
Fields struct {
Summary string `json:"summary"`
} `json:"fields"`
} `json:"issues"`
}
_, err = c.client.Do(req, &searchResult)
if err != nil {
return nil, errorlib.Wrap(err, "failed to search jira issues")
}
I was able to patch it locally using a similar approach from this PR:
func (c *Client) SearchV3(ctx context.Context, jql string) ([]j.Issue, *j.Response, error) {
u := url.URL{
Path: "rest/api/3/search/jql",
}
uv := url.Values{}
if jql != "" {
uv.Add("jql", jql)
}
u.RawQuery = uv.Encode()
req, err := c.client.NewRequest(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return []j.Issue{}, nil, err
}
v := new(searchResult)
resp, err := c.client.Do(req, v)
if err != nil {
err = j.NewJiraError(resp, err)
}
return v.Issues, resp, err
}
Hey any news? The API still doesn't work 🙏
@andygrunwald Is this still in-progress? Just wondering if we should be looking at a workaround internally.
@andygrunwald any update?
Hey all,
I am working on this right now. https://github.com/andygrunwald/go-jira/pull/717 itself is not mergeable as is, as it defines types like integer (which do not exist).
I am playing around with my Jira Cloud instance at https://go-jira-opensource.atlassian.net/.
In this setup, the v2 API still works as before - See https://go-jira-opensource.atlassian.net/rest/api/2/search?jql=type+%3D+Bug+and+Status+NOT+IN+%28Resolved%29
Can you provide me the information on what setup you are running?
On another note: I am making the change in the current main branch. I keep you posted as I progress.
@andygrunwald here is a snippet that produces the error for us using 1.16 of the lib.
username := "testuser"
jql := fmt.Sprintf(`project in ("Example") AND
statusCategory = "In Progress" AND
(assignee = "%[email protected]" OR reviewer = "%[email protected]" OR "Prod Confirmation Owner" = "%[email protected]")`, username, username, username)
issues, _, err := client.Issue.Search(jql, nil)
if err != nil {
log.Printf("Error Retrieving Issues: %v", err)
}
2025/08/25 15:39:52 Error Retrieving Issues: The requested API has been removed. Please migrate to the /rest/api/3/search/jql API. A full migration guideline is available at https://developer.atlassian.com/changelog/#CHANGE-2046: request failed. Please analyze the request body for more details. Status code: 410
Hey all, I put out a new PR, please see https://github.com/andygrunwald/go-jira/pull/724
I only patched this in main, not in https://github.com/andygrunwald/go-jira/releases/tag/v1.16.0
What I would need from you
- Please test this branch, and if the search functionality works as expected
- Please provide back the feedback
You should be able to use the new branch by go get github.com/andygrunwald/go-jira@fix-search-jql-api-deprecation
See https://stackoverflow.com/questions/53682247/how-to-point-go-module-dependency-in-go-mod-to-a-latest-commit-in-a-repo
@andygrunwald - hey, is this a fix for v1 or v2? when trying to install it I get
go: github.com/andygrunwald/go-jira@fix-search-jql-api-deprecation: github.com/andygrunwald/[email protected]: invalid version: go.mod has post-v1 module path "github.com/andygrunwald/go-jira/v2" at revision a1568d030dcc
@ofirdagan The fix is only in v2 / based on the current main. We are not able to fix this in v1, as v1 doesn't have the split between the on-premises and Cloud versions. This breaking change is only in the Cloud version, but not in the On-Premise one. If we were to modify the existing Search functionality, it would break on-premises.
One possibility would be to add a new Search function like SearchV3JQL or anything like this. Happy to accept a PR on this against version 1, then I would ship the new version.
The code should be nearly the same as in https://github.com/andygrunwald/go-jira/pull/724
@All: Did anyone test it already?
I wasn't able to test for the same reason as mentioned above wrt to getting the v2 version to install/resolve correctly.
However, I'm happy to try to get a PR together to port the changes to v1
We are running into the same issue as above with v1
@conor-naranjo This would be great. Lets ensure to have a new function to not break on-premise.
When i find some time, i will see how I can document the move to v2.
@andygrunwald should I branch off v1.16.1-dev for these changes?
@conor-naranjo Yes please. I created https://github.com/andygrunwald/go-jira/tree/v1.16.1-dev for this purpose.
@andygrunwald https://github.com/andygrunwald/go-jira/pull/725 please review at your convenience
@conor-naranjo @andygrunwald Would like to help test this v1 fix, but not sure how to go about using it where the go.mod still points to /v2 in the fork.
Any ETA when this will merge to the main branch? They conveniently killed the old API over labor day weekend for us
Hi @andygrunwald,
We have panic hot fixed most of our tooling today with your PR branch and it looks alright.
However, I have run into the issue where SearchOptions{Fields: []string{"*all"}} is causing this error here:
json: cannot unmarshal object into Go struct field Issue.issues.fields.Alias.description of type string: file already closed
The fix/workaround is to explicitly only select fields, which I require.
EDIT: Looks like this already addressed in a comment in your PR: https://github.com/andygrunwald/go-jira/pull/724#issuecomment-3237491382.
Hey all, Quick update on this one.
v1 of go-jira
I merged https://github.com/andygrunwald/go-jira/pull/725 (Kudos to @conor-naranjo and @erezrokah). This introduces a IssueService.SearchV2JQL() and IssueService.SearchV2JQLWithContext() to keep backwards compatibility with on-premise instances. A new version https://github.com/andygrunwald/go-jira/releases/tag/v1.16.1 was released.
v2 / Current main of go-jira
I merged a backported version of https://github.com/andygrunwald/go-jira/pull/725 by @conor-naranjo in https://github.com/andygrunwald/go-jira/pull/731. This introduces a new function IssueService.SearchV2JQL. It looks like the original Search function is still working on some installations. At least I have access to one cloud instance where Search() is still working.
https://github.com/andygrunwald/go-jira/blob/610ff3d23bbdb0d20456545f13db496039389396/cloud/examples/jql/main.go shows how to use the IssueService.SearchV2JQL function.
@Jcparkyn hinted that we can stay on Jira's v2 API. This lowers the migration effort and we kick the can down the road to by some time to get this lib working for Jira v3.
Feedback needed
Please let me know if both new versions work for you or if anything else is needed to get your current code back into a working state. Even a comment "Yep, works" is a good signal. If you react to this comment with emojis, I won't receive a notification and most likely won't see it.
I will leave this issue open for a bit to let others have a chance to look into it / to find it. When the few positive feedback came in, I will close it as I assume this is working for you.
Thanks for all the pings, Pull Requests, feedback, and testing comments.
Using v1.16.1
issues, _, err := jiraClient.Issue.SearchV2JQL(jql, &jira.SearchOptionsV2{
MaxResults: 1000,
Fields: []string{"summary", "status", "priority", "labels", "issuetype"},
})
Works for me 👍
@andygrunwald I did the replacement from 1.13 to 1.17 today to cater for the deprecation warnings I was getting. Unfortunately, for my use case, it didn't work.
Considering the missing implementation of "Count Issues using JQL", I've been using the SearchResult.total present on the output of IssueService.Search() to count the issues. The absence of the "approximate count" method on the lib API is also reported in #692
The SearchV2JQL returns a different type, SearchAndReconciliateResult on JIRA docs (searchResultV2 in v1.16.1), which doesn't contain total.
UPDATE: I tried to put together the count endpoint quickly and realised after that there's a chance that this wouldn't work simultaneously for Cloud & OnPrem. It seems I do need the v3/search to fulfil my goal, or branch my code based on being on cloud or prem.
github.com/andygrunwald/[email protected] Works great 👍
Replaced:
startAt := 0
for {
searchOptions := &jira.SearchOptions{
StartAt: startAt,
MaxResults: 50,
Expand: "changelog,comment",
}
...
issues, resp, err := s.client.Issue.Search(jql, searchOptions)
...
startAt += len(issues)
}
with
nextPageToken := ""
for {
searchOptions := &jira.SearchOptionsV2{
NextPageToken: nextPageToken,
MaxResults: 50,
Expand: "changelog,comment",
Fields: []string{"*all"},
}
...
issues, resp, err := s.client.Issue.SearchV2JQL(jql, searchOptions)
...
nextPageToken = resp.NextPageToken
}
confirmed it works after refactoring my search wrapper (...I also switched to v2 at same time and that itself was more ... work?)
func (j *Jira) Search(ctx context.Context, jql string, fields ...string) ([]*jira.Issue, error) {
if fields == nil || len(fields) == 0 {
fields = []string{"*navigable"}
}
options := &jira.SearchOptionsV2{
NextPageToken: "",
MaxResults: 100,
Fields: fields,
}
var allIssues []*jira.Issue
for {
issues, resp, err := j.Client.Issue.SearchV2JQL(ctx, jql, options)
if err != nil {
respErr(resp, err, jql)
return nil, err
}
startLen := len(allIssues)
allIssues = append(allIssues, make([]*jira.Issue, len(issues))...)
for i := range issues {
allIssues[startLen+i] = &issues[i]
}
if resp.NextPageToken == "" {
break
}
options.NextPageToken = resp.NextPageToken
}
return allIssues, nil
}