Skip to main content

AtlassianClient

Struct AtlassianClient 

Source
pub struct AtlassianClient { /* private fields */ }
Expand description

Shared HTTP client with Basic and Bearer authentication.

Backs every JIRA, Confluence, and Agile helper exposed by this crate. Construct directly via AtlassianClient::new (instance URL + email + API token) or, more commonly, via AtlassianClient::from_credentials which accepts an AtlassianCredentials resolved from the ATLASSIAN_INSTANCE_URL, ATLASSIAN_EMAIL, and ATLASSIAN_API_TOKEN (or ATLASSIAN_PAT) environment variables (falling back to ~/.omni-dev/settings.json) by load_credentials.

Authenticates every request with the selected Basic or Bearer header. The precomputed, sensitive Authorization header is attached to all outbound calls. Requests time out after 30s and automatically retry up to three times on HTTP 429, honoring any Retry-After header.

Implementations§

Source§

impl AtlassianClient

Source

pub fn new(instance_url: &str, email: &str, api_token: &str) -> Result<Self>

Creates a new Atlassian API client.

Constructs the Basic Auth header from the email and API token.

Source

pub fn with_auth(instance_url: &str, auth: &AtlassianAuth) -> Result<Self>

Creates a client using Basic or Bearer credentials.

Source

pub fn from_credentials(creds: &AtlassianCredentials) -> Result<Self>

Creates a client from stored credentials.

Source

pub fn instance_url(&self) -> &str

Returns the instance URL.

Source

pub async fn get_json(&self, url: &str) -> Result<Response>

Sends an authenticated GET request and returns the raw response.

Shared transport method used by both JIRA and Confluence API implementations.

Source

pub async fn put_json<T: Serialize + Sync + ?Sized>( &self, url: &str, body: &T, ) -> Result<Response>

Sends an authenticated PUT request with a JSON body and returns the raw response.

Shared transport method used by both JIRA and Confluence API implementations.

Source

pub async fn post_json<T: Serialize + Sync + ?Sized>( &self, url: &str, body: &T, ) -> Result<Response>

Sends an authenticated POST request with a JSON body and returns the raw response.

Source

pub async fn get_bytes(&self, url: &str) -> Result<Vec<u8>>

Sends an authenticated GET request and returns raw bytes.

Source

pub async fn delete(&self, url: &str) -> Result<Response>

Sends an authenticated DELETE request and returns the raw response.

Source

pub async fn post_multipart( &self, url: &str, form: Form, extra_headers: &[(&str, &str)], ) -> Result<Response>

Sends an authenticated POST request with a multipart body and returns the raw response.

Does not retry on 429: a streamed multipart body cannot be replayed. Callers that need retry must rebuild the form and call again.

Source

pub async fn get_issue(&self, key: &str) -> Result<JiraIssue>

Fetches a JIRA issue by key with only the standard fields.

Thin shim over Self::get_issue_with_fields with FieldSelection::Standard. Preserved for callers that do not need custom field data.

Source

pub async fn get_issue_with_fields( &self, key: &str, selection: FieldSelection, ) -> Result<JiraIssue>

Fetches a JIRA issue by key with the given field selection.

Always requests expand=names,schema so human-readable field names and type metadata are available for rendering custom fields. When selection is FieldSelection::Standard, custom_fields on the returned issue will be empty.

Source

pub async fn update_issue( &self, key: &str, description_adf: &ValidatedAdfDocument, summary: Option<&str>, ) -> Result<()>

Updates a JIRA issue’s description and optionally its summary.

Thin shim over Self::update_issue_with_custom_fields that sends no custom field changes.

Source

pub async fn update_issue_with_custom_fields( &self, key: &str, description_adf: Option<&ValidatedAdfDocument>, summary: Option<&str>, custom_fields: &BTreeMap<String, Value>, ) -> Result<()>

Updates a JIRA issue with any subset of supported fields.

description_adf and summary are each Option: None leaves the field untouched, Some overwrites it. custom_fields is merged verbatim into the fields payload, keyed by stable JIRA field id — both standard fields (assignee, reporter, priority, labels) and custom fields (customfield_10088). The system parent field is set via Self::set_issue_parent, not here. Returns an error when nothing would be sent (avoids a no-op PUT that JIRA still validates).

Source

pub async fn get_editmeta(&self, key: &str) -> Result<EditMeta>

Fetches editable field metadata scoped to an issue’s edit screen.

GET /rest/api/3/issue/{key}/editmeta returns only fields on the issue’s screen, so field names are unambiguous even when multiple custom fields share a display name globally.

Source

pub async fn create_issue( &self, project_key: &str, issue_type: &str, summary: &str, description_adf: Option<&ValidatedAdfDocument>, labels: &[String], ) -> Result<JiraCreatedIssue>

Creates a new JIRA issue.

Thin shim over Self::create_issue_with_custom_fields that sends no custom field values.

Source

pub async fn create_issue_with_custom_fields( &self, project_key: &str, issue_type: &str, summary: &str, description_adf: Option<&ValidatedAdfDocument>, labels: &[String], custom_fields: &BTreeMap<String, Value>, ) -> Result<JiraCreatedIssue>

Creates a new JIRA issue with standard fields and any custom fields keyed by stable ID (e.g., customfield_10088).

Source

pub async fn get_createmeta( &self, project_key: &str, issue_type: &str, ) -> Result<EditMeta>

Fetches field metadata for creating a JIRA issue of a given project and issue type.

GET /rest/api/3/issue/createmeta?projectKeys={p}&issuetypeNames={t}&expand=projects.issuetypes.fields returns fields on the create screen, which is the write-time source of truth for custom-field resolution prior to issue creation.

Source

pub async fn get_project_create_meta( &self, project_key: &str, issue_type: &str, ) -> Result<CreateMeta>

Introspects the create screen for a project + issue type, returning each field with its required flag, schema type, allowed values, and default.

GET /rest/api/3/issue/createmeta?projectKeys={p}&issuetypeNames={t}&expand=projects.issuetypes.fields — the same endpoint as get_createmeta, parsed for the full field metadata an agent needs to prompt before creating.

Source

pub async fn get_comments( &self, key: &str, limit: u32, ) -> Result<Vec<JiraComment>>

Lists comments on a JIRA issue with auto-pagination.

limit caps the total number of comments returned. Pass 0 for unlimited.

Source

pub async fn add_comment( &self, key: &str, body_adf: &ValidatedAdfDocument, ) -> Result<()>

Adds a comment to a JIRA issue.

Source

pub async fn update_comment( &self, key: &str, comment_id: &str, body_adf: &ValidatedAdfDocument, visibility: Option<&JiraVisibility>, ) -> Result<JiraComment>

Updates an existing comment on a JIRA issue.

Issues a PUT /rest/api/3/issue/{key}/comment/{id} with the new ADF body and an optional visibility restriction. Returns the updated comment as parsed from the JIRA response so callers can surface the updated timestamp and any author/body changes JIRA applied.

Source

pub async fn delete_comment(&self, key: &str, comment_id: &str) -> Result<()>

Deletes a comment from a JIRA issue.

Issues a DELETE /rest/api/3/issue/{key}/comment/{id} (204 on success).

Source

pub async fn get_worklogs( &self, key: &str, limit: u32, ) -> Result<JiraWorklogList>

Lists worklogs for a JIRA issue.

Source

pub async fn add_worklog( &self, key: &str, time_spent: &str, started: Option<&str>, comment: Option<&str>, ) -> Result<()>

Adds a worklog entry to a JIRA issue.

Source

pub async fn update_worklog( &self, key: &str, worklog_id: &str, time_spent: Option<&str>, started: Option<&str>, comment: Option<&str>, ) -> Result<()>

Updates an existing worklog entry on a JIRA issue.

Issues a PUT /rest/api/3/issue/{key}/worklog/{id} with only the fields that are Some; omitted fields keep their current value. The comment is sent as an ADF document, mirroring Self::add_worklog.

Source

pub async fn delete_worklog(&self, key: &str, worklog_id: &str) -> Result<()>

Deletes a worklog entry from a JIRA issue.

Issues a DELETE /rest/api/3/issue/{key}/worklog/{id} (204 on success).

Source

pub async fn get_transitions(&self, key: &str) -> Result<Vec<JiraTransition>>

Lists available transitions for a JIRA issue.

Source

pub async fn get_transitions_with_fields( &self, key: &str, ) -> Result<(Vec<JiraTransition>, BTreeMap<String, EditMeta>)>

Lists available transitions for a JIRA issue together with each transition’s screen-field metadata.

Requests expand=transitions.fields so screen fields can be resolved for execute --set-field/--resolution and so a mandatory-comment screen can be detected. Returns the same JiraTransition list as Self::get_transitions plus a map keyed by transition id holding the screen EditMeta; screenless transitions have no entry.

Source

pub async fn do_transition(&self, key: &str, transition_id: &str) -> Result<()>

Executes a transition on a JIRA issue.

Thin shim over Self::do_transition_with_fields that sends no screen fields and no transition comment.

Source

pub async fn do_transition_with_fields( &self, key: &str, transition_id: &str, fields: &BTreeMap<String, Value>, comment: Option<&ValidatedAdfDocument>, ) -> Result<()>

Executes a transition, optionally setting transition-screen fields and adding a comment in the same request.

fields is a map of stable JIRA field id → API-shaped value (e.g. resolution → {"name": "Fixed"}); it is omitted from the body when empty. When comment is Some, it is added via the transition update.comment operation so it lands atomically with the transition — the only way to satisfy a transition screen that mandates a comment.

Source

pub async fn search_issues( &self, jql: &str, limit: u32, ) -> Result<JiraSearchResult>

Searches JIRA issues using JQL with auto-pagination.

limit controls total results: 0 means unlimited.

Source

pub async fn search_confluence( &self, cql: &str, limit: u32, ) -> Result<ConfluenceSearchResults>

Searches Confluence pages using CQL with auto-pagination.

Source

pub async fn search_jira_users( &self, query: &str, limit: u32, ) -> Result<JiraUserSearchResults>

Searches JIRA users by display name or email substring.

query is matched against displayName and emailAddress server- side; matching is substring and case-insensitive. limit of 0 returns every match (paginating internally), otherwise the result is truncated. Inactive users and app/customer account types are included — callers that need only assignable atlassian-account users should filter on active and account_type.

Note: many tenants strip emailAddress from search results due to GDPR / privacy settings, even when the user has an email on file.

Source

pub async fn search_confluence_users( &self, query: &str, limit: u32, ) -> Result<ConfluenceUserSearchResults>

Searches Confluence users by display name or email.

Source

pub async fn get_jira_user(&self, account_id: &str) -> Result<JiraUserRecord>

Resolves a single JIRA user by account ID (GET /rest/api/3/user?accountId=).

Failure-tolerant: an unknown / anonymised account (HTTP 404) or any other non-auth failure resolves to a stub record with error set rather than an Err, so a batch lookup never aborts for one bad ID. A 401 (bad credentials) is a hard error worth surfacing. Deactivated accounts come back from Atlassian as a real 200 record with active: false.

Source

pub async fn get_jira_users( &self, account_ids: &[String], ) -> Result<JiraUserGetResults>

Resolves multiple JIRA users by account ID, concurrently.

Each ID is fetched independently via Self::get_jira_user; per-ID failures become stub records, so the batch only errors on a genuine auth failure (or transport error). Results preserve request order.

Source

pub async fn get_confluence_user( &self, account_id: &str, ) -> Result<ConfluenceUserRecord>

Resolves a single Confluence user by account ID (GET /wiki/rest/api/user?accountId=).

Failure-tolerant in the same way as Self::get_jira_user. The v1 user object has no active flag, so ConfluenceUserRecord::active is always None; displayName falls back to publicName.

Source

pub async fn get_confluence_users( &self, account_ids: &[String], ) -> Result<ConfluenceUserGetResults>

Resolves multiple Confluence users by account ID, concurrently.

Behaves like Self::get_jira_users: per-ID failures become stub records; the batch only errors on a genuine auth / transport failure.

Source

pub async fn get_boards( &self, project: Option<&str>, board_type: Option<&str>, limit: u32, ) -> Result<AgileBoardList>

Lists agile boards with auto-pagination.

Source

pub async fn get_board_issues( &self, board_id: u64, jql: Option<&str>, limit: u32, ) -> Result<JiraSearchResult>

Lists issues on an agile board with auto-pagination.

Source

pub async fn get_sprints( &self, board_id: u64, state: Option<&str>, limit: u32, ) -> Result<AgileSprintList>

