diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index dab9568a..9282acd9 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -43,6 +43,7 @@ jobs: - name: Build Docker Images run: | + export DOCKER_DEFAULT_PLATFORM=linux/amd64 docker compose build appflowy_cloud appflowy_history appflowy_worker - name: Push docker images to docker hub @@ -56,7 +57,7 @@ jobs: docker push appflowyinc/appflowy_worker:${GITHUB_SHA} APPFLOWY_HISTORY_VERSION=${GITHUB_SHA} APPFLOWY_WORKER_VERSION=${GITHUB_SHA} - APPFLOWY_CLOUD_VERSION=0.1.1 + APPFLOWY_CLOUD_VERSION=${GITHUB_SHA} test: name: Integration Tests diff --git a/docker-compose-ci.yml b/docker-compose-ci.yml index 526a01a8..498a7076 100644 --- a/docker-compose-ci.yml +++ b/docker-compose-ci.yml @@ -13,11 +13,13 @@ services: - ./nginx/ssl/private_key.key:/etc/nginx/ssl/private_key.key # You do not need this if you have configured to use your own s3 file storage + # You can try to access http://localhost/minio/browser/appflowy in your browser minio: restart: on-failure image: minio/minio ports: - - "9000:9000" + - 9000:9000 + - 9001:9001 environment: - MINIO_BROWSER_REDIRECT_URL=http://localhost/minio - MINIO_ROOT_USER=${APPFLOWY_S3_ACCESS_KEY:-minioadmin} diff --git a/libs/appflowy-ai-client/Cargo.toml b/libs/appflowy-ai-client/Cargo.toml index c78b1fa2..6032dccf 100644 --- a/libs/appflowy-ai-client/Cargo.toml +++ b/libs/appflowy-ai-client/Cargo.toml @@ -26,5 +26,5 @@ infra.workspace = true [features] default = ["client-api"] -client-api = ["dto", "reqwest", "serde", "serde_json", "tracing", "serde_repr"] +client-api = ["dto", "reqwest", "serde", "serde_json", "tracing", "serde_repr", "infra/request_util"] dto = ["serde", "serde_json", "serde_repr"] \ No newline at end of file diff --git a/libs/client-api-test/src/client.rs b/libs/client-api-test/src/client.rs index e37082fc..96edd73b 100644 --- a/libs/client-api-test/src/client.rs +++ b/libs/client-api-test/src/client.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::env; use tracing::warn; use uuid::Uuid; -// + #[cfg(not(target_arch = "wasm32"))] lazy_static! { pub static ref LOCALHOST_URL: Cow<'static, str> = diff --git a/libs/client-api/src/http_chat.rs b/libs/client-api/src/http_chat.rs index 28f32bfa..1cd4e716 100644 --- a/libs/client-api/src/http_chat.rs +++ b/libs/client-api/src/http_chat.rs @@ -9,9 +9,7 @@ use futures_core::{ready, Stream}; use pin_project::pin_project; use reqwest::Method; use serde_json::Value; -use shared_entity::dto::ai_dto::{ - CreateTextChatContext, RepeatedRelatedQuestion, STREAM_ANSWER_KEY, STREAM_METADATA_KEY, -}; +use shared_entity::dto::ai_dto::{RepeatedRelatedQuestion, STREAM_ANSWER_KEY, STREAM_METADATA_KEY}; use shared_entity::response::{AppResponse, AppResponseError}; use std::pin::Pin; use std::task::{Context, Poll}; @@ -217,25 +215,6 @@ impl Client { .await? .into_data() } - - pub async fn create_chat_context( - &self, - workspace_id: &str, - params: CreateTextChatContext, - ) -> Result<(), AppResponseError> { - let url = format!( - "{}/api/chat/{workspace_id}/{}/context/text", - self.base_url, params.chat_id - ); - let resp = self - .http_client_with_auth(Method::POST, &url) - .await? - .json(¶ms) - .send() - .await?; - log_request_id(&resp); - AppResponse::<()>::from_response(resp).await?.into_error() - } } #[pin_project] diff --git a/libs/database-entity/src/dto.rs b/libs/database-entity/src/dto.rs index c10b1664..c5d3bd74 100644 --- a/libs/database-entity/src/dto.rs +++ b/libs/database-entity/src/dto.rs @@ -8,6 +8,7 @@ use collab_entity::proto; use collab_entity::CollabType; use prost::Message; use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; use serde_repr::{Deserialize_repr, Serialize_repr}; use std::cmp::Ordering; use std::collections::HashMap; @@ -777,6 +778,17 @@ pub struct ChatMetadataData { pub size: i64, } +impl ChatMetadataData { + pub fn from_text(text: String) -> Self { + let size = text.len() as i64; + Self { + content: text, + content_type: ChatMetadataContentType::Text, + size, + } + } +} + impl ChatMetadataData { /// Validates the `ChatMetadataData` instance. /// @@ -885,8 +897,14 @@ impl CreateChatMessageParams { } } - pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self { - self.metadata = Some(metadata); + pub fn with_metadata(mut self, metadata: T) -> Self { + if let Ok(metadata) = serde_json::to_value(&metadata) { + if !matches!(metadata, Value::Array(_)) { + self.metadata = Some(json!([metadata])); + } else { + self.metadata = Some(metadata); + } + } self } } diff --git a/script/run_ci_server.sh b/script/run_ci_server.sh index b2df9f2f..0f9235c9 100755 --- a/script/run_ci_server.sh +++ b/script/run_ci_server.sh @@ -4,30 +4,56 @@ set -eo pipefail cd "$(dirname "$0")/.." -# This script simulates the continuous integration (CI) environment on a local machine. It -# requires a `.env` file to be located in the project's root directory. The values in the `.env` -# file must be updated to reflect the specifications of the CI environment. # Check if .env file exists in the current directory - if [ -f ".env" ]; then echo ".env file exists" else - echo ".env file does not exist. Copying deploy.env to .env and update the values" + echo ".env file does not exist. Please copy deploy.env to .env and update the values." exit 1 # Exit with an error code to indicate failure fi -# Make sure to update the test client configuration in libs/client-api-test-util/src/client.rs -# export LOCALHOST_URL="http://localhost" -# export LOCALHOST_WS_URL="ws://localhost/ws/v1" -# export LOCALHOST_GOTRUE_URL="http://localhost:gotrue" +IMAGE_VERSION="${1:-latest}" # Default to 'latest' if no argument is provided + +# Stop and remove running containers +docker ps -q --filter "network=appflowy-cloud_default" | xargs -r docker stop +docker ps -aq --filter "network=appflowy-cloud_default" | xargs -r docker rm docker compose down -docker compose -f docker-compose-ci.yml pull -# SKIP_BUILD_APPFLOWY_CLOUD=true. -if [[ -z "${SKIP_BUILD_APPFLOWY_CLOUD+x}" ]] -then - docker build -t appflowy_cloud . && docker build -t appflowy_worker . -fi +# Build amd64 images with a new local tag +# Before running following command, make sure you have the .env file with the correct values +# For example: SKIP_BUILD=true ./script/run_ci_server.sh 0.6.51-amd64 +if [[ -z "${SKIP_BUILD+x}" ]]; then + docker build --platform=linux/amd64 -t appflowyinc/appflowy_cloud_local:$IMAGE_VERSION -f Dockerfile . + docker build --platform=linux/amd64 -t appflowyinc/appflowy_worker_local:$IMAGE_VERSION -f ./services/appflowy-worker/Dockerfile . + + cat > docker-compose.override.yml <, -) -> (TestClient, String) { +async fn import_notion_zip_until_complete(name: &str) -> (TestClient, String) { let client = TestClient::new_user().await; - upload_file(&client, name, upload_after_secs).await.unwrap(); + let file_path = PathBuf::from(format!("tests/workspace/asset/{name}")); + client.api_client.import_file(&file_path).await.unwrap(); let default_workspace_id = client.workspace_id().await; // when importing a file, the workspace for the file should be created and it's @@ -266,7 +262,7 @@ async fn wait_until_num_import_task_complete(client: &TestClient, num: usize) { let mut task_completed = false; let max_retries = 12; let mut retries = 0; - while !task_completed && retries < max_retries { + while !task_completed { tokio::time::sleep(Duration::from_secs(10)).await; let tasks = client.api_client.get_import_list().await.unwrap().tasks; assert_eq!(tasks.len(), num); @@ -274,6 +270,11 @@ async fn wait_until_num_import_task_complete(client: &TestClient, num: usize) { task_completed = true; } retries += 1; + + if retries > max_retries { + eprintln!("{:?}", tasks); + break; + } } assert!( diff --git a/tests/workspace/mod.rs b/tests/workspace/mod.rs index b6047982..2f35a24f 100644 --- a/tests/workspace/mod.rs +++ b/tests/workspace/mod.rs @@ -1,7 +1,7 @@ mod access_request; mod default_user_workspace; mod edit_workspace; -// mod import_test; +mod import_test; mod invitation_crud; mod member_crud; mod page_view;