diff --git a/.env b/.env new file mode 100644 index 0000000..0e267ec --- /dev/null +++ b/.env @@ -0,0 +1,109 @@ + +# Appwrite +_APP_ENV=development +_APP_EDITION=self-hosted +_APP_LOCALE=en +_APP_WORKER_PER_CORE=6 +_APP_CONSOLE_WHITELIST_ROOT=disabled +_APP_CONSOLE_WHITELIST_EMAILS= +_APP_CONSOLE_WHITELIST_IPS= +_APP_CONSOLE_COUNTRIES_DENYLIST=AQ +_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io +_APP_SYSTEM_EMAIL_NAME=Appwrite +_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io +_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io +_APP_SYSTEM_RESPONSE_FORMAT= +_APP_OPTIONS_ABUSE=disabled +_APP_OPTIONS_ROUTER_PROTECTION=disabled +_APP_OPTIONS_FORCE_HTTPS=disabled +_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled +_APP_OPENSSL_KEY_V1=your-secret-key +_APP_DOMAIN=localhost +_APP_DOMAIN_FUNCTIONS=functions.localhost +_APP_DOMAIN_TARGET=localhost +_APP_REDIS_HOST=redis +_APP_REDIS_PORT=6379 +_APP_REDIS_PASS= +_APP_REDIS_USER= +_APP_DB_HOST=mariadb +_APP_DB_PORT=3306 +_APP_DB_SCHEMA=appwrite +_APP_DB_USER=user +_APP_DB_PASS=password +_APP_DB_ROOT_PASS=rootsecretpassword +_APP_STORAGE_DEVICE=Local +_APP_STORAGE_S3_ACCESS_KEY= +_APP_STORAGE_S3_SECRET= +_APP_STORAGE_S3_REGION=us-east-1 +_APP_STORAGE_S3_BUCKET= +_APP_STORAGE_DO_SPACES_ACCESS_KEY= +_APP_STORAGE_DO_SPACES_SECRET= +_APP_STORAGE_DO_SPACES_REGION=us-east-1 +_APP_STORAGE_DO_SPACES_BUCKET= +_APP_STORAGE_BACKBLAZE_ACCESS_KEY= +_APP_STORAGE_BACKBLAZE_SECRET= +_APP_STORAGE_BACKBLAZE_REGION=us-west-004 +_APP_STORAGE_BACKBLAZE_BUCKET= +_APP_STORAGE_LINODE_ACCESS_KEY= +_APP_STORAGE_LINODE_SECRET= +_APP_STORAGE_LINODE_REGION=eu-central-1 +_APP_STORAGE_LINODE_BUCKET= +_APP_STORAGE_WASABI_ACCESS_KEY= +_APP_STORAGE_WASABI_SECRET= +_APP_STORAGE_WASABI_REGION=eu-central-1 +_APP_STORAGE_WASABI_BUCKET= +_APP_STORAGE_ANTIVIRUS=disabled +_APP_STORAGE_ANTIVIRUS_HOST=clamav +_APP_STORAGE_ANTIVIRUS_PORT=3310 +_APP_SMTP_HOST=maildev +_APP_SMTP_PORT=1025 +_APP_SMTP_SECURE= +_APP_SMTP_USERNAME= +_APP_SMTP_PASSWORD= +_APP_SMS_PROVIDER=sms://username:password@mock +_APP_SMS_FROM=+123456789 +_APP_SMS_PROJECTS_DENY_LIST= +_APP_STORAGE_LIMIT=30000000 +_APP_STORAGE_PREVIEW_LIMIT=20000000 +_APP_FUNCTIONS_SIZE_LIMIT=30000000 +_APP_FUNCTIONS_TIMEOUT=900 +_APP_FUNCTIONS_BUILD_TIMEOUT=900 +_APP_FUNCTIONS_CPUS=1 +_APP_FUNCTIONS_MEMORY=1024 +_APP_FUNCTIONS_INACTIVE_THRESHOLD=600 +_APP_FUNCTIONS_MAINTENANCE_INTERVAL=600 +_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes +_APP_EXECUTOR_SECRET=your-secret-key +_APP_EXECUTOR_HOST=http://proxy/v1 +_APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1 +_APP_MAINTENANCE_INTERVAL=86400 +_APP_MAINTENANCE_DELAY= +_APP_MAINTENANCE_RETENTION_CACHE=2592000 +_APP_MAINTENANCE_RETENTION_EXECUTION=1209600 +_APP_MAINTENANCE_RETENTION_ABUSE=86400 +_APP_MAINTENANCE_RETENTION_AUDIT=1209600 +_APP_USAGE_AGGREGATION_INTERVAL=30 +_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 +_APP_MAINTENANCE_RETENTION_SCHEDULES=86400 +_APP_USAGE_STATS=enabled +_APP_LOGGING_PROVIDER= +_APP_LOGGING_CONFIG= +_APP_GRAPHQL_MAX_BATCH_SIZE=10 +_APP_GRAPHQL_MAX_COMPLEXITY=250 +_APP_GRAPHQL_MAX_DEPTH=4 +_APP_DOCKER_HUB_USERNAME= +_APP_DOCKER_HUB_PASSWORD= +_APP_VCS_GITHUB_APP_NAME= +_APP_VCS_GITHUB_PRIVATE_KEY=disabled +_APP_VCS_GITHUB_APP_ID= +_APP_VCS_GITHUB_CLIENT_ID= +_APP_VCS_GITHUB_CLIENT_SECRET= +_APP_VCS_GITHUB_WEBHOOK_SECRET= +_APP_MIGRATIONS_FIREBASE_CLIENT_ID= +_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET= +_APP_ASSISTANT_OPENAI_API_KEY= +_APP_MESSAGE_SMS_TEST_DSN= +_APP_MESSAGE_EMAIL_TEST_DSN= +_APP_MESSAGE_PUSH_TEST_DSN= +_APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 +_APP_PROJECT_REGIONS=default \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b51d5e7..2e0b5ca 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,19 +1,69 @@ name: Tests + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE: migrations-dev + CACHE_KEY: migrations-dev-${{ github.sha }} + on: pull_request: push: { branches: [main] } jobs: - tests: - name: Run Test Suite + setup: + name: Setup & Build Migrations Image + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build Migrations + uses: docker/build-push-action@v5 + with: + context: . + push: false + tags: ${{ env.IMAGE }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Cache Docker Image + uses: actions/cache@v3 + with: + key: ${{ env.CACHE_KEY }} + path: /tmp/${{ env.IMAGE }}.tar + + source_unit_tests: + name: Run Source Unit Tests runs-on: ubuntu-latest + needs: setup env: COMPOSE_FILE: docker-compose.yml - + strategy: + fail-fast: false + matrix: + adapter: [Appwrite, Supabase, NHost] steps: - name: Checkout uses: actions/checkout@v2 - - name: Run Tests + - name: Load Cache + uses: actions/cache@v3 + with: + key: ${{ env.CACHE_KEY }} + path: /tmp/${{ env.IMAGE }}.tar + fail-on-cache-miss: true + + - name: Bring up services + run: docker-compose up -d + + - name: Run ${{matrix.adapter}} Tests run: | - docker-compose up -d --build && sleep 5 && docker compose exec tests php ./vendor/bin/phpunit \ No newline at end of file + docker compose exec tests php ./vendor/bin/phpunit /app/tests/Migration/Unit/Sources/${{matrix.adapter}}Test.php diff --git a/.gitignore b/.gitignore index 9c0bf12..c2ae082 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ composer.lock /vendor/ /.idea/ *.cache -.env test-service-account.json .DS_Store localBackup/ diff --git a/Dockerfile b/Dockerfile index f62c026..468bf2f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,16 +8,44 @@ COPY tests/Migration/resources/nhost/1_globals.sql /docker-entrypoint-initdb.d/1 COPY tests/Migration/resources/nhost/2_main.sql /docker-entrypoint-initdb.d/2_main.sql FROM composer:2.0 as composer + WORKDIR /usr/local/src/ COPY composer.json /usr/local/src/ RUN composer install --ignore-platform-reqs -FROM php:8.1.21-fpm-alpine3.18 as tests +FROM php:8.1.21 as tests + +# Install Appwrite Toolkit +RUN set -ex \ + && mkdir -p /app/toolkit \ + && cd /app/toolkit \ + && curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh \ + && bash nodesource_setup.sh \ + && apt-get install nodejs git -y \ + && git clone https://github.com/Meldiron/appwrite-toolkit.git \ + && cd appwrite-toolkit \ + && git checkout feat-refactor-cli \ + && npm install \ + && npm link + # Postgres RUN set -ex \ - && apk --no-cache add postgresql-libs postgresql-dev \ + && apt-get install -y libpq-dev \ && docker-php-ext-install pdo pdo_pgsql \ - && apk del postgresql-dev + && apt-get remove -y libpq-dev + +## Install XDebug, Remove before commit. +RUN \ + git clone --depth 1 --branch 3.3.1 https://github.com/xdebug/xdebug && \ + cd xdebug && \ + phpize && \ + ./configure && \ + make && make install + +# Enable Extensions +COPY dev/xdebug.ini /usr/src/code/dev/xdebug.ini +RUN cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini + COPY ./src /app/src COPY ./tests /app/src/tests COPY --from=composer /usr/local/src/vendor /app/vendor diff --git a/bin/.env b/bin/.env new file mode 100644 index 0000000..7ea0909 --- /dev/null +++ b/bin/.env @@ -0,0 +1,27 @@ +SOURCE=supabase + +SOURCE_APPWRITE_TEST_PROJECT=6646cbd3874a550d78e1 +SOURCE_APPWRITE_TEST_ENDPOINT=http://localhost/v1 +SOURCE_APPWRITE_TEST_KEY=d485cca1318af57b68213bcecc9defbeeccb1f3cf94774a4f097b61415f38b2f78f13faf2a3ec91930105df5b8266854f6f8219a8d693040a83ea600fd4458875f741fc7e318b3eca685c3c25a8523d765bcda9ec7f7e8129448cc5986b2fc2c7797300ae27ed68e764dbda508e82a66514fcf9da3187d0eb5f4453e031a1f7d + +FIREBASE_TEST_PROJECT=testProject +FIREBASE_TEST_ACCOUNT='{type: "service_account", ...}' + +SUPABASE_TEST_ENDPOINT=https://iwnzcwbimmpurmkqcueg.supabase.co +SUPABASE_TEST_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 +SUPABASE_TEST_HOST=aws-0-eu-west-2.pooler.supabase.com +SUPABASE_TEST_DATABASE=postgres +SUPABASE_TEST_USERNAME=postgres.iwnzcwbimmpurmkqcueg +SUPABASE_TEST_PASSWORD=ueTlfhe4bcNfiqHV + +NHOST_TEST_SUBDOMAIN=xxxxxxxxxxx +NHOST_TEST_REGION=eu-central-1 +NHOST_TEST_SECRET=xxxxxxxxxxxxxxxxx +NHOST_TEST_DATABASE=xxxxxxxxxxxxxxx +NHOST_TEST_USERNAME=postgres +NHOST_TEST_PASSWORD=xxxxxxxxxxxxxxx + + +DESTINATION_APPWRITE_TEST_PROJECT=6646dd50000c4b4f2b04 +DESTINATION_APPWRITE_TEST_ENDPOINT=http://localhost/v1 +DESTINATION_APPWRITE_TEST_KEY=c8c3ee7f9491b8320cd57aaad08531a5bbd77651da95b166ee5c26b7f9081dc124952b37a75d1cc4302dd9439d884d7265ceb8c88563cbb3d5bc2bad19381d272233e3836cc7035a166fc75e405dc5a674eeee0c11e646e35848326870974f4ef29412ad97bd81e095fb9c2739fed079f7704a83d8924d199cd65d02534cdda9 diff --git a/composer.json b/composer.json index 2ea999e..ccc4648 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "require-dev": { "phpunit/phpunit": "9.*", "vlucas/phpdotenv": "5.*", - "laravel/pint": "1.*" + "laravel/pint": "1.*", + "utopia-php/cli": "^0.18.0" } } diff --git a/dev/xdebug.ini b/dev/xdebug.ini new file mode 100644 index 0000000..e29c8bd --- /dev/null +++ b/dev/xdebug.ini @@ -0,0 +1,6 @@ +zend_extension=xdebug + +[xdebug] +xdebug.mode=develop,debug +xdebug.client_host=host.docker.internal +xdebug.start_with_request=yes \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index a151232..8118dfd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,28 @@ -version: '3' - services: + ## Tests + tests: + image: migration-tests + build: + context: . + target: tests + networks: + - tests + volumes: + - ./tests:/app/tests + - ./src:/app/src + - ./phpunit.xml:/app/phpunit.xml + working_dir: /app + depends_on: + - supabase-db + - nhost-db + - nhost-storage + environment: + - NHOST_DB_URL=postgres://postgres:postgres@nhost-db:5432/postgres + - SUPABASE_DB_URL=postgres://postgres:postgres@supabase-db:5432/postgres + + ## Supabase supabase-db: + image: migration-supabase build: context: . target: supabase-db @@ -14,7 +35,17 @@ services: POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres + supabase-api: + image: mockoon/cli:latest + command: ["--data", "/mockoon/api.json", "--port", "80", "--disable-log-to-file"] + networks: + - tests + volumes: + - ./tests/Migration/resources/supabase:/mockoon + + ## NHost nhost-db: + image: migration-nhost build: context: . target: nhost-db @@ -34,33 +65,727 @@ services: - tests volumes: - ./tests/Migration/resources/nhost:/mockoon - - supabase-api: - image: mockoon/cli:latest - command: ["--data", "/mockoon/api.json", "--port", "80", "--disable-log-to-file"] + + ## Appwrite + appwrite: + image: appwrite/appwrite:1.5.7 + container_name: appwrite + restart: unless-stopped networks: - tests - volumes: - - ./tests/Migration/resources/supabase:/mockoon + - appwrite + depends_on: + - mariadb + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_LOCALE + - _APP_CONSOLE_WHITELIST_ROOT + - _APP_CONSOLE_WHITELIST_EMAILS + - _APP_CONSOLE_WHITELIST_IPS + - _APP_CONSOLE_HOSTNAMES + - _APP_SYSTEM_EMAIL_NAME + - _APP_SYSTEM_EMAIL_ADDRESS + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_SYSTEM_RESPONSE_FORMAT + - _APP_OPTIONS_ABUSE + - _APP_OPTIONS_ROUTER_PROTECTION + - _APP_OPTIONS_FORCE_HTTPS + - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_DOMAIN_FUNCTIONS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_SMTP_HOST + - _APP_SMTP_PORT + - _APP_SMTP_SECURE + - _APP_SMTP_USERNAME + - _APP_SMTP_PASSWORD + - _APP_USAGE_STATS + - _APP_STORAGE_LIMIT + - _APP_STORAGE_PREVIEW_LIMIT + - _APP_STORAGE_ANTIVIRUS + - _APP_STORAGE_ANTIVIRUS_HOST + - _APP_STORAGE_ANTIVIRUS_PORT + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_FUNCTIONS_TIMEOUT + - _APP_FUNCTIONS_BUILD_TIMEOUT + - _APP_FUNCTIONS_CPUS + - _APP_FUNCTIONS_MEMORY + - _APP_FUNCTIONS_RUNTIMES + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_MAINTENANCE_INTERVAL + - _APP_MAINTENANCE_DELAY + - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_MAINTENANCE_RETENTION_CACHE + - _APP_MAINTENANCE_RETENTION_ABUSE + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY + - _APP_MAINTENANCE_RETENTION_SCHEDULES + - _APP_SMS_PROVIDER + - _APP_SMS_FROM + - _APP_GRAPHQL_MAX_BATCH_SIZE + - _APP_GRAPHQL_MAX_COMPLEXITY + - _APP_GRAPHQL_MAX_DEPTH + - _APP_VCS_GITHUB_APP_NAME + - _APP_VCS_GITHUB_PRIVATE_KEY + - _APP_VCS_GITHUB_APP_ID + - _APP_VCS_GITHUB_WEBHOOK_SECRET + - _APP_VCS_GITHUB_CLIENT_SECRET + - _APP_VCS_GITHUB_CLIENT_ID + - _APP_ASSISTANT_OPENAI_API_KEY - tests: - build: - context: . - target: tests + appwrite-realtime: + image: appwrite/appwrite:1.5.7 + entrypoint: realtime + container_name: appwrite-realtime + restart: unless-stopped networks: - - tests - volumes: - - ./tests:/app/tests - - ./src:/app/src - - ./phpunit.xml:/app/phpunit.xml - working_dir: /app + - appwrite depends_on: - - supabase-db - - nhost-db - - nhost-storage + - mariadb + - redis environment: - - NHOST_DB_URL=postgres://postgres:postgres@nhost-db:5432/postgres - - SUPABASE_DB_URL=postgres://postgres:postgres@supabase-db:5432/postgres + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPTIONS_ABUSE + - _APP_OPTIONS_ROUTER_PROTECTION + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-audits: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-audits + container_name: appwrite-worker-audits + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-webhooks: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-webhooks + container_name: appwrite-worker-webhooks + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-deletes: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-deletes + container_name: appwrite-worker-deletes + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + + appwrite-worker-databases: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-databases + container_name: appwrite-worker-databases + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-builds: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-builds + container_name: appwrite-worker-builds + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_VCS_GITHUB_APP_NAME + - _APP_VCS_GITHUB_PRIVATE_KEY + - _APP_VCS_GITHUB_APP_ID + - _APP_FUNCTIONS_TIMEOUT + - _APP_FUNCTIONS_BUILD_TIMEOUT + - _APP_FUNCTIONS_CPUS + - _APP_FUNCTIONS_MEMORY + - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_OPTIONS_FORCE_HTTPS + - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS + - _APP_DOMAIN + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + + appwrite-worker-certificates: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-certificates + container_name: appwrite-worker-certificates + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_DOMAIN_FUNCTIONS + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-functions: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-functions + container_name: appwrite-worker-functions + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + - openruntimes-executor + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_FUNCTIONS_TIMEOUT + - _APP_FUNCTIONS_BUILD_TIMEOUT + - _APP_FUNCTIONS_CPUS + - _APP_FUNCTIONS_MEMORY + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_USAGE_STATS + - _APP_DOCKER_HUB_USERNAME + - _APP_DOCKER_HUB_PASSWORD + - _APP_LOGGING_CONFIG + - _APP_LOGGING_PROVIDER + + appwrite-worker-mails: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-mails + container_name: appwrite-worker-mails + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_SYSTEM_EMAIL_NAME + - _APP_SYSTEM_EMAIL_ADDRESS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_SMTP_HOST + - _APP_SMTP_PORT + - _APP_SMTP_SECURE + - _APP_SMTP_USERNAME + - _APP_SMTP_PASSWORD + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-messaging: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-messaging + container_name: appwrite-worker-messaging + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_SMS_FROM + - _APP_SMS_PROVIDER + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + + appwrite-worker-migrations: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-migrations + container_name: appwrite-worker-migrations + restart: unless-stopped + networks: + - appwrite + depends_on: + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_MIGRATIONS_FIREBASE_CLIENT_ID + - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET + + appwrite-task-maintenance: + image: appwrite/appwrite:1.5.7 + entrypoint: maintenance + container_name: appwrite-task-maintenance + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_DOMAIN_FUNCTIONS + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_MAINTENANCE_INTERVAL + - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_MAINTENANCE_RETENTION_CACHE + - _APP_MAINTENANCE_RETENTION_ABUSE + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY + - _APP_MAINTENANCE_RETENTION_SCHEDULES + + appwrite-worker-usage: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-usage + container_name: appwrite-worker-usage + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_USAGE_AGGREGATION_INTERVAL + + appwrite-worker-usage-dump: + image: appwrite/appwrite:1.5.7 + entrypoint: worker-usage-dump + container_name: appwrite-worker-usage-dump + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_USAGE_AGGREGATION_INTERVAL + + appwrite-task-scheduler-functions: + image: appwrite/appwrite:1.5.7 + entrypoint: schedule-functions + container_name: appwrite-task-scheduler-functions + restart: unless-stopped + networks: + - appwrite + depends_on: + - mariadb + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + + appwrite-task-scheduler-messages: + image: appwrite/appwrite:1.5.7 + entrypoint: schedule-messages + container_name: appwrite-task-scheduler-messages + restart: unless-stopped + networks: + - appwrite + depends_on: + - mariadb + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + + appwrite-assistant: + image: appwrite/assistant:0.4.0 + container_name: appwrite-assistant + + restart: unless-stopped + networks: + - appwrite + environment: + - _APP_ASSISTANT_OPENAI_API_KEY + + openruntimes-executor: + container_name: openruntimes-executor + hostname: exc1 + restart: unless-stopped + stop_signal: SIGINT + image: openruntimes/executor:0.5.5 + networks: + - appwrite + - runtimes + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # Host mount nessessary to share files between executor and runtimes. + # It's not possible to share mount file between 2 containers without host mount (copying is too slow) + - /tmp:/tmp:rw + environment: + - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD + - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL + - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK + - OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME + - OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD + - OPR_EXECUTOR_ENV=$_APP_ENV + - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES + - OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET + - OPR_EXECUTOR_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER + - OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG + - OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE + - OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY + - OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET + - OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION + - OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET + - OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY + - OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET + - OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION + - OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=$_APP_STORAGE_DO_SPACES_BUCKET + - OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=$_APP_STORAGE_BACKBLAZE_ACCESS_KEY + - OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=$_APP_STORAGE_BACKBLAZE_SECRET + - OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=$_APP_STORAGE_BACKBLAZE_REGION + - OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=$_APP_STORAGE_BACKBLAZE_BUCKET + - OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=$_APP_STORAGE_LINODE_ACCESS_KEY + - OPR_EXECUTOR_STORAGE_LINODE_SECRET=$_APP_STORAGE_LINODE_SECRET + - OPR_EXECUTOR_STORAGE_LINODE_REGION=$_APP_STORAGE_LINODE_REGION + - OPR_EXECUTOR_STORAGE_LINODE_BUCKET=$_APP_STORAGE_LINODE_BUCKET + - OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=$_APP_STORAGE_WASABI_ACCESS_KEY + - OPR_EXECUTOR_STORAGE_WASABI_SECRET=$_APP_STORAGE_WASABI_SECRET + - OPR_EXECUTOR_STORAGE_WASABI_REGION=$_APP_STORAGE_WASABI_REGION + - OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET + + mariadb: + image: mariadb:10.11 + container_name: appwrite-mariadb + + restart: unless-stopped + networks: + - appwrite + environment: + - MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS} + - MYSQL_DATABASE=${_APP_DB_SCHEMA} + - MYSQL_USER=${_APP_DB_USER} + - MYSQL_PASSWORD=${_APP_DB_PASS} + - MARIADB_AUTO_UPGRADE=1 + command: 'mysqld --innodb-flush-method=fsync' + + redis: + image: redis:7.2.4-alpine + container_name: appwrite-redis + restart: unless-stopped + command: > + redis-server + --maxmemory 512mb + --maxmemory-policy allkeys-lru + --maxmemory-samples 5 + networks: + - appwrite networks: tests: + name: tests + appwrite: + name: appwrite + runtimes: + name: runtimes diff --git a/phpunit.xml b/phpunit.xml index 9a35000..9dbb40b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -9,8 +9,8 @@ stopOnFailure="false" > - - ./tests/Migration/E2E + + ./tests/Migration/Unit diff --git a/src/Migration/Transfer.php b/src/Migration/Transfer.php index 6049ec9..7a10114 100644 --- a/src/Migration/Transfer.php +++ b/src/Migration/Transfer.php @@ -203,4 +203,20 @@ public function getReport(string $statusLevel = ''): array return $report; } + + /** + * Get Source + */ + public function getSource(): Source + { + return $this->source; + } + + /** + * Get Destination + */ + public function getDestination(): Destination + { + return $this->destination; + } } diff --git a/tests/Migration/E2E/Adapters/Mock.php b/tests/Migration/Unit/Adapters/MockDestination.php similarity index 71% rename from tests/Migration/E2E/Adapters/Mock.php rename to tests/Migration/Unit/Adapters/MockDestination.php index e2c318a..447732e 100644 --- a/tests/Migration/E2E/Adapters/Mock.php +++ b/tests/Migration/Unit/Adapters/MockDestination.php @@ -1,17 +1,17 @@ getStart() === 0) { - $this->data[$resource->getGroup()][$resource->getName()][$resource->getInternalId()] = $resource->asArray(); + $this->data[$resource->getName()][$resource->getInternalId()] = $resource->asArray(); } // file_put_contents($this->path . 'deployments/' . $resource->getId() . '.tar.gz', $resource->getData(), FILE_APPEND); @@ -50,6 +50,9 @@ public function import(array $resources, callable $callback): void case Resource::TYPE_FILE: /** @var File $resource */ break; + default: + $this->data[$resource->getName()][$resource->getId()] = $resource->asArray(); + break; } $resource->setStatus(Resource::STATUS_SUCCESS); @@ -63,4 +66,17 @@ public function report(array $groups = []): array { return []; } + + public function get(string $resource, string $id): ?array + { + if (! array_key_exists($resource, $this->data)) { + return null; + } + + if (! array_key_exists($id, $this->data[$resource])) { + return null; + } + + return $this->data[$resource][$id]; + } } diff --git a/tests/Migration/Unit/Sources/AppwriteTest.php b/tests/Migration/Unit/Sources/AppwriteTest.php new file mode 100644 index 0000000..35eb876 --- /dev/null +++ b/tests/Migration/Unit/Sources/AppwriteTest.php @@ -0,0 +1,263 @@ + 0) { + if ($tries === 0) { + throw new \Exception('Appwrite was offline after 5 tries'); + } + + // Static doesn't have access to $this->call + $ch = curl_init('http://appwrite/v1/health'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + curl_exec($ch); + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($status === 200) { + break; + } + + sleep(5); + $tries--; + } + + Console::info('Bootstrapping Appwrite...'); + + $stdout = ''; + Console::execute( + 'appwrite-toolkit --endpoint http://appwrite/v1 --auto bootstrap --amount 1', + '', + $stdout, + ); + Console::info($stdout); + + Console::info('Running Faker...'); + + $stdout = ''; + Console::execute( + 'appwrite-toolkit --endpoint http://appwrite/v1 --auto faker', + '', + $stdout + ); + Console::info($stdout); + + Console::info('Initial setup complete'); + } + + public function setup(): void + { + // Parse Faker JSON + $projects = json_decode(file_get_contents('projects.json'), true); + $project = $projects[0]; + + $this->source = new Appwrite( + $project['$id'], + 'http://appwrite/v1', + $project['apiKey'] + ); + + $this->client = new Client(); + $this->client + ->setEndpoint('http://appwrite/v1') + ->setProject($project['$id']) + ->setKey($project['apiKey']); + + $this->destination = new MockDestination(); + } + + public function testSourceReport() + { + // Test report all + $report = $this->source->report(); + + $this->assertNotEmpty($report); + + return [ + 'report' => $report, + ]; + } + + /** + * @depends testSourceReport + */ + public function testRunTransfer($state) + { + $transfer = new Transfer($this->source, $this->destination); + + $transfer->run( + $this->source->getSupportedResources(), + function () { + } + ); + + $this->assertEquals(0, count($transfer->getReport('error'))); + + return array_merge($state, [ + 'transfer' => $transfer, + 'source' => $this->source, + ]); + } + + /** + * @depends testRunTransfer + */ + public function testValidateTransfer($state) + { + $statusCounters = $state['transfer']->getStatusCounters(); + $this->assertNotEmpty($statusCounters); + + foreach ($statusCounters as $resource => $counters) { + $this->assertNotEmpty($counters); + + if ($counters[Resource::STATUS_ERROR] > 0) { + $this->fail('Resource ' . $resource . ' has ' . $counters[Resource::STATUS_ERROR] . ' errors'); + + return; + } + } + + return $state; + } + + /** + * @depends testValidateTransfer + */ + public function testValidateAuthTransfer($state): void + { + $userClient = new Users($this->client); + $teamClient = new Teams($this->client); + + /** @var Transfer $transfer */ + $transfer = $state['transfer']; + + /** @var MockDestination $destination */ + $destination = $transfer->getDestination(); + + // Check Users + $last = ''; + while (true) { + $response = $userClient->list( + empty($last) ? [] : [Query::cursorAfter($last)] + ); + + foreach ($response['users'] as $user) { + // Check if exists + $destinationUser = $destination->get('user', $user['$id']); + + if (empty($destinationUser)) { + $this->fail('User ' . $user['$id'] . ' not found in destination'); + } + + // Compare data + $this->assertEquals($user['$id'], $destinationUser['id']); + $this->assertEquals($user['email'], $destinationUser['email']); + $this->assertEquals($user['name'], $destinationUser['username']); + $this->assertEquals($user['password'], $destinationUser['passwordHash']); + $this->assertEquals($user['phone'], $destinationUser['phone']); + $this->assertEquals($user['emailVerification'], $destinationUser['emailVerified']); + $this->assertEquals($user['phoneVerification'], $destinationUser['phoneVerified']); + + $last = $user['$id']; + } + + if (empty($response['sum'])) { + break; + } + } + + // Check Teams + $last = ''; + while (true) { + $response = $teamClient->list( + empty($last) ? [] : [Query::cursorAfter($last)] + ); + + foreach ($response['teams'] as $team) { + // Check if exists + $destinationTeam = $destination->get('team', $team['$id']); + + if (empty($destinationTeam)) { + $this->fail('Team ' . $team['$id'] . ' not found in destination'); + } + + // Compare data + $this->assertEquals($team['$id'], $destinationTeam['id']); + $this->assertEquals($team['name'], $destinationTeam['name']); + $this->assertEquals($team['prefs'], $destinationTeam['preferences']); + + $last = $team['$id']; + } + + if (empty($response['sum'])) { + break; + } + } + } + + /** + * @depends testValidateAuthTransfer + */ + public function testValidateDatabaseTransfer($state): void + { + // Check each resource and make sure it's 1:1 + + // Databases + + // Collections + + // Attributes + + // Indexes + + // Documents + } + + /** + * @depends testValidateDatabaseTransfer + */ + public function testValidateStorageTransfer($state): void + { + // Check each resource and make sure it's 1:1 + + // Validate Buckets + + // Validate Files + } + + /** + * Compare data between original and copy ignoring any fields that are not relevant + * + * + * @return bool + */ + private function compareData(array $original, array $copy, array $ignore) + { + } +} diff --git a/tests/Migration/E2E/Sources/Base.php b/tests/Migration/Unit/Sources/Base.php similarity index 95% rename from tests/Migration/E2E/Sources/Base.php rename to tests/Migration/Unit/Sources/Base.php index c5a7f23..47594fd 100644 --- a/tests/Migration/E2E/Sources/Base.php +++ b/tests/Migration/Unit/Sources/Base.php @@ -1,13 +1,12 @@ destination = new Mock(); + $this->destination = new MockDestination(); $this->transfer = new Transfer($this->source, $this->destination); } diff --git a/tests/Migration/E2E/Sources/NHostTest.php b/tests/Migration/Unit/Sources/NHostTest.php similarity index 96% rename from tests/Migration/E2E/Sources/NHostTest.php rename to tests/Migration/Unit/Sources/NHostTest.php index 4412b3f..37cc577 100644 --- a/tests/Migration/E2E/Sources/NHostTest.php +++ b/tests/Migration/Unit/Sources/NHostTest.php @@ -1,22 +1,14 @@ source->pdo = new \PDO('pgsql:host=nhost-db'.';port=5432;dbname=postgres', 'postgres', 'postgres'); $this->source->storageURL = 'http://nhost-storage'; - $this->destination = new Mock(); + $this->destination = new MockDestination(); $this->transfer = new Transfer($this->source, $this->destination); } diff --git a/tests/Migration/E2E/Sources/SupabaseTest.php b/tests/Migration/Unit/Sources/SupabaseTest.php similarity index 96% rename from tests/Migration/E2E/Sources/SupabaseTest.php rename to tests/Migration/Unit/Sources/SupabaseTest.php index 66b8025..fb9b61c 100644 --- a/tests/Migration/E2E/Sources/SupabaseTest.php +++ b/tests/Migration/Unit/Sources/SupabaseTest.php @@ -1,22 +1,14 @@ destination = new Mock(); + $this->destination = new MockDestination(); $this->transfer = new Transfer($this->source, $this->destination); }