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
- func ADFModeFor(cmd *cobra.Command, mutation bool) adfmode.Mode
- func ActiveProfile(cmd *cobra.Command, cfg *config.Config) config.Profile
- func AddCacheStateFields(data map[string]any, sourceState string, count int)
- func AddIssueColumnFlags(flags *pflag.FlagSet, columns *[]string, tsv *bool)
- func AddParallelismFlag(cmd *cobra.Command, target *int)
- func AssigneeSummary(user *jira.User) map[string]any
- func CacheConfigPath(cmd *cobra.Command) string
- func CacheKeyForProfile(cmd *cobra.Command, profile config.Profile) string
- func CacheKeyFromStartup(globals startup.Globals, cfg *config.Config, profileName string) string
- func CacheReadOrFetch(profile, resource string, ttl time.Duration, refresh bool, ...) (json.RawMessage, bool, time.Time, string, error)
- func CacheStateForCount(sourceState string, count int) string
- func CompleteProfileNames(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective)
- func ConfigPath(cmd *cobra.Command) string
- func ConfiguredEditorFor(cmd *cobra.Command) string
- func CopyAnyMap(in map[string]any) map[string]any
- func CredentialStoreFor(backend config.SecretBackend) config.CredentialStore
- func DetectorFromContext(cmd *cobra.Command) cli.Detection
- func DiagnosticWritten(err error) error
- func EnvelopeWritten(err error) error
- func ExistingProfileOrDefault(cfg *config.Config, name string) config.Profile
- func ExtendDryRunFlag(flags *pflag.FlagSet)
- func ExtendFileFlag(flags *pflag.FlagSet, name, group, placeholder string)
- func ExtendFlag(flags *pflag.FlagSet, name string, extra clib.FlagExtra)
- func ExtendForceFlag(flags *pflag.FlagSet)
- func ExtendPaginationFlags(flags *pflag.FlagSet)
- func ExtendRefreshFlags(flags *pflag.FlagSet)
- func ExtendSafetyFlag(flags *pflag.FlagSet, name string)
- func ExtendWatcherUserFlag(flags *pflag.FlagSet)
- func ExtendWatcherValidationFlags(flags *pflag.FlagSet)
- func FirstNonEmpty(values ...string) string
- func FoldRawWarningsIntoData(data any, warnings []map[string]any) any
- func FoldWarningsIntoData(data any, warnings []cli.Warning) any
- func GroupCommand(use, short, group string) *cobra.Command
- func HumanJSONPrintTheme(cmd *cobra.Command) *clogtheme.Theme
- func IsStructuredAgentCommand(cmd *cobra.Command) bool
- func IssueOutput(issues []*jira.Issue, detail bool) any
- func IssueSummary(issue *jira.Issue) map[string]any
- func JiraClientForCommand(cmd *cobra.Command) (*jira.Client, config.Profile, bool, error)
- func JiraClientForProfile(cmd *cobra.Command, profile config.Profile) (*jira.Client, config.Profile, bool, error)
- func KeyedDataWithWarnings(warnings []adf.Warning) func(string, map[string]any) any
- func MarshalNonNilSlice(v any) (json.RawMessage, error)
- func MaxRetryWaitFor(cmd *cobra.Command) time.Duration
- func MirrorADFWarningsToStderr(stderr io.Writer, warnings []cli.Warning) error
- func NewHelpRenderer() *help.Renderer
- func NoInputRequested(cmd *cobra.Command) bool
- func PlainOptionsForCommand(cmd *cobra.Command) []cli.PlainOption
- func PrimeAndCacheBoards(ctx context.Context, cacheKey string, client *jira.Client, ttlMinutes int, ...) (jira.BoardsCacheFile, cache.Entry, []map[string]any, error)
- func PrimeBoards(ctx context.Context, client *jira.Client, ttlMinutes int, unbounded bool) (jira.BoardsCacheFile, []map[string]any, error)
- func ProfileForCommand(cmd *cobra.Command) (config.Profile, error)
- func ProfileForEnvelope(cmd *cobra.Command) string
- func RawWarningsToCLI(warnings []map[string]any) []cli.Warning
- func ReadJSONFile(path string, dst any) error
- func ReadOnlyEnabled(cmd *cobra.Command) bool
- func RecordCredentialWarnings(cmd *cobra.Command, warns []string)
- func RecordRateNearLimit(ctx context.Context, rate jira.Rate)
- func RequestedProfile(cmd *cobra.Command) string
- func SecretRefFor(profile config.Profile, backend config.SecretBackend) (config.SecretRef, error)
- func Spin(cmd *cobra.Command, op string, fn func(context.Context) error) error
- func StandardHelpSections(cmd *cobra.Command) []help.Section
- func StringFromAny(v any) string
- func UpsertProfile(cfg *config.Config, profile config.Profile)
- func UseCompactOutput(cmd *cobra.Command) bool
- func UseHumanJSONOutput(cmd *cobra.Command) bool
- func UsePlainOutput(cmd *cobra.Command) bool
- func WireObjectString(v any, key string) string
- func WithCredentialWarnSink(ctx context.Context) context.Context
- func WithDetector(ctx context.Context, det cli.Detection) context.Context
- func WithRateWarnSink(ctx context.Context) context.Context
- func WriteEnvelope(cmd *cobra.Command, command string, data any) error
- func WriteEnvelopeWithErrors(cmd *cobra.Command, command string, data any, errorsOut []cli.Error) error
- func WriteEnvelopeWithPaginationAndRawWarnings(cmd *cobra.Command, command string, data any, pagination *cli.Pagination, ...) error
- func WriteEnvelopeWithRawWarnings(cmd *cobra.Command, command string, data any, warnings []map[string]any) error
- func WriteEnvelopeWithResponse(cmd *cobra.Command, command string, data any, resp *jira.Response) error
- func WriteEnvelopeWithResponseAndErrors(cmd *cobra.Command, command string, data any, resp *jira.Response, ...) error
- func WriteEnvelopeWithResponseAndWarnings(cmd *cobra.Command, command string, data any, resp *jira.Response, ...) error
- func WriteEnvelopeWithWarnings(cmd *cobra.Command, command string, data any, warnings []adf.Warning) error
- func WriteKeyedResultsEnvelope[T any](cmd *cobra.Command, command string, results []KeyResult[T], ...) error
- func WriteWebEnvelope(cmd *cobra.Command, command, url string, extra map[string]any) error
- type DiagnosticWrittenError
- type EnvelopeWrittenError
- type KeyResult
- type KeyedResult
- type KeyedResultsData
- type ServiceFactory
- func (f *ServiceFactory) Attachment() jira.AttachmentService
- func (f *ServiceFactory) Board() jira.BoardService
- func (f *ServiceFactory) Comment() jira.CommentService
- func (f *ServiceFactory) Epic() jira.EpicService
- func (f *ServiceFactory) Issue() jira.IssueService
- func (f *ServiceFactory) IssueLink() jira.IssueLinkService
- func (f *ServiceFactory) IssueLinkType() jira.IssueLinkTypeService
- func (f *ServiceFactory) JQL() jira.JQLService
- func (f *ServiceFactory) Label() jira.LabelService
- func (f *ServiceFactory) Project(ttl time.Duration) jira.ProjectService
- func (f *ServiceFactory) Search() jira.SearchService
- func (f *ServiceFactory) User() jira.UserService
- func (f *ServiceFactory) Watcher() jira.WatcherService
- func (f *ServiceFactory) Worklog() jira.WorklogService
Constants ¶
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).
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 ¶
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 ¶
ActiveProfile returns the env-overlaid profile selected by the --profile flag from cfg.
func AddCacheStateFields ¶
AddCacheStateFields writes the cache_state / cache_source_state / cache_empty trio onto an envelope's data map.
func AddIssueColumnFlags ¶ added in v0.3.0
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
AddParallelismFlag registers the local -p/--parallelism flag for commands that support bounded multi-key work.
func AssigneeSummary ¶
AssigneeSummary projects a user onto the compact {account_id, display_name} shape used inside an issue summary.
func CacheConfigPath ¶
CacheConfigPath returns the config path used for cache-key identity: the root --config flag value when set, otherwise the default config path.
func CacheKeyForProfile ¶
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 ¶
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 ¶
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 ¶
ConfigPath returns the value of the root --config persistent flag.
func ConfiguredEditorFor ¶
ConfiguredEditorFor resolves the editor command for a command: the active profile's editor when set, otherwise the global config editor.
func CopyAnyMap ¶
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 ¶
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
DiagnosticWritten wraps err so the central error writer does not log the same failure a second time.
func EnvelopeWritten ¶
EnvelopeWritten wraps err so a RunE can tell the central error writer it already emitted a structured error envelope.
func ExistingProfileOrDefault ¶
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 ¶
ExtendDryRunFlag attaches Safety-group metadata to the --dry-run flag.
func ExtendFileFlag ¶
ExtendFileFlag marks a flag as a file-path input with the given group and placeholder label.
func ExtendFlag ¶
ExtendFlag attaches clib display metadata to the named flag in flags.
func ExtendForceFlag ¶
ExtendForceFlag attaches Safety-group metadata to the --force flag.
func ExtendPaginationFlags ¶
ExtendPaginationFlags attaches Pagination-group metadata to the --limit and --all flags.
func ExtendRefreshFlags ¶
ExtendRefreshFlags attaches Cache-group metadata to the --refresh and --ttl-minutes flags, and Pagination-group metadata to --unbounded.
func ExtendSafetyFlag ¶
ExtendSafetyFlag attaches Safety-group metadata to the named flag.
func ExtendWatcherUserFlag ¶
ExtendWatcherUserFlag attaches User-group metadata to the --user flag.
func ExtendWatcherValidationFlags ¶
ExtendWatcherValidationFlags attaches Validation-group metadata to the --no-readback and --validate-remote flags.
func FirstNonEmpty ¶
FirstNonEmpty returns the first non-empty string in values, or "".
func FoldRawWarningsIntoData ¶
FoldRawWarningsIntoData folds a raw map-shaped warning slice into a compact payload. See foldWarnings.
func FoldWarningsIntoData ¶
FoldWarningsIntoData folds a typed cli.Warning slice into a compact payload. See foldWarnings.
func GroupCommand ¶
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
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
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 ¶
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 ¶
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 ¶
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
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
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 ¶
MirrorADFWarningsToStderr is a thin wrapper around cli.RouteWarnings for the plain-mode warning-only path used by both WriteEnvelopeWithWarnings and WriteEnvelopeWithResponseAndWarnings.
func NewHelpRenderer ¶
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 ¶
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 ¶
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 ¶
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 ¶
RawWarningsToCLI converts free-form map-shaped warnings into typed cli.Warning values, dropping empty entries.
func ReadJSONFile ¶
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 ¶
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 ¶
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
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 ¶
RequestedProfile returns the value of the root --profile persistent flag.
func SecretRefFor ¶
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
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 ¶
StandardHelpSections returns the standard clib help sections for cmd, with subcommand listing made optional and the Output group rendered last.
func StringFromAny ¶
StringFromAny returns v when it is a string, or "" otherwise.
func UpsertProfile ¶
UpsertProfile replaces the matching profile in cfg by name, or appends it when no profile with that name exists.
func UseCompactOutput ¶
UseCompactOutput reports whether the command runs in compact mode.
func UseHumanJSONOutput ¶ added in v0.1.1
UseHumanJSONOutput reports whether the command runs in human mode but should still render a JSON document through clog's pretty JSON printer.
func UsePlainOutput ¶
UsePlainOutput reports whether the command runs in a plain (human) or TUI output mode.
func WireObjectString ¶
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 ¶
WithCredentialWarnSink returns a context carrying a fresh credential-warning sink. PersistentPreRunE installs one per command invocation.
func WithDetector ¶
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
WithRateWarnSink returns a context carrying a fresh rate-limit-warning sink. PersistentPreRunE installs one per command invocation.
func WriteEnvelope ¶
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
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
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 (*ServiceFactory) IssueLink ¶ added in v0.3.0
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
func (f *ServiceFactory) Project(ttl time.Duration) jira.ProjectService
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