Skip to content
This repository has been archived by the owner on Dec 21, 2024. It is now read-only.

Commit

Permalink
chore: add deploy command
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Aug 7, 2024
1 parent bddfa6d commit 56f4a16
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 84 deletions.
7 changes: 5 additions & 2 deletions rivet-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ name = "rivet-cli"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "rivet"
path = "src/main.rs"

[dependencies]
clap = { version = "4.5.9", features = ["derive"] }
global-error = { git = "https://github.com/rivet-gg/rivet.git", rev = "22baf31efa3ffcdad65ecc72ce25425ab61b9c6f" }
toolchain = { version = "0.1.0", path = "../rivet-toolchain", package = "rivet-toolchain" }
tokio = { version = "1.38.1", features = ["full"] }
serde_json = "1.0.120"

serde_json = "1.0.120"
78 changes: 78 additions & 0 deletions rivet-cli/src/commands/deploy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use clap::Parser;
use std::process::ExitCode;
use toolchain::{
tasks::{deploy, get_bootstrap_data, RunConfig},
util::task::run_task,
};

#[derive(Parser)]
pub struct Opts {
environment: String,
#[clap(long, conflicts_with = "only_backend")]
only_game_server: bool,
#[clap(long, conflicts_with = "only_game_server")]
only_backend: bool,
}

impl Opts {
pub async fn execute(&self) -> ExitCode {
let run_config = RunConfig::empty();

let bootstrap_data = match run_task::<get_bootstrap_data::Task>(
run_config.clone(),
get_bootstrap_data::Input {},
)
.await
{
Ok(x) => x,
Err(e) => {
eprintln!("Error getting bootstrap: {e}");
return ExitCode::FAILURE;
}
};

// Find environment
let environment = match bootstrap_data
.backend_environments
.iter()
.find(|env| env.name_id == self.environment)
{
Some(env) => env,
None => {
eprintln!(
"Environment '{}' not found. Available environments:",
self.environment
);
for env in &bootstrap_data.backend_environments {
eprintln!("- {}", env.name_id);
}
return ExitCode::FAILURE;
}
};

match run_task::<deploy::Task>(
run_config,
deploy::Input {
cwd: std::env::current_dir()
.unwrap_or_default()
.to_string_lossy()
.to_string(),
environment_id: environment.environment_id.to_string(),
game_server: !self.only_backend,
backend: !self.only_game_server,
},
)
.await
{
Ok(_) => {
println!("Deployment completed successfully.");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("Error during deployment: {e}");
ExitCode::FAILURE
}
}
}
}

91 changes: 53 additions & 38 deletions rivet-cli/src/commands/login.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,65 @@
use clap::Parser;
use global_error::prelude::*;
use std::process::ExitCode;
use toolchain::{
tasks::{check_login_state, start_device_link, wait_for_login, RunConfig},
util::task::run_task,
tasks::{check_login_state, start_device_link, wait_for_login, RunConfig},
util::task::run_task,
};

#[derive(Parser)]
pub struct Opts {
#[clap(long, default_value = "https://api.rivet.gg")]
api_endpoint: String,
#[clap(long, default_value = "https://api.rivet.gg")]
api_endpoint: String,
}

impl Opts {
pub async fn execute(&self) -> GlobalResult<()> {
let run_config = RunConfig::empty();
pub async fn execute(&self) -> ExitCode {
let run_config = RunConfig::empty();

// Check if linked
let output =
run_task::<check_login_state::Task>(run_config.clone(), check_login_state::Input {})
.await?;
if output.logged_in {
eprintln!("Already logged in. Sign out with `rivet unlink`.");
return Ok(());
}
// Check if linked
match run_task::<check_login_state::Task>(run_config.clone(), check_login_state::Input {}).await {
Ok(output) => {
if output.logged_in {
eprintln!("Already logged in. Sign out with `rivet unlink`.");
return ExitCode::SUCCESS;
}
}
Err(e) => {
eprintln!("Error checking login state: {}", e);
return ExitCode::from(1);
}
}

// Start device link
let output = run_task::<start_device_link::Task>(
run_config.clone(),
start_device_link::Input {
api_endpoint: self.api_endpoint.clone(),
},
)
.await?;
eprintln!("{}", output.device_link_url);
// Start device link
let device_link_output = match run_task::<start_device_link::Task>(
run_config.clone(),
start_device_link::Input {
api_endpoint: self.api_endpoint.clone(),
},
).await {
Ok(output) => output,
Err(e) => {
eprintln!("Error starting device link: {}", e);
return ExitCode::from(2);
}
};
eprintln!("{}", device_link_output.device_link_url);

// Wait for finish
run_task::<wait_for_login::Task>(
run_config.clone(),
wait_for_login::Input {
api_endpoint: self.api_endpoint.clone(),
device_link_token: output.device_link_token,
},
)
.await?;
eprintln!("Logged in");

Ok(())
}
}
// Wait for finish
match run_task::<wait_for_login::Task>(
run_config.clone(),
wait_for_login::Input {
api_endpoint: self.api_endpoint.clone(),
device_link_token: device_link_output.device_link_token,
},
).await {
Ok(_) => {
eprintln!("Logged in");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("Error waiting for login: {}", e);
ExitCode::from(3)
}
}
}
}
28 changes: 17 additions & 11 deletions rivet-cli/src/commands/logout.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
use clap::Parser;
use global_error::prelude::*;
use std::process::ExitCode;
use toolchain::{
tasks::{unlink, RunConfig},
util::task::run_task,
tasks::{unlink, RunConfig},
util::task::run_task,
};

#[derive(Parser)]
pub struct Opts {}

impl Opts {
pub async fn execute(&self) -> GlobalResult<()> {
let run_config = RunConfig::empty();
pub async fn execute(&self) -> ExitCode {
let run_config = RunConfig::empty();

run_task::<unlink::Task>(run_config.clone(), unlink::Input {}).await?;
eprintln!("Logged out");

Ok(())
}
}
match run_task::<unlink::Task>(run_config.clone(), unlink::Input {}).await {
Ok(_) => {
eprintln!("Logged out");
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("Error logging out: {}", e);
ExitCode::from(1)
}
}
}
}
33 changes: 18 additions & 15 deletions rivet-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
pub mod login;
pub mod logout;
pub mod task;
pub mod deploy;

use clap::Parser;
use global_error::prelude::*;
use std::process::ExitCode;

#[derive(Parser)]
pub enum SubCommand {
Login(login::Opts),
Task {
#[clap(subcommand)]
subcommand: task::SubCommand,
},
Logout(logout::Opts),
Login(login::Opts),
Task {
#[clap(subcommand)]
subcommand: task::SubCommand,
},
Logout(logout::Opts),
Deploy(deploy::Opts),
}

impl SubCommand {
pub async fn execute(&self) -> GlobalResult<()> {
match self {
SubCommand::Login(opts) => opts.execute().await,
SubCommand::Task { subcommand } => subcommand.execute().await,
SubCommand::Logout(opts) => opts.execute().await,
}
}
}
pub async fn execute(&self) -> ExitCode {
match self {
SubCommand::Login(opts) => opts.execute().await,
SubCommand::Task { subcommand } => subcommand.execute().await,
SubCommand::Logout(opts) => opts.execute().await,
SubCommand::Deploy(opts) => opts.execute().await,
}
}
}
28 changes: 21 additions & 7 deletions rivet-cli/src/commands/task.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clap::Parser;
use global_error::prelude::*;
use std::process::ExitCode;

/// EXPERIMENTAL
#[derive(Parser)]
Expand All @@ -8,7 +8,7 @@ pub enum SubCommand {
}

impl SubCommand {
pub async fn execute(&self) -> GlobalResult<()> {
pub async fn execute(&self) -> ExitCode {
match self {
SubCommand::Run(opts) => opts.execute().await,
}
Expand All @@ -26,10 +26,24 @@ pub struct RunOpts {
}

impl RunOpts {
pub async fn execute(&self) -> GlobalResult<()> {
let run_config = serde_json::from_str(&self.run_config)?;
let output = toolchain::tasks::run_task_json(run_config, &self.name, &self.input).await;
println!("{output}");
Ok(())
pub async fn execute(&self) -> ExitCode {
match serde_json::from_str(&self.run_config) {
Ok(run_config) => {
let result =
toolchain::tasks::run_task_json(run_config, &self.name, &self.input).await;
println!("{}", result.output);

if result.success {
ExitCode::SUCCESS
} else {
ExitCode::FAILURE
}
}
Err(e) => {
eprintln!("Error parsing run_config: {}", e);
ExitCode::from(2)
}
}
}
}

8 changes: 3 additions & 5 deletions rivet-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod commands;

use clap::Parser;
use global_error::GlobalResult;
use std::process::ExitCode;

#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
Expand All @@ -11,9 +11,7 @@ struct Cli {
}

#[tokio::main]
async fn main() -> GlobalResult<()> {
async fn main() -> ExitCode {
let cli = Cli::parse();
cli.command.execute().await?;
Ok(())
cli.command.execute().await
}

8 changes: 4 additions & 4 deletions rivet-toolchain/src/tasks/deploy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use crate::util::task::TaskCtx;

#[derive(Deserialize)]
pub struct Input {
cwd: String,
environment_id: String,
game_server: bool,
backend: bool,
pub cwd: String,
pub environment_id: String,
pub game_server: bool,
pub backend: bool,
}

#[derive(Serialize)]
Expand Down
14 changes: 12 additions & 2 deletions rivet-toolchain/src/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,28 @@ pub trait Task {
fn run(task: TaskCtx, input: Self::Input) -> impl Future<Output = GlobalResult<Self::Output>>;
}

pub struct RunTaskJsonOutput {
pub output: String,
pub success: bool,
}

/// Used to run tasks with raw input/output string. This is useful for binding tasks to non-Rust
/// environments, such as raw dylibs or odd engines.
macro_rules! gen_run_task {
( $( $task:ty ),* $(,)? ) => {
pub async fn run_task_json(run_config: RunConfig, name: &str, input_json: &str) -> String {
pub async fn run_task_json(run_config: RunConfig, name: &str, input_json: &str) -> RunTaskJsonOutput {
$(
if name == <$task>::name() {
let input = serde_json::from_str::<<$task as Task>::Input>(&input_json)
.expect("deserialize task input");
let output = run_task::<$task>(run_config, input).await;
let success = output.is_ok();
let output_serialize = output.map_err(|x| x.to_string());
return serde_json::to_string(&output_serialize).expect("serialize task output");
let output_json = serde_json::to_string(&output_serialize).expect("serialize task output");
return RunTaskJsonOutput {
output: output_json,
success,
};
}
)*

Expand Down

0 comments on commit 56f4a16

Please sign in to comment.