client

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package client implements the Jira Cloud HTTP transport for gojira.

It handles Basic authentication (email:token base64-encoded), request construction, 429 rate-limit retry with Retry-After / exponential backoff, transient network-error retry, and typed sentinel errors for callers.

The package knows nothing about issues, ADF, links, Markdown, or crawling. Its only project-internal import is internal/config.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnauthorized is returned when the server responds with 401.
	// This is a total-failure condition: credentials are invalid.
	ErrUnauthorized = errors.New("client: unauthorized (401)")

	// ErrForbidden is returned when the server responds with 403.
	// The caller should render a permission-denied stub and continue.
	ErrForbidden = errors.New("client: forbidden (403)")

	// ErrNotFound is returned when the server responds with 404.
	// The caller should render a not-found stub and continue.
	ErrNotFound = errors.New("client: not found (404)")

	// ErrRateLimited is returned when the server responds with 429 and
	// all retry attempts are exhausted.
	ErrRateLimited = errors.New("client: rate limited (429) after retries")

	// ErrBadRequest is returned when the server responds with 400. The
	// returned error may be a *APIError carrying Jira's per-field error
	// details (see phase-a-transport-2); callers can still match it with
	// errors.Is(err, ErrBadRequest).
	ErrBadRequest = errors.New("client: bad request (400)")

	// ErrConflict is returned when the server responds with 409, e.g. an
	// invalid workflow transition.
	ErrConflict = errors.New("client: conflict (409)")
)

Sentinel errors that callers can match with errors.Is.

Functions

func RenderCreateBody

func RenderCreateBody(project, issueType string, opts ...CreateOption) ([]byte, error)

RenderCreateBody assembles the JSON body for Client.CreateIssue from the required project key + issuetype name plus zero or more options. It is exported so the gojira facade can offer a dry-run affordance (build-without-send) reusing exactly the same assembly path the real CreateIssue method will use.

func RenderUpdateBody

func RenderUpdateBody(opts ...UpdateOption) ([]byte, error)

RenderUpdateBody assembles the JSON body for Client.UpdateIssue from zero or more options. With no options the result is "{}" — a no-op edit that Jira accepts without complaint, rather than the malformed {"fields":{}} that some servers reject.

Types

type APIError

type APIError struct {
	// Status is the HTTP status code that produced this error (400 or 409
	// for Jira REST v3 in the current client).
	Status int

	// Messages are the top-level "errorMessages" entries from the Jira
	// response body. nil/empty when the body had none.
	Messages []string

	// FieldErrors maps a Jira field id (e.g. "summary",
	// "customfield_10010") to its per-field validation message. nil/empty
	// when the body had no "errors" object.
	FieldErrors map[string]string
	// contains filtered or unexported fields
}

APIError is a structured representation of a Jira REST API error response, returned for 400 (Bad Request) and 409 (Conflict) statuses. It wraps the matching sentinel (ErrBadRequest or ErrConflict) so callers can both classify the failure with errors.Is and inspect which specific fields the server rejected via errors.As.

Jira Cloud v3 returns errors in the shape

{"errorMessages": ["..."], "errors": {"summary": "...", "...": "..."}}

Either key may be absent. When the body is empty, not JSON, or shaped differently, [parseAPIError] still returns an *APIError carrying only the status and the sentinel — degrading gracefully so classification is never lost.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface. The returned string is stable for a given *APIError value: field-error keys are sorted alphabetically so message text does not depend on Go's map iteration order, which keeps log lines and test assertions reproducible.

Shape (omitted sections are dropped):

"client: bad request (400): <message1>; <message2> [field1=msg; field2=msg]"

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

Unwrap returns the wrapped sentinel so errors.Is(err, ErrBadRequest) (or ErrConflict) classifies an *APIError exactly as it would the bare sentinel. Returning the sentinel rather than nil is what makes the typed error additive over the existing sentinel API.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the Jira Cloud HTTP transport. Construct via New. The zero value is not valid.

func New

func New(cfg config.Config, opts ...Option) (*Client, error)

