| title | Code Generation |
|---|---|
| description | How atla generates Rust API clients from Atlassian OpenAPI specs using progenitor. |
atla generates type-safe Rust API clients at compile time using progenitor, a Rust-native OpenAPI code generator. No external tools (Java, Python, etc.) are required.
Atlassian CDN (upstream specs)
|
v
update-specs.sh Download upstream OpenAPI JSON
|
v
JS filter scripts Filter/patch specs to partial subsets
|
v
specs/*.json Checked-in spec files
|
v
build.rs (progenitor) Generate Rust code at compile time
|
v
$OUT_DIR/codegen.rs Included via include!() in lib.rs
| Crate | Spec file | Upstream source | Filter script |
|---|---|---|---|
atla-jira-api |
specs/jira-v3-partial.json |
Jira Cloud v3 | scripts/jira-v3-partial-spec.js |
atla-confluence-api |
specs/confluence-v2.json |
Confluence Cloud v2 | None (full spec) |
atla-confluence-v1-api |
specs/confluence-v1-partial.json |
Confluence Cloud v1 | scripts/confluence-v1-partial-spec.js |
Each crate contains only three hand-maintained files:
Cargo.toml— declares build-dependencies on progenitor and runtime dependencies on progenitor-clientbuild.rs— reads the spec and invokes progenitor to generate$OUT_DIR/codegen.rssrc/lib.rs—include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
All API client code is generated at compile time. There are no hand-maintained API modules.
All three crates follow the same pattern:
use progenitor::{Generator, GenerationSettings, InterfaceStyle};
fn main() {
let src = "../../specs/<spec-file>.json";
println!("cargo:rerun-if-changed={}", src);
let file = std::fs::File::open(src).unwrap();
let spec: openapiv3::OpenAPI = serde_json::from_reader(file).unwrap();
let mut settings = GenerationSettings::default();
settings
.with_interface(InterfaceStyle::Builder)
.with_derive("PartialEq");
let mut generator = Generator::new(&settings);
let tokens = generator.generate_tokens(&spec).unwrap();
let ast = syn::parse2(tokens).unwrap();
let content = prettyplease::unparse(&ast);
let out_path = std::path::Path::new(&std::env::var("OUT_DIR").unwrap())
.join("codegen.rs");
std::fs::write(out_path, content).unwrap();
}Key points:
cargo:rerun-if-changedensures the crate only rebuilds when the spec file changesInterfaceStyle::Buildergenerates builder-pattern methods:client.create_issue().body(body).send().awaitprettypleaseformats the generated code for readable compiler errors
[build-dependencies]
progenitor = "0.14"
serde_json = "1"
openapiv3 = "2"
syn = { version = "2", features = ["full"] }
prettyplease = "0.2"[dependencies]
progenitor-client = "0.14"
reqwest.workspace = true
serde.workspace = true
serde_json.workspace = trueSome crates require additional dependencies (chrono, uuid, serde_repr, etc.) depending on the spec's schema types.
Full Atlassian specs are very large. The Jira v3 spec alone produces around 1,000 files and 12 MB of Rust code. Filtering to only the endpoints atla uses keeps compile times manageable.
Filters the full Jira Cloud v3 spec to include only:
- Issues: create, search, get, update, delete, transitions
- Comments: list, create, get, update, delete
- Projects: search, get
- Issue types, attachments, issue links
Also provides simplified schemas for complex types (CreatedIssue, IssueUpdateDetails, Transitions, etc.) to avoid pulling in the entire Jira type graph.
Jira Software Agile endpoints (boards, sprints) are not part of the Jira platform v3 spec. atla calls those endpoints directly via raw reqwest calls in atla-core.
Filters the Confluence v1 spec and applies compatibility patches:
- Paths included: content search, general search, user search, attachments, space info, content labels
- Patches: normalizes multipart operations, fixes form-data fields, removes unsupported query parameters
- Provides simplified schemas for
Content,SearchResult,Space, etc.
Page label mutation also uses Confluence v1 raw REST calls because the v2 API does not expose label add/remove endpoints.
Uses the full upstream spec without filtering. The v2 spec is small enough to generate directly.
scripts/update-specs.sh handles the full refresh cycle:
- Downloads upstream specs from Atlassian CDN
- Runs JS filter scripts to produce partial specs
- Updates
specs/manifest.jsonwith SHA256 hashes and metadata
scripts/update-specs.sh
cargo check --workspaceTracks integrity and provenance for each spec:
- Source file path and SHA256 hash
- Upstream URL and SHA256 hash
- Filter script path (if applicable)
- Generator tool and version metadata
| Spec | URL |
|---|---|
| Jira v3 | https://dac-static.atlassian.com/cloud/jira/platform/swagger-v3.v3.json |
| Confluence v2 | https://dac-static.atlassian.com/cloud/confluence/openapi-v2.v3.json |
| Confluence v1 | https://dac-static.atlassian.com/cloud/confluence/swagger.v3.json |
progenitor generates a Client struct with builder-pattern methods:
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
// Build an authenticated reqwest client
let mut headers = HeaderMap::new();
let creds = base64::encode(format!("{}:{}", email, api_token));
headers.insert(AUTHORIZATION, HeaderValue::from_str(&format!("Basic {}", creds))?);
let http_client = reqwest::Client::builder().default_headers(headers).build()?;
// Create the progenitor client
let client = atla_jira_api::Client::new_with_client(&base_url, http_client);
// Use builder-pattern API calls
let result = client.create_issue().body(body).send().await?;
let issue = result.into_inner();Auth is handled via reqwest::Client default headers — progenitor's Client has no built-in auth fields.
To expose a new Jira or Confluence endpoint in atla:
- Identify the endpoint in the upstream spec (check the downloaded spec in
specs/) - Add the path to the relevant JS filter script (e.g.
scripts/jira-v3-partial-spec.js) - Re-run filtering:
scripts/update-specs.sh - Verify:
cargo check --workspace - Consume the new generated method in
atla-core
For endpoints not covered by any upstream spec (e.g. Jira Software Agile REST API), implement them directly in atla-core using raw reqwest calls.
- Getting Started — installation and first-time setup
- Agent Reference — complete command reference for automation