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

feat: adds rover docs open and rover docs list #314

Merged
merged 1 commit into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ git2 = "0.13.17"
git-url-parse = "0.3.1"
heck = "0.3.2"
humantime = "2.1.0"
opener = "0.4.1"
os_info = "3.0"
prettytable-rs = "0.8.0"
serde = "1.0"
serde_json = "1.0"
structopt = "0.3.21"
tracing = "0.1.22"
regex = "1"
url = "2.2.0"
os_info = "3.0"

[dev-dependencies]
assert_cmd = "1.0.1"
assert_fs = "1.0.0"
reqwest = "0.11.1"
rustversion = "1.0.4"
serial_test = "0.5.0"
predicates = "1.0.5"
Expand Down
14 changes: 12 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use std::path::PathBuf;
#[derive(Debug, Serialize, StructOpt)]
#[structopt(name = "Rover", global_settings = &[structopt::clap::AppSettings::ColoredHelp], about = "
Rover - Your Graph Companion
Read the getting started guide: https://go.apollo.dev/r/start
Read the getting started guide by running:

$ rover docs open start

To begin working with Rover and to authenticate with Apollo Studio,
run the following command:
Expand All @@ -33,7 +35,9 @@ The most common commands from there are:
- rover graph check: Check for breaking changes in a local graph schema against a graph schema in the Apollo graph registry
- rover graph push: Push an updated graph schema to the Apollo graph registry

You can find full documentation for Rover here: https://go.apollo.dev/r/docs
You can open the full documentation for Rover by running:

$ rover docs open
")]
pub struct Rover {
#[structopt(subcommand)]
Expand Down Expand Up @@ -90,9 +94,14 @@ pub enum Command {
/// Federated schema/graph commands
Subgraph(command::Subgraph),

/// Interact with Rover's documentation
Docs(command::Docs),

/// Installs Rover
#[structopt(setting(structopt::clap::AppSettings::Hidden))]
Install(command::Install),

/// Get system information
#[structopt(setting(structopt::clap::AppSettings::Hidden))]
Info(command::Info),
}
Expand All @@ -103,6 +112,7 @@ impl Rover {
Command::Config(command) => {
command.run(self.get_rover_config()?, self.get_client_config()?)
}
Command::Docs(command) => command.run(),
Command::Graph(command) => {
command.run(self.get_client_config()?, self.get_git_context()?)
}
Expand Down
2 changes: 1 addition & 1 deletion src/command/config/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{anyhow, Result};
/// Running without the --profile flag will set an API key for
/// a profile named "default".
///
/// See https://go.apollo.dev/r/api-keys for more details on Apollo's API keys.
/// Run `rover docs open api-keys` for more details on Apollo's API keys.
pub struct Auth {
#[structopt(long = "profile", default_value = "default")]
#[serde(skip_serializing)]
Expand Down
17 changes: 17 additions & 0 deletions src/command/docs/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::{command::RoverStdout, Result};

use super::shortlinks;

use serde::Serialize;
use structopt::StructOpt;

#[derive(Debug, Serialize, StructOpt)]
pub struct List {}

impl List {
pub fn run(&self) -> Result<RoverStdout> {
Ok(RoverStdout::DocsList(
shortlinks::get_shortlinks_with_description(),
))
}
}
32 changes: 32 additions & 0 deletions src/command/docs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
mod list;
mod open;
pub mod shortlinks;

use serde::Serialize;
use structopt::StructOpt;

use crate::{command::RoverStdout, Result};

#[derive(Debug, Serialize, StructOpt)]
pub struct Docs {
#[structopt(subcommand)]
command: Command,
}

#[derive(Debug, Serialize, StructOpt)]
pub enum Command {
/// List all available docs links
List(list::List),

/// Open a docs link
Open(open::Open),
}

impl Docs {
pub fn run(&self) -> Result<RoverStdout> {
match &self.command {
Command::List(command) => command.run(),
Command::Open(command) => command.run(),
}
}
}
45 changes: 45 additions & 0 deletions src/command/docs/open.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::{anyhow, command::RoverStdout, Result};

use super::shortlinks;

use ansi_term::Colour::{Cyan, Yellow};
use serde::Serialize;
use structopt::StructOpt;

use std::process::Command;

#[derive(Debug, Serialize, StructOpt)]
pub struct Open {
#[structopt(name = "slug", default_value = "docs", possible_values = &shortlinks::possible_shortlinks())]
slug: String,
}

impl Open {
pub fn run(&self) -> Result<RoverStdout> {
let url = shortlinks::get_url_from_slug(&self.slug);
let yellow_browser_var = format!("{}", Yellow.normal().paint("$BROWSER"));
let cyan_url = format!("{}", Cyan.normal().paint(&url));

if let Some(browser_override) = std::env::var_os("BROWSER") {
eprintln!(
"Opening {} with the application specified by {}.",
&cyan_url, &yellow_browser_var
);
if let Err(e) = Command::new(&browser_override).arg(&url).status() {
Err(anyhow!(
"Couldn't open docs with {}: {}",
browser_override.to_string_lossy(),
e
))
} else {
Ok(())
}
} else {
eprintln!("Opening {} with your default browser. This can be overridden by setting the {} environment variable.", &cyan_url, &yellow_browser_var);
opener::open(&url)?;
Ok(())
}?;

Ok(RoverStdout::None)
}
}
50 changes: 50 additions & 0 deletions src/command/docs/shortlinks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
pub const URL_BASE: &str = "https://go.apollo.dev/r";

use std::collections::HashMap;

pub fn get_shortlinks_with_description() -> HashMap<&'static str, &'static str> {
let mut links = HashMap::new();
links.insert("docs", "Rover's Documentation Homepage");
links.insert("api-keys", "Understanding Apollo's API Keys");
links.insert("contributing", "Contributing to Rover");
links.insert("start", "Getting Started with Rover");
links
}

pub fn possible_shortlinks() -> Vec<&'static str> {
let mut res = Vec::new();
for (slug, _) in get_shortlinks_with_description() {
res.push(slug);
}
res
}

pub fn get_url_from_slug(slug: &str) -> String {
format!("{}/{}", URL_BASE, slug)
}

mod tests {
#[test]
fn can_make_shortlink_vec_from_map() {
let shortlinks = super::possible_shortlinks();
assert!(!shortlinks.is_empty())
}

#[test]
fn can_get_url_from_slug() {
let expected_link = "https://go.apollo.dev/r/start";
let actual_link = super::get_url_from_slug("start");
assert_eq!(expected_link, actual_link);
}

#[test]
fn each_url_is_valid() {
for link in super::possible_shortlinks() {
let url = super::get_url_from_slug(link);
assert!(reqwest::blocking::get(&url)
.unwrap()
.error_for_status()
.is_ok());
}
}
}
2 changes: 2 additions & 0 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod config;
mod docs;
mod graph;
mod info;
mod install;
mod output;
mod subgraph;

pub use config::Config;
pub use docs::Docs;
pub use graph::Graph;
pub use info::Info;
pub use install::Install;
Expand Down
15 changes: 15 additions & 0 deletions src/command/output.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::HashMap;
use std::fmt::Debug;

use ansi_term::Colour::Yellow;
use prettytable::{cell, row, Table};
use rover_client::query::subgraph::list::ListDetails;

Expand All @@ -13,6 +15,7 @@ use rover_client::query::subgraph::list::ListDetails;
/// return something that is not described well in this enum, it should be added.
#[derive(Clone, PartialEq, Debug)]
pub enum RoverStdout {
DocsList(HashMap<&'static str, &'static str>),
SDL(String),
SchemaHash(String),
SubgraphList(ListDetails),
Expand All @@ -23,6 +26,18 @@ pub enum RoverStdout {
impl RoverStdout {
pub fn print(&self) {
match self {
RoverStdout::DocsList(shortlinks) => {
eprintln!(
"You can open any of these documentation pages by running {}.\n",
Yellow.normal().paint("`rover docs open <slug>`")
);
let mut table = Table::new();
table.add_row(row!["Slug", "Description"]);
EverlastingBugstopper marked this conversation as resolved.
Show resolved Hide resolved
for (shortlink_slug, shortlink_description) in shortlinks {
table.add_row(row![shortlink_slug, shortlink_description]);
}
println!("{}", table);
}
RoverStdout::SDL(sdl) => {
eprintln!("SDL:");
println!("{}", &sdl);
Expand Down
12 changes: 6 additions & 6 deletions src/error/metadata/suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ impl Display for Suggestion {
Suggestion::RerunWithSensitive => {
format!(
"Try re-running this command with the {} flag",
Yellow.normal().paint("'--sensitive'")
Yellow.normal().paint("`--sensitive`")
)
}
Suggestion::SetConfigHome => {
format!(
"You can override this path by setting the {} environment variable.",
Yellow.normal().paint(RoverEnvKey::ConfigHome.to_string())
Yellow.normal().paint(&format!("${}", RoverEnvKey::ConfigHome))
)
}
Suggestion::MigrateConfigHomeOrCreateConfig => {
format!("If you've recently changed the {} environment variable, you may need to migrate your old configuration directory to the new path. Otherwise, try setting up a new configuration profile by running {}.",
Yellow.normal().paint(RoverEnvKey::ConfigHome.to_string()),
Yellow.normal().paint(&format!("${}", RoverEnvKey::ConfigHome)),
Yellow.normal().paint("`rover config auth`"))
}
Suggestion::CreateConfig => {
Expand All @@ -56,7 +56,7 @@ impl Display for Suggestion {
format!(
"Try running {} to see the possible values for the {} argument.",
Yellow.normal().paint("`rover config list`"),
Yellow.normal().paint("'--profile'")
Yellow.normal().paint("`--profile`")
)
}
Suggestion::UseFederatedGraph => {
Expand All @@ -82,11 +82,11 @@ impl Display for Suggestion {
"Check your API key to make sure it's valid (are you using the right profile?).".to_string()
}
Suggestion::ProperKey => {
format!("Visit {} for more details on Apollo's API keys.", Cyan.normal().paint("https://go.apollo.dev/r/api-keys"))
format!("Try running {} for more details on Apollo's API keys.", Yellow.normal().paint("`rover docs open api-keys`"))
}
Suggestion::NewUserNoProfiles => {
format!("It looks like you may be new here (we couldn't find any existing config profiles). To authenticate with Apollo Studio, run {}",
Cyan.normal().paint("rover config auth")
Yellow.normal().paint("`rover config auth`")
)
}
Suggestion::Adhoc(msg) => msg.to_string()
Expand Down