cmdutil

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 36 Imported by: 0

Documentation

Overview

Package cmdutil holds the cross-cutting helper layer shared by every jira-cli command: envelope writers, client/profile accessors, output-mode resolution, mutation gates, the credential-warning sink, and small generic value helpers. It is a strict leaf package — it depends on the shared internal/cli, internal/config, internal/jira, and internal/adf layers but never on cmd/jira or any internal/cli/<command> package.

Index

Constants

View Source
const (
	CacheStateEmpty     = "empty"
	CacheStateFresh     = "fresh"
	CacheStateMalformed = "malformed"
	CacheStateMissing   = "missing"
	CacheStateRefresh   = "refresh"
	CacheStateStale     = "stale"
)

Cache source-state labels recorded on an envelope's data.cache_source_state field, describing how a cached resource was served (or why it was refetched).

View Source
const DefaultMaxRetryWait = 30 * time.Second

DefaultMaxRetryWait is the out-of-the-box rate-limit retry budget: the longest a single request sleeps out 429 / 503 Retry-After responses before it gives up. The transport always caps the effective wait at the invocation's context deadline (--timeout), so this is an upper bound, never an extension.

Variables

This section is empty.

Functions

func ADFModeFor

func ADFModeFor(cmd *cobra.Command, mutation bool) adfmode.Mode

ADFModeFor resolves the ADF strict/best-effort mode for a single mutation invocation. mutation=true selects the mutation-submit default (strict) when nothing else overrides.

func ActiveProfile

func ActiveProfile(cmd *cobra.Command, cfg *config.Config) config.Profile

ActiveProfile returns the env-overlaid profile selected by the --profile flag from cfg.

func AddCacheStateFields

func AddCacheStateFields(data map[string]any, sourceState string, count int)

AddCacheStateFields writes the cache_state / cache_source_state / cache_empty trio onto an envelope's data map.

func AddIssueColumnFlags added in v0.3.0

func AddIssueColumnFlags(flags *pflag.FlagSet, columns *[]string, tsv *bool)

AddIssueColumnFlags registers the --columns and --tsv human-output flags on flags, binding them to columns and tsv, and groups them under Output.

func AddParallelismFlag added in v0.2.0

func AddParallelismFlag(cmd *cobra.Command, target *int)

AddParallelismFlag registers the local -p/--parallelism flag for commands that support bounded multi-key work.

func AssigneeSummary

func AssigneeSummary(user *jira.User) map[string]any

AssigneeSummary projects a user onto the compact {account_id, display_name} shape used inside an issue summary.

func CacheConfigPath

func CacheConfigPath(cmd *cobra.Command) string

CacheConfigPath returns the config path used for cache-key identity: the root --config flag value when set, otherwise the default config path.

func CacheKeyForProfile

func CacheKeyForProfile(cmd *cobra.Command, profile config.Profile) string

CacheKeyForProfile returns the cache namespace key for an explicit profile, derived from the profile identity (name + base URL) and the active config path. The key names the on-disk cache directory, so its composition must stay stable — see TestCacheKeyFromStartupGolden.

func CacheKeyFromStartup

func CacheKeyFromStartup(globals startup.Globals, cfg *config.Config, profileName string) string

CacheKeyFromStartup returns the cache namespace key for the pre-cobra startup scan, resolving the named profile against cfg when available and falling back to the bare (profile, "", configPath) identity otherwise.

func CacheReadOrFetch

func CacheReadOrFetch(profile, resource string, ttl time.Duration, refresh bool, fetch func() (json.RawMessage, error)) (json.RawMessage, bool, time.Time, string, error)

CacheReadOrFetch is the read-then-fetch helper every cache subcommand uses. Returns the JSON-encoded resource bytes, whether the value was served from disk, and the state observed before any fetch.

func CacheStateForCount

func CacheStateForCount(sourceState string, count int) string

CacheStateForCount collapses the source state to "empty" when the resource carried no records, otherwise returns the observed state.

func CompleteProfileNames

func CompleteProfileNames(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective)

CompleteProfileNames completes the names of all profiles in the config. It is shared by every command that accepts a profile argument (e.g. config and auth). On any config-load error it returns no completions rather than an error, so the shell degrades gracefully.