New constructs a Client from cfg and applies any provided options.

It validates cfg.Site as a parseable URL with a non-empty host and pre-computes the Basic auth header. Returns an error if cfg.Site is not a valid URL.

func (*Client) AddComment

func (c *Client) AddComment(ctx context.Context, key string, opts ...CommentOption) (Comment, error)

AddComment appends a comment to an existing Jira issue. When no option supplies a body the default is an empty ADF paragraph; Jira accepts this as a deliberately empty comment.

func (*Client) CreateIssue

func (c *Client) CreateIssue(ctx context.Context, project, issueType string, opts ...CreateOption) (CreatedIssue, error)

CreateIssue creates a new Jira issue. The project key and issue-type name are required and explicit (signature-honesty: behavior-affecting inputs are not hidden in options). Everything else — summary, description, assignee, labels, parent, custom fields — is supplied via the CreateOption functional-option set in fields.go, so adding a new Jira field will not widen this signature.

On success Jira returns 201 with {id, key, self}; the parsed struct is returned. On 400/409 the error is an *APIError that still satisfies errors.Is against ErrBadRequest / ErrConflict via Unwrap.

func (*Client) DevStatus

func (c *Client) DevStatus(ctx context.Context, issueNumericID, application, dataType string) (DevStatusResponse, error)

DevStatus fetches the development metadata (pull requests, branches, commits, repositories, builds — depending on dataType) that Jira surfaces in its UI Development panel for the issue identified by its numeric ID.

GET <site>/rest/dev-status/1.0/issue/detail
    ?issueId=<numeric>&applicationType=<application>&dataType=<dataType>

# Important: this endpoint is NOT in the documented Jira Cloud platform REST API

The /rest/dev-status/1.0 path is not part of the platform OpenAPI specification at developer.atlassian.com. It is the same endpoint Atlassian's own Jira UI consumes to populate the Development panel on every issue page; it has been stable for over a decade for that reason. gojira treats it as best-effort enrichment: callers can opt out cleanly by setting GOJIRA_INCLUDE_DEV_STATUS=false (handled at the devstatus enricher and crawl orchestrator layers), in which case this method is never invoked.

429, 401, 403, 404, and transient network errors are handled identically to Client.GetIssue, using the same retry/backoff machinery and propagating the same typed sentinel errors.

issueNumericID must be the numeric issue id (the top-level "id" field of the standard GET /issue/<KEY> response, e.g. "86679"). The endpoint silently returns an empty detail array for issue *keys* — passing the human-readable key by mistake therefore looks like "no entities" rather than an error. application is the upstream applicationType value (e.g. "GitHub", "Bitbucket", "GitLab", "GitHubEnterprise"); the caller is expected to fan out one call per configured application.

dataType selects which entity list the response will populate. Valid values mirror the Jira UI Development panel groupings:

The endpoint accepts any string and silently returns an empty detail for unrecognised values; callers (the devstatus enricher in production) restrict dataType to the configured set.

func (*Client) GetIssue

func (c *Client) GetIssue(ctx context.Context, key string, expand []string) ([]byte, error)

GetIssue fetches the raw JSON body for the Jira issue identified by key from the configured site's REST API v3 endpoint:

GET <site>/rest/api/3/issue/<key>[?expand=<csv>]

On success it returns the raw response bytes. On failure it returns one of the typed sentinel errors (ErrUnauthorized, ErrForbidden, ErrNotFound, ErrRateLimited) or a wrapped error containing the HTTP status code.

429 responses are retried up to maxRateLimitRetries times, honouring the Retry-After header when present. Transient network errors (timeouts and mid-stream io.EOF) are retried up to maxNetworkRetries times. Context cancellation is respected throughout.

expand is the list of Jira expansion tokens to pass via the `expand` query parameter (e.g. []string{"names"} to receive the top-level "names" object mapping every field ID, including customfield_*, to its human-readable label). The values are comma-joined into a single `expand=<a>,<b>,...` query parameter exactly as documented at https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-get. When expand is empty or nil, no `expand` query parameter is sent and the response shape matches the pre-expansion behaviour.

