diff --git a/.env b/.env index 6aaa6ca..419976f 100644 --- a/.env +++ b/.env @@ -1,11 +1 @@ INVARIANT_API_URL=https://explorer.invariantlabs.ai - -# For the testing stack only -# TODO: Check if these can be removed. -# Currently we rely on the `invariant explorer` command -# to setup a local instance of explorer to test the proxy. -# That requires these variables to be set in the .env file. -POSTGRES_USER=postgres -POSTGRES_PASSWORD=postgres -POSTGRES_DB=invariantmonitor -POSTGRES_HOST=database \ No newline at end of file diff --git a/run.sh b/run.sh index ce3dfc3..6a06d77 100755 --- a/run.sh +++ b/run.sh @@ -22,20 +22,45 @@ down() { tests() { - # Run tests - pip install invariant-ai - invariant explorer up -d --build + echo "Setting up test environment..." - until curl -X GET -I http://127.0.0.1/api/v1 --fail --silent --output /dev/null; do - echo "Backend API not available yet - checking health..." - sleep 2 - done + # Ensure test network exists + docker network inspect invariant-explorer-web-test >/dev/null 2>&1 || \ + docker network create invariant-explorer-web-test - echo "Backend API is available. Running tests..." + # Setup the explorer.test.yml file + CONFIG_DIR="/tmp/invariant-proxy-test/configs" + FILE="$CONFIG_DIR/explorer.test.yml" + mkdir -p "$CONFIG_DIR" + # Download the file + curl -L -o "$FILE" https://raw.githubusercontent.com/invariantlabs-ai/explorer/main/configs/explorer.test.yml + # Verify if the file exists + if [ ! -f "$FILE" ]; then + echo "Error: File $FILE not found. Issue with download." + exit 1 + fi + echo "File successfully downloaded: $FILE" - docker build -t 'explorer-proxy-test' -f ./tests/Dockerfile.test ./tests + # Start containers + docker compose -f tests/docker-compose.test.yml down + docker compose -f tests/docker-compose.test.yml build + docker compose -f tests/docker-compose.test.yml up -d - docker run \ + until [ "$(docker inspect -f '{{.State.Health.Status}}' explorer-proxy-test-app-api)" = "healthy" ]; do + echo "explorer-proxy-test-app-api container starting..." + sleep 2 + done + + until [ "$(docker inspect -f '{{.State.Health.Status}}' explorer-proxy-test)" = "healthy" ]; do + echo "explorer-proxy-test container starting..." + sleep 2 + done + + echo "app-api and proxy are available. Running tests..." + + docker build -t 'explorer-proxy-test' -f ./tests/Dockerfile.test ./tests + + docker run \ --mount type=bind,source=./tests,target=/tests \ --network host \ explorer-proxy-test $@ diff --git a/tests/.env.test b/tests/.env.test new file mode 100644 index 0000000..d0b7167 --- /dev/null +++ b/tests/.env.test @@ -0,0 +1,6 @@ +INVARIANT_API_URL=http://127.0.0.1 + +POSTGRES_USER=postgres +POSTGRES_PASSWORD=postgres +POSTGRES_DB=invariantmonitor +POSTGRES_HOST=database \ No newline at end of file diff --git a/tests/docker-compose.test.yml b/tests/docker-compose.test.yml new file mode 100644 index 0000000..92f0377 --- /dev/null +++ b/tests/docker-compose.test.yml @@ -0,0 +1,110 @@ +name: explorer-proxy-test +services: + traefik: + image: traefik:v2.0 + container_name: "explorer-proxy-test-traefik" + command: + - --providers.docker=true + # Enable the API handler in insecure mode, + # which means that the Traefik API will be available directly + # on the entry point named traefik. + - --api.insecure=true + # Define Traefik entry points to port [80] for http and port [443] for https. + - --entrypoints.invariant-explorer-web-test.address=0.0.0.0:80 + networks: + - invariant-explorer-web-test + ports: + - '${PORT_HTTP:-80}:80' + volumes: + - /var/run/docker.sock:/var/run/docker.sock + labels: + - "traefik.enable=true" + - "traefik.http.routers.traefik-http.entrypoints=invariant-explorer-web-test" + + explorer-proxy: + container_name: explorer-proxy-test + build: + context: ../proxy + dockerfile: ../proxy/Dockerfile.proxy + depends_on: + app-api: + condition: service_healthy + working_dir: /srv/proxy + env_file: + - .env.test + environment: + - DEV_MODE=true + volumes: + - type: bind + source: ../proxy + target: /srv/proxy + networks: + - invariant-explorer-web-test + ports: [] + labels: + - "traefik.enable=true" + - "traefik.http.routers.explorer-proxy-api.rule=(Host(`localhost`) && PathPrefix(`/api/v1/proxy/`)) || (Host(`127.0.0.1`) && PathPrefix(`/api/v1/proxy/`))" + - "traefik.http.routers.explorer-proxy-api.entrypoints=invariant-explorer-web-test" + - "traefik.http.services.explorer-proxy-api.loadbalancer.server.port=8000" + - "traefik.docker.network=invariant-explorer-web-test" + healthcheck: + test: curl -X GET -I http://localhost:8000/api/v1/proxy/health --fail + interval: 1s + timeout: 5s + + app-api: + container_name: explorer-proxy-test-app-api + image: ghcr.io/invariantlabs-ai/explorer/app-api:latest + platform: linux/amd64 + depends_on: + database: + condition: service_healthy + working_dir: /srv/app + env_file: + - .env.test + environment: + - PROJECTS_DIR=/srv/projects + - KEYCLOAK_CLIENT_ID_SECRET=local-does-not-use-keycloak + - TZ=Europe/Berlin + - DEV_MODE=true + - APP_NAME=explorer-test + - CONFIG_FILE=/config/explorer.config.yml + - PORT_HTTP=8000 + - PORT_API=80 + networks: + - internal + - invariant-explorer-web-test + volumes: + - /tmp/invariant-proxy-test/configs/explorer.test.yml:/config/explorer.config.yml + labels: + - "traefik.enable=true" + - "traefik.http.routers.explorer-test-api.rule=(Host(`localhost`) && PathPrefix(`/api/`)) || (Host(`127.0.0.1`) && PathPrefix(`/api/`))" + - "traefik.http.routers.explorer-test-api.entrypoints=invariant-explorer-web-test" + - "traefik.http.services.explorer-test-api.loadbalancer.server.port=8000" + - "traefik.docker.network=invariant-explorer-web-test" + healthcheck: + test: curl -X GET -I http://localhost:8000/api/v1 --fail + interval: 1s + timeout: 5s + + database: + container_name: explorer-proxy-test-database + image: postgres:16 + env_file: + - .env.test + networks: + - internal + volumes: + - type: bind + source: /tmp/invariant-explorer-test/data/database + target: /var/lib/postgresql/data + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres" ] + interval: 5s + timeout: 5s + retries: 5 + +networks: + invariant-explorer-web-test: + external: true + internal: