Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39ec958f04 | |||
| 097d46886d |
+28
-10
@@ -2,9 +2,9 @@ package sync
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -47,23 +47,41 @@ type jiraIssue struct {
|
|||||||
} `json:"fields"`
|
} `json:"fields"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search runs a JQL query via POST /rest/api/3/search/jql — the replacement
|
||||||
|
// for the removed GET /rest/api/3/search endpoint (Atlassian CHANGE-2046).
|
||||||
|
// It uses cursor pagination (nextPageToken/isLast); the legacy startAt/total
|
||||||
|
// fields no longer exist.
|
||||||
func (j *jiraConnector) search(ctx context.Context, jql, fields string) ([]jiraIssue, error) {
|
func (j *jiraConnector) search(ctx context.Context, jql, fields string) ([]jiraIssue, error) {
|
||||||
|
fieldList := strings.Split(fields, ",")
|
||||||
|
u := j.baseURL + "/rest/api/3/search/jql"
|
||||||
var all []jiraIssue
|
var all []jiraIssue
|
||||||
for startAt := 0; ; {
|
nextPageToken := ""
|
||||||
var page struct {
|
for {
|
||||||
Issues []jiraIssue `json:"issues"`
|
reqBody := map[string]any{
|
||||||
Total int `json:"total"`
|
"jql": jql,
|
||||||
|
"fields": fieldList,
|
||||||
|
"maxResults": 100,
|
||||||
}
|
}
|
||||||
u := fmt.Sprintf("%s/rest/api/3/search?jql=%s&fields=%s&maxResults=100&startAt=%d",
|
if nextPageToken != "" {
|
||||||
j.baseURL, url.QueryEscape(jql), url.QueryEscape(fields), startAt)
|
reqBody["nextPageToken"] = nextPageToken
|
||||||
if err := getJSON(ctx, j.Authorize, u, &page); err != nil {
|
}
|
||||||
|
body, err := json.Marshal(reqBody)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("jira search: encode request: %w", err)
|
||||||
|
}
|
||||||
|
var page struct {
|
||||||
|
Issues []jiraIssue `json:"issues"`
|
||||||
|
NextPageToken string `json:"nextPageToken"`
|
||||||
|
IsLast bool `json:"isLast"`
|
||||||
|
}
|
||||||
|
if err := doJSON(ctx, j.Authorize, http.MethodPost, u, body, &page); err != nil {
|
||||||
return nil, fmt.Errorf("jira search: %w", err)
|
return nil, fmt.Errorf("jira search: %w", err)
|
||||||
}
|
}
|
||||||
all = append(all, page.Issues...)
|
all = append(all, page.Issues...)
|
||||||
startAt += len(page.Issues)
|
if page.IsLast || page.NextPageToken == "" || len(page.Issues) == 0 {
|
||||||
if len(page.Issues) == 0 || startAt >= page.Total {
|
|
||||||
return all, nil
|
return all, nil
|
||||||
}
|
}
|
||||||
|
nextPageToken = page.NextPageToken
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -441,7 +441,7 @@ account** in that system, updated since `lastSyncAt − 5 min` (overlap window):
|
|||||||
|
|
||||||
| System | Query mechanism |
|
| System | Query mechanism |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Jira Cloud | `GET /rest/api/3/search?jql=assignee="<email>" AND project=<key> AND updated >= "<ts>"` (Basic auth: email+API token) |
|
| Jira Cloud | `POST /rest/api/3/search/jql` with body `{jql:'assignee="<email>" AND project=<key> AND updated >= "<ts>"', fields, maxResults}`, cursor-paginated via `nextPageToken`/`isLast` (Basic auth: email+API token). The legacy `GET /rest/api/3/search` was removed by Atlassian — CHANGE-2046. |
|
||||||
| Azure DevOps | `POST …/_apis/wit/wiql?api-version=7.1` with WIQL `[System.AssignedTo] = '<email>' AND [System.TeamProject] = '<project>' AND [System.ChangedDate] >= '<ts>'`, then batch `GET workitems` (PAT auth) |
|
| Azure DevOps | `POST …/_apis/wit/wiql?api-version=7.1` with WIQL `[System.AssignedTo] = '<email>' AND [System.TeamProject] = '<project>' AND [System.ChangedDate] >= '<ts>'`, then batch `GET workitems` (PAT auth) |
|
||||||
| YouTrack | `GET /api/issues?query=assignee: <login> project: <key> updated: <ts> .. *` (Bearer permanent token) |
|
| YouTrack | `GET /api/issues?query=assignee: <login> project: <key> updated: <ts> .. *` (Bearer permanent token) |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user