Rust Azure DevOps集成库azure_devops_rust_api的使用,实现高效API调用与自动化任务管理
Azure DevOps Rust API
概述
azure_devops_rust_api
实现了 Rust 对 Azure DevOps REST API(版本 7.1)的接口。
该 crate 是从 Azure DevOps OpenAPI 规范自动生成的。
该 crate 包含 38 个模块
使用
使用概述
该 crate 有许多功能/模块,但通用方法对所有模块都类似:
- 获取认证凭据
- 查看示例了解如何使用
azure_identity
crate 实现此操作
- 查看示例了解如何使用
- 为您想要使用的功能/模块创建客户端
- 通常您需要为您想要使用的顶级模块创建一个客户端(例如
git_client
),然后为子模块创建一个(例如repositories_client
)。
- 通常您需要为您想要使用的顶级模块创建一个客户端(例如
- 使用客户端进行操作请求
- 每个操作有零个或多个必需参数和零个或多个可选参数。
必需参数作为操作请求方法的参数传递。可选
参数可以通过调用操作请求方法返回的“构建器”对象上的方法来提供。构建器对象通过调用
await
来最终确定,这将构建器转换为 Future(通过IntoFuture
特性)并等待响应。
- 每个操作有零个或多个必需参数和零个或多个可选参数。
必需参数作为操作请求方法的参数传递。可选
参数可以通过调用操作请求方法返回的“构建器”对象上的方法来提供。构建器对象通过调用
代码示例
示例用法(来自 examples/git_repo_list.rs):
// 从 PAT ("ADO_TOKEN") 或通过 az cli 获取认证凭据
let credential = utils::get_credential()
// 通过环境变量获取 ADO 配置
let organization = env::var("ADO_ORGANIZATION")
.expect("Must define ADO_ORGANIZATION");
let project = env::var("ADO_PROJECT")
.expect("Must define ADO_PROJECT");
// 创建 git 客户端
let git_client = git::ClientBuilder::new(credential).build();
// 获取指定组织/项目中的所有仓库
let repos = git_client
.repositories_client()
.list(organization, project)
.await?
.value;
// 输出仓库名称
for repo in repos.iter() {
println!("{}", repo.name);
}
println!("{} repos found", repos.len());
API 中的各个模块通过 Rust features
启用。
查看 Cargo.toml 的 features
部分以获取完整的功能列表。
示例应用程序 Cargo.toml
依赖规范,显示如何指定所需功能:
[dependencies]
...
azure_devops_rust_api = { version = "0.29.0", features = ["git", "pipelines"] }
示例
查看示例目录。
定义环境变量:
export ADO_ORGANIZATION=<organization-name>
export ADO_PROJECT=<project-name>
要运行示例,您需要通过以下方式提供认证凭据:
az
CLI,您只需在运行示例之前通过运行az login
进行认证。- 个人访问令牌 (PAT),通过环境变量
ADO_TOKEN
提供注意:个人访问令牌包含您在 Azure DevOps 中的安全凭据。 PAT 标识您、您可访问的组织以及访问范围。 因此,它们与密码一样关键,您应该以相同的方式对待它们。 创建 PAT 时,仅授予其所需的最小范围,并将过期时间设置得较短。
通过 cargo run --example
运行示例。您需要启用示例所需的
功能。如果您未指定必要的功能,您会收到有用的错误
消息。
示例:
cargo run --example git_repo_get --features="git" <repo-name>
问题报告
如果您发现任何问题,请通过 Github 提出。
完整示例代码
以下是一个完整的示例,演示如何使用 azure_devops_rust_api 库列出 Azure DevOps 项目中的所有 Git 仓库:
use azure_devops_rust_api::git;
use azure_identity::token_credentials::{AzureCliCredential, TokenCredential};
use std::env;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 获取认证凭据 - 使用 Azure CLI 凭据
let credential = AzureCliCredential {};
// 从环境变量获取组织名称和项目名称
let organization = env::var("ADO_ORGANIZATION")
.expect("Must define ADO_ORGANIZATION environment variable");
let project = env::var("ADO_PROJECT")
.expect("Must define ADO_PROJECT environment variable");
// 创建 Git 客户端
let git_client = git::ClientBuilder::new(credential).build();
// 获取指定组织/项目中的所有仓库
let repos = git_client
.repositories_client()
.list(&organization, &project)
.await?
.value;
// 输出每个仓库的详细信息
println!("Found {} repositories in project '{}':", repos.len(), project);
for repo in repos.iter() {
println!("----------------------------------------");
println!("Name: {}", repo.name.as_deref().unwrap_or("Unknown"));
println!("ID: {}", repo.id.as_deref().unwrap_or("Unknown"));
println!("URL: {}", repo.url.as_deref().unwrap_or("Unknown"));
println!("Default branch: {}", repo.default_branch.as_deref().unwrap_or("Unknown"));
println!("Size: {} bytes", repo.size.unwrap_or(0));
}
Ok(())
}
要运行此示例,您需要:
- 在 Cargo.toml 中添加依赖:
[dependencies]
azure_devops_rust_api = { version = "0.29.0", features = ["git"] }
azure_identity = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
- 设置环境变量:
export ADO_ORGANIZATION=your-organization-name
export ADO_PROJECT=your-project-name
- 确保已通过 Azure CLI 登录:
az login
- 运行程序:
cargo run
此示例展示了如何使用 azure_devops_rust_api 库进行基本的 Azure DevOps API 调用,实现高效的自动化任务管理。
Rust Azure DevOps集成库azure_devops_rust_api使用指南
概述
azure_devops_rust_api是一个用于与Azure DevOps服务进行交互的Rust库。它提供了类型安全的API调用接口,支持高效地管理和自动化Azure DevOps中的各项任务,包括项目管理、版本控制、流水线管理和工作项跟踪等功能。
安装方法
在Cargo.toml中添加依赖:
[dependencies]
azure_devops_rust_api = "0.1"
tokio = { version = "1.0", features = ["full"] }
基本使用方法
1. 创建客户端实例
use azure_devops_rust_api::Client;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let personal_access_token = env::var("AZURE_DEVOPS_PAT")?;
let organization = "your-organization-name";
let client = Client::new(organization, personal_access_token);
Ok(())
}
2. 获取项目列表
use azure_devops_rust_api::projects;
async fn list_projects(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
let projects_client = client.projects_client();
let projects = projects_client.list().await?;
for project in projects.value {
println!("Project: {} - {}", project.name, project.description.unwrap_or_default());
}
Ok(())
}
3. 创建工作项
use azure_devops_rust_api::wit;
use serde_json::json;
async fn create_work_item(client: &Client, project: &str) -> Result<(), Box<dyn std::error::Error>> {
let wit_client = client.wit_client();
let work_item = json!([
{
"op": "add",
"path": "/fields/System.Title",
"value": "New bug report"
},
{
"op": "add",
"path": "/fields/System.Description",
"value": "Detailed description of the issue"
}
]);
let result = wit_client
.create(project, "Bug", work_item)
.await?;
println!("Created work item: {}", result.id);
Ok(())
}
4. 触发构建流水线
use azure_devops_rust_api::build;
async fn trigger_build(client: &Client, project: &str, pipeline_id: i32) -> Result<(), Box<dyn std::error::Error>> {
let build_client = client.build_client();
let build_parameters = json!({
"definition": {
"id": pipeline_id
},
"parameters": {
"configuration": "release",
"platform": "x64"
}
});
let build = build_client
.queue_build(project, build_parameters)
.await?;
println!("Build queued: {}", build.id);
Ok(())
}
高级功能示例
批量处理工作项
async fn batch_update_work_items(client: &Client, project: &str, item_ids: Vec<i32>) -> Result<(), Box<dyn std::error::Error>> {
let wit_client = client.wit_client();
let operations: Vec<serde_json::Value> = item_ids.iter().map(|&id| {
json!({
"op": "add",
"path": format!("/{}/fields/System.State", id),
"value": "Done"
})
}).collect();
wit_client
.update_work_items_batch(project, operations)
.await?;
println!("Updated {} work items", item_ids.len());
Ok(())
}
监控构建状态
use std::time::{Duration, Instant};
use tokio::time::sleep;
async fn monitor_build(client: &Client, project: &str, build_id: i32) -> Result<(), Box<dyn std::error::Error>> {
let build_client = client.build_client();
let start_time = Instant::now();
while start_time.elapsed() < Duration::from_secs(300) { // 5分钟超时
let build = build_client.get_build(project, build_id).await?;
match build.status.as_str() {
"completed" => {
println!("Build completed with result: {}", build.result.unwrap_or_default());
break;
}
"inProgress" => {
println!("Build in progress...");
sleep(Duration::from_secs(10)).await;
}
_ => {
println!("Build status: {}", build.status);
sleep(Duration::from_secs(10)).await;
}
}
}
Ok(())
}
错误处理最佳实践
use azure_devops_rust_api::Error;
async fn safe_api_call(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
match client.projects_client().list().await {
Ok(response) => {
// 处理成功响应
Ok(())
}
Err(Error::ApiError { status, body }) => {
eprintln!("API error: Status {}, Body: {}", status, body);
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"API call failed"
)))
}
Err(e) => {
eprintln!("Other error: {}", e);
Err(Box::new(e))
}
}
}
环境变量配置
建议使用环境变量管理认证信息:
export AZURE_DEVOPS_PAT=your_personal_access_token
export AZURE_DEVOPS_ORG=your_organization_name
完整示例demo
use azure_devops_rust_api::Client;
use azure_devops_rust_api::{projects, wit, build};
use serde_json::json;
use std::env;
use std::time::{Duration, Instant};
use tokio::time::sleep;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 从环境变量获取认证信息
let personal_access_token = env::var("AZURE_DEVOPS_PAT")?;
let organization = env::var("AZURE_DEVOPS_ORG").unwrap_or_else(|_| "your-organization-name".to_string());
// 创建客户端实例
let client = Client::new(&organization, personal_access_token);
// 示例1: 获取项目列表
println!("=== 获取项目列表 ===");
list_projects(&client).await?;
// 示例2: 创建工作项
println!("\n=== 创建工作项 ===");
let project_name = "your-project-name"; // 替换为实际项目名称
create_work_item(&client, project_name).await?;
// 示例3: 触发构建流水线
println!("\n=== 触发构建流水线 ===");
let pipeline_id = 1; // 替换为实际流水线ID
trigger_build(&client, project_name, pipeline_id).await?;
// 示例4: 批量更新工作项状态
println!("\n=== 批量更新工作项 ===");
let item_ids = vec![1001, 1002, 1003]; // 替换为实际工作项ID
batch_update_work_items(&client, project_name, item_ids).await?;
Ok(())
}
// 获取项目列表函数
async fn list_projects(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
let projects_client = client.projects_client();
let projects = projects_client.list().await?;
println!("找到 {} 个项目:", projects.count);
for project in projects.value {
println!("项目: {} - {}",
project.name,
project.description.unwrap_or_default());
}
Ok(())
}
// 创建工作项函数
async fn create_work_item(client: &Client, project: &str) -> Result<(), Box<dyn std::error::Error>> {
let wit_client = client.wit_client();
// 创建工作项的JSON操作数组
let work_item = json!([
{
"op": "add",
"path": "/fields/System.Title",
"value": "新的Bug报告"
},
{
"op": "add",
"path": "/fields/System.Description",
"value": "问题的详细描述"
},
{
"op": "add",
"path": "/fields/System.AssignedTo",
"value": "user@example.com"
}
]);
let result = wit_client
.create(project, "Bug", work_item)
.await?;
println!("创建工作项成功: ID {}", result.id);
Ok(())
}
// 触发构建流水线函数
async fn trigger_build(client: &Client, project: &str, pipeline_id: i32) -> Result<(), Box<dyn std::error::Error>> {
let build_client = client.build_client();
// 构建参数配置
let build_parameters = json!({
"definition": {
"id": pipeline_id
},
"parameters": {
"configuration": "release",
"platform": "x64",
"buildReason": "Manual"
},
"sourceBranch": "refs/heads/main"
});
let build = build_client
.queue_build(project, build_parameters)
.await?;
println!("构建已加入队列: ID {}", build.id);
// 监控构建状态
monitor_build(client, project, build.id).await?;
Ok(())
}
// 批量更新工作项函数
async fn batch_update_work_items(client: &Client, project: &str, item_ids: Vec<i32>) -> Result<(), Box<dyn std::error::Error>> {
let wit_client = client.wit_client();
// 为每个工作项创建更新操作
let operations: Vec<serde_json::Value> = item_ids.iter().map(|&id| {
json!({
"op": "add",
"path": format!("/{}/fields/System.State", id),
"value": "Done"
})
}).collect();
if !operations.is_empty() {
wit_client
.update_work_items_batch(project, operations)
.await?;
println!("成功更新 {} 个工作项状态为 'Done'", item_ids.len());
}
Ok(())
}
// 监控构建状态函数
async fn monitor_build(client: &Client, project: &str, build_id: i32) -> Result<(), Box<dyn std::error::Error>> {
let build_client = client.build_client();
let start_time = Instant::now();
let timeout = Duration::from_secs(300); // 5分钟超时
println!("开始监控构建 {} 的状态...", build_id);
while start_time.elapsed() < timeout {
let build = build_client.get_build(project, build_id).await?;
match build.status.as_str() {
"completed" => {
let result = build.result.unwrap_or_default();
println!("构建完成: 结果 - {}", result);
return Ok(());
}
"inProgress" => {
println!("构建进行中...");
sleep(Duration::from_secs(15)).await;
}
"notStarted" => {
println!("构建尚未开始...");
sleep(Duration::from_secs(10)).await;
}
"cancelling" => {
println!("构建正在取消...");
sleep(Duration::from_secs(5)).await;
}
_ => {
println!("构建状态: {}", build.status);
sleep(Duration::from_secs(10)).await;
}
}
}
println!("构建监控超时");
Ok(())
}
// 错误处理示例函数
async fn safe_api_call(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
use azure_devops_rust_api::Error;
match client.projects_client().list().await {
Ok(response) => {
println!("成功获取 {} 个项目", response.count);
Ok(())
}
Err(Error::ApiError { status, body }) => {
eprintln!("API调用错误: 状态码 {}, 响应体: {}", status, body);
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"API调用失败"
)))
}
Err(Error::ReqwestError(e)) => {
eprintln!("网络请求错误: {}", e);
Err(Box::new(e))
}
Err(Error::SerdeError(e)) => {
eprintln!("JSON解析错误: {}", e);
Err(Box::new(e))
}
Err(e) => {
eprintln!("其他错误: {}", e);
Err(Box::new(e))
}
}
}
这个库提供了完整的Azure DevOps API覆盖,支持异步操作和类型安全的数据处理,是构建自动化工具和集成解决方案的理想选择。