func ConfigPath

func ConfigPath(cmd *cobra.Command) string

ConfigPath returns the value of the root --config persistent flag.

func ConfiguredEditorFor

func ConfiguredEditorFor(cmd *cobra.Command) string

ConfiguredEditorFor resolves the editor command for a command: the active profile's editor when set, otherwise the global config editor.

func CopyAnyMap

func CopyAnyMap(in map[string]any) map[string]any

CopyAnyMap returns a shallow copy of in.

func CredentialStoreFor

func CredentialStoreFor(backend config.SecretBackend) config.CredentialStore

CredentialStoreFor returns the credential store implementation for a secret backend.

func DetectorFromContext

func DetectorFromContext(cmd *cobra.Command) cli.Detection

DetectorFromContext returns the output-detection result installed on the command context, or the zero Detection when none is present.

func DiagnosticWritten added in v0.2.0

func DiagnosticWritten(err error) error

DiagnosticWritten wraps err so the central error writer does not log the same failure a second time.

func EnvelopeWritten

func EnvelopeWritten(err error) error

EnvelopeWritten wraps err so a RunE can tell the central error writer it already emitted a structured error envelope.

func ExistingProfileOrDefault

func ExistingProfileOrDefault(cfg *config.Config, name string) config.Profile

ExistingProfileOrDefault returns a copy of the named profile from cfg if it exists, or a new Profile with the given name. Used to merge a partial update instead of wholesale replacing the persisted profile.

func ExtendDryRunFlag

func ExtendDryRunFlag(flags *pflag.FlagSet)

ExtendDryRunFlag attaches Safety-group metadata to the --dry-run flag.

func ExtendFileFlag

func ExtendFileFlag(flags *pflag.FlagSet, name, group, placeholder string)

ExtendFileFlag marks a flag as a file-path input with the given group and placeholder label.

func ExtendFlag

func ExtendFlag(flags *pflag.FlagSet, name string, extra clib.FlagExtra)

ExtendFlag attaches clib display metadata to the named flag in flags.

func ExtendForceFlag

func ExtendForceFlag(flags *pflag.FlagSet)

ExtendForceFlag attaches Safety-group metadata to the --force flag.

func ExtendPaginationFlags

func ExtendPaginationFlags(flags *pflag.FlagSet)

ExtendPaginationFlags attaches Pagination-group metadata to the --limit and --all flags.

func ExtendRefreshFlags

func ExtendRefreshFlags(flags *pflag.FlagSet)

ExtendRefreshFlags attaches Cache-group metadata to the --refresh and --ttl-minutes flags, and Pagination-group metadata to --unbounded.

func ExtendSafetyFlag

func ExtendSafetyFlag(flags *pflag.FlagSet, name string)

ExtendSafetyFlag attaches Safety-group metadata to the named flag.

func ExtendWatcherUserFlag

func ExtendWatcherUserFlag(flags *pflag.FlagSet)

ExtendWatcherUserFlag attaches User-group metadata to the --user flag.

func ExtendWatcherValidationFlags

func ExtendWatcherValidationFlags(flags *pflag.FlagSet)

ExtendWatcherValidationFlags attaches Validation-group metadata to the --no-readback and --validate-remote flags.

func FirstNonEmpty

func FirstNonEmpty(values ...string) string

FirstNonEmpty returns the first non-empty string in values, or "".

func FoldRawWarningsIntoData

func FoldRawWarningsIntoData(data any, warnings []map[string]any) any

FoldRawWarningsIntoData folds a raw map-shaped warning slice into a compact payload. See foldWarnings.

func FoldWarningsIntoData

func FoldWarningsIntoData(data any, warnings []cli.Warning) any

FoldWarningsIntoData folds a typed cli.Warning slice into a compact payload. See foldWarnings.

func GroupCommand

func GroupCommand(use, short, group string) *cobra.Command

GroupCommand returns a *cobra.Command suitable for use as a named subcommand group (no Run/RunE — only subcommands are registered on it).

func HumanJSONPrintTheme added in v0.4.0

func HumanJSONPrintTheme(cmd *cobra.Command) *clogtheme.Theme

HumanJSONPrintTheme resolves clog's print theme for human-mode JSON so its syntax highlighting follows the same light/dark decision as hash-based entity colors. It mirrors the resolution in PlainOptionsForCommand exactly — JIRA_THEME wins, the "auto" theme detects the terminal background — so highlighted JSON and entity colors never disagree about the background.

func IsStructuredAgentCommand added in v0.1.1

func IsStructuredAgentCommand(cmd *cobra.Command) bool

IsStructuredAgentCommand reports whether a command is an agent-facing structured metadata endpoint. These commands always print JSON documents; even --output=human uses clog's JSON printer rather than key-value logs.

func IssueOutput

func IssueOutput(issues []*jira.Issue, detail bool) any

IssueOutput renders a list of issues for an envelope's data payload. With detail it returns the full issue records; otherwise it returns the compact per-issue summary maps. Shared by the issue list and search commands so both surface an identical compact shape.

func IssueSummary

func IssueSummary(issue *jira.Issue) map[string]any

IssueSummary projects an issue onto the stable compact field set (key, summary, status, assignee, priority, updated). Null-safe: missing fields keep their zero placeholder so the shape never varies.

func JiraClientForCommand

func JiraClientForCommand(cmd *cobra.Command) (*jira.Client, config.Profile, bool, error)

JiraClientForCommand builds a Jira client for the env-overlaid active profile selected by the --profile flag.

func JiraClientForProfile

func JiraClientForProfile(cmd *cobra.Command, profile config.Profile) (*jira.Client, config.Profile, bool, error)

JiraClientForProfile builds a Jira client targeting an explicit profile rather than the env-overlaid active profile. Read-modify-write commands that persist server data (`auth whoami --save`) use this so the live request and the saved record come from the same file-backed profile: a JIRA_PROFILE_*_BASE_URL overlay cannot redirect the request to another tenant whose identity would then be written into the file profile. Credential env sources (token/password env vars) are still honored.

func KeyedDataWithWarnings added in v0.2.0

func KeyedDataWithWarnings(warnings []adf.Warning) func(string, map[string]any) any

KeyedDataWithWarnings folds command-wide mutation warnings into each successful per-key data payload. Batch mutation envelopes do not have a single persisted resource, so the warning travels with each resource result.

func MarshalNonNilSlice

func MarshalNonNilSlice(v any) (json.RawMessage, error)

MarshalNonNilSlice marshals v but rewrites nil slices to `[]` so cache files never contain `null`. Without this, decoding back into a typed slice produces nil and downstream consumers either crash or paper over the bug with `if x == nil` patches.

func MaxRetryWaitFor added in v0.5.0

func MaxRetryWaitFor(cmd *cobra.Command) time.Duration

MaxRetryWaitFor resolves the rate-limit retry budget for an invocation. Precedence: an explicit --max-retry-wait flag, then the JIRA_MAX_RETRY_WAIT env var, then the built-in default. A negative result is clamped to zero (auto-retry disabled). The transport caps the effective wait at the context deadline, so this value is only ever an upper bound.

func MirrorADFWarningsToStderr

func MirrorADFWarningsToStderr(stderr io.Writer, warnings []cli.Warning) error

MirrorADFWarningsToStderr is a thin wrapper around cli.RouteWarnings for the plain-mode warning-only path used by both WriteEnvelopeWithWarnings and WriteEnvelopeWithResponseAndWarnings.

func NewHelpRenderer

func NewHelpRenderer() *help.Renderer

NewHelpRenderer builds the themed clib help renderer used by every command in jira-cli. The JIRA env-prefix is set so that JIRA_NO_COLOR and related variables are honored. config.DefaultTheme resolves the JIRA_THEME override (or the dark built-in), which clib v0.5 no longer does for us after dropping the old theme.Default().

func NoInputRequested

func NoInputRequested(cmd *cobra.Command) bool

NoInputRequested reports whether interactive prompts are off. It is the single source of truth for headless-mode detection across every subcommand.

An explicit --no-input always wins. When the flag is not set, no-input is implied for a non-interactive session — an agent harness or a piped/ redirected stdin — so a scripted mutation never stalls waiting for a prompt it cannot show. The probe is stdin, not stdout: `jira issue edit KEY | tee` pipes stdout but keeps an interactive stdin, and must still open the editor.

Commands MUST read root persistent flags through this helper rather than re-declaring a same-name local flag: a local flag of the same name shadows the inherited one, so `jira --no-input issue create` would set the root flag while the handler read an unset local copy.

func PlainOptionsForCommand

func PlainOptionsForCommand(cmd *cobra.Command) []cli.PlainOption

PlainOptionsForCommand builds the plain-renderer option set for a command, threading TTY detection, terminal width, execution hints, and (when available) the active profile's base URL.

func PrimeAndCacheBoards added in v0.3.0

func PrimeAndCacheBoards(ctx context.Context, cacheKey string, client *jira.Client, ttlMinutes int, unbounded bool) (jira.BoardsCacheFile, cache.Entry, []map[string]any, error)

PrimeAndCacheBoards primes the boards for the profile and writes them to the per-profile boards cache, returning the normalized file, the written cache entry, and any prime warnings. It is the shared fetch-and-store step behind `cache boards --refresh` and the post-login boards-cache warm.

func PrimeBoards

func PrimeBoards(ctx context.Context, client *jira.Client, ttlMinutes int, unbounded bool) (jira.BoardsCacheFile, []map[string]any, error)

PrimeBoards fetches every board (and its project keys) for the profile and returns the normalized cache file plus any warnings describing data dropped during the prime (bad records, unsafe project keys, partial pagination).

func ProfileForCommand

func ProfileForCommand(cmd *cobra.Command) (config.Profile, error)

ProfileForCommand resolves the active profile for a command WITHOUT constructing a Jira client or touching any credential backend. Local preview and dry-run paths use this so a validation-only run cannot fail on a locked keyring or an offline 1Password backend. Commands that make live HTTP calls must still go through JiraClientForCommand.

func ProfileForEnvelope

func ProfileForEnvelope(cmd *cobra.Command) string

ProfileForEnvelope returns the profile name to record in an envelope: the requested profile when set, otherwise the configured default profile, or "default" when neither is available.

func RawWarningsToCLI

func RawWarningsToCLI(warnings []map[string]any) []cli.Warning

RawWarningsToCLI converts free-form map-shaped warnings into typed cli.Warning values, dropping empty entries.

func ReadJSONFile

func ReadJSONFile(path string, dst any) error

ReadJSONFile decodes exactly one JSON document from path (or stdin when path is "-") into dst. A trailing second value, stray structural byte, or syntax error is reported as a malformed-payload error.

func ReadOnlyEnabled

func ReadOnlyEnabled(cmd *cobra.Command) bool

ReadOnlyEnabled reports whether the active profile (or the JIRA_READ_ONLY env var) blocks mutations. Env wins on the OFF→ON direction so an agent shell can enforce read-only globally without editing config.

func RecordCredentialWarnings

func RecordCredentialWarnings(cmd *cobra.Command, warns []string)

RecordCredentialWarnings appends resolution warnings to the command's sink, if one is installed. Commands without a sink (direct test calls) drop the warnings silently — they are diagnostics, not results.

func RecordRateNearLimit added in v0.5.1

func RecordRateNearLimit(ctx context.Context, rate jira.Rate)

RecordRateNearLimit is the jira.RateObserver the CLI installs on the client. It runs on each successful response — possibly concurrently under -p — and trips the command's sink when Jira flags the response as near the limit. Calls without a sink (direct test clients) drop the signal silently.

func RequestedProfile

func RequestedProfile(cmd *cobra.Command) string

RequestedProfile returns the value of the root --profile persistent flag.

func SecretRefFor

func SecretRefFor(profile config.Profile, backend config.SecretBackend) (config.SecretRef, error)

SecretRefFor derives the credential identity for a profile under a given backend. The credential is keyed by the profile's Jira site host and name; an unsafe profile name is rejected here rather than producing a malformed keyring entry.

func Spin added in v0.4.0

func Spin(cmd *cobra.Command, op string, fn func(context.Context) error) error

Spin runs a blocking network or disk operation while giving the user feedback: a present-progressive spinner on a TTY ("Caching boards") and a structured debug lifecycle that records the elapsed time and any failure reason as fields rather than baking them into prose:

DBG Caching boards
DBG Cached boards time=320ms
DBG Failed to cache boards time=110ms status=403 reason="403 Forbidden"

The spinner mirrors the auth-login gating: NonTTYSilent suppresses it whenever stderr is not a terminal (piped, redirected, or an agent capturing output), and clog writes to stderr, so machine output on stdout stays clean even under --output=json.

Under --debug the spinner is suppressed entirely: the debug lifecycle below already narrates progress, and an animated spinner sharing stderr with the verbose request/response logging only corrupts both — each redraw frame strands onto its own line between the debug records. Verbose narration and the spinner are alternatives, never shown together.

func StandardHelpSections

func StandardHelpSections(cmd *cobra.Command) []help.Section

StandardHelpSections returns the standard clib help sections for cmd, with subcommand listing made optional and the Output group rendered last.

func StringFromAny

func StringFromAny(v any) string

StringFromAny returns v when it is a string, or "" otherwise.

func UpsertProfile

func UpsertProfile(cfg *config.Config, profile config.Profile)

UpsertProfile replaces the matching profile in cfg by name, or appends it when no profile with that name exists.

func UseCompactOutput

func UseCompactOutput(cmd *cobra.Command) bool

UseCompactOutput reports whether the command runs in compact mode.

func UseHumanJSONOutput added in v0.1.1

func UseHumanJSONOutput(cmd *cobra.Command) bool

UseHumanJSONOutput reports whether the command runs in human mode but should still render a JSON document through clog's pretty JSON printer.

func UsePlainOutput

func UsePlainOutput(cmd *cobra.Command) bool

UsePlainOutput reports whether the command runs in a plain (human) or TUI output mode.

func WireObjectString

func WireObjectString(v any, key string) string

WireObjectString reads a string field out of a Jira wire object value (e.g. the "key" of a {"key":"JCT"} project object). It returns "" when the value is not an object or the field is absent / not a string.

func WithCredentialWarnSink

func WithCredentialWarnSink(ctx context.Context) context.Context

WithCredentialWarnSink returns a context carrying a fresh credential-warning sink. PersistentPreRunE installs one per command invocation.

func WithDetector

func WithDetector(ctx context.Context, det cli.Detection) context.Context

WithDetector returns a context carrying the resolved output-detection result. PersistentPreRunE installs one per command invocation; tests use it to seed a command context directly.

func WithRateWarnSink added in v0.5.1

func WithRateWarnSink(ctx context.Context) context.Context

WithRateWarnSink returns a context carrying a fresh rate-limit-warning sink. PersistentPreRunE installs one per command invocation.

func WriteEnvelope

func WriteEnvelope(cmd *cobra.Command, command string, data any) error

WriteEnvelope emits the standard envelope shape for a command with no warnings.

func WriteEnvelopeWithErrors

func WriteEnvelopeWithErrors(cmd *cobra.Command, command string, data any, errorsOut []cli.Error) error

WriteEnvelopeWithErrors emits an ok:false envelope while preserving a command's data payload. Use this when the command successfully gathered diagnostics but the diagnostics themselves mean the command is unhealthy (for example auth.status with an invalid profile).

func WriteEnvelopeWithPaginationAndRawWarnings added in v0.3.3

func WriteEnvelopeWithPaginationAndRawWarnings(cmd *cobra.Command, command string, data any, pagination *cli.Pagination, warnings []map[string]any) error

WriteEnvelopeWithPaginationAndRawWarnings is WriteEnvelopeWithRawWarnings plus a pagination block in the JSON meta. The bounded --all drain uses it: the drain knows its terminal state (isLast = not truncated, total = the drained count), but has no *jira.Response to derive it from, so the caller builds the pagination directly. Pagination rides only in the JSON envelope, matching the single-page WriteEnvelopeWithResponse path.

func WriteEnvelopeWithRawWarnings

func WriteEnvelopeWithRawWarnings(cmd *cobra.Command, command string, data any, warnings []map[string]any) error

WriteEnvelopeWithRawWarnings emits the standard envelope shape with a caller-supplied list of free-form warning maps. Necessary for warnings whose schema (cache-truncated, rate-limit-during-paginate) carries fields outside the cli.Warning struct's Type/Message/Field/Path/etc. surface — see contracts/envelope-shapes.md.

func WriteEnvelopeWithResponse

func WriteEnvelopeWithResponse(cmd *cobra.Command, command string, data any, resp *jira.Response) error

WriteEnvelopeWithResponse emits the standard envelope shape with pagination derived from an HTTP response and no pipeline warnings.

func WriteEnvelopeWithResponseAndErrors added in v0.2.0

func WriteEnvelopeWithResponseAndErrors(cmd *cobra.Command, command string, data any, resp *jira.Response, errorsOut []cli.Error) error

WriteEnvelopeWithResponseAndErrors emits an ok:false envelope with both a preserved data payload and pagination metadata from resp.

func WriteEnvelopeWithResponseAndWarnings

func WriteEnvelopeWithResponseAndWarnings(cmd *cobra.Command, command string, data any, resp *jira.Response, warnings []adf.Warning) error

WriteEnvelopeWithResponseAndWarnings is the warning-emitting envelope entry point for commands that BOTH have a paginated/HTTP response AND need to surface pipeline warnings (e.g., live-submit issue create / edit / comment / worklog where the pipeline has already validated and produced best-effort warnings before the API call). Mirrors WriteEnvelopeWithWarnings's TTY routing for plain mode so the data stays on stdout and warnings mirror to stderr as clog WRN lines.

func WriteEnvelopeWithWarnings

func WriteEnvelopeWithWarnings(cmd *cobra.Command, command string, data any, warnings []adf.Warning) error

WriteEnvelopeWithWarnings is the warning-emitting envelope entry point — every command emitting structured warnings (typically from pipeline.RunMutation) calls this so warnings travel in the envelope under JSON mode and mirror to stderr under TTY/--plain (via the route helper).

func WriteKeyedResultsEnvelope added in v0.2.0

func WriteKeyedResultsEnvelope[T any](
	cmd *cobra.Command,
	command string,
	results []KeyResult[T],
	dataFor func(string, T) any,
) error

WriteKeyedResultsEnvelope writes the shared multi-key result shape. It preserves requested-key order in data.results and returns a non-zero command error when any key failed while retaining successful keys in the envelope.

func WriteWebEnvelope added in v0.3.0

func WriteWebEnvelope(cmd *cobra.Command, command, url string, extra map[string]any) error

WriteWebEnvelope opens url in the OS default browser when the session is interactive, then writes an envelope carrying the url and whether it was opened. The url is always reported, so an agent or piped invocation gets the link without a browser spawning, and a launch failure is surfaced as a warning rather than an error — the url is still usable by hand.

extra may be nil; it is not mutated. The "url" and "opened" keys are added to a fresh copy.

Types

type DiagnosticWrittenError added in v0.2.0

type DiagnosticWrittenError struct{ Inner error }

DiagnosticWrittenError wraps an error a RunE returns after it has already emitted the terminal-facing diagnostic for that failure. The inner error remains available for exit-code classification.

func (DiagnosticWrittenError) Error added in v0.2.0

func (e DiagnosticWrittenError) Error() string

func (DiagnosticWrittenError) Unwrap added in v0.2.0

func (e DiagnosticWrittenError) Unwrap() error

type EnvelopeWrittenError

type EnvelopeWrittenError struct{ Inner error }

EnvelopeWrittenError wraps an error a RunE returns to signal that it already emitted a structured error envelope, so the central error writer must not double-write. The inner error is still unwrapped for exit-code classification.

func (EnvelopeWrittenError) Error

func (e EnvelopeWrittenError) Error() string

func (EnvelopeWrittenError) Unwrap

func (e EnvelopeWrittenError) Unwrap() error

type KeyResult added in v0.2.0

type KeyResult[T any] struct {
	Key   string
	Value T
	Err   error
}

KeyResult carries one per-key read result while preserving the original key.

func FanOutKeys added in v0.2.0

func FanOutKeys[T any](
	ctx context.Context,
	keys []string,
	parallelism int,
	fn func(context.Context, string) (T, error),
) ([]KeyResult[T], error)

FanOutKeys runs fn for each key with bounded concurrency and returns results in the same order as keys. Per-key errors are stored in the result slot so one failed key does not cancel unrelated work.

