Test deploy docker log (#105)

* chore: try to fix logs in docker

* ci: test deploy

* ci: log level
This commit is contained in:
Nathan.fooo 2023-10-08 21:42:25 +08:00 committed by GitHub
parent 375c463566
commit a02da07627
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 58 deletions

View File

@ -1,7 +1,9 @@
name: Deployment for Test Environment name: Deployment for Test Environment
on: on:
push: push:
branches: main branches:
- 'main'
- 'test_deploy_*'
jobs: jobs:
deploy: deploy:

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ node_modules
**/libs/AppFlowy-Collab/ **/libs/AppFlowy-Collab/
data/ data/
.env .env
.logs

4
Cargo.lock generated
View File

@ -866,7 +866,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=489cae0#489cae080419bd327282f974efe49ee447390b1d" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4a4df0b#4a4df0b287f197db99a02748548a5c0836c91588"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -885,7 +885,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-define" name = "collab-define"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=489cae0#489cae080419bd327282f974efe49ee447390b1d" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=4a4df0b#4a4df0b287f197db99a02748548a5c0836c91588"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",

View File

@ -66,7 +66,7 @@ sqlx = { version = "0.7", default-features = false, features = ["runtime-tokio-r
async-trait = "0.1.73" async-trait = "0.1.73"
# collab # collab
collab = { version = "0.1.0" } collab = { version = "0.1.0", features = ["async-plugin"] }
#Local crate #Local crate
token = { path = "libs/token" } token = { path = "libs/token" }
@ -126,8 +126,8 @@ lto = false
opt-level = 3 opt-level = 3
[patch.crates-io] [patch.crates-io]
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "489cae0" } collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4a4df0b" }
collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "489cae0" } collab-define = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "4a4df0b" }
# Comment the above and uncomment the below to use local version of collab by cloning the repo and placing it in libs folder # Comment the above and uncomment the below to use local version of collab by cloning the repo and placing it in libs folder
#collab = { path = "libs/AppFlowy-Collab/collab" } #collab = { path = "libs/AppFlowy-Collab/collab" }

View File

