parse

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: 4 Imported by: 0

Documentation

Overview

Package parse converts raw Jira Cloud REST API v3 issue JSON into a typed Issue value. It is a pure package: no network calls, no filesystem access, and no project-internal imports. The caller supplies raw bytes (typically from internal/fetch) and a Jira site base URL; Parse returns a fully populated Issue or an error.

Signature choice: Parse(raw []byte, site string) (Issue, error)

The site parameter (e.g. "https://example.atlassian.net") is used to construct SourceURL as "<site>/browse/<KEY>". This keeps the Issue self-contained for downstream renderers without requiring them to know the site URL separately. If site is empty, SourceURL is left empty.

Null description: a null or absent JSON description field is stored as a nil json.RawMessage (len == 0). Downstream consumers (internal/adf) must treat a nil/empty RawMessage as an empty document.

Custom field detection: every key in the "fields" object whose name begins with "customfield_" and that does not have a dedicated typed slot in Issue is preserved verbatim in CustomFields as a json.RawMessage. No custom field is ever silently dropped (AC13).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Branch

type Branch struct {
	Name             string
	URL              string
	Repository       string // "org/repo"
	RepositoryURL    string
	LastCommitID     string // seven-character abbreviation (displayId)
	LastCommitURL    string
	LastCommitMsg    string // first line only
	LastCommitAuthor string
	LastUpdated      time.Time
}

Branch is the gojira-side representation of a development branch associated with a Jira issue, discovered via Jira's Dev Status API with dataType=branch. Fields not provided by the upstream response are zero-valued.

LastCommit* fields capture the head commit of the branch as the upstream API reports it, so the renderer can surface a one-line summary without a separate commit lookup. LastCommitMsg is the first line of the upstream commit message (everything before the first newline); preserving multi-line commit bodies would bloat the Markdown listing.

type Build

type Build struct {
	ID          string
	Name        string
	URL         string
	State       string
	Description string
	Repository  string // "org/repo"; may be empty
	LastUpdated time.Time
	TestsPassed int
	TestsFailed int
	TestsTotal  int
}

Build is the gojira-side representation of a single CI build associated with a Jira issue, discovered via Jira's Dev Status API with dataType=build. State is the upstream lifecycle string ("SUCCESSFUL", "FAILED", "IN_PROGRESS", "STOPPED", "PENDING", ...); gojira does not normalise it.

Tests* are extracted from the upstream testSummary block when present; all three fields are zero when the build did not publish a test summary, and the renderer elides the [tests P/T] suffix in that case.

type Commit

type Commit struct {
	ID         string
	ShortID    string
	URL        string
	Message    string // first line only
	Author     string
	Repository string // "org/repo"
	AuthoredAt time.Time
}

Commit is the gojira-side representation of a single development commit associated with a Jira issue, discovered via Jira's Dev Status API with dataType=commit. Fields not provided by the upstream response are zero-valued.

ID is the full SHA; ShortID is the upstream displayId (typically seven characters) preserved verbatim rather than re-abbreviated locally. Message is the first line of the upstream commit message.

type DevStatusData

type DevStatusData struct {
	PullRequests []PullRequest
	Branches     []Branch
	Commits      []Commit
	Repositories []Repository
	Builds       []Build
}

DevStatusData groups the five entity lists surfaced by Jira's Dev Status API: pull requests, branches, commits, repositories, and builds. Each list is independent and may be empty. The renderer elides the corresponding subsection when its list is empty.

The type lives in parse so Issue can carry a single typed bundle and so internal/render can consume it without importing the devstatus package (which would create a cycle: devstatus imports parse for Issue). The crawl orchestrator owns the conversion from upstream client.DevStatus* shapes into these types via internal/devstatus.

type Issue

type Issue struct {
	// Key is the Jira issue key, e.g. "EXAMPLE-1".
	Key string

	// NumericID is the opaque integer ID Jira assigns to each issue,
	// distinct from the human-readable Key. It is the top-level "id"
	// field of the standard GET /issue/<KEY> response (a string of
	// digits, e.g. "86679"). gojira preserves it because the
	// undocumented Dev Status endpoint
	// (/rest/dev-status/1.0/issue/detail?issueId=<NUMERIC>) only
	// accepts the numeric form. Empty when the response omitted the
	// id field.
	NumericID string

	// Summary is the one-line issue title.
	Summary string

	// Status is the display name of the issue status, e.g. "In Progress".
	Status string

	// IssueType is the display name of the issue type, e.g. "Story".
	IssueType string

	// Assignee is the display name of the assignee, or empty if unassigned.
	Assignee string

	// Reporter is the display name of the reporter.
	Reporter string

	// Created is the issue creation timestamp.
	Created time.Time

	// Updated is the timestamp of the most recent issue update.
	Updated time.Time

	// SourceURL is the canonical Jira browse URL for this issue,
	// e.g. "https://example.atlassian.net/browse/EXAMPLE-1".
	// Empty when Parse is called with an empty site string.
	SourceURL string

	// Description holds the raw ADF JSON document from the issue's description
	// field. It is nil/empty when the description is null or absent. The adf
	// package is responsible for traversing this opaque value.
	Description json.RawMessage

	// Parent is the direct parent issue, or nil if the issue has no parent.
	Parent *ParentRef

	// Subtasks lists the direct child subtasks of this issue (i.e. legacy
	// Jira "Sub-task" type children carried inline on the parent issue's
	// fields.subtasks array).
	Subtasks []LinkedIssue

	// Children is the list of modern Jira hierarchy child keys discovered
	// for this issue via JQL search (parent = "KEY" and, where the Epic
	// Link custom field is configured/detected, "Epic Link" = "KEY").
	//
	// Parse() ALWAYS returns this as nil; it is populated externally by
	// internal/crawl after parsing (when children discovery is enabled)
	// so that the rendered output's Children section sits naturally
	// alongside Parent, Sub-tasks, and IssueLinks in the Relationships
	// group. Adding parsing logic for this field would be a layering
	// regression: hierarchy children are not encoded in the per-issue
	// GET response.
	Children []string

	// IssueLinks lists the explicit Jira issue links (blocks, relates to, etc.).
	IssueLinks []IssueLink

	// RemoteLinks lists the remote (external) links attached to this issue.
	RemoteLinks []RemoteLink

	// CustomFields preserves every "customfield_*" key from the Jira fields
	// object that does not have a dedicated typed slot above. Values are stored
	// as raw JSON so no information is lost regardless of the field type.
	// This map is never nil after a successful Parse call; it may be empty.
	CustomFields map[string]json.RawMessage

	// Names maps Jira field IDs (e.g. "customfield_10115") to their
	// human-readable labels (e.g. "Sprint"). Populated from the
	// top-level "names" object on the Jira issue response when the
	// caller requested expand=names; nil when absent.
	//
	// The map's keys are NOT guaranteed to be limited to custom
	// fields: standard field IDs ("summary", "status", "assignee",
	// ...) also appear in the names object. internal/render
	// consults this map only when it needs a label for a custom
	// field, and falls back to the raw customfield_NNNNN id when
	// the lookup misses. Entries with non-string values in the
	// response are skipped silently so a single malformed entry
	// cannot make the whole Names map disappear.
	Names map[string]string

	// DevStatus is the per-dataType bundle of development metadata
	// associated with this issue, discovered via Jira's Dev Status
	// endpoint by the crawl orchestrator. Parse() ALWAYS returns the
	// zero value; the inner slices are populated externally by
	// internal/crawl after parsing (when Dev Status enrichment is
	// enabled) so that the rendered "## Development" section sits
	// naturally between Description and Relationships. Adding parsing
	// logic here would be a layering regression: the per-issue GET
	// response only carries an opaque summary blob (customfield_10000)
	// with overall counts, not the actual entity lists.
	//
	// The five lists mirror the five dataType values the Jira UI
	// Development panel surfaces: pull requests, branches, commits,
	// repositories, and builds.
	DevStatus DevStatusData
}

