Skip to content

Commit

Permalink
feat(rover): checks
Browse files Browse the repository at this point in the history
  • Loading branch information
EverlastingBugstopper committed Dec 7, 2020
1 parent 036eedd commit b128a40
Show file tree
Hide file tree
Showing 31 changed files with 9,094 additions and 39 deletions.
126 changes: 124 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ binstall = { path = "./installers/binstall" }
anyhow = "1.0.31"
atty = "0.2.14"
console = "0.13.0"
prettytable-rs = "0.8.0"
serde = "1.0"
serde_json = "1.0"
structopt = "0.3.15"
url = "2.1.1"
tracing = "0.1.21"
url = "2.1.1"

[dev-dependencies]
assert_cmd = "1.0.1"
Expand Down
1 change: 1 addition & 0 deletions crates/rover-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ graphql_client = "0.9"
http = "0.2"
reqwest = { version = "0.10", features = ["json", "blocking", "native-tls-vendored"] }
thiserror = "1.0"
tracing = "0.1"
serde = "1"
serde_json = "1.0.57"
7 changes: 1 addition & 6 deletions crates/rover-client/src/blocking/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,7 @@ impl Client {
pub fn handle_response<Q: graphql_client::GraphQLQuery>(
response: reqwest::blocking::Response,
) -> Result<Q::ResponseData, RoverClientError> {
let response_body: graphql_client::Response<Q::ResponseData> =
response
.json()
.map_err(|_| RoverClientError::HandleResponse {
msg: String::from("failed to parse response JSON"),
})?;
let response_body: graphql_client::Response<Q::ResponseData> = response.json()?;

if let Some(errs) = response_body.errors {
return Err(RoverClientError::GraphQL {
Expand Down
10 changes: 9 additions & 1 deletion crates/rover-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub enum RoverClientError {
#[error("invalid header value")]
InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),

/// Invalid JSON in response body.
#[error("could not parse JSON")]
InvalidJSON(#[from] serde_json::Error),

/// Encountered an error handling the received response.
#[error("encountered an error handling the response: {msg}")]
HandleResponse {
Expand All @@ -32,9 +36,13 @@ pub enum RoverClientError {
#[error("The response from the server was malformed. There was no data found in the reponse body. This is likely an error in GraphQL execution")]
NoData,

/// when someone provides a bad service/variant combingation or isn't
/// when someone provides a bad service/variant combination or isn't
/// validated properly, we don't know which reason is at fault for data.service
/// being empty, so this error tells them to check both.
#[error("No service found. Either the service/variant combination wasn't found or your API key is invalid.")]
NoService,

/// The API returned an invalid ChangeSeverity value
#[error("Invalid ChangeSeverity.")]
InvalidSeverity,
}
35 changes: 35 additions & 0 deletions crates/rover-client/src/query/graph/check.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
mutation CheckSchemaQuery(
$graphId: ID!
$variant: String
$schema: String
) {
service(id: $graphId) {
checkSchema(
proposedSchemaDocument: $schema
baseSchemaTag: $variant
) {
targetUrl
diffToPrevious {
severity
affectedClients {
__typename
}
affectedQueries {
__typename
}
numberOfCheckedOperations
changes {
severity
code
description
}
validationConfig {
from
to
queryCountThreshold
queryCountThresholdPercentage
}
}
}
}
}
76 changes: 76 additions & 0 deletions crates/rover-client/src/query/graph/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use crate::blocking::StudioClient;
use crate::RoverClientError;
use graphql_client::*;

use reqwest::Url;

type Timestamp = String;

#[derive(GraphQLQuery)]
// The paths are relative to the directory where your `Cargo.toml` is located.
// Both json and the GraphQL schema language are supported as sources for the schema
#[graphql(
query_path = "src/query/graph/check.graphql",
schema_path = "schema.graphql",
response_derives = "PartialEq, Debug, Serialize, Deserialize",
deprecated = "warn"
)]
/// This struct is used to generate the module containing `Variables` and
/// `ResponseData` structs.
/// Snake case of this name is the mod name. i.e. check_schema_query
pub struct CheckSchemaQuery;

/// The main function to be used from this module.
/// This function takes a proposed schema and validates it against a pushed
/// schema.
pub fn run(
variables: check_schema_query::Variables,
client: &StudioClient,
) -> Result<CheckResponse, RoverClientError> {
let data = client.post::<CheckSchemaQuery>(variables)?;
get_check_response_from_data(data)
}

#[derive(Debug)]
pub struct CheckResponse {
pub target_url: Option<Url>,
pub number_of_checked_operations: i64,
pub change_severity: check_schema_query::ChangeSeverity,
pub changes: Vec<check_schema_query::CheckSchemaQueryServiceCheckSchemaDiffToPreviousChanges>,
}

fn get_check_response_from_data(
data: check_schema_query::ResponseData,
) -> Result<CheckResponse, RoverClientError> {
tracing::debug!("{:#?}", &data);
let service = data.service.ok_or(RoverClientError::NoService)?;
let target_url = get_url(service.check_schema.target_url);

let diff_to_previous = service.check_schema.diff_to_previous;

let number_of_checked_operations = diff_to_previous.number_of_checked_operations.unwrap_or(0);

let change_severity = diff_to_previous.severity;
let changes = diff_to_previous.changes;

Ok(CheckResponse {
target_url,
number_of_checked_operations,
change_severity,
changes,
})
}

fn get_url(url: Option<String>) -> Option<Url> {
match url {
Some(url) => {
let url = Url::parse(&url);
match url {
Ok(url) => Some(url),
// if the API returns an invalid URL, don't put it in the response
Err(_) => None,
}
}
None => None,
}
}
Loading

0 comments on commit b128a40

Please sign in to comment.