13 releases
Uses new Rust 2024
| 0.1.16 | Jan 13, 2026 |
|---|---|
| 0.1.15 | Dec 29, 2025 |
| 0.1.11 | Sep 19, 2025 |
| 0.1.10 | Jun 5, 2025 |
| 0.1.2 | Feb 28, 2025 |
#406 in HTTP server
180KB
4.5K
SLoC
πΊπΈ English Β· π¨π³ δΈζ | Table of Contents βοΈ
jenkins-sdk-rust
π¦ Jenkins API SDK in pure Rust β async and blocking clients, typed endpoints, pluggable middleware & zero magic strings.
β¨ Features
| Feature | Description |
|---|---|
| Async and Blocking | Choose the I/O model at compile-time: async by default, enable blocking for non-async environments. |
| Core services | Discoverable client.jobs()/queue()/system()/... APIs β no manual path building. |
| Composable middleware | Ready-made CSRF-crumb fetching, retries, custom transports β just chain builders. |
| No magic strings | URL build, query/form encoding, error mapping & JSON decoding handled for you. |
| Pure Rust, tiny deps | Built on reqwest + rustls; no C bindings, minimal footprint. |
πΌ Architecture
Quick-glance architecture (click to collapse)
flowchart LR
%% ββ Your App ββββββββββββββββββββββββββ
subgraph A["Your App"]
direction TB
CLI["Binary / Service"]
end
%% ββ SDK Core ββββββββββββββββββββββββββ
subgraph S["jenkins-sdk-rust"]
direction LR
Builder["Client Builder"] --> Client["Jenkins<br/>Async / Blocking"] --> Middleware["Middleware<br/><sub>retry β’ crumbs β’ custom</sub>"] --> Service["Core Services<br/><sub>jobs β’ queue β’ system β’ ...</sub>"]
end
%% ββ External ββββββββββββββββββββββββββ
subgraph J["Jenkins Master"]
direction TB
API["REST API"]
end
%% ββ Flows βββββββββββββββββββββββββββββ
CLI --> Builder
Service --> API
%% ββ Styling βββββββββββββββββββββββββββ
classDef app fill:#e3f2fd,stroke:#1976d2,stroke-width:1px;
classDef sdk fill:#e8f5e9,stroke:#388e3c,stroke-width:1px;
classDef server fill:#fff8e1,stroke:#f57f17,stroke-width:1px;
class CLI app;
class Builder,Client,Middleware,Service sdk;
class API server;
π Supported API Matrix
| Service | APIs (core) | Status |
|---|---|---|
system() |
/api/json, /whoAmI/api/json, /crumbIssuer/api/json, /overallLoad/api/json, /loadStatistics/api/json, /jnlpJars/agent.jar, /jnlpJars/jenkins-cli.jar, /config.xml get/update, /quietDown/cancelQuietDown/reload/safeRestart/restart/exit |
β |
jobs() |
list/get + lastBuild selectors, build info, consoleText, logText/progressiveText, artifact download, stop/term/kill/doDelete/toggleLogKeep/submitDescription, config.xml get/update, createItem(xml), copy/rename/delete/enable/disable |
β |
queue() |
list/item/cancel | β |
computers() |
list/computer + typed executors_info(), doCreateItem(xml)/copy, toggleOffline/doDelete, config.xml get/update, connect/disconnect/launchSlaveAgent |
β |
views() |
list/get, createView(xml), config.xml get/update, doDelete/doRename, addJobToView/removeJobFromView |
β |
users() |
/user/<id>/api/json, /whoAmI/api/json, config.xml get/update |
β |
people() |
/people/api/json, /asynchPeople/api/json |
β |
π₯ Installation
# quickest
cargo add jenkins-sdk
# Cargo.toml β async client (default)
[dependencies]
jenkins-sdk = "0.1"
# blocking client (choose one TLS backend)
# jenkins-sdk = { version = "0.1", default-features = false, features = ["blocking", "rustls"] }
# jenkins-sdk = { version = "0.1", default-features = false, features = ["blocking", "native-tls"] }
β‘Quick Start
Base URL can include a sub-path (e.g.
https://example.com/jenkins); a trailing/is optional, the SDK normalises it for you.
Async Example
use jenkins_sdk::Client;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), jenkins_sdk::Error> {
// Build a client with some sugar ββ>
let j = Client::builder("https://jenkins.example.com")?
.auth_basic("user", "apitoken")
.no_system_proxy()
.with_retry(3, Duration::from_millis(300))
.with_crumb(Duration::from_secs(1800))
.build()?;
// Queue length
let q: serde_json::Value = j.queue().list(None).await?;
println!("queue items = {}", q["items"].as_array().map_or(0, |a| a.len()));
// Executor stats (typed deserialisation)
let mut ex = j.computers().executors_info().await?;
ex = ex.calc_idle();
println!("idle executors = {}", ex.idle_executors);
// Raw job list
let jobs: serde_json::Value = j.jobs().list().await?;
println!("first job = {}", jobs["jobs"][0]["name"]);
Ok(())
}
Blocking Example
// Compile with `default-features = false, features = ["blocking", "rustls"]`
// or `default-features = false, features = ["blocking", "native-tls"]`.
use jenkins_sdk::BlockingClient;
use std::time::Duration;
fn main() -> Result<(), jenkins_sdk::Error> {
let j = BlockingClient::builder("https://jenkins.example.com")?
.auth_basic("user", "apitoken")
.timeout(Duration::from_secs(15))
.with_retry(2, Duration::from_millis(250))
.build()?;
let q: serde_json::Value = j.queue().list(None)?;
println!("queue items = {}", q["items"].as_array().unwrap().len());
Ok(())
}
Any Endpoint (Unstable Raw Request)
Enable the unstable-raw feature and use raw::Request + execute() when an API endpoint isn't
modeled yet:
use jenkins_sdk::Client;
use jenkins_sdk::raw::Request;
# async fn demo(client: Client) -> Result<(), jenkins_sdk::Error> {
let resp = client
.execute(&Request::get(["api", "json"]).query_pair("tree", "jobs[name]"))
.await?;
let root: serde_json::Value = resp.json()?;
println!("{root:?}");
# Ok(())
#
}
Note: when using the blocking client inside a Tokio runtime, call it via
tokio::task::spawn_blockingor a dedicated thread pool.
π Changelog
See CHANGELOG.md for release notes.
π License
This project is licensed under the MIT License.
Dependencies
~10β27MB
~417K SLoC