Skip to content

Commit cc9cd88

Browse files
authored
feat: adds readme fetch and readme publish (#1128)
adds the following: - `readme`, `readme::fetch` and `readme::publish` modules to `rover-client/src/operations` and `src/command` - tests inside `crates/rover-client/src/operations/readme/{fetch|publish}/runner.rs` - types `RoverOutput::ReadmeFetchResponse`, `ReadmeFetchInput`, `ReadmePublishResponse`, `ReadmePublishInput`.
1 parent 85d78d7 commit cc9cd88

File tree

16 files changed

+512
-1
lines changed

16 files changed

+512
-1
lines changed

crates/rover-client/src/operations/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/// all rover-client functionality for the "graph" commands in rover
22
pub mod graph;
33

4+
/// all rover-client functionality for the "readme" commands in rover
5+
pub mod readme;
6+
47
/// all rover-client functionality for the "subgraph" commands in rover
58
pub mod subgraph;
69

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
query ReadmeFetchQuery($graph_id: ID!, $variant: String!) {
2+
frontendUrlRoot
3+
graph(id: $graph_id) {
4+
variant(name: $variant) {
5+
readme {
6+
content
7+
lastUpdatedTime
8+
}
9+
}
10+
variants {
11+
name
12+
}
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod runner;
2+
mod types;
3+
4+
pub use runner::run;
5+
pub use types::ReadmeFetchInput;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use super::types::ReadmeFetchResponse;
2+
use crate::blocking::StudioClient;
3+
use crate::operations::readme::fetch::ReadmeFetchInput;
4+
use crate::shared::GraphRef;
5+
use crate::RoverClientError;
6+
use graphql_client::*;
7+
8+
type Timestamp = String;
9+
10+
#[derive(GraphQLQuery, Debug)]
11+
// The paths are relative to the directory where your `Cargo.toml` is located.
12+
// Both json and the GraphQL schema language are supported as sources for the schema
13+
#[graphql(
14+
query_path = "src/operations/readme/fetch/fetch_query.graphql",
15+
schema_path = ".schema/schema.graphql",
16+
response_derives = "PartialEq, Debug, Serialize, Deserialize",
17+
deprecated = "warn"
18+
)]
19+
pub struct ReadmeFetchQuery;
20+
21+
pub fn run(
22+
input: ReadmeFetchInput,
23+
client: &StudioClient,
24+
) -> Result<ReadmeFetchResponse, RoverClientError> {
25+
let graph_ref = input.graph_ref.clone();
26+
let data = client.post::<ReadmeFetchQuery>(input.into())?;
27+
build_response(data, graph_ref)
28+
}
29+
30+
fn build_response(
31+
data: readme_fetch_query::ResponseData,
32+
graph_ref: GraphRef,
33+
) -> Result<ReadmeFetchResponse, RoverClientError> {
34+
let graph = data.graph.ok_or(RoverClientError::GraphNotFound {
35+
graph_ref: graph_ref.clone(),
36+
})?;
37+
38+
let valid_variants = graph.variants.iter().map(|it| it.name.clone()).collect();
39+
40+
let variant = graph.variant.ok_or(RoverClientError::NoSchemaForVariant {
41+
graph_ref: graph_ref.clone(),
42+
valid_variants,
43+
frontend_url_root: data.frontend_url_root,
44+
})?;
45+
46+
let readme = variant.readme;
47+
Ok(ReadmeFetchResponse {
48+
graph_ref,
49+
content: readme.content,
50+
last_updated_time: readme.last_updated_time,
51+
})
52+
}
53+
54+
#[cfg(test)]
55+
mod tests {
56+
use super::*;
57+
use crate::shared::GraphRef;
58+
use serde_json::json;
59+
60+
fn mock_graph_ref() -> GraphRef {
61+
GraphRef {
62+
name: "mygraph".to_string(),
63+
variant: "current".to_string(),
64+
}
65+
}
66+
67+
#[test]
68+
fn get_readme_from_response_data_works() {
69+
let last_updated_time = "2022-05-12T20:50:06.687276000Z";
70+
let json_response = json!({
71+
"frontendUrlRoot": "https://studio.apollographql.com",
72+
"graph": {
73+
"variant": {
74+
"readme": {
75+
"content": "this is a readme",
76+
"lastUpdatedTime": last_updated_time,
77+
},
78+
},
79+
"variants": []
80+
}
81+
});
82+
let data = serde_json::from_value(json_response).unwrap();
83+
let output = build_response(data, mock_graph_ref());
84+
85+
let expected_response = ReadmeFetchResponse {
86+
last_updated_time: Some(last_updated_time.to_string()),
87+
content: "this is a readme".to_string(),
88+
graph_ref: mock_graph_ref(),
89+
};
90+
assert!(output.is_ok());
91+
assert_eq!(output.unwrap(), expected_response);
92+
}
93+
94+
#[test]
95+
fn get_readme_from_response_data_errs_with_no_variant() {
96+
let json_response = json!({
97+
"frontendUrlRoot": "https://studio.apollographql.com",
98+
"graph": {
99+
"variant": null,
100+
"variants": []
101+
}});
102+
let data = serde_json::from_value(json_response).unwrap();
103+
let output = build_response(data, mock_graph_ref());
104+
assert!(output.is_err());
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use crate::operations::readme::fetch::runner::readme_fetch_query;
2+
use crate::shared::GraphRef;
3+
4+
type QueryVariables = readme_fetch_query::Variables;
5+
type Timestamp = String;
6+
7+
#[derive(Debug, Clone, PartialEq)]
8+
pub struct ReadmeFetchInput {
9+
pub graph_ref: GraphRef,
10+
}
11+
12+
impl From<ReadmeFetchInput> for QueryVariables {
13+
fn from(input: ReadmeFetchInput) -> Self {
14+
Self {
15+
graph_id: input.graph_ref.name,
16+
variant: input.graph_ref.variant,
17+
}
18+
}
19+
}
20+
21+
#[derive(Clone, Debug, PartialEq)]
22+
pub struct ReadmeFetchResponse {
23+
pub graph_ref: GraphRef,
24+
pub content: String,
25+
pub last_updated_time: Option<Timestamp>,
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// "readme fetch"
2+
pub mod fetch;
3+
4+
/// "readme publish"
5+
pub mod publish;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod runner;
2+
mod types;
3+
4+
pub use runner::run;
5+
pub use types::ReadmePublishInput;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
mutation ReadmePublishMutation($readme: String!, $variant: String!, $graphId: ID!) {
2+
graph(id: $graphId) {
3+
variant(name: $variant) {
4+
updateVariantReadme(readme: $readme) {
5+
readme {
6+
content
7+
lastUpdatedTime
8+
}
9+
}
10+
}
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use super::types::*;
2+
use crate::blocking::StudioClient;
3+
use crate::operations::readme::publish::ReadmePublishInput;
4+
use crate::shared::GraphRef;
5+
use crate::RoverClientError;
6+
use graphql_client::*;
7+
8+
type Timestamp = String;
9+
10+
#[derive(GraphQLQuery)]
11+
// The paths are relative to the directory where your `Cargo.toml` is located.
12+
// Both json and the GraphQL schema language are supported as sources for the schema
13+
#[graphql(
14+
query_path = "src/operations/readme/publish/publish_mutation.graphql",
15+
schema_path = ".schema/schema.graphql",
16+
response_derives = "PartialEq, Debug, Serialize, Deserialize",
17+
deprecated = "warn"
18+
)]
19+
20+
pub struct ReadmePublishMutation;
21+
22+
pub fn run(
23+
input: ReadmePublishInput,
24+
client: &StudioClient,
25+
) -> Result<ReadmePublishResponse, RoverClientError> {
26+
let graph_ref = input.graph_ref.clone();
27+
let response = client.post::<ReadmePublishMutation>(input.into())?;
28+
build_response(response, graph_ref)
29+
}
30+
31+
fn build_response(
32+
data: readme_publish_mutation::ResponseData,
33+
graph_ref: GraphRef,
34+
) -> Result<ReadmePublishResponse, RoverClientError> {
35+
let readme = data
36+
.graph
37+
.ok_or(RoverClientError::GraphNotFound {
38+
graph_ref: graph_ref.clone(),
39+
})?
40+
.variant
41+
.ok_or(RoverClientError::GraphNotFound {
42+
graph_ref: graph_ref.clone(),
43+
})?
44+
.update_variant_readme
45+
.ok_or(RoverClientError::MalformedResponse {
46+
null_field: "update_variant_readme".to_string(),
47+
})?
48+
.readme;
49+
Ok(ReadmePublishResponse {
50+
graph_ref,
51+
new_content: readme.content,
52+
last_updated_time: readme.last_updated_time,
53+
})
54+
}
55+
56+
#[cfg(test)]
57+
mod tests {
58+
use super::*;
59+
use crate::shared::GraphRef;
60+
use serde_json::json;
61+
62+
fn mock_graph_ref() -> GraphRef {
63+
GraphRef {
64+
name: "mygraph".to_string(),
65+
variant: "current".to_string(),
66+
}
67+
}
68+
69+
#[test]
70+
fn get_new_readme_from_response_data_works() {
71+
let content = "this is a readme";
72+
let last_updated_time = "2022-05-12T20:50:06.687276000Z";
73+
74+
let json_response = json!({
75+
"graph": {
76+
"variant": {
77+
"updateVariantReadme": {
78+
"readme": {
79+
"content": content,
80+
"lastUpdatedTime": last_updated_time,
81+
}
82+
}
83+
},
84+
}
85+
});
86+
let data = serde_json::from_value(json_response).unwrap();
87+
let graph_ref = mock_graph_ref();
88+
let output = build_response(data, graph_ref.clone());
89+
90+
let expected = ReadmePublishResponse {
91+
graph_ref,
92+
new_content: content.to_string(),
93+
last_updated_time: Some(last_updated_time.to_string()),
94+
};
95+
assert!(output.is_ok());
96+
assert_eq!(output.unwrap(), expected);
97+
}
98+
99+
#[test]
100+
fn get_readme_errs_with_no_variant() {
101+
let json_response = json!({ "graph": { "variant": null }});
102+
let data = serde_json::from_value(json_response).unwrap();
103+
let output = build_response(data, mock_graph_ref());
104+
assert!(output.is_err());
105+
}
106+
107+
#[test]
108+
fn null_update_variant_readme_errors() {
109+
let json_response = json!({
110+
"graph": {
111+
"variant": {
112+
"updateVariantReadme": null
113+
},
114+
}
115+
});
116+
let data = serde_json::from_value(json_response).unwrap();
117+
let output = build_response(data, mock_graph_ref());
118+
119+
assert!(output.is_err());
120+
}
121+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use crate::operations::readme::publish::runner::readme_publish_mutation;
2+
use crate::shared::GraphRef;
3+
4+
type QueryVariables = readme_publish_mutation::Variables;
5+
type Timestamp = String;
6+
7+
#[derive(Debug, Clone, PartialEq)]
8+
pub struct ReadmePublishInput {
9+
pub graph_ref: GraphRef,
10+
pub readme: String,
11+
}
12+
13+
impl From<ReadmePublishInput> for QueryVariables {
14+
fn from(input: ReadmePublishInput) -> Self {
15+
Self {
16+
graph_id: input.graph_ref.name,
17+
variant: input.graph_ref.variant,
18+
readme: input.readme,
19+
}
20+
}
21+
}
22+
23+
#[derive(Clone, Debug, PartialEq)]
24+
pub struct ReadmePublishResponse {
25+
pub graph_ref: GraphRef,
26+
pub new_content: String,
27+
pub last_updated_time: Option<Timestamp>,
28+
}

src/cli.rs

+4
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ impl Rover {
195195
Command::Graph(command) => {
196196
command.run(self.get_client_config()?, self.get_git_context()?)
197197
}
198+
Command::Readme(command) => command.run(self.get_client_config()?),
198199
Command::Subgraph(command) => {
199200
command.run(self.get_client_config()?, self.get_git_context()?)
200201
}
@@ -318,6 +319,9 @@ pub enum Command {
318319
/// Graph API schema commands
319320
Graph(command::Graph),
320321

322+
/// Readme commands
323+
Readme(command::Readme),
324+
321325
/// Subgraph schema commands
322326
Subgraph(command::Subgraph),
323327

src/command/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod fed2;
55
mod graph;
66
mod info;
77
mod install;
8+
mod readme;
89
mod subgraph;
910
mod supergraph;
1011
mod update;
@@ -19,6 +20,7 @@ pub use graph::Graph;
1920
pub use info::Info;
2021
pub use install::Install;
2122
pub use output::RoverOutput;
23+
pub use readme::Readme;
2224
pub use subgraph::Subgraph;
2325
pub use supergraph::Supergraph;
2426
pub use update::Update;

0 commit comments

Comments
 (0)