Lists sprints for an agile board with auto-pagination.

Source

pub async fn get_sprint_issues( &self, sprint_id: u64, jql: Option<&str>, limit: u32, ) -> Result<JiraSearchResult>

Lists issues in an agile sprint with auto-pagination.

Source

pub async fn add_issues_to_sprint( &self, sprint_id: u64, issue_keys: &[&str], ) -> Result<()>

Adds issues to an agile sprint.

Source

pub async fn create_sprint( &self, board_id: u64, name: &str, start_date: Option<&str>, end_date: Option<&str>, goal: Option<&str>, ) -> Result<AgileSprint>

Creates a new sprint on an agile board.

Source

pub async fn update_sprint( &self, sprint_id: u64, name: Option<&str>, state: Option<&str>, start_date: Option<&str>, end_date: Option<&str>, goal: Option<&str>, ) -> Result<()>

Updates an existing sprint.

Source

pub async fn delete_sprint(&self, sprint_id: u64) -> Result<()>

Deletes a sprint.

Issues DELETE /rest/agile/1.0/sprint/{id}.

Source

pub async fn get_project_versions( &self, project_key: &str, released: Option<bool>, archived: Option<bool>, ) -> Result<JiraProjectVersionList>

Lists versions for a JIRA project.

Uses the lightweight GET /rest/api/3/project/{key}/versions endpoint, which returns all versions in a single response without pagination. released and archived filters are applied client-side.

Source

pub async fn create_project_version( &self, project_key: &str, name: &str, description: Option<&str>, release_date: Option<&str>, start_date: Option<&str>, released: bool, archived: bool, ) -> Result<JiraProjectVersion>

Creates a new version in a JIRA project.

Validates release_date and start_date as YYYY-MM-DD client-side to surface clear errors before JIRA rejects the request with an opaque 400.

Source

pub async fn update_project_version( &self, version_id: &str, name: Option<&str>, description: Option<&str>, released: Option<bool>, release_date: Option<&str>, archived: Option<bool>, start_date: Option<&str>, ) -> Result<()>

Updates an existing project version — the shared backend for release / archive / rename / edit.

Issues PUT /rest/api/3/version/{id} with only the Some fields; omitted fields keep their current value. Any provided dates are validated first. Returns () (mirroring Self::update_sprint); the caller already knows the mutation it requested.

Source

pub async fn delete_project_version( &self, version_id: &str, move_fix_issues_to: Option<&str>, move_affected_issues_to: Option<&str>, ) -> Result<()>

Deletes a project version.

Issues DELETE /rest/api/3/version/{id}. Issues that reference the version can be reassigned first via moveFixIssuesTo / moveAffectedIssuesTo (each a target version id); omit both to delete and simply drop the references.

Source

pub async fn get_project_components( &self, project_key: &str, ) -> Result<Vec<JiraComponent>>

Lists the components of a JIRA project.

GET /rest/api/3/project/{key}/components.

Source

pub async fn create_component( &self, project_key: &str, name: &str, description: Option<&str>, ) -> Result<JiraComponent>

Creates a component on a JIRA project.

POST /rest/api/3/component.

Source

pub async fn update_component( &self, component_id: &str, name: Option<&str>, description: Option<&str>, ) -> Result<()>

Updates a JIRA component’s name and/or description.

PUT /rest/api/3/component/{id} with only the Some fields.

Source

pub async fn delete_component( &self, component_id: &str, move_issues_to: Option<&str>, ) -> Result<()>

Deletes a JIRA component.

DELETE /rest/api/3/component/{id}. Issues that reference the component can be reassigned via moveIssuesTo (another component id).

Lists links on a JIRA issue.

Lists remote (external URL) issue links on a JIRA issue.

Endpoint: GET /rest/api/3/issue/{key}/remotelink — returns a bare JSON array (not a wrapped { links: [...] } envelope).

Creates (or, when global_id matches an existing link, updates) a remote (external-URL) link on a JIRA issue.

Issues POST /rest/api/3/issue/{key}/remotelink. Returns the new/updated link’s id (normalized to String, since JIRA returns it as a number).

Deletes a remote (external-URL) link from a JIRA issue by its link id.

Issues DELETE /rest/api/3/issue/{key}/remotelink/{linkId}.

Lists available issue link types.

Creates a link between two JIRA issues.

Removes an issue link by ID.

Source

pub async fn set_issue_parent( &self, issue_key: &str, parent_key: &str, ) -> Result<()>

Sets the parent of a JIRA issue (e.g., links a Story to its Epic, a Sub-task to its Story, or any issue to a parent of a hierarchy-allowed type).

Source

pub async fn modify_issue_labels( &self, key: &str, add: &[String], remove: &[String], ) -> Result<()>

Incrementally adds and/or removes labels on a JIRA issue.

Issues PUT /rest/api/3/issue/{key} with the update verb ({"update": {"labels": [{"add": …}, {"remove": …}]}}), so labels not mentioned are preserved — unlike a full-array fields.labels replace (which jira write --set labels=… performs).

Source

pub async fn get_issue_id(&self, key: &str) -> Result<String>

Resolves a JIRA issue key to its numeric ID.

Source

pub async fn get_dev_status_summary( &self, key: &str, ) -> Result<JiraDevStatusSummary>

Fetches a development status summary (counts per category) for a JIRA issue.

Uses the DevStatus summary endpoint. Returns counts and providers (each carrying both the applicationType instance-type key and its display name) for each category (pull requests, branches, repositories).

Source

pub async fn get_dev_status( &self, key: &str, data_type: Option<&str>, application_type: Option<&str>, ) -> Result<JiraDevStatus>

Fetches development status (PRs, branches, repositories) for a JIRA issue.

Uses the DevStatus API which requires the numeric issue ID. The key is resolved automatically via get_issue_id.

If application_type is None, discovers available providers via the summary endpoint and queries each one. If Some, queries only that provider (e.g., “GitHub”, “bitbucket”, “stash”).

Source

pub async fn get_attachments(&self, key: &str) -> Result<Vec<JiraAttachment>>

Gets attachment metadata for a JIRA issue.

Source

pub async fn upload_attachments( &self, key: &str, files: &[PathBuf], ) -> Result<Vec<JiraAttachment>>

Uploads one or more files as attachments to a JIRA issue.

Streams each file body — files are never fully buffered in memory. All files ride a single multipart POST (JIRA accepts repeated file parts), and the endpoint returns metadata for every created attachment.

Sends X-Atlassian-Token: no-check (Atlassian’s XSRF opt-out required on this endpoint). Does not retry on 429: see AtlassianClient::post_multipart.

Source

pub async fn delete_attachment(&self, attachment_id: &str) -> Result<()>

Deletes a JIRA attachment by ID.

DELETE /rest/api/3/attachment/{id} — permanent (JIRA has no trash).

Source

pub async fn get_changelog( &self, key: &str, limit: u32, ) -> Result<Vec<JiraChangelogEntry>>

Gets the changelog for a JIRA issue with auto-pagination.

Source

pub async fn get_fields(&self) -> Result<Vec<JiraField>>

Lists all JIRA field definitions.

Source

pub async fn get_field_contexts(&self, field_id: &str) -> Result<Vec<String>>

Lists options for a JIRA custom field. Lists contexts for a JIRA custom field.

Source

pub async fn get_field_options( &self, field_id: &str, context_id: Option<&str>, ) -> Result<Vec<JiraFieldOption>>

Lists options for a JIRA custom field.

When context_id is None, auto-discovers the first context for the field.

Source

pub async fn get_projects(&self, limit: u32) -> Result<JiraProjectList>

Lists JIRA projects.

Source

pub async fn delete_issue(&self, key: &str) -> Result<()>

Deletes a JIRA issue.

Source

pub async fn get_watchers(&self, key: &str) -> Result<JiraWatcherList>

Lists watchers on a JIRA issue.

Source

pub async fn add_watcher(&self, key: &str, account_id: &str) -> Result<()>

Adds a user as a watcher on a JIRA issue.

Source

pub async fn remove_watcher(&self, key: &str, account_id: &str) -> Result<()>

Removes a user from watchers on a JIRA issue.

Source

pub async fn auth_identity(&self, service: AuthService) -> Result<AuthIdentity>

Verifies credentials against the selected service’s current-user API.

Source

pub async fn get_myself(&self) -> Result<JiraUser>

Verifies authentication by fetching the current user.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more