expand is a parameter rather than a hard-coded default inside the body: callers know what they want from the response, and embedding a "blessed" value here would violate the project's signature-honesty rule (see docs/engineering-principles.md). Internal callers that want human-readable custom-field labels pass []string{"names"} explicitly; callers that want the legacy shape pass nil.

func (*Client) ListFields

func (c *Client) ListFields(ctx context.Context) ([]Field, error)

ListFields fetches the tenant's field metadata from:

GET <site>/rest/api/3/field

It is used by the hierarchy discoverer to auto-detect the Epic Link custom field ID, which varies per tenant. 429 and transient network errors are retried using the same machinery as GetIssue.

func (*Client) ListTransitions

func (c *Client) ListTransitions(ctx context.Context, key string) ([]Transition, error)

ListTransitions fetches the workflow transitions currently available for the issue identified by key. The list is workflow-state dependent: Jira only returns transitions whose preconditions are met for the current state.

func (*Client) Search

func (c *Client) Search(ctx context.Context, jql string, maxResults int) (SearchResult, error)

Search executes a JQL query against the modern Jira Cloud search endpoint:

POST <site>/rest/api/3/search/jql
{"jql": "...", "fields": ["key"], "maxResults": N}

Only the issue keys from the response are returned; the rest of each issue payload is discarded. This is sufficient for hierarchy discovery, which only needs keys to feed back into the crawl queue.

429, 401, 403, 404, and transient network errors are handled identically to GetIssue, using the same retry/backoff machinery.

maxResults caps the maxResults parameter sent in the request body. When maxResults <= 0, the Jira API default is used (currently 50).

The modern endpoint uses cursor-based pagination via nextPageToken. Search currently returns only the first page (up to maxResults results) and surfaces NextPageToken on SearchResult so callers can detect when more results exist. Automatic multi-page aggregation is deferred to post-MVP.

func (*Client) TransitionIssue

func (c *Client) TransitionIssue(ctx context.Context, key, transitionID string, opts ...TransitionOption) error

