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

Commit

Permalink
feat: add settings file
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Jul 16, 2024
1 parent 65b1a5c commit 8d0ab65
Show file tree
Hide file tree
Showing 19 changed files with 429 additions and 150 deletions.
79 changes: 79 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions rivet-toolchain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ repository = "https://github.com/rivet-gg/cli"
async-posthog = { git = "https://github.com/rivet-gg/posthog-rs.git", rev = "ef4e80e" }
async-stream = "0.3.3"
chrono = "0.4.21"
config = { version = "0.14", default-features = false, features = ["json", "async"] }
console = "0.15"
ctrlc = { version = "3.2", features = ["termination"] }
dirs = "5.0"
Expand All @@ -26,6 +27,7 @@ ignore = "0.4"
indicatif = "0.17"
lz4 = "1.24"
mime_guess = "2.0"
open = "5.3.0"
openssl = { version = "*", features = ["vendored"] } # Required for cross compilation, see https://github.com/sfackler/rust-openssl/issues/603#issuecomment-822619837
rand = "0.8"
regex = "1.10"
Expand Down
48 changes: 19 additions & 29 deletions rivet-toolchain/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,59 @@ pub mod database;

use global_error::prelude::*;
use rivet_api::{apis, models};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, io::Write, path::PathBuf, str::FromStr};
use tempfile::NamedTempFile;
use tokio::{fs, process::Command, signal};

use crate::{
config,
util::{cmd::shell_cmd, task::TaskCtx},
Ctx,
};

const DEFAULT_OPENGB_DOCKER_TAG: &'static str = "ghcr.io/rivet-gg/opengb/v0.1.2";
pub struct OpenGbCommandOpts {
pub opengb_target: OpenGbTarget,
pub args: Vec<String>,
pub env: HashMap<String, String>,
pub cwd: PathBuf,
}

#[derive(PartialEq)]
pub enum OpenGbTarget {
#[derive(PartialEq, Serialize, Deserialize, Clone)]
pub enum OpenGbRuntime {
Native,
Docker,
}

impl Default for OpenGbTarget {
impl Default for OpenGbRuntime {
fn default() -> Self {
Self::Docker
}
}
impl FromStr for OpenGbTarget {
type Err = GlobalError;

fn from_str(s: &str) -> GlobalResult<Self> {
match s {
"native" => Ok(Self::Native),
"docker" => Ok(Self::Docker),
_ => bail!("unknown opengb target: {s}"),
}
}
}
pub async fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> {
let (runtime, image_tag) = config::settings::try_read(|settings| {
Ok((
settings.backend.opengb_runtime.clone(),
settings.backend.opengb_docker_image.clone(),
))
})
.await?;

pub fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> {
// Build command
match opts.opengb_target {
OpenGbTarget::Native => {
match runtime {
OpenGbRuntime::Native => {
let mut cmd = shell_cmd("opengb");
cmd.args(opts.args);
cmd.envs(opts.env);
cmd.current_dir(opts.cwd);
Ok(cmd)
}
OpenGbTarget::Docker => {
let image_tag = std::env::var("RIVET_OPENGB_DOCKER_IMAGE")
.ok()
.unwrap_or_else(|| DEFAULT_OPENGB_DOCKER_TAG.to_string());
OpenGbRuntime::Docker => {
let image_tag = image_tag.unwrap_or_else(|| DEFAULT_OPENGB_DOCKER_TAG.to_string());

// Build env file
let mut env_file = NamedTempFile::new().expect("Failed to create temp file");
for (k, v) in std::env::vars() {
writeln!(env_file, "{k}={v}")?;
}
if std::env::var("DATABASE_URL").is_err() {
writeln!(env_file, "DATABASE_URL=postgres://postgres:[email protected]:5432/postgres?sslmode=disable")?;
}
for (k, v) in opts.env {
writeln!(env_file, "{k}={v}")?;
}
Expand All @@ -88,13 +78,13 @@ pub fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> {
}

pub async fn run_opengb_command(task: TaskCtx, opts: OpenGbCommandOpts) -> GlobalResult<i32> {
let cmd = build_opengb_command(opts)?;
let cmd = build_opengb_command(opts).await?;
let exit_code = task.spawn_cmd(cmd).await?;
Ok(exit_code.code().unwrap_or(0))
}

pub async fn spawn_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<u32> {
let child = build_opengb_command(opts)?.spawn()?;
let child = build_opengb_command(opts).await?.spawn()?;
Ok(unwrap!(child.id(), "child already exited"))
}

Expand Down
1 change: 1 addition & 0 deletions rivet-toolchain/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod global;
pub mod settings;
129 changes: 129 additions & 0 deletions rivet-toolchain/src/config/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use global_error::prelude::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tokio::sync::{Mutex, OnceCell};

use crate::{
backend::OpenGbRuntime,
paths,
util::docker::{build::DockerBuildMethod, BuildCompression, BuildKind},
};

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct Settings {
#[serde(default)]
pub backend: BackendConfig,
#[serde(default)]
pub game_server: GameServerConfig,
#[serde(default)]
pub net: NetConfig,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct BackendConfig {
/// Env vars to pass to all OpenGB commands.
#[serde(default)]
pub command_environment: HashMap<String, String>,
#[serde(default)]
pub opengb_runtime: OpenGbRuntime,
#[serde(default)]
pub opengb_docker_image: Option<String>,

#[serde(default)]
pub sdk: BackendSdkConfig,
#[serde(default)]
pub dev: BackendDevConfig,
#[serde(default)]
pub deploy: BackendDeployConfig,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct BackendSdkConfig {
/// Env vars to pass to the deploy OpenGB commands.
#[serde(default)]
pub command_environment: HashMap<String, String>,
#[serde(default)]
pub path: Option<String>,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct BackendDevConfig {
/// Env vars to pass to the deploy OpenGB commands.
#[serde(default)]
pub command_environment: HashMap<String, String>,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct BackendDeployConfig {
/// Env vars to pass to the deploy OpenGB commands.
#[serde(default)]
pub command_environment: HashMap<String, String>,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct GameServerConfig {
#[serde(default)]
pub deploy: GameServerDeployConfig,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct GameServerDeployConfig {
#[serde(default)]
pub dockerfile_path: Option<String>,
#[serde(default)]
pub docker_image: Option<String>,
#[serde(default)]
pub build_args: Option<HashMap<String, String>>,
#[serde(default)]
pub allow_root: bool,
#[serde(default)]
pub build_method: DockerBuildMethod,
#[serde(default)]
pub build_kind: BuildKind,
// Default value depends on build_kind
#[serde(default)]
pub build_compression: Option<BuildCompression>,
}

#[derive(Default, Clone, Serialize, Deserialize)]
pub struct NetConfig {
#[serde(default)]
pub disable_upload_multipart: bool,
}

static SINGLETON: OnceCell<Mutex<Settings>> = OnceCell::const_new();

async fn read() -> GlobalResult<&'static Mutex<Settings>> {
let config = SINGLETON
.get_or_try_init::<GlobalError, _, _>(|| async {
let mut config_builder =
config::ConfigBuilder::<config::builder::AsyncState>::default();

if paths::user_settings_config_file()?.exists() {
config_builder = config_builder
.add_source(config::File::from(paths::user_settings_config_file()?));
}
if paths::project_settings_config_file()?.exists() {
config_builder = config_builder
.add_source(config::File::from(paths::project_settings_config_file()?));
}

let config = unwrap!(config_builder.build().await, "find config");
let config_deserialized =
unwrap!(config.try_deserialize::<Settings>(), "deserialize config");

Result::Ok(Mutex::new(config_deserialized))
})
.await?;
Ok(config)
}

pub async fn try_read<F: FnOnce(&Settings) -> GlobalResult<T>, T>(cb: F) -> GlobalResult<T> {
let singleton = read().await?;
let mut lock = singleton.lock().await;

// Fetch value
let value = cb(&mut *lock)?;

Ok(value)
}
Loading

0 comments on commit 8d0ab65

Please sign in to comment.