Documentation
¶
Overview ¶
Package jira is the Atlassian Cloud REST client: read paths plus user-initiated writes.
The token lives only in the Authorization header. It is never put in an error, a log line or a URL (constitution article 8), which is why transport reports the method and path but never the request itself.
Index ¶
- Constants
- Variables
- func Doc(text string, mentions map[string]string) json.RawMessage
- func DocWithMedia(text string, mentions map[string]string, media []Media) json.RawMessage
- func FormatTransition(t Transition) string
- func ISOTime(s string) string
- func IsBotAccountType(t string) bool
- func JoinTransitions(list []Transition) string
- func PickTransition(key, want string, list []Transition) (string, error)
- func PlainText(raw json.RawMessage) string
- func ReachableCategories(list []Transition) []string
- func StatusCategoryToken(s string) (string, bool)
- type APIError
- type Attachment
- type Changelog
- type ClaimResult
- type Client
- func (c *Client) AddComment(ctx context.Context, key string, adf json.RawMessage, ...) (Comment, error)
- func (c *Client) BaseURL() string
- func (c *Client) Changelog(ctx context.Context, key string) ([]History, error)
- func (c *Client) Claim(ctx context.Context, key, transitionID string, takeOver bool) (ClaimResult, error)
- func (c *Client) Comments(ctx context.Context, key string) ([]Comment, error)
- func (c *Client) Count(ctx context.Context, jql string) (int, error)
- func (c *Client) CreateFields(ctx context.Context, projectIDOrKey, issueTypeID string) ([]CreateFieldMeta, error)
- func (c *Client) CreateIssue(ctx context.Context, fields map[string]any) (string, error)
- func (c *Client) CreateMeta(ctx context.Context, projects []string) ([]CreateMetaProject, error)
- func (c *Client) CreatesVersionsByName() bool
- func (c *Client) DevStatusPRCount(ctx context.Context, issueID string) (int, error)
- func (c *Client) DevStatusPRs(ctx context.Context, issueID string) ([]DevPR, error)
- func (c *Client) EditIssue(ctx context.Context, key string, fields, update map[string]any) error
- func (c *Client) EditMeta(ctx context.Context, key string) (map[string]FieldMeta, error)
- func (c *Client) EnableNameCreatedVersions()
- func (c *Client) Fields(ctx context.Context) ([]FieldInfo, error)
- func (c *Client) IssueLinkTypes(ctx context.Context) ([]IssueLinkType, error)
- func (c *Client) IssueStatus(ctx context.Context, key string) (Status, *User, error)
- func (c *Client) LinkDevBuild(ctx context.Context, issueID string, state DevBuildState, number, url string) (DevBuild, error)
- func (c *Client) LinkDevDeployment(ctx context.Context, issueID, environment, state, url string) (DevDeployment, error)
- func (c *Client) LinkDevPR(ctx context.Context, issueID, prURL, name, author, branch string, ...) (DevPR, error)
- func (c *Client) LinkIssues(ctx context.Context, typeID, outwardKey, inwardKey string) error
- func (c *Client) MediaRef(ctx context.Context, attachmentID string) (mediaID, filename string, err error)
- func (c *Client) MyFilters(ctx context.Context) ([]SavedFilter, error)
- func (c *Client) Myself(ctx context.Context) (User, error)
- func (c *Client) Priorities(ctx context.Context) ([]string, error)
- func (c *Client) PriorityCatalog(ctx context.Context) ([]NamedID, error)
- func (c *Client) ProjectVersions(ctx context.Context, projectKey string) ([]Version, error)
- func (c *Client) Projects(ctx context.Context, limit int) (list []Project, truncated bool, err error)
- func (c *Client) Raw(ctx context.Context, method, path string, body []byte, mutating bool) (status int, out []byte, err error)
- func (c *Client) Resolutions(ctx context.Context) ([]NamedID, error)
- func (c *Client) Search(ctx context.Context, jql string, fields []string, withChangelog bool, ...) error
- func (c *Client) SearchUsers(ctx context.Context, query string) ([]User, error)
- func (c *Client) SetAssignee(ctx context.Context, key, accountID string) error
- func (c *Client) Statuses(ctx context.Context) (map[string]string, error)
- func (c *Client) TakeUsage() Usage
- func (c *Client) Transition(ctx context.Context, key, transitionID string, fields map[string]any, ...) error
- func (c *Client) Transitions(ctx context.Context, key string) ([]Transition, error)
- func (c *Client) UpdateFields(ctx context.Context, key string, fields map[string]any) error
- func (c *Client) Upload(ctx context.Context, key, filename string, file io.Reader) ([]Attachment, error)
- func (c *Client) Usage() Usage
- type Comment
- type CommentPage
- type CommentVisibility
- type CreateFieldMeta
- type CreateMetaIssueType
- type CreateMetaProject
- type DevBuild
- type DevBuildState
- type DevDeployment
- type DevPR
- type DevPRActor
- type DevPRAuthor
- type DevPRSource
- type DevPRStatus
- type FieldInfo
- type FieldMeta
- type Fields
- type History
- type HistoryItem
- type Issue
- type IssueLink
- type IssueLinkType
- type Media
- type NamedID
- type Project
- type SavedFilter
- type Status
- type Transition
- type TransitionField
- type Usage
- type User
- type Version
Constants ¶
const Layout = "2006-01-02T15:04:05.000-0700"
Layout is how Jira stamps timestamps: ISO-8601 with a numeric offset and no colon in it, which is why time.RFC3339 does not parse them.
Variables ¶
var DefaultBackoff = httppolicy.DefaultBackoff
DefaultBackoff is the first wait New applies, doubling per attempt and capped at httppolicy.MaxWait. Tests may assign 0 and restore it with t.Cleanup.
var DefaultCreatesVersionsByName = false
DefaultCreatesVersionsByName is copied onto Client at New. Production is false (Cloud Jira). Tests that drive the issuetap mint-by-name path through a Connected httptest client set this and restore with t.Cleanup (same seam as DefaultRetries). origin.transportJira then enables it for real issuetap clients regardless of this default.
var DefaultRetries = httppolicy.DefaultRetries
DefaultRetries is the production retry budget New applies (total attempts). Tests may assign a smaller value and restore it with t.Cleanup. The value is httppolicy.DefaultRetries; this var exists so tests can override it.
var ErrAuth = atlhttp.Auth("jira")
ErrAuth is the Jira-named rejected credential. It unwraps to atlhttp.ErrAuth so Watch detects it without a per-source branch. Error() keeps the "jira:" prefix so last_error names the source. Callers keep using errors.Is(err, jira.ErrAuth).
Functions ¶
func Doc ¶
func Doc(text string, mentions map[string]string) json.RawMessage
Doc builds the ADF document a comment body has to be. The composer sends plain text with `@Display Name` typed into it plus the account ids it resolved, so this is where those become real mention nodes — a mention that stays plain text notifies nobody, which is the whole point of typing it.
mentions maps display name to account id.
func DocWithMedia ¶
DocWithMedia is Doc plus inline images, appended after the text — where a screenshot belongs in a comment that describes it.
func FormatTransition ¶ added in v0.17.0
func FormatTransition(t Transition) string
func ISOTime ¶
ISOTime normalizes a Jira timestamp to the ISO-8601 UTC form every stored column uses (data-model.md, "Conventions"), so string comparison sorts chronologically. An unparseable value passes through untouched.
func IsBotAccountType ¶ added in v0.17.0
IsBotAccountType is the one bot judgement (GDK-590): "agent" (standalone actor accounts) and "app" (Cloud Connect accounts) are bots, everything else — "atlassian", "customer", "" — is a human or unknown. Web, CLI and MCP all call this; nothing re-derives it from display names.
func JoinTransitions ¶ added in v0.17.0
func JoinTransitions(list []Transition) string
func PickTransition ¶ added in v0.17.0
func PickTransition(key, want string, list []Transition) (string, error)
PickTransition resolves want against the issue's available transitions. Order: transition id, target status id, transition name / target status name, then category tokens (new|inprogress|done). Two landings in the same category refuse rather than picking the first. A token that is one transition's id and a different transition's to.id is also refused.
func PlainText ¶
func PlainText(raw json.RawMessage) string
PlainText flattens an ADF document to plain text: it is what FTS indexes and what makes a repro-steps custom field searchable. A field that holds a bare string (the older wiki-markup shape) passes through unchanged.
func ReachableCategories ¶ added in v0.17.0
func ReachableCategories(list []Transition) []string
func StatusCategoryToken ¶ added in v0.17.0
StatusCategoryToken accepts only the three values data-model.md documents. Category and jql.mapStatusCategory both fold aliases (todo, indeterminate) onto those values; applying either to the user token would reopen the localization trap this command is closing. Apply's category no-op uses this same function so a token PickTransition would refuse cannot no-op.
Types ¶
type APIError ¶
APIError is a non-2xx answer with its body parsed. Errors is Jira's per-field rejection map, which the server passes to the client as `jira_errors` so the message lands on the input that caused it. Neither the request nor the credential is ever recorded here (constitution article 8).
type Attachment ¶
type Changelog ¶
type Changelog struct {
Total int `json:"total"`
MaxResults int `json:"maxResults"`
Histories []History `json:"histories"`
}
Changelog as returned inline by expand=changelog. Total above len(Histories) means it was truncated and the dedicated endpoint has to be paged.
type ClaimResult ¶ added in v0.17.0
type ClaimResult struct {
Key string `json:"key"`
Assignee User `json:"assignee"`
Status Status `json:"status"`
ClaimedAt string `json:"claimedAt"`
}
ClaimResult is the answer from POST /issue/{key}/claim: who holds the issue now, in which status, since when.
type Client ¶
type Client struct {
HTTP *http.Client
// Retries is the total number of attempts per request; Backoff is the first
// wait, doubling per attempt and capped at 30 s.
Retries int
Backoff time.Duration
// contains filtered or unexported fields
}
Client talks to one Atlassian Cloud site over REST. The credential is held only as an Authorization header value; it is never copied into an error, a log line, or a URL. Retries and Backoff apply to reads; writes use a narrower policy (see write).
func New ¶
New builds a Client for site using Basic auth (email:token). The HTTP client times out at httppolicy.DefaultTimeout; Retries is DefaultRetries; the first Backoff is DefaultBackoff.
origin.Client is the only production construction path for this workspace's Jira client. origin.Connected is the candidate-credential sibling; both live in internal/origin and call New. Tests may call New to stand up httptest servers. internal/origin/direct_new_gate_test.go fails if a new production call site appears outside that package.
func (*Client) AddComment ¶
func (c *Client) AddComment(ctx context.Context, key string, adf json.RawMessage, visibility *CommentVisibility, internal bool) (Comment, error)
AddComment posts an ADF body (not plain text). Mentions must already be mention nodes — a leftover "@Name" string notifies nobody. visibility is sent as Jira's visibility object when non-nil. internal adds the JSM sd.public.comment property. Neither key is present when the corresponding argument is unset, so a flagless CLI comment matches the previous POST body.
func (*Client) Changelog ¶
Changelog pages the full history of one issue, for the issues whose inline expand=changelog came back truncated.
func (*Client) Claim ¶ added in v0.17.0
func (c *Client) Claim(ctx context.Context, key, transitionID string, takeOver bool) (ClaimResult, error)
Claim is POST /issue/{key}/claim — issuetap's claim extension (GDK-591): assignee plus the in-progress transition as one mutation, so of two agents claiming concurrently exactly one wins. An empty transitionID lets the origin pick the first destination whose category is in-progress; takeOver replaces another assignee that already holds the issue in progress. Atlassian Cloud has no claim route and answers 404 — internal/claim falls back to the two calls this route fuses there. The acting account is the credential (or X-Issuetap-Actor on an issuetap origin), never the body.
func (*Client) Comments ¶
Comments pages every comment on one issue, for the issues with more than the inline limit.
func (*Client) Count ¶
Count returns Jira's approximate issue count for a JQL. It exists only to give progress output a denominator, so a failure is not the caller's problem: callers treat any error as "unknown" and keep going.
func (*Client) CreateFields ¶ added in v0.17.0
func (c *Client) CreateFields(ctx context.Context, projectIDOrKey, issueTypeID string) ([]CreateFieldMeta, error)
CreateFields pages GET /issue/createmeta/{project}/issuetypes/{type}. The expand=projects.issuetypes.fields form is the discarded path; this is the current Cloud list (fields[], startAt/maxResults/total).
func (*Client) CreateIssue ¶
CreateIssue returns the new issue's key.
func (*Client) CreateMeta ¶
CreateMeta lists what can be created. Restricted to the configured projects: the site-wide answer is large and most of it is unreachable from this UI.
func (*Client) CreatesVersionsByName ¶ added in v0.17.0
CreatesVersionsByName is true when a fixVersions add {"name": token} mints the version on this origin (issuetap). Cloud Jira is false: unknown names 400, and creating a version is a separate project-admin permission (GDK-678).
func (*Client) DevStatusPRCount ¶ added in v0.17.0
DevStatusPRCount reads the summary's pullrequest count — one cheap call to decide whether the detail call is worth making. issueID is the origin's issue id verbatim (numeric on Cloud), never the key.
func (*Client) DevStatusPRs ¶ added in v0.17.0
DevStatusPRs reads the pull requests the panel holds for one issue. applicationType=GitHub is what Cloud's own frontend sends for the GitHub app (and issuetap accepts any value); the response is parsed defensively — unknown fields are ignored, missing ones stay zero.
func (*Client) EditIssue ¶ added in v0.14.1
EditIssue PUTs /issue/{key} with fields and/or update. Either map may be empty; empty maps are omitted so a labels-only edit is {"update":…} only.
func (*Client) EditMeta ¶
EditMeta returns the fields this user may edit on this issue, keyed by field id.
func (*Client) EnableNameCreatedVersions ¶ added in v0.17.0
func (c *Client) EnableNameCreatedVersions()
EnableNameCreatedVersions marks this client as talking to an origin that mints a project version from {"name": token} on a fixVersions add. origin.transportJira is the production caller (issuetap in-process, routed serve, and paired home).
func (*Client) IssueLinkTypes ¶ added in v0.17.0
func (c *Client) IssueLinkTypes(ctx context.Context) ([]IssueLinkType, error)
IssueLinkTypes is GET /rest/api/3/issueLinkType — the site catalog.
func (*Client) IssueStatus ¶ added in v0.17.0
IssueStatus is GET /issue/{key}?fields=status,assignee — the two facts a claim must judge locally on an origin with no atomic claim route (Cloud): is the issue in progress, and who holds it. Nothing else is fetched. The answer nests under "fields" like every GET /issue/{key} does.
func (*Client) LinkDevBuild ¶ added in v0.17.0
func (c *Client) LinkDevBuild(ctx context.Context, issueID string, state DevBuildState, number, url string) (DevBuild, error)
LinkDevBuild posts one build record (GDK-592). state is the closed three-bucket vocabulary; url and number are optional keys (the origin requires one) and are omitted from the body when empty.
func (*Client) LinkDevDeployment ¶ added in v0.17.0
func (c *Client) LinkDevDeployment(ctx context.Context, issueID, environment, state, url string) (DevDeployment, error)
LinkDevDeployment posts one deployment record (GDK-592). environment and state are required by the origin; url is optional — omitted from the body when empty so the origin keys the row by its environment. The actor is never sent — issuetap stamps it from the request identity.
func (*Client) LinkDevPR ¶ added in v0.17.0
func (c *Client) LinkDevPR(ctx context.Context, issueID, prURL, name, author, branch string, status DevPRStatus) (DevPR, error)
LinkDevPR posts one pull-request link to the origin's dev-status store. Only issuetap (standalone) implements the endpoint — Jira Cloud's panel is written by its marketplace apps, so a connected origin answers 404 and the caller says so instead of pretending. author (the PR author's login) and branch (the head ref) are optional (GDK-589): empty ones are omitted so a re-link without them keeps what the origin already holds, and an older origin ignores both keys. The actor is never sent — issuetap stamps it from the request identity.
func (*Client) LinkIssues ¶ added in v0.17.0
LinkIssues is POST /rest/api/3/issueLink. outwardIssue is the subject of the type's outward description (MKY-1 duplicates HSP-1 when outward is MKY-1). 201/200 with an empty body is success.
func (*Client) MediaRef ¶
func (c *Client) MediaRef(ctx context.Context, attachmentID string) (mediaID, filename string, err error)
MediaRef resolves an attachment id to both the media UUID Jira needs in an ADF node and the filename our own renderer matches on (`alt`), which is what makes an inline image resolve without persisting the UUID anywhere.
There is no documented endpoint for this. Requesting the attachment's content answers 3xx to a pre-signed media URL that carries the UUID, so the redirect is read rather than followed — following it would download the whole file for a string, and the credential must not travel to the media host.
func (*Client) MyFilters ¶ added in v0.13.0
func (c *Client) MyFilters(ctx context.Context) ([]SavedFilter, error)
MyFilters returns filters the user owns, plus visible favourites when includeFavourites is honoured (Cloud's GET /filter/my).
func (*Client) Myself ¶
Myself verifies a credential and identifies its owner. It is the only call `PUT credential/` makes before storing a token.
func (*Client) Priorities ¶
Priorities returns the site's priority names, most urgent first, which is the order priority_rank counts from.
func (*Client) PriorityCatalog ¶
PriorityCatalog is the site's priority list, most urgent first. Names are in the account language; writes should send the id.
func (*Client) ProjectVersions ¶ added in v0.17.0
ProjectVersions is GET /rest/api/3/project/{key}/versions — the project's version catalog. Names can be renamed; writes should send the id.
func (*Client) Projects ¶
func (c *Client) Projects(ctx context.Context, limit int) (list []Project, truncated bool, err error)
Projects lists the projects this credential can browse, newest API first (`/project/search` is the only paged, permission-filtered listing).
It stops after limit projects and reports truncated=true, because a very large site would otherwise turn a first-run picker into hundreds of requests.
func (*Client) Raw ¶
func (c *Client) Raw(ctx context.Context, method, path string, body []byte, mutating bool) (status int, out []byte, err error)
Raw sends a request and returns the HTTP status and response body without JSON decoding. Path must be site-relative (leading "/"); absolute URLs and scheme-relative paths are rejected so the Authorization header never leaves the configured site. mutating selects the write retry policy (429/503 only).
A completed HTTP response always returns err == nil with the status and body (including non-2xx). err is reserved for transport failures and bad paths.
func (*Client) Resolutions ¶ added in v0.17.0
Resolutions is GET /rest/api/3/resolution — the site catalog. Names are in the account language; writes should send the id.
func (*Client) Search ¶
func (c *Client) Search(ctx context.Context, jql string, fields []string, withChangelog bool, fn func([]Issue) error) error
Search pages a JQL query and calls fn once per page, which is what lets sync commit page by page. Pagination is by nextPageToken: the legacy startAt search is deprecated and drifts under concurrent writes.
func (*Client) SearchUsers ¶
SearchUsers backs the assignee picker. Jira's own endpoint decides what matches; there is no local user table to search.
func (*Client) SetAssignee ¶
SetAssignee assigns or, with an empty id, unassigns. Jira distinguishes "no assignee" (null) from "default assignee" (-1); the UI only ever asks for the former.
func (*Client) Statuses ¶
Statuses maps every status id on the site to its category. This is the input the derived-field rules need, because a changelog entry carries ids only.
func (*Client) TakeUsage ¶
TakeUsage returns the current counters and zeroes the numeric fields so a flusher can accumulate into daily totals without double-counting.
LastThrottledAt is a timestamp, not a counter: it is included in the snapshot but is NOT cleared. The in-process "last 429" stays visible until the process exits or a later 429 overwrites it.
func (*Client) Transition ¶
func (c *Client) Transition(ctx context.Context, key, transitionID string, fields map[string]any, comment json.RawMessage) error
Transition performs the transition id on key. fields and comment are omitted from the body when empty — a screen that does not list a field rejects it with 400, so an empty map is not sent. comment is ADF (callers use Doc). Only 429 and 503 are retried, because a 500 may mean Jira already acted.
func (*Client) Transitions ¶
Transitions lists the status changes Jira will currently accept on key. Each entry's To carries StatusCategory so callers can key on the stable category; names are localized per account.
func (*Client) UpdateFields ¶
UpdateFields sets raw field values. The caller is responsible for the shape each field id expects, which EditMeta describes.
func (*Client) Upload ¶
func (c *Client) Upload(ctx context.Context, key, filename string, file io.Reader) ([]Attachment, error)
Upload attaches one file. Jira requires the nosniff header on this endpoint and answers with the created attachments.
ponytail: buffers the whole file in memory. Fine for the screenshots this is for; stream with io.Pipe if someone starts attaching video.
type Comment ¶
type Comment struct {
ID string `json:"id"`
Author User `json:"author"`
Body json.RawMessage `json:"body"`
Created string `json:"created"`
Updated string `json:"updated"`
Visibility *CommentVisibility `json:"visibility"`
JsdPublic *bool `json:"jsdPublic"` // nil = key absent; false ≠ absent
}
type CommentPage ¶
type CommentVisibility ¶ added in v0.17.0
CommentVisibility is Jira's comment restriction. Type is "role" or "group"; Value is the role or group name. Unrestricted comments omit the JSON key (nil here). gadak mirrors the fields; it does not compute who may read the comment.
type CreateFieldMeta ¶ added in v0.17.0
type CreateFieldMeta struct {
FieldID string `json:"fieldId"`
Name string `json:"name"`
Required bool `json:"required"`
HasDefaultValue bool `json:"hasDefaultValue"`
Schema struct {
Type string `json:"type"`
Items string `json:"items"`
Custom string `json:"custom"`
} `json:"schema"`
AllowedValues []struct {
ID string `json:"id"`
Value string `json:"value"`
Name string `json:"name"`
} `json:"allowedValues"`
}
CreateFieldMeta is one field Jira lists at create time. Distinct from FieldMeta: createmeta fields are a list with fieldId on each object and carry hasDefaultValue; editmeta is a map keyed by field id with no fieldId on the value (GDK-254). Schema matches FieldMeta's anonymous shape.
type CreateMetaIssueType ¶ added in v0.17.0
type CreateMetaIssueType struct {
ID string `json:"id"`
Name string `json:"name"`
UntranslatedName string `json:"untranslatedName,omitempty"`
Subtask bool `json:"subtask,omitempty"`
HierarchyLevel int `json:"hierarchyLevel,omitempty"`
}
CreateMetaIssueType is one creatable issue type. Distinct from NamedID: priorities, resolutions, components, and versions share {id,name} but have no hierarchy, and putting subtask/hierarchyLevel/untranslatedName on NamedID would leak meaningless fields onto those catalogs. JSON names match Jira's createmeta object (id, name, untranslatedName, subtask, hierarchyLevel). omitempty keeps a standard type (false, 0, empty untranslatedName) looking the way it did before these fields existed.
func (CreateMetaIssueType) NamedID ¶ added in v0.17.0
func (t CreateMetaIssueType) NamedID() NamedID
NamedID is the id/name pair FormatTypes, NeedTypeError, and Priority matching use. Hierarchy is dropped on purpose: those catalogs share {id,name} and have no rank. create.Type matches CreateMetaIssueType directly so it can see subtask, hierarchyLevel, and untranslatedName.
type CreateMetaProject ¶
type CreateMetaProject struct {
Key string `json:"key"`
Name string `json:"name"`
IssueTypes []CreateMetaIssueType `json:"issuetypes"`
}
CreateMetaProject is one project a person may file into, with its issue types.
func (CreateMetaProject) NamedTypes ¶ added in v0.17.0
func (p CreateMetaProject) NamedTypes() []NamedID
NamedTypes is the id/name catalog FormatTypes and NeedTypeError consume.
type DevBuild ¶ added in v0.17.0
type DevBuild struct {
ID string `json:"id"`
URL string `json:"url"`
Number string `json:"number"`
State string `json:"state"`
Actor DevPRActor `json:"actor"`
}
DevBuild is one build record the link POST answers (GDK-592). Number is the build number as a string; a url-less build's ID is build:<number>.
type DevBuildState ¶ added in v0.17.0
type DevBuildState string
DevBuildState is the build-record state vocabulary (GDK-592): the three buckets the dev-status summary counts. Deployment states are free-form — only "successful" is load-bearing there — so they stay plain strings.
const ( DevBuildSuccessful DevBuildState = "successful" DevBuildFailed DevBuildState = "failed" DevBuildUnknown DevBuildState = "unknown" )
func ParseDevBuildState ¶ added in v0.17.0
func ParseDevBuildState(s string) (DevBuildState, bool)
ParseDevBuildState accepts the CLI/origin tokens (any case); anything outside the three buckets is rejected — an in-progress build is not a state this vocabulary has.
type DevDeployment ¶ added in v0.17.0
type DevDeployment struct {
ID string `json:"id"`
URL string `json:"url"`
Environment string `json:"environment"`
State string `json:"state"`
Actor DevPRActor `json:"actor"`
}
DevDeployment is one deployment record the link POST answers (GDK-592). issuetap's own vocabulary — Cloud's detail rows for deployments were never captured, so no read path produces this type; it exists for the write's 201 echo. A url-less deployment's ID is environment:<name>.
type DevPR ¶ added in v0.17.0
type DevPR struct {
ID string `json:"id"`
URL string `json:"url"`
Name string `json:"name"`
Status DevPRStatus `json:"status"`
// Author is the pull request's author. Actor is who WROTE the link —
// issuetap stamps it from the request identity and serves it back;
// Cloud has no such field and it stays empty. Different axes — a bot
// links a human's PR — never merged (GDK-589). Source is the head ref.
Author DevPRAuthor `json:"author"`
Source DevPRSource `json:"source"`
Actor DevPRActor `json:"actor"`
}
DevPR is one pull request from the dev-status detail payload.
type DevPRActor ¶ added in v0.17.0
type DevPRActor struct {
AccountID string `json:"accountId"`
DisplayName string `json:"displayName"`
}
DevPRActor is issuetap's extension naming who wrote the link: accountId is the X-Issuetap-Actor slug, displayName its human form. Cloud's dev-status has no such block — both fields stay empty there.
type DevPRAuthor ¶ added in v0.17.0
type DevPRAuthor struct {
Name string `json:"name"`
}
DevPRAuthor is the PR author block (Cloud vocabulary: author.name is the GitHub login).
type DevPRSource ¶ added in v0.17.0
type DevPRSource struct {
Branch string `json:"branch"`
}
DevPRSource is where the PR heads from (Cloud vocabulary: source.branch is the head ref).
type DevPRStatus ¶ added in v0.17.0
type DevPRStatus string
DevPRStatus is the origin's development-panel pull-request state (Jira Cloud / issuetap). These three tokens are the whole vocabulary.
const ( DevPROpen DevPRStatus = "OPEN" DevPRMerged DevPRStatus = "MERGED" DevPRDeclined DevPRStatus = "DECLINED" )
func DevPRStatusFromGitHub ¶ added in v0.17.0
func DevPRStatusFromGitHub(ghState string) DevPRStatus
DevPRStatusFromGitHub maps `gh pr list --json state` onto the origin vocabulary. CLOSED is DECLINED; anything else (including OPEN) is OPEN.
func ParseDevPRStatus ¶ added in v0.17.0
func ParseDevPRStatus(s string) (DevPRStatus, bool)
ParseDevPRStatus accepts the origin/CLI tokens (any case). Unknown input is rejected — callers that need a default (gh scan) use DevPRStatusFromGitHub.
func (DevPRStatus) Stored ¶ added in v0.17.0
func (s DevPRStatus) Stored() string
Stored is the mirror-column form (lowercase). store.DevLink.Status stores this so list/detail JSON stays "open"|"merged"|"declined".
type FieldInfo ¶
type FieldInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Custom bool `json:"custom"`
Schema struct {
Type string `json:"type"`
Custom string `json:"custom"`
Items string `json:"items"`
} `json:"schema"`
}
FieldInfo is one row from GET /rest/api/3/field — the site-wide field catalog. Distinct from FieldMeta (editmeta for one issue); do not reuse that type here.
type FieldMeta ¶
type FieldMeta struct {
Required bool `json:"required"`
Operations []string `json:"operations"`
Schema struct {
Type string `json:"type"`
Items string `json:"items"`
Custom string `json:"custom"`
} `json:"schema"`
AllowedValues []struct {
ID string `json:"id"`
Value string `json:"value"`
Name string `json:"name"`
} `json:"allowedValues"`
}
FieldMeta is one editable field as Jira describes it: what it accepts and, for a closed set, every value it accepts.
type Fields ¶
type Fields struct {
Summary string `json:"summary"`
Description json.RawMessage `json:"description"`
Environment json.RawMessage `json:"environment"`
IssueType NamedID `json:"issuetype"`
Status Status `json:"status"`
Priority *NamedID `json:"priority"`
Assignee *User `json:"assignee"`
Reporter *User `json:"reporter"`
Creator *User `json:"creator"`
Project struct {
Key string `json:"key"`
} `json:"project"`
Parent *struct {
Key string `json:"key"`
} `json:"parent"`
Labels []string `json:"labels"`
Components []NamedID `json:"components"`
FixVersions []NamedID `json:"fixVersions"`
Versions []NamedID `json:"versions"` // affects versions
Duedate string `json:"duedate"`
Resolution *NamedID `json:"resolution"`
// Security is the issue security level (id+name). Nil when the
// payload omits the key (unrestricted). NamedID is the existing
// {id,name} shape; do not invent a second struct.
Security *NamedID `json:"security"`
Created string `json:"created"`
Updated string `json:"updated"`
Comment CommentPage `json:"comment"`
Attachment []Attachment `json:"attachment"`
IssueLinks []IssueLink `json:"issuelinks"`
}
type History ¶
type History struct {
ID string `json:"id"`
Created string `json:"created"`
Author User `json:"author"`
Items []HistoryItem `json:"items"`
}
type HistoryItem ¶
type HistoryItem struct {
Field string `json:"field"`
FieldID string `json:"fieldId"`
From string `json:"from"`
FromString string `json:"fromString"`
To string `json:"to"`
ToString string `json:"toString"`
}
HistoryItem's FieldID is the stable identifier ("status", "assignee"); Field is the display name and is localized.
type Issue ¶
type Issue struct {
ID string
Key string
Fields Fields
Extra map[string]json.RawMessage
Raw json.RawMessage
Changelog *Changelog
}
Issue keeps the fields object three ways: typed for the mapping, verbatim per field id so configured custom fields need no code, and whole as Raw.
func (*Issue) UnmarshalJSON ¶
type IssueLinkType ¶ added in v0.17.0
type IssueLinkType struct {
ID string `json:"id"`
Name string `json:"name"`
Inward string `json:"inward"`
Outward string `json:"outward"`
}
IssueLinkType is one row of GET /rest/api/3/issueLinkType. Names and inward/outward descriptions can be renamed and localized; writes send the id.
type Media ¶
Media is one inline image in a comment: the Jira media UUID (not the attachment id — see Client.MediaRef) plus the filename, which is carried as `alt` so our own renderer can match the node to the attachment without persisting the UUID anywhere (web/src/lib/adf.ts, findAttachment).
type Project ¶
type Project struct {
Key string `json:"key"`
Name string `json:"name"`
TypeKey string `json:"projectTypeKey"`
}
Project is one row of the site's project list, as the onboarding picker needs it: the key sync will use, a name to recognise it by, and Jira's own type slug.
type SavedFilter ¶ added in v0.13.0
SavedFilter is a Jira filter the account owns or has starred.
type Status ¶
type Status struct {
ID string `json:"id"`
Name string `json:"name"`
StatusCategory struct {
Key string `json:"key"`
} `json:"statusCategory"`
}
Status carries the category because every piece of logic keys on it: names come back in the account's display language (contracts/sync.md, "Localization hazard").
type Transition ¶
type Transition struct {
ID string `json:"id"`
Name string `json:"name"`
To Status `json:"to"`
Fields map[string]TransitionField `json:"fields"`
}
Transition is one available status change, with the target's category so the UI can colour it without knowing the site's status names. Fields is the screen Jira returned for expand=transitions.fields (often empty).
type TransitionField ¶ added in v0.17.0
type TransitionField struct {
Required bool `json:"required"`
Name string `json:"name"`
Schema struct {
Type string `json:"type"`
} `json:"schema"`
AllowedValues []NamedID `json:"allowedValues"`
}
TransitionField is the subset of a transition screen field the write path uses: required, a display name, the schema type, and closed-set values. Names in AllowedValues are localized per account; writes send the id.
type Usage ¶
Usage is a point-in-time snapshot of this client's outbound Jira traffic. Counters are process-local until a caller persists them (see store.api_usage).
Requests counts every HTTP attempt, including retries: that is the unit that draws from Jira's rate budget. This is our own call volume, not Jira's remaining point pool — the site does not expose that.
type User ¶
type User struct {
AccountID string `json:"accountId"`
DisplayName string `json:"displayName"`
Email string `json:"emailAddress"`
// AccountType is the bot axis (GDK-590): standalone issuetap mints
// "agent" for the accounts behind X-Issuetap-Actor, Cloud sends "app"
// for Connect accounts and "atlassian"/"customer" for humans. Judge it
// only through IsBotAccountType.
AccountType string `json:"accountType"`
// The two below are only ever filled by the user search the assignee picker
// calls; the mirror stores neither.
AvatarURLs map[string]string `json:"avatarUrls"`
Active bool `json:"active"`
}
type Version ¶ added in v0.17.0
type Version struct {
ID string `json:"id"`
Name string `json:"name"`
Released bool `json:"released"`
Archived bool `json:"archived"`
ReleaseDate string `json:"releaseDate"`
}
Version is one row of GET /rest/api/3/project/{key}/versions. Writes send the id: names can be renamed on the site.