Skip to content

Commit

Permalink
feat: rover persisted-queries publish (#1599)
Browse files Browse the repository at this point in the history
Co-authored-by: David Glasser <[email protected]>
  • Loading branch information
EverlastingBugstopper and glasser authored Jun 8, 2023
1 parent 373da09 commit f6166d5
Show file tree
Hide file tree
Showing 29 changed files with 760 additions and 20 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license-file = "./LICENSE"
name = "rover"
readme = "README.md"
repository = "https://github.com/apollographql/rover/"
version = "0.14.2"
version = "0.15.0-alpha.1"
default-run = "rover"

publish = false
Expand Down
2 changes: 1 addition & 1 deletion crates/rover-client/.schema/hash.id

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

2 changes: 1 addition & 1 deletion crates/rover-client/.schema/last_run.uuid

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

26 changes: 26 additions & 0 deletions crates/rover-client/.schema/schema.graphql

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

6 changes: 3 additions & 3 deletions crates/rover-client/package-lock.json

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

16 changes: 13 additions & 3 deletions crates/rover-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ pub enum RoverClientError {
msg: String,
},

/// Tried to build a [HeaderMap] with an invalid header name.
/// Tried to build a [`HeaderMap`] with an invalid header name.
#[error("Invalid header name")]
InvalidHeaderName(#[from] reqwest::header::InvalidHeaderName),

/// Tried to build a [HeaderMap] with an invalid header value.
/// Tried to build a [`HeaderMap`] with an invalid header value.
#[error("Invalid header value")]
InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),

Expand Down Expand Up @@ -87,6 +87,10 @@ pub enum RoverClientError {
#[error("Could not find graph with name \"{graph_ref}\"")]
GraphNotFound { graph_ref: GraphRef },

/// when someone provides a graph ID that doesn't exist.
#[error("Could not find graph with ID \"{graph_id}\"")]
GraphIdNotFound { graph_id: String },

/// if someone attempts to get a core schema from a supergraph that has
/// no successful build in the API, we return this error.
#[error("No supergraph SDL exists for \"{graph_ref}\" because its subgraphs failed to build.")]
Expand Down Expand Up @@ -198,7 +202,7 @@ pub enum RoverClientError {
#[error("The input provided is invalid")]
InvalidInputError { graph_ref: GraphRef },

#[error("You don't have the required permissions to perform this operation")]
#[error("You don't have the required permissions to perform this operation: {msg}.")]
PermissionError { msg: String },

#[error(
Expand All @@ -214,6 +218,12 @@ pub enum RoverClientError {
subgraph_name: String,
graph_ref: GraphRef,
},

#[error("Could not find a persisted query list linked to {graph_ref}.")]
NoPersistedQueryList {
graph_ref: GraphRef,
frontend_url_root: String,
},
}

fn contract_publish_errors_msg(msgs: &Vec<String>, no_launch: &bool) -> String {
Expand Down
3 changes: 3 additions & 0 deletions crates/rover-client/src/operations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ pub mod subgraph;
/// all rover-client functionality for the "supergraph" commands in rover
pub mod supergraph;

/// all rover-client functionality for the "persisted-queries" commands in rover
pub mod persisted_queries;

/// all rover config-related functionality
pub mod config;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# All fields in this query must be accessible by the `PERSISTED_QUERY_PUBLISHER` role
query DescribePersistedQueryListQuery($graphId: ID!, $variant: String!) {
frontendUrlRoot
graph(id: $graphId) {
variant(name: $variant) {
persistedQueryList {
id
}
}
variants {
name
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod runner;
mod types;

pub use runner::run;
pub use types::{DescribePQLInput, DescribePQLResponse};
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use super::types::{DescribePQLInput, DescribePQLResponse};
use crate::blocking::StudioClient;
use crate::shared::GraphRef;
use crate::RoverClientError;
use graphql_client::*;

#[derive(GraphQLQuery, Debug)]
// 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/operations/persisted_queries/describe_pql/describe_pql_query.graphql",
schema_path = ".schema/schema.graphql",
response_derives = "Eq, PartialEq, Debug, Serialize, Deserialize",
deprecated = "warn"
)]
pub struct DescribePersistedQueryListQuery;

pub fn run(
input: DescribePQLInput,
client: &StudioClient,
) -> Result<DescribePQLResponse, RoverClientError> {
let graph_ref = input.graph_ref.clone();
let data = client.post::<DescribePersistedQueryListQuery>(input.into())?;
build_response(data, graph_ref)
}

fn build_response(
data: describe_persisted_query_list_query::ResponseData,
graph_ref: GraphRef,
) -> Result<DescribePQLResponse, RoverClientError> {
let graph = data.graph.ok_or(RoverClientError::GraphNotFound {
graph_ref: graph_ref.clone(),
})?;

let valid_variants = graph
.variants
.iter()
.map(|variant| variant.name.clone())
.collect();

let variant = graph.variant.ok_or(RoverClientError::NoSchemaForVariant {
graph_ref: graph_ref.clone(),
valid_variants,
frontend_url_root: data.frontend_url_root.clone(),
})?;

if let Some(list) = variant.persisted_query_list {
Ok(DescribePQLResponse {
graph_ref,
id: list.id,
})
} else {
Err(RoverClientError::NoPersistedQueryList {
graph_ref,
frontend_url_root: data.frontend_url_root,
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::operations::persisted_queries::describe_pql::runner::describe_persisted_query_list_query;
use crate::shared::GraphRef;

type QueryVariables = describe_persisted_query_list_query::Variables;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DescribePQLInput {
pub graph_ref: GraphRef,
}

impl From<DescribePQLInput> for QueryVariables {
fn from(input: DescribePQLInput) -> Self {
Self {
graph_id: input.graph_ref.name,
variant: input.graph_ref.variant,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DescribePQLResponse {
pub graph_ref: GraphRef,
pub id: String,
}
2 changes: 2 additions & 0 deletions crates/rover-client/src/operations/persisted_queries/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod describe_pql;
pub mod publish;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod runner;
mod types;

pub use runner::run;
pub use types::{
PersistedQueriesOperationCounts, PersistedQueriesPublishInput, PersistedQueriesPublishResponse,
PersistedQueryManifest, PersistedQueryPublishOperationResult,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
mutation PublishOperationsMutation($graphId: ID!, $listId: ID!, $operationManifest: [PersistedQueryInput!]) {
graph(id: $graphId) {
persistedQueryList(id: $listId) {
publishOperations(operations: $operationManifest) {
__typename
... on PermissionError {
message
}
... on PublishOperationsResult {
build {
revision
publish {
operationCounts {
added
identical
updated
unaffected
removed
}
}
list {
name
}
}
unchanged
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::blocking::StudioClient;
use crate::operations::persisted_queries::publish::{
PersistedQueriesOperationCounts, PersistedQueriesPublishInput, PersistedQueriesPublishResponse,
PersistedQueryPublishOperationResult,
};
use crate::RoverClientError;
use graphql_client::*;

type GraphQLDocument = String;

#[derive(GraphQLQuery, Debug)]
// 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/operations/persisted_queries/publish/publish_mutation.graphql",
schema_path = ".schema/schema.graphql",
response_derives = "Eq, PartialEq, Debug, Serialize, Deserialize",
deprecated = "warn"
)]
pub struct PublishOperationsMutation;

pub fn run(
input: PersistedQueriesPublishInput,
client: &StudioClient,
) -> Result<PersistedQueriesPublishResponse, RoverClientError> {
let graph_id = input.graph_id.clone();
let list_id = input.list_id.clone();
let total_operations = input.operation_manifest.operations.len();
let data = client.post::<PublishOperationsMutation>(input.into())?;
build_response(data, graph_id, list_id, total_operations)
}

fn build_response(
data: publish_operations_mutation::ResponseData,
graph_id: String,
list_id: String,
total_published_operations: usize,
) -> Result<PersistedQueriesPublishResponse, RoverClientError> {
let graph = data.graph.ok_or(RoverClientError::GraphIdNotFound {
graph_id: graph_id.clone(),
})?;

match graph.persisted_query_list.publish_operations {
PersistedQueryPublishOperationResult::PermissionError(error) => {
Err(RoverClientError::PermissionError { msg: error.message })
}
PersistedQueryPublishOperationResult::PublishOperationsResult(result) => {
Ok(PersistedQueriesPublishResponse {
revision: result.build.revision,
graph_id,
list_id,
total_published_operations,
list_name: result.build.list.name,
unchanged: result.unchanged,
operation_counts: PersistedQueriesOperationCounts {
added: result.build.publish.operation_counts.added,
updated: result.build.publish.operation_counts.updated,
removed: result.build.publish.operation_counts.removed,
identical: result.build.publish.operation_counts.identical,
unaffected: result.build.publish.operation_counts.unaffected,
},
})
}
}
}
Loading

0 comments on commit f6166d5

Please sign in to comment.