Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,940 changes: 2,030 additions & 910 deletions Cargo.lock

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions github/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ version = "0.10.0"
documentation = "https://docs.rs/octorust/"
repository = "https://github.com/oxidecomputer/third-party-api-clients/tree/main/github"
readme = "README.md"
edition = "2021"
edition = "2024"
license = "MIT"

[features]
default = ["middleware", "rustls-tls"]
# enable etag-based http_cache functionality
httpcache = ["dirs"]
native-tls = ["reqwest/default-tls", "openssl"]
rustls-tls = ["reqwest/rustls-tls", "ring", "pem"]
rustls-tls = ["reqwest/rustls", "ring", "pem"]
middleware = [
"reqwest-conditional-middleware",
"reqwest-middleware",
Expand All @@ -24,40 +24,40 @@ middleware = [
[dependencies]
async-recursion = "^1.0"
chrono = { version = "0.4.38", default-features = false, features = ["alloc", "serde"] }
dirs = { version = "^3.0.2", optional = true }
dirs = { version = "6", optional = true }
http = "1"
jsonwebtoken = "9"
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
log = { version = "^0.4", features = ["serde"] }
mime = "0.3"
openssl = { version = "0.10", default-features = false, optional = true }
parse_link_header = "0.3.3"
parse_link_header = "0.4"
pem = { version = "3.0.5", default-features = false, optional = true }
percent-encoding = "2.2"
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart"] }
reqwest-conditional-middleware = { version = "0.4", optional = true }
reqwest-middleware = { version = "0.4", features = ["multipart"], optional = true }
reqwest-retry = { version = "0.7", optional = true }
reqwest-tracing = { version = "0.5.4", optional = true }
reqwest = { version = "0.13", default-features = false, features = ["json", "multipart", "rustls"] }
reqwest-conditional-middleware = { version = "0.5", optional = true }
reqwest-middleware = { version = "0.5", features = ["multipart"], optional = true }
reqwest-retry = { version = "0.9", optional = true }
reqwest-tracing = { version = "0.7", optional = true }
ring = { version = "0.17", default-features = false, optional = true }
schemars = { version = "0.8", features = ["bytes", "chrono", "url", "uuid1"] }
schemars = { version = "1", features = ["bytes1", "chrono04", "url2", "uuid1"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_urlencoded = "^0.7"
url = { version = "2", features = ["serde"] }
bytes = { version = "1", features = ["serde"] }
async-trait = "^0.1.80"
uuid = { version = "1.1", features = ["serde", "v4"] }
thiserror = "1"
thiserror = "2"
tokio = { version = "1.25.0", default-features = false }

[dev-dependencies]
base64 = "^0.21"
dirs = "^3.0.2"
dirs = "6"
nom_pem = "4"
rand = "0.8.5"
rsa = "0.8.1"
rand = "0.10"
rsa = "=0.10.0-rc.18"
tokio = { version = "1.25.0", features = ["full", "test-util"] }
wiremock = "0.5.17"
wiremock = "0.6"

[package.metadata.docs.rs]
all-features = true
Expand Down
4 changes: 2 additions & 2 deletions github/examples/get_repo_in_org.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use base64::{engine::general_purpose::STANDARD, Engine};
use base64::{Engine, engine::general_purpose::STANDARD};
use std::env;

#[cfg(feature = "httpcache")]
use octorust::http_cache::FileBasedCache;
use octorust::{
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
Client,
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
};

#[tokio::main]
Expand Down
4 changes: 2 additions & 2 deletions github/examples/list_pulls_for_repo.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use base64::{engine::general_purpose::STANDARD, Engine};
use base64::{Engine, engine::general_purpose::STANDARD};
use std::env;

#[cfg(feature = "httpcache")]
use octorust::http_cache::FileBasedCache;
use octorust::{
Client,
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
types::IssuesListState,
Client,
};

#[tokio::main]
Expand Down
4 changes: 2 additions & 2 deletions github/examples/list_repos_for_org.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use base64::{engine::general_purpose::STANDARD, Engine};
use base64::{Engine, engine::general_purpose::STANDARD};
use std::env;

#[cfg(feature = "httpcache")]
use octorust::http_cache::FileBasedCache;
use octorust::{
Client,
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
types::{Order, ReposListOrgSort, ReposListOrgType},
Client,
};

#[tokio::main]
Expand Down
10 changes: 5 additions & 5 deletions github/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,22 +232,22 @@ impl PartialEq for InstallationTokenGenerator {
#[cfg(test)]
mod tests {
use super::*;
use rand::RngCore;
use rsa::{pkcs1::EncodeRsaPrivateKey, RsaPrivateKey};
use rand::Rng;
use rsa::{RsaPrivateKey, pkcs1::EncodeRsaPrivateKey};
use std::time::Duration;

fn app_id() -> i64 {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
rng.next_u32() as i64
}

fn installation_id() -> i64 {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
rng.next_u32() as i64
}

fn private_key() -> Vec<u8> {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let private_key = RsaPrivateKey::new(&mut rng, 2048)
.unwrap()
.to_pkcs1_der()
Expand Down
6 changes: 3 additions & 3 deletions github/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ pub mod users;
#[doc(hidden)]
pub mod utils;

pub use reqwest::{header::HeaderMap, StatusCode};
pub use reqwest::{StatusCode, header::HeaderMap};

#[derive(Debug)]
pub struct Response<T> {
Expand Down Expand Up @@ -310,7 +310,7 @@ pub enum ClientError {
pub const FALLBACK_HOST: &str = "https://api.github.com";

mod progenitor_support {
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
use percent_encoding::{AsciiSet, CONTROLS, utf8_percent_encode};

const PATH_SET: &AsciiSet = &CONTROLS
.add(b' ')
Expand Down Expand Up @@ -739,7 +739,7 @@ impl Client {
}
} else {
let error = match (remaining, reset) {
(Some(remaining), Some(reset)) if remaining == 0 => {
(Some(0), Some(reset)) => {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
Expand Down
30 changes: 15 additions & 15 deletions github/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub mod date_format {
}

pub mod date_time_format {
use chrono::{DateTime, TimeZone, Utc};
use chrono::{DateTime, NaiveDateTime, Utc};
use serde::{self, Deserialize, Deserializer};

// The date format Ramp returns looks like this: "2021-04-24T01:03:21"
Expand All @@ -176,14 +176,15 @@ pub mod date_time_format {
Ok(t) => Ok(Some(t)),
Err(_) => {
// This is google calendar.
match Utc.datetime_from_str(&s, "%Y-%m-%dT%H:%M:%S%.3fZ") {
Ok(t) => Ok(Some(t)),
Err(_) => match Utc.datetime_from_str(&s, FORMAT) {
Ok(t) => Ok(Some(t)),
Err(_) => match Utc.datetime_from_str(&s, "%+") {
Ok(t) => Ok(Some(t)),

match NaiveDateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.3fZ") {
Ok(t) => Ok(Some(t.and_utc())),
Err(_) => match NaiveDateTime::parse_from_str(&s, FORMAT) {
Ok(t) => Ok(Some(t.and_utc())),
Err(_) => match NaiveDateTime::parse_from_str(&s, "%+") {
Ok(t) => Ok(Some(t.and_utc())),
Err(_) => match chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
Ok(d) => Ok(Some(DateTime::<Utc>::from_utc(
Ok(d) => Ok(Some(DateTime::from_naive_utc_and_offset(
chrono::NaiveDateTime::new(
d,
chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
Expand All @@ -192,10 +193,11 @@ pub mod date_time_format {
))),
Err(_) => {
s = format!("{}+00:00", s);
match Utc.datetime_from_str(&s, FORMAT) {
Ok(r) => Ok(Some(r)),
Err(_) => match Utc.datetime_from_str(&s, "%+") {
Ok(d) => Ok(Some(d)),
match NaiveDateTime::parse_from_str(&s, FORMAT) {
Ok(r) => Ok(Some(r.and_utc())),
Err(_) => match NaiveDateTime::parse_from_str(&s, "%+")
{
Ok(d) => Ok(Some(d.and_utc())),
Err(e) => Err(serde::de::Error::custom(format!(
"deserializing {} as DateTime<Utc> failed: {}",
s, e
Expand Down Expand Up @@ -240,7 +242,7 @@ pub mod deserialize_empty_url {
return Err(serde::de::Error::custom(format!(
"error url parsing {}: {}",
s, e
)))
)));
}
}
}
Expand Down Expand Up @@ -368,7 +370,6 @@ impl Visitor<'_> for I32Visitor {
where
E: de::Error,
{
use std::i32;
if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
Ok(value as i32)
} else {
Expand Down Expand Up @@ -507,7 +508,6 @@ impl Visitor<'_> for F32Visitor {
where
E: de::Error,
{
use std::i32;
if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
Ok(value as f32)
} else {
Expand Down
39 changes: 20 additions & 19 deletions github/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
use rand::RngCore;
use rsa::{pkcs1::EncodeRsaPrivateKey, RsaPrivateKey};
use rand::Rng;
use rsa::{RsaPrivateKey, pkcs1::EncodeRsaPrivateKey};
use std::{mem, time::Duration, time::SystemTime};

use wiremock::{
Mock, MockServer, ResponseTemplate,
http::{HeaderName, HeaderValue},
matchers::{bearer_token, header, method, path, query_param},
Mock, MockServer, ResponseTemplate,
};

use octorust::{
Client, ClientError,
auth::{Credentials, InstallationTokenGenerator, JWTCredentials},
types::InstallationToken,
Client, ClientError,
};

fn app_id() -> i64 {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
rng.next_u32() as i64
}

fn installation_id() -> i64 {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
rng.next_u32() as i64
}

fn private_key() -> Vec<u8> {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let private_key = RsaPrivateKey::new(&mut rng, 2048)
.unwrap()
.to_pkcs1_der()
Expand Down Expand Up @@ -105,8 +105,8 @@ async fn test_follows_next_links_during_unfold() {
let with_next = ResponseTemplate::new(200)
.set_delay(Duration::from_secs(1))
.append_header(
HeaderName::from_bytes("link".as_bytes().to_vec()).unwrap(),
HeaderValue::from_bytes(next_url.into_bytes()).unwrap(),
HeaderName::from_bytes("link".as_bytes()).unwrap(),
HeaderValue::from_bytes(next_url.as_bytes()).unwrap(),
)
.set_body_json(vec![empty_issue(), empty_issue()]);

Expand Down Expand Up @@ -343,9 +343,9 @@ async fn test_does_not_follow_redirects() {
ResponseTemplate::new(302)
.set_delay(Duration::from_secs(1))
.append_header(
HeaderName::from_bytes("Location".as_bytes().to_vec()).unwrap(),
HeaderName::from_bytes("Location".as_bytes()).unwrap(),
HeaderValue::from_bytes(
format!("{}{}", server.uri(), download_path).into_bytes(),
format!("{}{}", server.uri(), download_path).as_bytes(),
)
.unwrap(),
)
Expand All @@ -371,12 +371,13 @@ async fn test_does_not_follow_redirects() {

mem::drop(server);

assert!(res
.unwrap()
.headers
.get("Location")
.unwrap()
.to_str()
.unwrap()
.ends_with("/fake-download-path"));
assert!(
res.unwrap()
.headers
.get("Location")
.unwrap()
.to_str()
.unwrap()
.ends_with("/fake-download-path")
);
}