func FanOutKeysProgress added in v0.4.0

func FanOutKeysProgress[T any](
	ctx context.Context,
	op string,
	keys []string,
	parallelism int,
	fn func(context.Context, string) (T, error),
) ([]KeyResult[T], error)

FanOutKeysProgress runs FanOutKeys with user feedback for the operation named by op (a cli.VerbFor key like "issue.delete"): a determinate progress bar while keys complete, plus a per-key debug lifecycle that records each key's elapsed time and, on failure, the HTTP status and reason as fields:

DBG Deleting issue key=ABC-1
DBG Deleted issue key=ABC-1 time=210ms
DBG Failed to delete issue key=ABC-2 time=95ms status=404 reason="..."

The bar mirrors the auth-login spinner's gating: NonTTYSilent suppresses it whenever stderr is not a terminal — piped, redirected, or captured by an agent — and clog writes status to stderr, so a stdout JSON envelope stays clean even under --output=json. The debug lines surface only under --debug. A single key gets the debug lifecycle but no bar.

type KeyedResult added in v0.2.0

type KeyedResult struct {
	Key   string     `json:"key"`
	OK    bool       `json:"ok"`
	Data  any        `json:"data,omitempty"`
	Error *cli.Error `json:"error,omitempty"`
}

KeyedResult carries one issue-key result. Data is command-specific and Error is the normalized per-key failure.

type KeyedResultsData added in v0.2.0

type KeyedResultsData struct {
	Results   []KeyedResult `json:"results"`
	Succeeded int           `json:"succeeded"`
	Failed    int           `json:"failed"`
}

KeyedResultsData is the common envelope payload for commands that operate on a set of issue keys independently.

type ServiceFactory added in v0.3.0

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

ServiceFactory builds the typed Jira services a command needs from a single client. Centralizing construction here keeps every command's service wiring identical: a command resolves one client through JiraClientForCommand, then reaches every domain service through the factory rather than calling jira.NewXService itself.

It is a concrete type, not an interface. There is one implementation, so an interface here would be indirection without a second implementer; a command that wants a test seam declares a narrow interface of just the accessors it uses (for example interface{ Issue() jira.IssueService }) and this concrete factory satisfies it structurally.

Accessors are stateless: each builds a fresh service from the bound client. The services are thin wrappers over one *jira.Client, so construction is free and there is no shared state to cache or guard.

func ServicesForClient

func ServicesForClient(client *jira.Client) *ServiceFactory

ServicesForClient returns the factory bound to client.

func (*ServiceFactory) Attachment added in v0.3.0

func (f *ServiceFactory) Attachment() jira.AttachmentService

func (*ServiceFactory) Board added in v0.3.0

func (f *ServiceFactory) Board() jira.BoardService

func (*ServiceFactory) Comment added in v0.3.0

func (f *ServiceFactory) Comment() jira.CommentService

func (*ServiceFactory) Epic added in v0.3.0

func (f *ServiceFactory) Epic() jira.EpicService

func (*ServiceFactory) Issue added in v0.3.0

func (f *ServiceFactory) Issue() jira.IssueService
func (f *ServiceFactory) IssueLink() jira.IssueLinkService

func (*ServiceFactory) IssueLinkType added in v0.3.0

func (f *ServiceFactory) IssueLinkType() jira.IssueLinkTypeService

func (*ServiceFactory) JQL added in v0.3.3

func (f *ServiceFactory) JQL() jira.JQLService

func (*ServiceFactory) Label added in v0.3.0

func (f *ServiceFactory) Label() jira.LabelService

func (*ServiceFactory) Project added in v0.3.0

Project carries a schema cache scoped by ttl, so it takes the lifetime the caller wants for that cache.

func (*ServiceFactory) Search added in v0.3.0

func (f *ServiceFactory) Search() jira.SearchService

func (*ServiceFactory) User added in v0.3.0

func (f *ServiceFactory) User() jira.UserService

func (*ServiceFactory) Watcher added in v0.3.0

func (f *ServiceFactory) Watcher() jira.WatcherService

func (*ServiceFactory) Worklog added in v0.3.0

func (f *ServiceFactory) Worklog() jira.WorklogService

Jump to

Keyboard shortcuts

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