Test deploy docker log (#105)
* chore: try to fix logs in docker * ci: test deploy * ci: log level
This commit is contained in:
parent
375c463566
commit
a02da07627
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@ node_modules
|
||||||
**/libs/AppFlowy-Collab/
|
**/libs/AppFlowy-Collab/
|
||||||
data/
|
data/
|
||||||
.env
|
.env
|
||||||
|
.logs
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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" }
|
||||||
|
|
|
||||||
|
|
@ -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!(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue