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

Enable Supergraph Output using the --output flag in rover dev #1887

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
8 changes: 5 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,11 @@ impl Rover {
match &self.command {
Command::Config(command) => command.run(self.get_client_config()?),
Command::Contract(command) => command.run(self.get_client_config()?),
Command::Dev(command) => {
command.run(self.get_install_override_path()?, self.get_client_config()?)
}
Command::Dev(command) => command.run(
self.get_install_override_path()?,
self.get_client_config()?,
&self.output_opts,
),
Command::Fed2(command) => command.run(self.get_client_config()?),
Command::Supergraph(command) => {
command.run(self.get_install_override_path()?, self.get_client_config()?)
Expand Down
1 change: 1 addition & 0 deletions src/command/dev/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io::prelude::*;
use anyhow::{Context, Error};
use apollo_federation_types::config::{FederationVersion, SupergraphConfig};
use camino::Utf8PathBuf;

use rover_std::{Emoji, Fs};

use crate::command::dev::do_dev::log_err_and_continue;
Expand Down
3 changes: 3 additions & 0 deletions src/command/dev/do_dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use super::router::RouterConfigHandler;
use super::Dev;

use crate::command::dev::protocol::FollowerMessage;
use crate::options::OutputOpts;
use crate::utils::client::StudioClientConfig;
use crate::{RoverError, RoverOutput, RoverResult};

Expand All @@ -22,6 +23,7 @@ impl Dev {
&self,
override_install_path: Option<Utf8PathBuf>,
client_config: StudioClientConfig,
output_opts: &OutputOpts,
) -> RoverResult<RoverOutput> {
self.opts
.plugin_opts
Expand All @@ -48,6 +50,7 @@ impl Dev {
follower_channel.clone(),
self.opts.plugin_opts.clone(),
router_config_handler,
output_opts,
)? {
eprintln!("{0}Do not run this command in production! {0}It is intended for local development.", Emoji::Warn);
let (ready_sender, ready_receiver) = sync_channel(1);
Expand Down
2 changes: 2 additions & 0 deletions src/command/dev/no_dev.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::Dev;
use crate::options::OutputOpts;
use crate::{utils::client::StudioClientConfig, RoverError, RoverOutput, RoverResult};
use anyhow::anyhow;
use camino::Utf8PathBuf;
Expand All @@ -8,6 +9,7 @@ impl Dev {
&self,
_override_install_path: Option<Utf8PathBuf>,
_client_config: StudioClientConfig,
_output_opts: &OutputOpts,
) -> RoverResult<RoverOutput> {
Err(RoverError::new(anyhow!(
"rover dev is not supported on this platform"
Expand Down
8 changes: 5 additions & 3 deletions src/command/dev/protocol/leader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use crate::{
router::{RouterConfigHandler, RouterRunner},
OVERRIDE_DEV_COMPOSITION_VERSION,
},
options::PluginOpts,
options::{OutputOpts, PluginOpts},
utils::client::StudioClientConfig,
RoverError, RoverErrorSuggestion, RoverResult, PKG_VERSION,
};

use anyhow::{anyhow, Context};
use apollo_federation_types::{
build::SubgraphDefinition,
Expand Down Expand Up @@ -57,6 +58,7 @@ impl LeaderSession {
follower_channel: FollowerChannel,
plugin_opts: PluginOpts,
router_config_handler: RouterConfigHandler,
output_opts: &OutputOpts,
) -> RoverResult<Option<Self>> {
let ipc_socket_addr = router_config_handler.get_ipc_address()?;
let router_socket_addr = router_config_handler.get_router_address();
Expand Down Expand Up @@ -91,12 +93,12 @@ impl LeaderSession {
plugin_opts.clone(),
override_install_path.clone(),
client_config.clone(),
router_config_handler.get_supergraph_schema_path(),
router_config_handler.get_supergraph_schema_path(output_opts.get_output_path()),
);

// create a [`RouterRunner`] that we will use to spawn the router when we have a successful composition
let mut router_runner = RouterRunner::new(
router_config_handler.get_supergraph_schema_path(),
router_config_handler.get_supergraph_schema_path(output_opts.get_output_path()),
router_config_handler.get_router_config_path(),
plugin_opts,
router_socket_addr,
Expand Down
7 changes: 5 additions & 2 deletions src/command/dev/router/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,11 @@ impl RouterConfigHandler {
}

/// The path to the composed supergraph schema
pub fn get_supergraph_schema_path(&self) -> Utf8PathBuf {
self.tmp_supergraph_schema_path.clone()
pub fn get_supergraph_schema_path(&self, output_path: Option<String>) -> Utf8PathBuf {
match output_path {
Some(path) => Utf8PathBuf::from(path),
_ => self.tmp_supergraph_schema_path.clone(),
}
}

/// The path to the patched router config YAML
Expand Down
23 changes: 21 additions & 2 deletions src/options/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use anyhow::Result;
use calm_io::{stderrln, stdoutln};
use camino::Utf8PathBuf;
use clap::{error::ErrorKind as ClapErrorKind, CommandFactory, Parser, ValueEnum};
use rover_std::{Emoji, Fs, Style};
use serde::Serialize;
use serde_json::{json, Value};

use rover_std::{Emoji, Fs, Style};

use crate::{
cli::{Rover, RoverOutputFormatKind},
RoverError, RoverOutput, RoverResult,
Expand Down Expand Up @@ -116,7 +117,7 @@ impl RoverPrinter for RoverError {
}
}

#[derive(Debug, Parser, Serialize)]
#[derive(Debug, Parser, Serialize, Clone)]
pub struct OutputOpts {
/// Specify Rover's format type
#[arg(long = "format", global = true)]
Expand Down Expand Up @@ -167,6 +168,24 @@ impl OutputOpts {
rover_command_output.write_or_print(self)
}

/// Get the path to the output file
pub fn get_output_path(&self) -> Option<String> {
let output_type = self.output_file.clone();
let b = match (&self.format_kind, output_type) {
(Some(RoverOutputFormatKind::Plain), Some(OutputOpt::File(path))) => {
RoverOutputDestination::File(path)
}
(Some(RoverOutputFormatKind::Json), Some(OutputOpt::File(path))) => {
RoverOutputDestination::File(path)
}
_ => RoverOutputDestination::Stdout,
};
match b {
RoverOutputDestination::File(path) => Some(path.into_string()),
_ => None,
}
}

/// Get the format (plain/json) and strategy (stdout/file)
pub fn get_format_and_strategy(&self) -> (RoverOutputFormatKind, RoverOutputDestination) {
let output_type = self.output_file.clone();
Expand Down
26 changes: 20 additions & 6 deletions xtask/src/tools/lychee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use lychee_lib::{
Result as LycheeResult, Uri,
};
use reqwest::StatusCode;
use std::sync::Arc;
use std::{collections::HashSet, fs, path::PathBuf, time::Duration};
use tokio::runtime::Runtime;
use tokio::sync::{OwnedSemaphorePermit, Semaphore};
use tokio_stream::StreamExt;

pub(crate) struct LycheeRunner {
Expand Down Expand Up @@ -37,6 +39,8 @@ impl LycheeRunner {
pub(crate) fn lint(&self) -> Result<()> {
crate::info!("Checking HTTP links in repository");

let semaphore = Arc::new(Semaphore::new(5));

let inputs: Vec<Input> = get_md_files()
.iter()
.map(|file| Input {
Expand All @@ -56,11 +60,16 @@ impl LycheeRunner {
.await
.collect::<LycheeResult<Vec<_>>>()
.await?;

let failed_link_futures: Vec<_> = links
.into_iter()
.map(|link| tokio::spawn(get_failed_request(lychee_client.clone(), link)))
.collect();
let mut failed_link_futures: Vec<_> = Vec::new();

for link in links {
let permit = semaphore.clone().acquire_owned().await.unwrap();
failed_link_futures.push(tokio::spawn(get_failed_request(
lychee_client.clone(),
link,
permit,
)));
}

let links_size = failed_link_futures.len();

Expand Down Expand Up @@ -88,11 +97,16 @@ impl LycheeRunner {
}
}

async fn get_failed_request(lychee_client: Client, link: Request) -> Option<Uri> {
async fn get_failed_request(
lychee_client: Client,
link: Request,
permit: OwnedSemaphorePermit,
) -> Option<Uri> {
let response = lychee_client
.check(link)
.await
.expect("could not execute lychee request");
drop(permit);
if response.status().is_failure() {
Some(response.1.uri)
} else {
Expand Down