Issue is the central typed representation of a Jira Cloud issue produced by Parse. It is consumed by internal/extract (link discovery), internal/render (Markdown generation), and internal/crawl (orchestration).

func Parse

func Parse(raw []byte, site string) (Issue, error)

Parse converts raw Jira Cloud REST API v3 issue JSON into a typed Issue.

site is the Jira Cloud base URL (e.g. "https://example.atlassian.net") used to construct SourceURL. Pass an empty string to leave SourceURL empty.

All "customfield_*" keys in the fields object that do not have a dedicated typed slot are preserved verbatim in Issue.CustomFields (never dropped).

type IssueLink struct {
	// Direction is "inward" or "outward", indicating which side of the link
	// relationship this issue occupies.
	Direction string

	// Type is the link type name as returned by Jira, e.g. "Blocks" or "Relates".
	Type string

	// Key is the issue key of the linked issue.
	Key string

	// Summary is the summary of the linked issue.
	Summary string
}

IssueLink represents a directed Jira issue link (e.g. "blocks", "relates to").

type LinkedIssue

type LinkedIssue struct {
	Key     string
	Summary string
}

LinkedIssue holds the key and summary of a subtask or similar lightweight issue reference.

type ParentRef

type ParentRef struct {
	Key     string
	Summary string
}

ParentRef holds the key and summary of a parent issue.

type PullRequest

type PullRequest struct {
	// ID is the upstream pull-request identifier as reported by Jira,
	// e.g. "#557" for GitHub or "1" for Bitbucket. The format varies
	// by provider; gojira preserves it verbatim.
	ID string

	// URL is the canonical web URL of the pull request, e.g.
	// "https://github.com/org/repo/pull/557". Used as the
	// deduplication key when merging results from multiple Dev Status
	// application queries.
	URL string

	// Title is the human-readable pull-request title (Jira's "name"
	// field on the upstream entry).
	Title string

	// Status is the upstream lifecycle state as reported by Jira:
	// "MERGED", "OPEN", "DECLINED", "DRAFT", or any other value the
	// provider returns. gojira does not normalise this.
	Status string

	// Application identifies the development-tool integration that
	// owns this pull request: "GitHub", "Bitbucket", "GitLab",
	// "GitHubEnterprise", etc. Populated by the devstatus enricher
	// from the configured applicationType used to query the entry.
	Application string

	// Repository is the upstream "repositoryName", e.g.
	// "org/repo". Empty when the provider does not surface a
	// repository name.
	Repository string

	// SourceBranch and DestBranch hold the source ("from") and
	// destination ("into") branch names. Either may be empty when
	// the upstream entry omits them.
	SourceBranch string
	DestBranch   string

	// Author is the pull-request author's display name (Jira's
	// "author.name"). Empty when omitted.
	Author string

	// LastUpdate is the parsed timestamp of the upstream "lastUpdate"
	// field. Zero when omitted or unparseable; preserving partial
	// data is preferable to dropping the entire entry.
	LastUpdate time.Time

	// Reviewers lists each reviewer's display name and approval
	// state. nil when the upstream entry omits reviewers entirely.
	Reviewers []Reviewer
}

PullRequest is the gojira-side representation of a pull request associated with a Jira issue, discovered via the Jira Dev Status API. Fields not provided by the upstream response are zero-valued.

The type lives in parse so that internal/render can consume it without importing internal/devstatus (which would create a cycle: devstatus imports parse for Issue). The crawl orchestrator owns the conversion from the upstream client.DevStatusPR shape into this type via internal/devstatus.

type RemoteLink struct {
	Title string
	URL   string
}

RemoteLink represents a remote (external) link attached to a Jira issue.

type Repository

type Repository struct {
	Name string // "org/repo"
	URL  string
}

Repository is the gojira-side representation of a single repository associated with a Jira issue, discovered via Jira's Dev Status API with dataType=repository. The Jira UI surfaces these so users can see which repositories reference an issue even when no PR or branch carries the issue key directly.

type Reviewer

type Reviewer struct {
	Name     string
	Approved bool
}

Reviewer holds a single pull-request reviewer entry.

Jump to

Keyboard shortcuts

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