v0.28.0¶
Release Date: 2025-12-12
This release adds workflow automation through issue transitions, status category filtering, and batch operations for labels and custom fields.
Highlights¶
- Issue Transitions API for workflow automation
- Status Category Filtering and histograms
- Batch Issue Operations for labels and patches
- Enhanced JQL Builder with text search operators
New Features¶
Issue Transitions¶
Automate workflow transitions with the new transitions API.
import "github.com/grokify/gojira/rest"
// Get available transitions for an issue
transitions, err := client.IssueAPI.GetTransitions(ctx, "ISSUE-123")
if err != nil {
log.Fatal(err)
}
// Print available transitions
for _, t := range transitions {
fmt.Printf("ID: %s, Name: %s\n", t.ID, t.Name)
}
// Execute a transition by name
err = client.IssueAPI.DoTransitionWithNameAndPayload(ctx, "ISSUE-123", "Done", nil)
// Batch transitions
options := rest.TransitionOptionSet{
Options: []rest.TransitionOption{
{IssueKey: "ISSUE-1", TransitionName: "In Progress"},
{IssueKey: "ISSUE-2", TransitionName: "Done"},
},
}
results, err := client.IssueAPI.DoTransitions(ctx, options)
Status Category Filtering¶
Filter and analyze issues by Jira's built-in status categories (To Do, In Progress, Done).
// Filter by status category
doneIssues := issuesSet.FilterByStatusCategory("Done")
inProgressIssues := issuesSet.FilterByStatusCategory("In Progress")
// Histogram by status category
histogram := issuesSet.HistogramByStatusCategory()
for category, count := range histogram {
fmt.Printf("%s: %d\n", category, count)
}
// Get statuses for specific categories
categories := gojira.StatusCategories{...}
statuses := categories.StatusesForCategories([]string{"Done", "In Progress"})
Batch Issue Operations¶
Update multiple issues efficiently.
// Batch patch issues
keys := []string{"ISSUE-1", "ISSUE-2", "ISSUE-3"}
reqBody := rest.IssuePatchRequestBody{
Fields: map[string]rest.IssuePatchRequestBodyField{
"priority": {Value: "High"},
},
}
results, err := client.IssueAPI.IssuesPatch(ctx, keys, reqBody)
// Batch add label
results, err := client.IssueAPI.IssuesPatchAddLabel(ctx, keys, "reviewed")
Cached Issue Search¶
Cache search results to a file for repeated queries.
issuesSet, err := client.IssueAPI.SearchIssuesSetWithFileCache(
"project = FOO",
"cache/foo-issues.json",
24*time.Hour, // Cache TTL
)
JQL Text Search¶
New JQL builder fields for text searching.
jql := gojira.JQL{
ProjectsIncl: [][]string{{"FOO"}},
SummaryLike: []string{"login", "auth"}, // summary ~ "login" AND summary ~ "auth"
TextLike: []string{"error"}, // text ~ "error"
TextNotLike: []string{"test"}, // text !~ "test"
}
Issue Resolution Time¶
Calculate time from creation to resolution.
im := rest.NewIssueMore(issue)
resolutionTime := im.ResolutionTime()
if resolutionTime > 0 {
fmt.Printf("Resolved in: %s\n", resolutionTime)
}
Custom Field Histograms¶
Generate histograms by any custom field.
histogram, err := issuesSet.HistogramByCustomField("customfield_10001")
for value, count := range histogram {
fmt.Printf("%s: %d\n", value, count)
}
API Changes¶
Added¶
| Type | Method/Field | Description |
|---|---|---|
| Method | IssueService.DoTransitions() |
Batch issue transitions |
| Method | IssueService.DoTransitionWithNameAndPayload() |
Named transition with payload |
| Method | IssueService.GetTransitions() |
Get available transitions |
| Method | IssueService.IssuesPatch() |
Batch update issues |
| Method | IssueService.IssuesPatchAddLabel() |
Batch add label |
| Method | IssueService.SearchIssuesSetWithFileCache() |
Cached search |
| Method | IssuesSet.FilterByStatusCategory() |
Filter by status category |
| Method | IssuesSet.FilterByKeys() |
Filter by issue keys |
| Method | IssuesSet.HistogramByStatus() |
Histogram by status |
| Method | IssuesSet.HistogramByStatusCategory() |
Histogram by category |
| Method | IssuesSet.HistogramByCustomField() |
Histogram by custom field |
| Method | IssuesSet.KeysFilterLabelIncl() |
Keys with label |
| Method | IssuesSet.KeysFilterSummaryNotLike() |
Keys without summary text |
| Method | IssuesSet.Summaries() |
Get all summaries |
| Method | IssueMore.Description() |
Get issue description |
| Method | IssueMore.ResolutionTime() |
Time to resolution |
| Method | IssuesSets.Histogram() |
Histogram across sets |
| Method | IssuesSets.BarChartsText() |
Text bar charts |
| Method | StatusCategories.StatusesForCategories() |
Statuses for categories |
| Method | Transitions.Names() |
Get transition names |
| Field | JQL.SummaryLike |
Summary text search |
| Field | JQL.SummaryNotLike |
Summary exclusion |
| Field | JQL.TextLike |
Full text search |
| Field | JQL.TextNotLike |
Text exclusion |
| Type | Transition{} |
Transition type |
| Type | Transitions{} |
Transitions slice |
| Type | TransitionOption{} |
Transition option |
| Type | TransitionOptionSet{} |
Batch transitions |
Changed¶
| Change | Description |
|---|---|
IssueMore.Issue |
Now public for direct access |
IssuesSet.Items |
Renamed attribute |
IssueMore.LabelExists() |
Added matchToLowerTrimSpace parameter |
Example: Workflow Automation¶
Complete example automating issue transitions based on labels:
package main
import (
"context"
"fmt"
"log"
"github.com/grokify/gojira/rest"
)
func main() {
client, err := rest.NewClientFromBasicAuth(
"https://your-instance.atlassian.net",
"your-email@example.com",
"your-api-token",
false,
)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Find issues with "ready-for-review" label
issues, err := client.IssueAPI.SearchIssues(
"project = FOO AND labels = ready-for-review AND status = 'In Progress'",
true,
)
if err != nil {
log.Fatal(err)
}
// Transition each to "In Review"
for _, issue := range issues {
err := client.IssueAPI.DoTransitionWithNameAndPayload(ctx, issue.Key, "In Review", nil)
if err != nil {
log.Printf("Failed to transition %s: %v", issue.Key, err)
continue
}
fmt.Printf("Transitioned %s to In Review\n", issue.Key)
}
}
Commits¶
| Type | Description | Commit |
|---|---|---|
| Added | IssueService.DoTransitions() |
350db95 |
| Added | IssueService.DoTransitionWithNameAndPayload() |
48b51bc |
| Added | IssueService.GetTransitions() |
f066b2d |
| Added | Transition{}, Transitions{} types |
59e1796 |
| Added | IssuesSet.FilterByStatusCategory() |
7640a46 |
| Added | IssuesSet.HistogramByStatus(), HistogramByStatusCategory() |
f7e0fdf |
| Added | IssuesSet.HistogramByCustomField() |
af1d8ab |
| Added | IssueService.IssuesPatch(), IssuesPatchAddLabel() |
9944a42 |
| Added | IssueService.SearchIssuesSetWithFileCache() |
38dd2f3 |
| Added | IssuesSet.FilterByKeys(), filter methods |
f6a59f9 |
| Added | IssueMore.Description() |
edf1a04 |
| Added | IssuesSet.Summaries() |
6bcf571 |
| Added | IssueMore.ResolutionTime() |
adc5a25 |
| Added | JQL.SummaryLike, TextLike, etc. |
7ba5f3a |
| Added | StatusCategories.StatusesForCategories() |
46ea60f |
| Added | IssuesSets.Histogram(), BarChartsText() |
d77c98a |
| Changed | Externalized IssueMore.Issue |
8f21c6a |
| Changed | Renamed IssuesSet.Items |
72f52c2 |