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

Commit

Permalink
chore: rename manifest.json -> output_manifest.json
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Sep 13, 2024
1 parent 02ef12c commit ad73b48
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 4 deletions.
280 changes: 280 additions & 0 deletions :w
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
use anyhow::*;
use futures_util::{StreamExt, TryStreamExt};
use rivet_api::{apis, models};
use serde::Deserialize;
use std::{
collections::HashMap,
path::{Path, PathBuf},
sync::Arc,
};
use tokio::fs;

use crate::{
backend, config,
game::TEMPEnvironment,
paths,
toolchain_ctx::ToolchainCtx,
util::{net::upload, task, term},
};

pub struct DeployOpts {
pub env: TEMPEnvironment,

/// The location of the project.
pub project_path: String,

/// Skip the migration step.
pub skip_migrate: bool,
}

pub async fn deploy(ctx: &ToolchainCtx, task: task::TaskCtx, opts: DeployOpts) -> Result<()> {
task.log("[Deploying Backend]");

let backend = backend::get_or_create_backend(ctx, opts.env.id).await?;
let game_id_str = ctx.game_id.to_string();
let env_id_str = opts.env.id.to_string();
let project_path = PathBuf::from(opts.project_path.clone());

// Build
task.log(format!("[Building Project] {}", project_path.display()));
let (cmd_env, config_path) = config::settings::try_read(&paths::data_dir()?, |settings| {
let mut env = settings.backend.command_environment.clone();
env.extend(settings.backend.deploy.command_environment.clone());
Ok((env, settings.backend.deploy.config_path.clone()))
})
.await?;
let cmd = backend::run_backend_command_from_task(
task.clone(),
backend::BackendCommandOpts {
command: "build",
opts: serde_json::json!({
"watch": false,
"runtime": "cloudflare_workers_platforms",
"outputFormat": "bundled",
"dbDriver": "neon_serverless",
"migrate": false,
"project": config_path,
}),
env: cmd_env,
},
)
.await?;
ensure!(cmd == 0, "Failed to build backend project");

backend::database::provision_database(task.clone(), ctx, opts.env.id).await?;

let db_url = config::meta::try_read_project(&paths::data_dir()?, |config| {
let env_config = config
.environments
.get(&opts.env.id)
.context("could not find environment")?;
Ok(env_config.backend.db_url.clone())
})
.await?;

if !opts.skip_migrate {
task.log("[Migrating Database]");

// Migrate
let mut migrate_env = HashMap::new();
migrate_env.insert(
"DATABASE_URL".to_string(),
db_url.context("no db url for env")?,
);

let migrate_cmd = backend::run_backend_command_from_task(
task.clone(),
backend::BackendCommandOpts {
command: "dbMigrateApply",
opts: serde_json::json!({
"project": config_path,
}),
env: migrate_env,
},
)
.await?;
ensure!(migrate_cmd == 0, "Failed to migrate databases");
}

// Read files for upload
let gen_manifest = read_generated_manifest(&project_path).await?;
let bundle_path = project_path.join(gen_manifest.bundle);
let wasm_path = gen_manifest.wasm.map(|x| project_path.join(x));
let mut files = vec![upload::prepare_upload_file(
&bundle_path,
"bundle.js",
fs::metadata(&bundle_path).await?,
)?];
if let Some(wasm) = wasm_path.as_ref() {
files.push(upload::prepare_upload_file(
wasm,
"query-engine.wasm",
fs::metadata(wasm).await?,
)?);
}
let total_len = files
.iter()
.fold(0, |acc, x| acc + x.prepared.content_length);

task.log(format!(
"[Uploading Environment] {name} ({count} files, {size} total)",
name = &opts.env.name,
count = files.len(),
size = upload::format_file_size(total_len as u64)?,
));

task.log(format!("[Fetching Environment Variables]"));
// let variables = apis::ee_backend_api::ee_backend_get_variables(
// &ctx.openapi_config_cloud,
// &game_id_str,
// &env_id_str,
// )
// .await?
// .variables;
let mut update_variables = HashMap::<String, _>::new();
// if !variables.contains_key("RIVET_BACKEND_PUBLIC_ENDPOINT") {
update_variables.insert(
"RIVET_BACKEND_PUBLIC_ENDPOINT".to_string(),
models::EeBackendUpdateVariable {
text: Some(backend.endpoint.clone()),
..Default::default()
},
);
// }
// if !variables.contains_key("RIVET_API_ENDPOINT") {
update_variables.insert(
"RIVET_API_ENDPOINT".to_string(),
models::EeBackendUpdateVariable {
text: Some(ctx.api_endpoint.clone()),
..Default::default()
},
);
// }
// if !variables.contains_key("RIVET_GAME_ID") {
update_variables.insert(
"RIVET_GAME_ID".to_string(),
models::EeBackendUpdateVariable {
text: Some(game_id_str.clone()),
..Default::default()
},
);
// }
// if !variables.contains_key("RIVET_ENVIRONMENT_ID") {
update_variables.insert(
"RIVET_ENVIRONMENT_ID".to_string(),
models::EeBackendUpdateVariable {
text: Some(env_id_str.clone()),
..Default::default()
},
);
// }
// if !variables.contains_key("RIVET_SERVICE_TOKEN") {
task.log(format!("[Creating Service Token]"));
let service_token =
apis::games_environments_tokens_api::games_environments_tokens_create_service_token(
&ctx.openapi_config_cloud,
&game_id_str,
&opts.env.id.to_string(),
)
.await?;
update_variables.insert(
"RIVET_SERVICE_TOKEN".to_string(),
models::EeBackendUpdateVariable {
secret: Some(service_token.token),
..Default::default()
},
);
// }
if !update_variables.is_empty() {
task.log(format!(
"[Updating Variables] {}",
update_variables
.keys()
.cloned()
.collect::<Vec<_>>()
.join(", ")
));
}

let prepare_res = apis::ee_backend_api::ee_backend_prepare_deploy(
&ctx.openapi_config_cloud,
&game_id_str,
&env_id_str,
models::EeBackendPrepareDeployRequest {
files: files.iter().map(|f| f.prepared.clone()).collect(),
},
)
.await
.context("failed to prepare deploy")?;

// Upload files
let reqwest_client = Arc::new(reqwest::Client::new());
let pb = term::EitherProgressBar::Multi(term::multi_progress_bar(task.clone()));

futures_util::stream::iter(prepare_res.presigned_requests)
.map(Ok)
.try_for_each_concurrent(8, |presigned_req| {
let task = task.clone();
let pb = pb.clone();
let files = files.clone();
let reqwest_client = reqwest_client.clone();

async move {
// Find the matching prepared file
let file = files
.iter()
.find(|f| f.prepared.path == presigned_req.path)
.context("missing prepared file")?;

upload::upload_file(
task.clone(),
&reqwest_client,
&presigned_req,
&file.absolute_path,
file.prepared.content_type.as_ref(),
pb,
)
.await?;

Result::<()>::Ok(())
}
})
.await?;

task.log(format!("[Deploying Environment] {}", opts.env.name));

let deploy_res = apis::ee_backend_api::ee_backend_deploy(
&ctx.openapi_config_cloud,
&game_id_str,
&env_id_str,
models::EeBackendDeployRequest {
upload_id: prepare_res.upload_id,
variables: Some(update_variables),
},
)
.await?;

task.log(format!(
"[Done] Backend API available at {}",
deploy_res.url
));

Ok(())
}

