Skip to content

Commit

Permalink
Added check-suites endpoints (#596)
Browse files Browse the repository at this point in the history
* added /repos/{owner}/{repo}/check-suites

* added /repos/{owner}/{repo}/check-suites/preferences

* added /repos/{owner}/{repo}/check-suites/{check_suite_id}

* added rerequest check [run/suite]

* added 'list check run annotations'

* added "List check suites for a Git reference"

* added query parameters

* fixed `cargo fmt --all`

* fixed timeout methods not being feature gated (#519)

* fixed timeout methods not being feature gated

* removed the `timeout` feature gate as requested

* Revert "removed the `timeout` feature gate as requested"

This reverts commit 6024850.

* chore: release (#520)

* Added a test for `repos().is_collaborator()`. The 204 case is good! (#553)

* Resolving issue with deleting reactions from issues. (#555)

* Resolving issue with deleting reactions from issues.
Issue: manchicken#182

* Reverting changes to CHANGELOG.md since that's automated.

* chore: release (#554)

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Tests for locking and unlocking issue comments (#557)

* Handle redirects in ReleasesHandler::stream_asset(). (#556)

* chore: release (#558)

* Added tests for `repos().merges()` (#560)

* Don't send Authorization headers to third-party services. (#562)

* chore: release (#561)

* Upgrade http/hyper 1.0 (#564)

* chore: release (#565)

* Fixed `issues().delete_comment_reaction()` (#566)

- Added a test for 204 and 500 cases
- Fixed broken functionality in the 204 case.

* Adding test for `issues().delete_comment()` (#569)

* Added tests to prove `repos().secrets().delete_secret()` (#570)

- Added test for 204 case
- Added test for 500 case

* chore: release (#567)

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Added a test (#577)

- Update case of `repos().secrets().create_or_update_secret()` test added

* Added some more tests (#578)

- `repos().issues().check_assignee()`
  - Covers 204 case
  - Covers 404 case
  - Covers 500 case

* Fixing the test that `wiremock@v0.6.0` breaks. (#579)

- Updated wiremock to 0.6.0
- Fixed the one test broken by the update

* Fixing `snafu` version update (#580)

* Adding test for actions().actions_delete_workflow_run_logs_test() (#584)

* Added more tests, for `repos().delete()` (#585)

* Fixed the `projects().delete_project().send() function (#587)

* Adding tests for `actions().remove_selected_repo_from_org_secret()` (#586)

* Add Public and Release events (#589)

* Update base64 requirement from 0.21.0 to 0.22.0 (#592)

Updates the requirements on [base64](https://github.com/marshallpierce/rust-base64) to permit the latest version.
- [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md)
- [Commits](marshallpierce/rust-base64@v0.21.2...v0.22.0)

---
updated-dependencies:
- dependency-name: base64
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: release (#581)

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Adding tests to `orgs().secrets().create_or_update_secret()` (#590)

- Added 204 case

* Add delete_ref in RepoHandler (#573)

Fixes: #572

* chore: release (#593)

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* rebased to actual; fixed Response<Body>

* added /repos/{owner}/{repo}/check-suites

* added /repos/{owner}/{repo}/check-suites/preferences

* added /repos/{owner}/{repo}/check-suites/{check_suite_id}

* added rerequest check [run/suite]

* added 'list check run annotations'

* added "List check suites for a Git reference"

* added query parameters

* fixed `cargo fmt --all`

* rebased to actual; fixed Response<Body>

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Frank Elsinga <frank@elsinga.de>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mike Stemle <hello@mikestemle.com>
Co-authored-by: Kor Nielsen <korn@xdas.com>
Co-authored-by: Kor Nielsen <kor@google.com>
Co-authored-by: Toru Ogawa <Hakuyume@users.noreply.github.com>
Co-authored-by: Evan Graham <me@luakt.net>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
10 people authored Mar 7, 2024
1 parent f4a7fb5 commit 44ef7d4
Show file tree
Hide file tree
Showing 8 changed files with 1,477 additions and 3 deletions.
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

0 comments on commit 44ef7d4

Please sign in to comment.