TransitionIssue moves an issue through the given workflow transition (identified by Jira's tenant/workflow-specific transition id). Options allow setting fields or appending a comment during the transition. Jira responds with 204 on success.

func (*Client) UpdateIssue

func (c *Client) UpdateIssue(ctx context.Context, key string, opts ...UpdateOption) error

UpdateIssue edits fields on an existing Jira issue identified by key. Field selection mirrors [CreateIssue] via the UpdateOption set, which shares the underlying builder so options stay in lockstep. Jira responds with 204 No Content on success; the method therefore returns no value beyond the error.

type Comment

type Comment struct {
	ID                string
	AuthorAccountID   string
	AuthorDisplayName string
	Created           string
}

Comment is the response payload from a successful Client.AddComment call, carrying the Jira-assigned id, author identity, and creation timestamp (left as the raw ISO-8601 string Jira returns).

type CommentOption

type CommentOption func(*commentBody)

CommentOption customizes an Client.AddComment request body. The body is always an ADF document; WithCommentText converts plain text, while WithCommentADF lets callers supply a rich pre-built document.

func WithCommentADF

func WithCommentADF(doc json.RawMessage) CommentOption

WithCommentADF sets the comment body from a caller-supplied ADF document. Use this for rich-text content (lists, code blocks, links) the plain-text helper cannot express.

func WithCommentText

func WithCommentText(text string) CommentOption

WithCommentText sets the comment body from plain text, converting it to ADF via adf.BuildParagraphDoc.

type CreateOption

type CreateOption func(*fieldsBuilder)

CreateOption customizes a CreateIssue request body. It is shaped as a function over the internal builder so each option stays a tiny, independently-testable unit and new options can be added with zero disruption to existing call sites.

func WithAssigneeAccountID

func WithAssigneeAccountID(id string) CreateOption

WithAssigneeAccountID sets the assignee on a Create request by Atlassian accountId — the only assignee write form Jira Cloud supports since the 2019 GDPR migration.

func WithDescriptionADF

func WithDescriptionADF(doc json.RawMessage) CreateOption

WithDescriptionADF sets the issue description from a caller-supplied ADF document on a Create request. Use this when you already have rich ADF (lists, code blocks, etc.) you do not want to re-parse from text.

func WithDescriptionText

func WithDescriptionText(text string) CreateOption

WithDescriptionText sets the issue description from plain text on a Create request. The text is converted to ADF via adf.BuildParagraphDoc so Jira accepts it.

func WithField

func WithField(fieldID string, value any) CreateOption

WithField is the generic escape hatch: set fields[fieldID]=value with no typed wrapper. Use this for any custom field or for fields the typed options above do not cover. This is the seam that lets gojira support a new Jira field with ZERO signature churn.

func WithLabels

func WithLabels(labels ...string) CreateOption

WithLabels sets the labels array on a Create request.

func WithParent

func WithParent(key string) CreateOption

WithParent sets the parent issue key on a Create request (e.g. a Sub-task's parent). Update has its own "parent" semantics that differ per workflow; we therefore expose WithParent only on Create.

func WithRawFields

func WithRawFields(m map[string]any) CreateOption

WithRawFields merges a caller-supplied map of fieldID→value into the fields object. Useful when the gRPC layer hands in a bulk map of custom-field overrides. Conflicts with earlier typed options resolve last-write-wins.

func WithSummary

func WithSummary(s string) CreateOption

WithSummary sets the issue summary on a Create request.

type CreatedIssue

type CreatedIssue struct {
	Key  string
	ID   string
	Self string
}

CreatedIssue is the response payload from a successful Client.CreateIssue call. Self is the canonical REST URL Jira returns for the new issue.

type DevStatusBranch

type DevStatusBranch struct {
	Branch string `json:"branch"`
	URL    string `json:"url"`
}

DevStatusBranch holds a branch reference from a Dev Status PR entry (the source/destination "branch" field of a pull request). It is a distinct type from DevStatusBranchEntry which represents a top- level entry returned by a dataType=branch query.

type DevStatusBranchEntry

type DevStatusBranchEntry struct {
	Name                 string             `json:"name"`
	URL                  string             `json:"url"`
	CreatePullRequestURL string             `json:"createPullRequestUrl"`
	Repository           DevStatusRepoRef   `json:"repository"`
	LastCommit           DevStatusCommitRef `json:"lastCommit"`
}

DevStatusBranchEntry is a single entry returned by a Dev Status query for dataType=branch. The Jira UI surfaces these in the Development panel alongside pull requests and commits; gojira mirrors that grouping in its Markdown output.

type DevStatusBuild

type DevStatusBuild struct {
	ID          string                `json:"id"`
	BuildNumber int                   `json:"buildNumber"`
	Name        string                `json:"name"`
	Description string                `json:"description"`
	URL         string                `json:"url"`
	State       string                `json:"state"`
	LastUpdated string                `json:"lastUpdated"`
	TestSummary *DevStatusTestSummary `json:"testSummary,omitempty"`
	References  []DevStatusBuildRef   `json:"references"`
}

DevStatusBuild is a single entry returned by a Dev Status query for dataType=build. State is the upstream lifecycle string ("SUCCESSFUL", "FAILED", "IN_PROGRESS", "STOPPED", "PENDING", ...); gojira does not normalise it. TestSummary is a pointer so a build that does not report test counts can be distinguished from one that reports zero.

type DevStatusBuildRef

type DevStatusBuildRef struct {
	Name string `json:"name"`
	URI  string `json:"uri"`
}

DevStatusBuildRef is a single git reference (branch or tag) tied to a build. Jira surfaces it so the build can be attributed to the branch its CI ran on.

type DevStatusCommit

type DevStatusCommit struct {
	ID              string           `json:"id"`
	DisplayID       string           `json:"displayId"`
	URL             string           `json:"url"`
	Message         string           `json:"message"`
	Author          DevStatusPerson  `json:"author"`
	AuthorTimestamp string           `json:"authorTimestamp"`
	FileCount       int              `json:"fileCount"`
	Merge           bool             `json:"merge"`
	Repository      DevStatusRepoRef `json:"repository"`
}

DevStatusCommit is a single entry returned by a Dev Status query for dataType=commit. Fields mirror the upstream response exactly; gojira preserves the full SHA in ID and the seven-character abbreviation in DisplayID rather than re-deriving the latter, in case future Jira versions change the abbreviation length.

type DevStatusCommitRef

type DevStatusCommitRef struct {
	ID              string          `json:"id"`
	DisplayID       string          `json:"displayId"`
	URL             string          `json:"url"`
	Message         string          `json:"message"`
	Author          DevStatusPerson `json:"author"`
	AuthorTimestamp string          `json:"authorTimestamp"`
}

DevStatusCommitRef is the last-commit pointer embedded inside a Dev Status branch entry. It mirrors the same fields as DevStatusCommit but without the standalone-entity fields (fileCount, merge, repository) that only appear on a top-level commit query.

type DevStatusInstance

type DevStatusInstance struct {
	Instance     DevStatusInstanceMeta  `json:"_instance"`
	PullRequests []DevStatusPR          `json:"pullRequests"`
	Branches     []DevStatusBranchEntry `json:"branches"`
	Commits      []DevStatusCommit      `json:"commits"`
	Repositories []DevStatusRepository  `json:"repositories"`
	Builds       []DevStatusBuild       `json:"builds"`
}

DevStatusInstance groups the development entities returned by a single development-tool integration (e.g. one connected GitHub app).

Exactly one of the entity lists is non-empty for a given response, depending on the dataType the caller requested. The struct unmarshals all five tolerantly so a single Go type can carry the response for any dataType the Client.DevStatus caller asked for.

type DevStatusInstanceMeta

type DevStatusInstanceMeta struct {
	Type    string `json:"type"`
	Name    string `json:"name"`
	BaseURL string `json:"baseUrl"`
}

DevStatusInstanceMeta describes the development-tool integration that owns a DevStatusInstance's entries.

type DevStatusPR

type DevStatusPR struct {
	ID            string              `json:"id"`
	URL           string              `json:"url"`
	Name          string              `json:"name"`
	Status        string              `json:"status"`
	LastUpdate    string              `json:"lastUpdate"`
	Source        DevStatusBranch     `json:"source"`
	Destination   DevStatusBranch     `json:"destination"`
	Author        DevStatusPerson     `json:"author"`
	Reviewers     []DevStatusReviewer `json:"reviewers"`
	Repository    string              `json:"repositoryName"`
	RepositoryURL string              `json:"repositoryUrl"`
	CommentCount  int                 `json:"commentCount"`
}

DevStatusPR is a single pull-request entry returned by the Dev Status endpoint. Field names match Jira's response shape exactly; semantic translation (e.g. mapping Name → Title) happens in the devstatus package, not here.

type DevStatusPerson

type DevStatusPerson struct {
	Name string `json:"name"`
}

DevStatusPerson holds the author of a Dev Status PR/commit/branch entry. The Jira response also carries an "avatar" URL, which gojira does not consume.

type DevStatusRepoRef

type DevStatusRepoRef struct {
	Name string `json:"name"`
	URL  string `json:"url"`
}

DevStatusRepoRef is the small repository pointer embedded inside other Dev Status entities (branches, commits). The Jira response nests a {"name", "url"} pair; gojira preserves both so the renderer can label the parent entity with its repository.

type DevStatusRepository

type DevStatusRepository struct {
	Name   string `json:"name"`
	URL    string `json:"url"`
	Avatar string `json:"avatar"`
}

DevStatusRepository is a single entry returned by a Dev Status query for dataType=repository. The Jira UI surfaces these so users can see which repositories have referenced an issue even when no PR or branch carries the issue key directly.

The upstream response also nests truncated commits[] and branches[] arrays inside each repository entry; gojira does not consume them (they are sparser than the top-level dataType=commit/branch queries and would risk duplication if rendered separately).

type DevStatusResponse

type DevStatusResponse struct {
	Errors []json.RawMessage   `json:"errors"`
	Detail []DevStatusInstance `json:"detail"`
}

DevStatusResponse is the parsed shape of a successful Dev Status API response. The endpoint returns a single envelope for any of the five supported dataType values (pullrequest, branch, commit, repository, build); the per-entity list inside each DevStatusInstance differs per dataType. A query for dataType=branch populates Branches and leaves PullRequests/Commits/Repositories/Builds empty, and so on.

Errors is the upstream response's "errors" array. A non-empty Errors slice does not by itself cause Client.DevStatus to return a Go error: the server returns HTTP 200 with embedded soft-error entries (e.g. when one connected GitHub instance is unreachable while another succeeded). Callers decide how to surface these.

The element type is intentionally json.RawMessage rather than a typed struct. The Dev Status endpoint is undocumented and the per-error entry shape is not guaranteed stable: production responses have been observed carrying both string entries (older tenants) and JSON objects with shape `{"code": <int>, "message": <string>, "userId": <string>, ...}` (newer tenants — observed on PROJ-1417 for dataType=commit and dataType=build). Modelling Errors as a typed slice against a single observed shape would break the unmarshal as soon as the other shape appears. json.RawMessage accepts any valid JSON element and lets the (rare) caller that wants to introspect the entries decode each one lazily. This is the "signature honesty" rule from docs/engineering-principles.md applied to response models: do not pretend to know a shape we have not verified across the entire observed input space.

type DevStatusReviewer

type DevStatusReviewer struct {
	Name     string `json:"name"`
	Approved bool   `json:"approved"`
}

DevStatusReviewer holds a single reviewer entry from a Dev Status PR.

type DevStatusTestSummary

type DevStatusTestSummary struct {
	TotalNumber   int `json:"totalNumber"`
	PassedNumber  int `json:"passedNumber"`
	FailedNumber  int `json:"failedNumber"`
	SkippedNumber int `json:"skippedNumber"`
}

DevStatusTestSummary holds the per-build test counts surfaced by Dev Status for CI integrations that publish them (Bitbucket Pipelines, GitHub Actions via the Atlassian app, etc.). Fields with no value default to zero.

type Field

type Field struct {
	ID     string
	Key    string
	Name   string
	Custom bool
}

Field is the subset of Jira field metadata that gojira needs. It mirrors the relevant fields in the GET /rest/api/3/field response:

[{"id": "...", "key": "...", "name": "...", "custom": true|false, ...}]

Only ID, Key, Name, and Custom are populated; everything else is dropped.

type Option

type Option func(*Client)

Option is a functional option for New.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient replaces the entire http.Client used for requests. Useful in tests that inject an httptest.Server-backed client.

func WithLogger

func WithLogger(lg *slog.Logger) Option

WithLogger installs a logging RoundTripper that emits one INFO summary per request (method/url/status/duration_ms/bytes) and, when the logger is enabled at log.LevelTrace, a full net/http/httptrace lifecycle plus the raw response body. Authorization and other sensitive headers are always redacted. A nil logger is a no-op: no request logging is emitted and the transport is left untouched, so existing callers see byte-identical behavior.

WithLogger composes with WithHTTPClient and WithRoundTripper: the logging RoundTripper is installed by New AFTER all options have been applied, so it wraps whatever Transport ended up on the client. Order between WithLogger and WithRoundTripper / WithHTTPClient is irrelevant.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the maximum number of 429 retry attempts.

func WithNetworkBackoff

func WithNetworkBackoff(base, max time.Duration) Option

WithNetworkBackoff overrides the base and max backoff durations for transient network-error retries. Exposed primarily for tests.

func WithRateLimitBackoff

func WithRateLimitBackoff(base, max time.Duration) Option

WithRateLimitBackoff overrides the base and max backoff durations for 429 retries. Exposed primarily for tests that need sub-second backoffs.

func WithRoundTripper

func WithRoundTripper(rt http.RoundTripper) Option

WithRoundTripper replaces only the transport on the default http.Client. Useful when a custom transport is needed without a full http.Client.

func WithUserAgent added in v0.4.2

func WithUserAgent(ua string) Option

WithUserAgent overrides the default User-Agent header value sent on every request. The default is buildinfo.UserAgent, so the stamped build identity is reported automatically; this option is provided for callers (typically downstream library consumers) that need to advertise their own product name in the header.

An empty string is ignored so callers cannot accidentally clobber the default with a zero value.

type SearchResult

type SearchResult struct {
	Keys          []string
	NextPageToken string
}

SearchResult is the result of a Search call. Keys lists the issue keys returned by the JQL query, in the order the Jira API returned them. NextPageToken is the opaque cursor for the next page; an empty value means there are no more pages. v0.1 does not paginate automatically; callers that need more than maxResults must call Search again with the returned token (post-MVP capability).

type Transition

type Transition struct {
	ID       string
	Name     string
	ToStatus string
}

Transition is one workflow transition available for an issue, projected from Jira's GET .../transitions response: id + display name + the name of the status the issue moves to when the transition is executed.

type TransitionOption

type TransitionOption func(*fieldsBuilder)

TransitionOption customizes a Client.TransitionIssue request body — either by merging additional fields/update ops onto the standard {"transition": {"id": "..."}} body, or by appending a comment via WithTransitionCommentText. It is layered on the same internal [fieldsBuilder] used by Create/Update so the marshalling logic does not diverge.

func WithTransitionCommentText

func WithTransitionCommentText(text string) TransitionOption

WithTransitionCommentText appends a comment-add op with an ADF body (built via adf.BuildParagraphDoc) to the transition's update map. The resulting body is {"transition":{"id":...}, "update":{"comment":[{"add":{"body":<ADF>}}]}}.

func WithTransitionField

func WithTransitionField(fieldID string, value any) TransitionOption

WithTransitionField sets fields[fieldID]=value during a transition. Useful for transitions that require a resolution, a comment, or any custom field. Mirrors WithField but for the transition body shape.

type UpdateOption

type UpdateOption func(*fieldsBuilder)

UpdateOption customizes an UpdateIssue request body. Same shape as CreateOption but a distinct named type so the compiler keeps Create-only options (like WithParent) out of Update call sites.

func WithAssigneeAccountIDUpdate

func WithAssigneeAccountIDUpdate(id string) UpdateOption

WithAssigneeAccountIDUpdate sets the assignee by accountId on an Update request.

func WithDescriptionADFUpdate

func WithDescriptionADFUpdate(doc json.RawMessage) UpdateOption

WithDescriptionADFUpdate sets the issue description from a caller-supplied ADF document on an Update request.

func WithDescriptionTextUpdate

func WithDescriptionTextUpdate(text string) UpdateOption

WithDescriptionTextUpdate sets the issue description from plain text on an Update request, converting to ADF via adf.BuildParagraphDoc.

func WithFieldUpdate

func WithFieldUpdate(fieldID string, value any) UpdateOption

WithFieldUpdate is the generic escape hatch on Update: set fields[fieldID]=value with no typed wrapper.

func WithLabelsUpdate

func WithLabelsUpdate(labels ...string) UpdateOption

WithLabelsUpdate sets the labels array on an Update request. Use WithUpdateVerb for incremental "add" / "remove" semantics.

func WithRawFieldsUpdate

func WithRawFieldsUpdate(m map[string]any) UpdateOption

WithRawFieldsUpdate merges a caller-supplied map into the fields object on an Update request.

func WithSummaryUpdate

func WithSummaryUpdate(s string) UpdateOption

WithSummaryUpdate sets the issue summary on an Update request.

func WithUpdateVerb

func WithUpdateVerb(fieldID, verb string, value any) UpdateOption

WithUpdateVerb appends an update op (verb is "add", "remove", or "set") for fieldID. Multi-valued fields like "labels" support incremental edits — call WithUpdateVerb several times to compose an operation list, applied by Jira in order. Update-only because the update verbs only have a defined meaning on existing issues.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL