diff --git a/.dockerignore b/.dockerignore index 3559649..ea3a36a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ -.idea -node_modules -docker-compose.* +**/.idea +**/node_modules +**/docker-compose.* .dockerignore diff --git a/.env.docker.example b/.env.docker.example index 4f096db..75b060c 100644 --- a/.env.docker.example +++ b/.env.docker.example @@ -6,3 +6,7 @@ CLIENT_PORT_APP_ROUTER=4400 CLIENT_PORT_PAGES_ROUTER=4401 WATCH="false" + +# for development +# MB_RUN_MODE="dev" +# METASTORE_DEV_SERVER_URL="" \ No newline at end of file diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index a39bbf4..601a5e3 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -17,7 +17,9 @@ jobs: timeout-minutes: 10 name: e2e-tests env: - PREMIUM_EMBEDDING_TOKEN: ${{ secrets.ENTERPRISE_TOKEN }} + PREMIUM_EMBEDDING_TOKEN: ${{ secrets.STAGING_MB_ALL_FEATURES_TOKEN }} + MB_RUN_MODE: dev + METASTORE_DEV_SERVER_URL: ${{ secrets.METASTORE_DEV_SERVER_URL }} permissions: id-token: write contents: read @@ -28,8 +30,7 @@ jobs: - name: Run Sample App in Docker run: | cp .env.docker.example .env.docker && - npm run docker:up -- -d && - while ! nc -z localhost 4400; do sleep 1; done + npm run docker:e2e:up -- --wait - name: Install Chrome v111 uses: browser-actions/setup-chrome@v1 diff --git a/docker-compose.local-dist.yml b/docker-compose.local-dist.yml new file mode 100644 index 0000000..7b24a77 --- /dev/null +++ b/docker-compose.local-dist.yml @@ -0,0 +1,9 @@ +services: + metabase: + volumes: + - type: bind + source: ./local-dist/metabase.jar + target: /app/metabase.jar + read_only: true + bind: + create_host_path: false diff --git a/docker-compose.yml b/docker-compose.yml index 8b53042..69ae4a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,16 @@ services: metabase: - build: - context: . - dockerfile: metabase/Dockerfile + image: metabase/metabase-enterprise:v1.55.x environment: - MB_CONFIG_FILE_PATH: "./app/init-config.yml" + MB_CONFIG_FILE_PATH: "./app/config.yml" MB_JETTY_PORT: "${MB_PORT}" MB_EDITION: "ee" MB_SITE_URL: "http://localhost:${MB_PORT}/" MB_JWT_SHARED_SECRET: "${METABASE_JWT_SHARED_SECRET}" MB_SETUP_TOKEN: "${PREMIUM_EMBEDDING_TOKEN}" MB_PREMIUM_EMBEDDING_TOKEN: "${PREMIUM_EMBEDDING_TOKEN}" + MB_RUN_MODE: "${MB_RUN_MODE}" + METASTORE_DEV_SERVER_URL: "${METASTORE_DEV_SERVER_URL}" MB_JWT_IDENTITY_PROVIDER_URI: "http://localhost:${AUTH_PROVIDER_PORT}/sso/metabase" healthcheck: test: curl --fail -X GET -I "http://localhost:${MB_PORT}/api/health" || exit 1 @@ -19,6 +19,8 @@ services: retries: 10 ports: - "${MB_PORT}:${MB_PORT}" + volumes: + - ./metabase/config.yml:/app/config.yml next-sample-app-router: depends_on: @@ -38,6 +40,11 @@ services: NEXT_PUBLIC_METABASE_INSTANCE_URL: "http://localhost:${MB_PORT}" METABASE_INSTANCE_URL: "http://metabase:${MB_PORT}" METABASE_JWT_SHARED_SECRET: "${METABASE_JWT_SHARED_SECRET}" + healthcheck: + test: curl --fail -X GET -I "http://localhost:${CLIENT_PORT_APP_ROUTER}/" || exit 1 + interval: 2s + timeout: 2s + retries: 5 ports: - "${CLIENT_PORT_APP_ROUTER}:${CLIENT_PORT_APP_ROUTER}" volumes: @@ -51,7 +58,7 @@ services: context: . dockerfile: ./next-sample-pages-router/Dockerfile args: - PORT: "${CLIENT_PORT_APP_ROUTER}" + PORT: "${CLIENT_PORT_PAGES_ROUTER}" NEXT_PUBLIC_METABASE_INSTANCE_URL: "http://localhost:${MB_PORT}" METABASE_INSTANCE_URL: "http://metabase:${MB_PORT}" METABASE_JWT_SHARED_SECRET: "${METABASE_JWT_SHARED_SECRET}" @@ -61,6 +68,11 @@ services: NEXT_PUBLIC_METABASE_INSTANCE_URL: "http://localhost:${MB_PORT}" METABASE_INSTANCE_URL: "http://metabase:${MB_PORT}" METABASE_JWT_SHARED_SECRET: "${METABASE_JWT_SHARED_SECRET}" + healthcheck: + test: curl --fail -X GET -I "http://localhost:${CLIENT_PORT_PAGES_ROUTER}/" || exit 1 + interval: 2s + timeout: 2s + retries: 5 ports: - "${CLIENT_PORT_PAGES_ROUTER}:${CLIENT_PORT_PAGES_ROUTER}" volumes: diff --git a/metabase/Dockerfile b/metabase/Dockerfile deleted file mode 100644 index d2250c1..0000000 --- a/metabase/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM metabase/metabase-enterprise:v1.55.x - -COPY ./metabase /app/ -COPY ./local-dist /app/local-dist - -RUN if [ -f ./app/local-dist/metabase.jar ]; then \ - echo "Local metabase.jar is found in ./app/local-dist, running it..."; \ - cp ./app/local-dist/metabase.jar /app/metabase.jar; \ - else \ - echo "Local metabase.jar is not found in ./app/local-dist, skipping copy"; \ - fi diff --git a/metabase/init-config.yml b/metabase/config.yml similarity index 100% rename from metabase/init-config.yml rename to metabase/config.yml diff --git a/next-sample-app-router/package-lock.json b/next-sample-app-router/package-lock.json index 5c7fe04..cc7a739 100644 --- a/next-sample-app-router/package-lock.json +++ b/next-sample-app-router/package-lock.json @@ -8,7 +8,7 @@ "name": "next-sample-app-router", "version": "0.1.0", "dependencies": { - "@metabase/embedding-sdk-react": "^0.55.2", + "@metabase/embedding-sdk-react": "^0.55.5", "dotenv-cli": "^8.0.0", "jsonwebtoken": "^9.0.2", "next": "14.2.18", @@ -1078,9 +1078,9 @@ "license": "MIT" }, "node_modules/@metabase/embedding-sdk-react": { - "version": "0.55.2", - "resolved": "https://registry.npmjs.org/@metabase/embedding-sdk-react/-/embedding-sdk-react-0.55.2.tgz", - "integrity": "sha512-PQGqEBOc5yefmNQ1JNj8PggoE0UmOulf/tE4np9PkJJsZh7FIrtaY96HfWD14G1hdzbJQfUuhZrLuWcRC6fRDQ==", + "version": "0.55.5", + "resolved": "https://registry.npmjs.org/@metabase/embedding-sdk-react/-/embedding-sdk-react-0.55.5.tgz", + "integrity": "sha512-v90dqnrH3yhCiMeEQWOVJ9tq+LGC63Ed9XyHA2vhJM4MfW5UMg3v6g713bKTPwZL/1585sUgp4jEntr2MSNCUQ==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@codemirror/autocomplete": "^6.18.3", @@ -1174,7 +1174,7 @@ "react-router-redux": "^4.0.8", "react-transition-group": "^4.4.5", "react-use": "^17.5.1", - "react-virtualized": "9.22.5", + "react-virtualized": "9.22.6", "reduce-reducers": "^1.0.4", "redux-actions": "^2.0.1", "redux-auth-wrapper": "^2.1.0", @@ -10338,9 +10338,9 @@ } }, "node_modules/react-virtualized": { - "version": "9.22.5", - "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz", - "integrity": "sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==", + "version": "9.22.6", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.6.tgz", + "integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", @@ -10351,8 +10351,8 @@ "react-lifecycles-compat": "^3.0.4" }, "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" + "react": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/reactcss": { diff --git a/next-sample-app-router/package.json b/next-sample-app-router/package.json index 1d1938b..a8e7a69 100644 --- a/next-sample-app-router/package.json +++ b/next-sample-app-router/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@metabase/embedding-sdk-react": "^0.55.2", + "@metabase/embedding-sdk-react": "^0.55.5", "dotenv-cli": "^8.0.0", "jsonwebtoken": "^9.0.2", "next": "14.2.18", diff --git a/next-sample-pages-router/package-lock.json b/next-sample-pages-router/package-lock.json index 1d39c42..6764546 100644 --- a/next-sample-pages-router/package-lock.json +++ b/next-sample-pages-router/package-lock.json @@ -8,7 +8,7 @@ "name": "next-sample-pages-router", "version": "0.1.0", "dependencies": { - "@metabase/embedding-sdk-react": "^0.55.2", + "@metabase/embedding-sdk-react": "^0.55.5", "dotenv-cli": "^8.0.0", "jsonwebtoken": "^9.0.2", "next": "14.2.18", @@ -1078,9 +1078,9 @@ "license": "MIT" }, "node_modules/@metabase/embedding-sdk-react": { - "version": "0.55.2", - "resolved": "https://registry.npmjs.org/@metabase/embedding-sdk-react/-/embedding-sdk-react-0.55.2.tgz", - "integrity": "sha512-PQGqEBOc5yefmNQ1JNj8PggoE0UmOulf/tE4np9PkJJsZh7FIrtaY96HfWD14G1hdzbJQfUuhZrLuWcRC6fRDQ==", + "version": "0.55.5", + "resolved": "https://registry.npmjs.org/@metabase/embedding-sdk-react/-/embedding-sdk-react-0.55.5.tgz", + "integrity": "sha512-v90dqnrH3yhCiMeEQWOVJ9tq+LGC63Ed9XyHA2vhJM4MfW5UMg3v6g713bKTPwZL/1585sUgp4jEntr2MSNCUQ==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@codemirror/autocomplete": "^6.18.3", @@ -1174,7 +1174,7 @@ "react-router-redux": "^4.0.8", "react-transition-group": "^4.4.5", "react-use": "^17.5.1", - "react-virtualized": "9.22.5", + "react-virtualized": "9.22.6", "reduce-reducers": "^1.0.4", "redux-actions": "^2.0.1", "redux-auth-wrapper": "^2.1.0", @@ -10338,9 +10338,9 @@ } }, "node_modules/react-virtualized": { - "version": "9.22.5", - "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz", - "integrity": "sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==", + "version": "9.22.6", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.6.tgz", + "integrity": "sha512-U5j7KuUQt3AaMatlMJ0UJddqSiX+Km0YJxSqbAzIiGw5EmNz0khMyqP2hzgu4+QUtm+QPIrxzUX4raJxmVJnHg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", @@ -10351,8 +10351,8 @@ "react-lifecycles-compat": "^3.0.4" }, "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" + "react": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/reactcss": { diff --git a/next-sample-pages-router/package.json b/next-sample-pages-router/package.json index c7e6970..dcde3b0 100644 --- a/next-sample-pages-router/package.json +++ b/next-sample-pages-router/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@metabase/embedding-sdk-react": "^0.55.2", + "@metabase/embedding-sdk-react": "^0.55.5", "dotenv-cli": "^8.0.0", "jsonwebtoken": "^9.0.2", "next": "14.2.18", diff --git a/package.json b/package.json index fe46897..3487996 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "scripts": { "start": "npm run docker:up", "docker:up": "docker compose --env-file .env.docker up", - "docker:down": "docker compose --env-file .env.docker down --rmi all --volumes" + "docker:e2e:up": "yarn docker:up", + "docker:local-dist:up": "docker compose -f docker-compose.yml -f docker-compose.local-dist.yml --env-file .env.docker up", + "docker:down": "docker compose --env-file .env.docker down", + "docker:rm": "yarn docker:down --rmi all --volumes" } } diff --git a/readme.md b/readme.md index 59b70c7..ff2c392 100644 --- a/readme.md +++ b/readme.md @@ -31,14 +31,21 @@ This option should be used if you don't want to test Metabase Embedding SDK with From the root directory: - Copy `.env.docker.example` to `.env.docker` and replace `` with your premium embedding token -- Start all services in Docker with `yarn start` +- Start all services in Docker with `yarn docker:up` It will: -- poll a Metabase image and run it -- build and run both `next-sample-app-router` and `next-sample-pages-router` apps +- Poll a Metabase image and run it +- Build and run containers with both `next-sample-app-router` and `next-sample-pages-router` apps and run it The pages router sample will start on port 4401 and the app router sample will start on port 4400. +#### Local development (For Metabase developers) + +- To run containers with a locally built `metabase.jar`, copy it to the `./local-dist` folder as `./local-dist/metabase.jar`. +- To run containers with a locally built Embedding SDK package, copy it to the `./local-dist` folder as `./local-dist/embedding-sdk`. +- Run `yarn docker:local-dist:up` to start containers and use locally built dist from the `./local-dist` folder. +- To remove containers and images completely run `yarn docker:rm`. + ## Authentication Both apps provide an endpoint for user authentication, replace the logic to match your authentication system.