#[derive(Deserialize)]
struct GenManifest {
bundle: String,
wasm: Option<String>,
}

async fn read_generated_manifest(project_path: &Path) -> Result<GenManifest> {
let manifest_str = fs::read_to_string(
project_path
.join(".rivet")
.join("backend")
.join("output_manifest.json"),
)
.await?;
Ok(serde_json::from_str::<GenManifest>(&manifest_str)?)
}
4 changes: 2 additions & 2 deletions packages/backend/toolchain/build/plan/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { generateEntrypoint } from "../entrypoint.ts";
import { generateOpenApi } from "../openapi.ts";
import { UnreachableError, UserError } from "../../error/mod.ts";
import { generateMeta } from "../meta.ts";
import { BUNDLE_PATH, ENTRYPOINT_PATH, MANIFEST_PATH, projectCachePath, PACKAGES_PATH } from "../../project/project.ts";
import { BUNDLE_PATH, ENTRYPOINT_PATH, OUTPUT_MANIFEST_PATH, projectCachePath, PACKAGES_PATH } from "../../project/project.ts";
import { compileActorTypeHelpers } from "../gen/mod.ts";
import { inflateArchive } from "../util.ts";
import packagesArchive from "../../../artifacts/packages_archive.json" with { type: "json" };
Expand Down Expand Up @@ -269,7 +269,7 @@ export async function planProjectBuild(
signal.throwIfAborted();

await Deno.writeTextFile(
projectCachePath(project, MANIFEST_PATH),
projectCachePath(project, OUTPUT_MANIFEST_PATH),
JSON.stringify(manifest),
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/toolchain/project/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ export const GITIGNORE_PATH = ".gitignore";
export const RUNTIME_CONFIG_PATH = "runtime_config.ts";
export const ENTRYPOINT_PATH = "entrypoint.ts";
export const BUNDLE_PATH = "output.js";
export const MANIFEST_PATH = "manifest.json";
export const OUTPUT_MANIFEST_PATH = "output_manifest.json";
export const META_PATH = "meta.json";
export const OPEN_API_PATH = "openapi.json";
export const CACHE_PATH = "cache.json";
Expand Down
2 changes: 1 addition & 1 deletion packages/toolchain/src/tasks/deploy/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ async fn read_generated_manifest(project_path: &Path) -> Result<GenManifest> {
project_path
.join(".rivet")
.join("backend")
.join("manifest.json"),
.join("output_manifest.json"),
)
.await?;
Ok(serde_json::from_str::<GenManifest>(&manifest_str)?)
Expand Down

0 comments on commit ad73b48

Please sign in to comment.