Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added check-suites endpoints #596

Merged
merged 50 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
51b7789
added /repos/{owner}/{repo}/check-suites
dmgorsky Jan 23, 2024
7d5d3f8
added /repos/{owner}/{repo}/check-suites/preferences
dmgorsky Feb 17, 2024
ee242ba
added /repos/{owner}/{repo}/check-suites/{check_suite_id}
dmgorsky Feb 18, 2024
1609698
added rerequest check [run/suite]
dmgorsky Mar 6, 2024
c1ebe7d
added 'list check run annotations'
dmgorsky Mar 6, 2024
6e6685e
added "List check suites for a Git reference"
dmgorsky Mar 6, 2024
b4db49c
added query parameters
dmgorsky Mar 6, 2024
26f6d77
fixed `cargo fmt --all`
dmgorsky Mar 6, 2024
4b4c4d6
fixed timeout methods not being feature gated (#519)
CommanderStorm Jan 15, 2024
3840a12
chore: release (#520)
github-actions[bot] Jan 15, 2024
a9b66fc
Added a test for `repos().is_collaborator()`. The 204 case is good! (…
manchicken Jan 22, 2024
5b920a4
Resolving issue with deleting reactions from issues. (#555)
manchicken Jan 24, 2024
778f355
chore: release (#554)
github-actions[bot] Jan 24, 2024
be77e74
Tests for locking and unlocking issue comments (#557)
manchicken Jan 26, 2024
5a62a99
Handle redirects in ReleasesHandler::stream_asset(). (#556)
korran Jan 26, 2024
c46953d
chore: release (#558)
github-actions[bot] Jan 26, 2024
cadf2ef
Added tests for `repos().merges()` (#560)
manchicken Feb 4, 2024
c78018c
Don't send Authorization headers to third-party services. (#562)
korran Feb 6, 2024
29114ab
chore: release (#561)
github-actions[bot] Feb 6, 2024
71e8a8e
Upgrade http/hyper 1.0 (#564)
Hakuyume Feb 7, 2024
872f509
chore: release (#565)
github-actions[bot] Feb 7, 2024
6a6b58d
Fixed `issues().delete_comment_reaction()` (#566)
manchicken Feb 8, 2024
abfe952
Adding test for `issues().delete_comment()` (#569)
manchicken Feb 9, 2024
9f76b0b
Added tests to prove `repos().secrets().delete_secret()` (#570)
manchicken Feb 9, 2024
4cc38f5
chore: release (#567)
github-actions[bot] Feb 12, 2024
d720e7d
Added a test (#577)
manchicken Feb 15, 2024
9d3ffa2
Added some more tests (#578)
manchicken Feb 15, 2024
fb43fa6
Fixing the test that `[email protected]` breaks. (#579)
manchicken Feb 15, 2024
054859e
Fixing `snafu` version update (#580)
manchicken Feb 15, 2024
a9789a3
Adding test for actions().actions_delete_workflow_run_logs_test() (#584)
manchicken Feb 22, 2024
8b7df0b
Added more tests, for `repos().delete()` (#585)
manchicken Feb 23, 2024
32b4374
Fixed the `projects().delete_project().send() function (#587)
manchicken Feb 23, 2024
ae93e91
Adding tests for `actions().remove_selected_repo_from_org_secret()` (…
manchicken Feb 23, 2024
ee1c893
Add Public and Release events (#589)
LuaKT Feb 27, 2024
41b423d
Update base64 requirement from 0.21.0 to 0.22.0 (#592)
dependabot[bot] Mar 4, 2024
2f83d8b
chore: release (#581)
github-actions[bot] Mar 4, 2024
473c061
Adding tests to `orgs().secrets().create_or_update_secret()` (#590)
manchicken Mar 5, 2024
5a9b0ca
Add delete_ref in RepoHandler (#573)
tniessen Mar 5, 2024
ed128e1
chore: release (#593)
github-actions[bot] Mar 5, 2024
28b333e
rebased to actual; fixed Response<Body>
dmgorsky Mar 6, 2024
684eb5a
added /repos/{owner}/{repo}/check-suites
dmgorsky Jan 23, 2024
a791763
added /repos/{owner}/{repo}/check-suites/preferences
dmgorsky Feb 17, 2024
a7360aa
added /repos/{owner}/{repo}/check-suites/{check_suite_id}
dmgorsky Feb 18, 2024
2bf1903
added rerequest check [run/suite]
dmgorsky Mar 6, 2024
cfe6ef5
added 'list check run annotations'
dmgorsky Mar 6, 2024
a82807d
added "List check suites for a Git reference"
dmgorsky Mar 6, 2024
0508fe8
added query parameters
dmgorsky Mar 6, 2024
0928b10
fixed `cargo fmt --all`
dmgorsky Mar 6, 2024
08cfcab
rebased to actual; fixed Response<Body>
dmgorsky Mar 6, 2024
d0c0e4f
Merge remote-tracking branch 'origin/feature/checks' into feature/checks
dmgorsky Mar 6, 2024
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
418 changes: 415 additions & 3 deletions src/api/checks.rs

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions src/models/checks.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::models::workflows::HeadCommit;

use super::*;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -32,3 +34,52 @@ pub struct ListCheckRuns {
pub total_count: u64,
pub check_runs: Vec<CheckRun>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CheckSuite {
pub id: CheckSuiteId,
pub node_id: String,
pub head_branch: String,
pub head_sha: String,
pub status: Option<String>,
pub conclusion: Option<String>,
pub url: String,
pub before: String,
pub after: String,
app: Option<App>,
pub repository: Repository,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
pub head_commit: HeadCommit,
latest_check_runs_count: i64,
check_runs_url: String,
rerequestable: Option<bool>,
runs_rerequestable: Option<bool>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ListCheckSuites {
pub total_count: u32,
pub check_suites: Vec<CheckSuite>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CheckSuitePreferences {
pub preferences: CheckSuiteUpdatePreferences,
pub repository: Repository,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CheckSuiteUpdatePreferences {
pub auto_trigger_checks: Vec<AutoTriggerCheck>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AutoTriggerCheck {
/// Enables or disables automatic creation of CheckSuite events upon pushes to the repository.
pub app_id: AppId,
pub setting: bool,
}
20 changes: 20 additions & 0 deletions src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,26 @@ pub mod checks {
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<String>,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct CheckRunAnnotation {
pub path: String,
pub start_line: u32,
pub end_line: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_column: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_column: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub annotation_level: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub raw_details: Option<String>,
pub blob_href: String,
}
}

pub mod issues {
Expand Down
255 changes: 255 additions & 0 deletions tests/check_suites.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
use wiremock::{
matchers::{method, path},
Mock, MockServer, ResponseTemplate,
};

use mock_error::setup_error_handler;
use octocrab::models::checks::{AutoTriggerCheck, CheckSuite, CheckSuitePreferences};
use octocrab::models::{AppId, CheckRunId, CheckSuiteId};
use octocrab::params::repos::Commitish;
use octocrab::Octocrab;

/// Unit test for calls to the `/repos/OWNER/REPO/contributors` endpoint
mod mock_error;

const OWNER: &str = "XAMPPRocky";
const REPO: &str = "octocrab";

async fn setup_api(template: ResponseTemplate) -> MockServer {
let mock_server = MockServer::start().await;

Mock::given(method("POST"))
.and(path(format!("/repos/{OWNER}/{REPO}/check-suites")))
.respond_with(template)
.mount(&mock_server)
.await;
setup_error_handler(
&mock_server,
"POST on /repos/OWNER/REPO/check-suites not called",
)
.await;
mock_server
}

fn setup_octocrab(uri: &str) -> Octocrab {
Octocrab::builder().base_uri(uri).unwrap().build().unwrap()
}

#[tokio::test]
async fn should_create_check_suite() {
let check_suite_response: CheckSuite =
serde_json::from_str(include_str!("resources/check_suite.json")).unwrap();
let template = ResponseTemplate::new(200).set_body_json(&check_suite_response);
let mock_server = setup_api(template).await;
let client = setup_octocrab(&mock_server.uri());

let head_sha = "d6fde92930d4715a2b49857d24b940956b26d2d3";
let result = client
.checks(OWNER, REPO)
.create_check_suite(head_sha)
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);

let check_suite = result.unwrap();

assert_eq!(check_suite.head_sha, head_sha);
}

#[tokio::test]
async fn should_patch_check_suite_preferences() {
// mock infrastructure
let mock_server = MockServer::start().await;
let check_suite_response: CheckSuitePreferences =
serde_json::from_str(include_str!("resources/check_suite_preferences.json")).unwrap();
let response = ResponseTemplate::new(200).set_body_json(&check_suite_response);

let mock = Mock::given(method("PATCH"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/check-suites/preferences"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());
// fixture
let check_suite_patches = vec![AutoTriggerCheck {
app_id: AppId(42),
setting: true,
}];

let result = client
.checks(OWNER, REPO) // though, mocking here 'octocat' / 'Hello-World'
.update_preferences(check_suite_patches)
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
let upd_pref_result = result.unwrap();
assert_eq!(upd_pref_result.preferences.auto_trigger_checks.len(), 2);
}

#[tokio::test]
async fn should_get_check_suite() {
// mock infrastructure
let mock_server = MockServer::start().await;
let check_suite_response: CheckSuite =
serde_json::from_str(include_str!("resources/check_suite.json")).unwrap();
let response = ResponseTemplate::new(200).set_body_json(&check_suite_response);

const CHECK_SUITE_ID: i32 = 5;
let mock = Mock::given(method("GET"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/check-suites/{CHECK_SUITE_ID}"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());

let result = client
.checks(OWNER, REPO)
.get_check_suite(CheckSuiteId(5))
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
let get_cs_result = result.unwrap();
assert_eq!(get_cs_result.id, CheckSuiteId(5));
}

#[tokio::test]
async fn should_trigger_rerequest_check_suite() {
// mock infrastructure
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(201);

const CHECK_SUITE_ID: i32 = 42;
let mock = Mock::given(method("POST"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/check-suites/{CHECK_SUITE_ID}/rerequest"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());

let result = client
.checks(OWNER, REPO)
.rerequest_check_suite(CheckSuiteId(42))
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
}

#[tokio::test]
async fn should_trigger_rerequest_check_run() {
// mock infrastructure
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(201).set_body_string("");

const CHECK_RUN_ID: i32 = 42;
let mock = Mock::given(method("POST"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/check-runs/{CHECK_RUN_ID}/rerequest"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());

let result = client
.checks(OWNER, REPO)
.rerequest_check_run(CheckRunId(42))
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
}

#[tokio::test]
async fn should_list_annotations() {
// mock infrastructure
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(200)
.set_body_string(include_str!("resources/check_run_annotations.json"));

const CHECK_RUN_ID: i32 = 42;
let mock = Mock::given(method("GET"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/check-runs/{CHECK_RUN_ID}/annotations"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());

let result = client
.checks(OWNER, REPO)
.list_annotations(CheckRunId(42))
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
let list_annotations_result = result.unwrap();
assert_eq!(list_annotations_result.len(), 1);
}

#[tokio::test]
async fn should_list_check_suites_for_ref() {
// mock infrastructure
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(200)
.set_body_string(include_str!("resources/list_check_suites_for_ref.json"));

const COMMIT: &str = "42";
let mock = Mock::given(method("GET"))
.and(path(format!(
"/repos/{OWNER}/{REPO}/commits/{COMMIT}/check-suites"
)))
.respond_with(response.clone());
mock_server.register(mock).await;
let client = setup_octocrab(&mock_server.uri());

let result = client
.checks(OWNER, REPO)
.list_check_suites_for_git_ref(Commitish(String::from("42")))
.send()
.await;

assert!(
result.is_ok(),
"expected successful result, got error: {:#?}",
result
);
let list_check_suites_for_ref_result = result.unwrap();
assert_eq!(
list_check_suites_for_ref_result.total_count as u32,
list_check_suites_for_ref_result.check_suites.len() as u32
);
assert_eq!(
list_check_suites_for_ref_result.check_suites[0].id,
CheckSuiteId(5)
);
}
14 changes: 14 additions & 0 deletions tests/resources/check_run_annotations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"path": "README.md",
"start_line": 2,
"end_line": 2,
"start_column": 5,
"end_column": 10,
"annotation_level": "warning",
"title": "Spell Checker",
"message": "Check your spelling for 'banaas'.",
"raw_details": "Do you mean 'bananas' or 'banana'?",
"blob_href": "https://api.github.com/repos/github/rest-api-description/git/blobs/abc"
}
]
Loading
Loading