@ -100,6 +100,8 @@ pub struct GoTrueError {
pub error_id: Option<String>, pub error_id: Option<String>,
} }
impl std::error::Error for GoTrueError {}
impl Display for GoTrueError { impl Display for GoTrueError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!( f.write_fmt(format_args!(

View File

@ -1,21 +1,14 @@
use crate::collaborate::{CollabBroadcast, CollabStoragePlugin, Subscription}; use crate::collaborate::{CollabBroadcast, CollabStoragePlugin, Subscription};
use crate::entities::RealtimeUser;
use anyhow::Error;
use collab::core::collab::MutexCollab; use collab::core::collab::MutexCollab;
use collab::core::origin::CollabOrigin; use collab::core::origin::CollabOrigin;
use collab::preclude::Collab; use collab::preclude::Collab;
use collab_define::CollabType; use collab_define::CollabType;
use std::collections::HashMap;
use anyhow::Error;
use database::collab::CollabStorage; use database::collab::CollabStorage;
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use crate::entities::RealtimeUser;
use tokio::task::spawn_blocking; use tokio::task::spawn_blocking;
use tracing::{error, warn}; use tracing::{error, warn};
@ -115,7 +108,7 @@ where
Arc::downgrade(&group), Arc::downgrade(&group),
); );
collab.lock().add_plugin(Arc::new(plugin)); collab.lock().add_plugin(Arc::new(plugin));
collab.async_initialize().await; collab.lock_arc().initialize().await;
self self
.storage .storage

View File

@ -11,6 +11,7 @@ use actix_web::cookie::Key;
use actix_web::{dev::Server, web, web::Data, App, HttpServer}; use actix_web::{dev::Server, web, web::Data, App, HttpServer};
use actix::Actor; use actix::Actor;
use anyhow::{Context, Error};
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
use openssl::x509::X509; use openssl::x509::X509;
use secrecy::{ExposeSecret, Secret}; use secrecy::{ExposeSecret, Secret};
@ -114,17 +115,17 @@ fn get_certificate_and_server_key(config: &Config) -> Option<(Secret<String>, Se
} }
} }
pub async fn init_state(config: &Config) -> AppState { pub async fn init_state(config: &Config) -> Result<AppState, Error> {
let pg_pool = get_connection_pool(&config.database).await; let pg_pool = get_connection_pool(&config.database).await?;
migrate(&pg_pool).await; migrate(&pg_pool).await?;
let s3_bucket = get_aws_s3_bucket(&config.s3).await; let s3_bucket = get_aws_s3_bucket(&config.s3).await?;
let gotrue_client = get_gotrue_client(&config.gotrue).await; let gotrue_client = get_gotrue_client(&config.gotrue).await?;
setup_admin_account(&gotrue_client, &pg_pool, &config.gotrue).await; setup_admin_account(&gotrue_client, &pg_pool, &config.gotrue).await?;
let redis_client = get_redis_client(config.redis_uri.expose_secret()).await; let redis_client = get_redis_client(config.redis_uri.expose_secret()).await?;
let collab_storage = init_storage(config, pg_pool.clone()).await; let collab_storage = init_storage(config, pg_pool.clone()).await?;
AppState { Ok(AppState {
pg_pool, pg_pool,
config: Arc::new(config.clone()), config: Arc::new(config.clone()),
user: Arc::new(Default::default()), user: Arc::new(Default::default()),
@ -133,17 +134,20 @@ pub async fn init_state(config: &Config) -> AppState {
s3_bucket, s3_bucket,
redis_client, redis_client,
collab_storage, collab_storage,
} })
} }
async fn setup_admin_account( async fn setup_admin_account(
gotrue_client: &gotrue::api::Client, gotrue_client: &gotrue::api::Client,
pg_pool: &PgPool, pg_pool: &PgPool,
gotrue_setting: &GoTrueSetting, gotrue_setting: &GoTrueSetting,
) { ) -> Result<(), Error> {
let admin_email = gotrue_setting.admin_email.as_str(); let admin_email = gotrue_setting.admin_email.as_str();
let password = gotrue_setting.admin_password.as_str(); let password = gotrue_setting.admin_password.as_str();
gotrue_client.sign_up(admin_email, password).await.unwrap(); gotrue_client
.sign_up(admin_email, password)
.await
.context("failed to sign-up for admin user")?;
// Unable to use query! macro here instead // Unable to use query! macro here instead
// because of the auth is a not default schema // because of the auth is a not default schema
@ -158,25 +162,30 @@ async fn setup_admin_account(
.bind(admin_email) .bind(admin_email)
.execute(pg_pool) .execute(pg_pool)
.await .await
.unwrap(); .context("failed to update the admin user")?;
Ok(())
} }
async fn get_redis_client(redis_uri: &str) -> redis::aio::ConnectionManager { async fn get_redis_client(redis_uri: &str) -> Result<redis::aio::ConnectionManager, Error> {
redis::Client::open(redis_uri) let manager = redis::Client::open(redis_uri)
.unwrap() .context("failed to connect to redis")?
.get_tokio_connection_manager() .get_tokio_connection_manager()
.await .await
.unwrap() .context("failed to get the connection manager")?;
Ok(manager)
} }
async fn get_aws_s3_bucket(s3_setting: &S3Setting) -> s3::Bucket { async fn get_aws_s3_bucket(s3_setting: &S3Setting) -> Result<s3::Bucket, Error> {
let region = { let region = {
match s3_setting.use_minio { match s3_setting.use_minio {
true => s3::Region::Custom { true => s3::Region::Custom {
region: "".to_owned(), region: "".to_owned(),
endpoint: s3_setting.minio_url.to_owned(), endpoint: s3_setting.minio_url.to_owned(),
}, },
false => s3_setting.region.parse::<s3::Region>().unwrap(), false => s3_setting
.region
.parse::<s3::Region>()
.context("failed to parser s3 setting")?,
} }
}; };
@ -196,16 +205,14 @@ async fn get_aws_s3_bucket(s3_setting: &S3Setting) -> s3::Bucket {
) )
.await .await
{ {
Ok(_) => {}, Ok(_) => Ok(()),
Err(e) => match e { Err(e) => match e {
s3::error::S3Error::Http(409, _) => {}, // Bucket already exists s3::error::S3Error::Http(409, _) => Ok(()), // Bucket already exists
_ => panic!("Failed to create bucket: {:?}", e), _ => Err(e),
}, },
} }?;
s3::Bucket::new(&s3_setting.bucket, region.clone(), cred.clone()) Ok(s3::Bucket::new(&s3_setting.bucket, region.clone(), cred.clone())?.with_path_style())
.unwrap()
.with_path_style()
} }
// async fn get_aws_s3_client() -> aws_sdk_s3::Client { // async fn get_aws_s3_client() -> aws_sdk_s3::Client {
@ -226,28 +233,28 @@ async fn get_aws_s3_bucket(s3_setting: &S3Setting) -> s3::Bucket {
// client // client
// } // }
async fn get_connection_pool(setting: &DatabaseSetting) -> PgPool { async fn get_connection_pool(setting: &DatabaseSetting) -> Result<PgPool, Error> {
PgPoolOptions::new() PgPoolOptions::new()
.acquire_timeout(std::time::Duration::from_secs(5)) .acquire_timeout(std::time::Duration::from_secs(5))
.connect_with(setting.with_db()) .connect_with(setting.with_db())
.await .await
.expect("Failed to connect to Postgres") .context("failed to connect to postgres database")
} }
async fn migrate(pool: &PgPool) { async fn migrate(pool: &PgPool) -> Result<(), Error> {
sqlx::migrate!("./migrations") sqlx::migrate!("./migrations")
.run(pool) .run(pool)
.await .await
.expect("Failed to run migrations"); .context("failed to run migrations")
} }
async fn get_gotrue_client(setting: &GoTrueSetting) -> gotrue::api::Client { async fn get_gotrue_client(setting: &GoTrueSetting) -> Result<gotrue::api::Client, Error> {
let gotrue_client = gotrue::api::Client::new(reqwest::Client::new(), &setting.base_url); let gotrue_client = gotrue::api::Client::new(reqwest::Client::new(), &setting.base_url);
gotrue_client gotrue_client
.health() .health()
.await .await
.expect("Failed to connect to GoTrue"); .context("failed to connect to GoTrue")?;
gotrue_client Ok(gotrue_client)
} }
fn make_ssl_acceptor_builder(certificate: Secret<String>) -> SslAcceptorBuilder { fn make_ssl_acceptor_builder(certificate: Secret<String>) -> SslAcceptorBuilder {
@ -269,10 +276,13 @@ fn make_ssl_acceptor_builder(certificate: Secret<String>) -> SslAcceptorBuilder
builder builder
} }
pub async fn init_storage(_config: &Config, pg_pool: PgPool) -> Storage<CollabStorageProxy> { pub async fn init_storage(
_config: &Config,
pg_pool: PgPool,
) -> Result<Storage<CollabStorageProxy>, Error> {
let collab_storage = CollabPostgresDBStorageImpl::new(pg_pool); let collab_storage = CollabPostgresDBStorageImpl::new(pg_pool);
let proxy = CollabStorageProxy::new(collab_storage); let proxy = CollabStorageProxy::new(collab_storage);
Storage { Ok(Storage {
collab_storage: proxy, collab_storage: proxy,
} })
} }

View File

@ -5,6 +5,8 @@ use appflowy_cloud::telemetry::{get_subscriber, init_subscriber};
#[actix_web::main] #[actix_web::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let level = std::env::var("RUST_LOG").unwrap_or("info".to_string()); let level = std::env::var("RUST_LOG").unwrap_or("info".to_string());
println!("Start AppFlowy Cloud with RUST_LOG={}", level);
let mut filters = vec![]; let mut filters = vec![];
filters.push(format!("actix_web={}", level)); filters.push(format!("actix_web={}", level));
filters.push(format!("collab={}", level)); filters.push(format!("collab={}", level));
@ -21,8 +23,10 @@ async fn main() -> anyhow::Result<()> {
); );
init_subscriber(subscriber); init_subscriber(subscriber);
let configuration = get_configuration().expect("Failed to read configuration."); let configuration = get_configuration().expect("The configuration should be configured.");
let state = init_state(&configuration).await; let state = init_state(&configuration)
.await
.expect("The AppState should be initialized");
let application = Application::build(configuration, state).await?; let application = Application::build(configuration, state).await?;
application.run_until_stopped().await?; application.run_until_stopped().await?;

View File

@ -112,6 +112,7 @@ impl TestClient {
.to_string() .to_string()
} }
#[allow(clippy::await_holding_lock)]
pub(crate) async fn create_collab( pub(crate) async fn create_collab(
&mut self, &mut self,
workspace_id: &str, workspace_id: &str,
@ -143,7 +144,7 @@ impl TestClient {
); );
collab.lock().add_plugin(Arc::new(sync_plugin)); collab.lock().add_plugin(Arc::new(sync_plugin));
collab.async_initialize().await; collab.lock().initialize().await;
let test_collab = TestCollab { origin, collab }; let test_collab = TestCollab { origin, collab };
self self
.collab_by_object_id .collab_by_object_id