diff --git a/.github/workflows/binary-combine-android.yml b/.github/workflows/binary-combine-android.yml new file mode 100644 index 000000000..d8d32ad49 --- /dev/null +++ b/.github/workflows/binary-combine-android.yml @@ -0,0 +1,46 @@ +name: Android Build Combine + +on: + workflow_call: + +jobs: + build-android-combined: + name: Combine Android binaries + runs-on: ubuntu-latest + steps: + - name: Fetch x86 build + uses: actions/download-artifact@v2 + with: + name: librealm-android-x86 + path: binary/android + - name: Fetch x86_64 build + uses: actions/download-artifact@v2 + with: + name: librealm-android-x86_64 + path: binary/android + - name: Fetch armeabi-v7a build + uses: actions/download-artifact@v2 + with: + name: librealm-android-armeabi-v7a + path: binary/android + - name: Fetch arm64-v8a build + uses: actions/download-artifact@v2 + with: + name: librealm-android-arm64-v8a + path: binary/android + + - name: Store combined artifact + uses: actions/upload-artifact@v2 + with: + name: librealm-android + path: binary/android + retention-days: 1 + + - name: Delete individual build artifacts + uses: geekyeggo/delete-artifact@v1 + with: + name: | + librealm-android-x86 + librealm-android-x86_64 + librealm-android-armeabi-v7a + librealm-android-arm64-v8a \ No newline at end of file diff --git a/.github/workflows/binary-combine-ios.yml b/.github/workflows/binary-combine-ios.yml new file mode 100644 index 000000000..0bee2505c --- /dev/null +++ b/.github/workflows/binary-combine-ios.yml @@ -0,0 +1,50 @@ +name: IOS Build Combine + +on: + workflow_call: + +jobs: + build-ios-xcframework: + name: Combine .xcframework + runs-on: macos-latest + + steps: + - name: Fetch device build + uses: actions/download-artifact@v2 + with: + name: librealm-ios-device + path: binary/ios + - name: Fetch simulator build + uses: actions/download-artifact@v2 + with: + name: librealm-ios-simulator + path: binary/ios + - name: Fetch catalyst build + uses: actions/download-artifact@v2 + with: + name: librealm-ios-catalyst + path: binary/ios + + - name: Build .xcframework + run: | + xcodebuild -create-xcframework \ + -framework ./binary/ios/Release-iphoneos/realm_dart.framework \ + -framework ./binary/ios/Release-iphonesimulator/realm_dart.framework \ + -framework ./binary/ios/Release-maccatalyst/realm_dart.framework \ + -output ./binary/ios/realm_dart.xcframework + rm -rf ./binary/ios/Release-* + + - name: Store .xcframework artifact + uses: actions/upload-artifact@v2 + with: + name: librealm-ios + path: binary/ios + retention-days: 1 + + - name: Delete individual framework artifacts + uses: geekyeggo/delete-artifact@v1 + with: + name: | + librealm-ios-device + librealm-ios-simulator + librealm-ios-catalyst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d6364680..436027f7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,76 +18,21 @@ jobs: runs-on: ubuntu-latest name: Deploy Cluster outputs: - clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} + clusterName: ${{ steps.cluster-name.outputs.clusterName }} steps: - - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 - id: deploy-mdb-apps - with: - realmUrl: ${{ secrets.REALM_QA_URL }} - atlasUrl: ${{ secrets.ATLAS_QA_URL }} - projectId: ${{ secrets.ATLAS_QA_PROJECT_ID }} - apiKey: ${{ secrets.ATLAS_QA_PUBLIC_API_KEY }} - privateApiKey: ${{ secrets.ATLAS_QA_PRIVATE_API_KEY }} - differentiator: realm-dart - - baas-matrix: - needs: - - deploy-cluster - strategy: - fail-fast: false - matrix: - package: [flutter, dart] - platform: [linux, windows, macos] - include: - - platform: ios - package: flutter - - platform: android - package: flutter - - platform: macos-arm - package: dart - runs-on: ubuntu-latest - name: Deploy apps ${{ matrix.platform }} for ${{ matrix.package }} - timeout-minutes: 20 - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: false + - name: Get cluster suffix + id: cluster-name + run: echo "::set-output name=clusterName::dart$(date +'%d%p')" - - name : Setup Dart SDK - uses: dart-lang/setup-dart@main + - uses: realm/ci-actions/mdb-realm/deployApps@63fb0c1678dd750e92709bb6c78aaafd03c5fade with: - sdk: stable - - - name: Deploy Apps - run: | - dart run realm_dart deploy-apps \ - --baas-url ${{ secrets.REALM_QA_URL }} \ - --atlas-cluster ${{ needs.deploy-cluster.outputs.clusterName }} \ - --api-key ${{ secrets.ATLAS_QA_PUBLIC_API_KEY }} \ - --private-api-key ${{ secrets.ATLAS_QA_PRIVATE_API_KEY }} \ - --project-id ${{ secrets.ATLAS_QA_PROJECT_ID }} \ - --differentiator "${{ matrix.package }}-${{ matrix.platform }}" - - cleanup-cluster: - runs-on: ubuntu-latest - name: Cleanup cluster - needs: - - flutter-desktop - - flutter-ios - - flutter-android - - tests-dart - if: always() - timeout-minutes: 5 - steps: - - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 - with: - realmUrl: ${{ secrets.REALM_QA_URL }} + realmUrl: ${{ env.BAAS_URL }} atlasUrl: ${{ secrets.ATLAS_QA_URL }} - projectId: ${{ secrets.ATLAS_QA_PROJECT_ID}} - apiKey: ${{ secrets.ATLAS_QA_PUBLIC_API_KEY}} - privateApiKey: ${{ secrets.ATLAS_QA_PRIVATE_API_KEY }} - differentiator: realm-dart + projectId: ${{ env.BAAS_PROJECT_ID }} + apiKey: ${{ env.BAAS_API_KEY }} + privateApiKey: ${{ env.BAAS_PRIVATE_API_KEY }} + clusterName: ${{ steps.cluster-name.outputs.clusterName }} + useExistingCluster: true build-native: runs-on: ${{ matrix.runner }}-latest @@ -132,8 +77,8 @@ jobs: run: echo "::set-output name=commit::$(git rev-parse HEAD)" - name: Setup Vcpkg - continue-on-error: true if: contains(github.head_ref, 'release/') || steps.check-cache.outputs.cache-hit != 'true' + continue-on-error: true uses: friendlyanon/setup-vcpkg@v1 with: path: src/realm-core/tools/vcpkg/ports @@ -157,116 +102,154 @@ jobs: path: binary/${{ matrix.binary || matrix.preset }}/** retention-days: 1 + build-android-combined: + name: Combine Android binaries + needs: build-native + uses: ./.github/workflows/binary-combine-android.yml + build-ios-xcframework: - name: Combine .xcframework - runs-on: macos-latest + name: Combine IOS binaries needs: build-native + uses: ./.github/workflows/binary-combine-ios.yml + baas-matrix: + needs: + - deploy-cluster + strategy: + fail-fast: false + matrix: + include: + - app: dm + description: dart macos + - app: dma + description: dart macos-arm + - app: dl + description: dart linux + - app: dw + description: dart windows + - app: fm + description: flutter macos + - app: fl + description: flutter linux + - app: fw + description: flutter windows + - app: fa + description: flutter android + - app: fi + description: flutter iOS + runs-on: ubuntu-latest + name: Deploy apps for ${{ matrix.description }} + timeout-minutes: 20 + env: + BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} + BAAS_DIFFERENTIATOR: ${{ matrix.app }}${{ github.run_id }}${{ github.run_attempt }} steps: - - name: Fetch device build - uses: actions/download-artifact@v2 - with: - name: librealm-ios-device - path: binary/ios - - name: Fetch simulator build - uses: actions/download-artifact@v2 - with: - name: librealm-ios-simulator - path: binary/ios - - name: Fetch catalyst build - uses: actions/download-artifact@v2 + - name: Checkout + uses: actions/checkout@v2 with: - name: librealm-ios-catalyst - path: binary/ios + submodules: false - - name: Build .xcframework - run: | - xcodebuild -create-xcframework \ - -framework ./binary/ios/Release-iphoneos/realm_dart.framework \ - -framework ./binary/ios/Release-iphonesimulator/realm_dart.framework \ - -framework ./binary/ios/Release-maccatalyst/realm_dart.framework \ - -output ./binary/ios/realm_dart.xcframework - rm -rf ./binary/ios/Release-* - - - name: Store .xcframework artifact - uses: actions/upload-artifact@v2 + - name : Setup Dart SDK + uses: dart-lang/setup-dart@main with: - name: librealm-ios - path: binary/ios - retention-days: 1 + sdk: stable - - name: Delete individual framework artifacts - uses: geekyeggo/delete-artifact@v1 - with: - name: | - librealm-ios-device - librealm-ios-simulator - librealm-ios-catalyst + - name: Random delay + id: cluster-name + run: echo "sleep $((RANDOM % 10))" - build-android-combined: - name: Combine Android binaries + - name: Deploy Apps + run: | + dart run realm_dart deploy-apps \ + --baas-url ${{ env.BAAS_URL }} \ + --atlas-cluster ${{ env.BAAS_CLUSTER }} \ + --api-key ${{ env.BAAS_API_KEY }} \ + --private-api-key ${{ env.BAAS_PRIVATE_API_KEY }} \ + --project-id ${{ env.BAAS_PROJECT_ID }} \ + --differentiator "${{ env.BAAS_DIFFERENTIATOR }}" + + cleanup-matrix: + needs: + - dart-tests + - flutter-desktop-tests + - flutter-ios + - flutter-android + - deploy-cluster + strategy: + fail-fast: false + matrix: + include: + - app: dm + description: dart macos + - app: dma + description: dart macos-arm + - app: dl + description: dart linux + - app: dw + description: dart windows + - app: fm + description: flutter macos + - app: fl + description: flutter linux + - app: fw + description: flutter windows + - app: fa + description: flutter android + - app: fi + description: flutter iOS runs-on: ubuntu-latest - needs: build-native - + name: Cleanup apps for ${{ matrix.description }} + timeout-minutes: 20 + if: always() + env: + BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} + BAAS_DIFFERENTIATOR: ${{ matrix.app }}${{ github.run_id }}${{ github.run_attempt }} steps: - - name: Fetch x86 build - uses: actions/download-artifact@v2 - with: - name: librealm-android-x86 - path: binary/android - - name: Fetch x86_64 build - uses: actions/download-artifact@v2 - with: - name: librealm-android-x86_64 - path: binary/android - - name: Fetch armeabi-v7a build - uses: actions/download-artifact@v2 - with: - name: librealm-android-armeabi-v7a - path: binary/android - - name: Fetch arm64-v8a build - uses: actions/download-artifact@v2 + - name: Checkout + uses: actions/checkout@v2 with: - name: librealm-android-arm64-v8a - path: binary/android + submodules: false - - name: Store combined artifact - uses: actions/upload-artifact@v2 + - name : Setup Dart SDK + uses: dart-lang/setup-dart@main with: - name: librealm-android - path: binary/android - retention-days: 1 + sdk: stable - - name: Delete individual build artifacts - uses: geekyeggo/delete-artifact@v1 - with: - name: | - librealm-android-x86 - librealm-android-x86_64 - librealm-android-armeabi-v7a - librealm-android-arm64-v8a + - name: Cleanup apps + run: | + dart run realm_dart delete-apps \ + --baas-url ${{ env.BAAS_URL }} \ + --atlas-cluster ${{ env.BAAS_CLUSTER }} \ + --api-key ${{ env.BAAS_API_KEY }} \ + --private-api-key ${{ env.BAAS_PRIVATE_API_KEY }} \ + --project-id ${{ env.BAAS_PROJECT_ID }} \ + --differentiator '${{ env.BAAS_DIFFERENTIATOR }}' # Dart jobs - tests-dart: - runs-on: ${{ matrix.platform == 'linux' && 'ubuntu' || matrix.platform }}-${{ matrix.architecture || 'latest' }} - name: Tests ${{ matrix.platform }} ${{ matrix.architecture }} + dart-tests: strategy: fail-fast: false matrix: include: - - platform: macos - - platform: macos + - os: macos + app: dm + - os: macos architecture: arm - - platform: windows - - platform: linux + app: dma + - os: windows + app: dw + - os: linux + app: dl + runs-on: ${{ matrix.os == 'linux' && 'ubuntu' || matrix.os }}-${{ matrix.architecture || 'latest' }} + name: Dart tests on ${{matrix.os }} ${{ matrix.architecture }} env: BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} - BAAS_DIFFERENTIATOR: dart-${{ matrix.platform }}${{ matrix.architecture && format('-{0}', matrix.architecture) || '' }} + BAAS_DIFFERENTIATOR: ${{ matrix.app }}${{ github.run_id }}${{ github.run_attempt }} needs: - - baas-matrix - deploy-cluster - build-native + - baas-matrix steps: - name: Checkout uses: actions/checkout@v2 @@ -279,8 +262,8 @@ jobs: - name: Fetch artifacts uses: actions/download-artifact@v2 with: - name: librealm-${{ matrix.platform }} - path: binary/${{ matrix.platform }} + name: librealm-${{ matrix.os }} + path: binary/${{ matrix.os }} - name : Setup Dart SDK uses: dart-lang/setup-dart@main @@ -291,46 +274,63 @@ jobs: - name: Install dependencies run: dart pub get + - uses: realm/ci-actions/mdb-realm/deployApps@63fb0c1678dd750e92709bb6c78aaafd03c5fade + with: + realmUrl: ${{ env.BAAS_URL }} + atlasUrl: ${{ secrets.ATLAS_QA_URL }} + projectId: ${{ env.BAAS_PROJECT_ID }} + apiKey: ${{ env.BAAS_API_KEY }} + privateApiKey: ${{ env.BAAS_PRIVATE_API_KEY }} + clusterName: ${{ env.BAAS_CLUSTER }} + useExistingCluster: true + - name: Run tests run: ${{ matrix.architecture == 'arm' && 'arch -arm64 ' || '' }}dart test -r expanded -j 1 --test-randomize-ordering-seed random # Flutter jobs - flutter-desktop: - runs-on: ${{ matrix.platform == 'linux' && 'ubuntu' || matrix.platform }}-latest + flutter-desktop-tests: strategy: fail-fast: false matrix: - platform: [ 'macos', 'windows', 'linux'] - name: Flutter ${{ matrix.platform }} + include: + - os: macos + app: fm + - os: windows + app: fw + - os: linux + app: fl + runs-on: ${{ matrix.os == 'linux' && 'ubuntu' || matrix.os }}-latest + name: Flutter tests on ${{matrix.os }} env: BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} - BAAS_DIFFERENTIATOR: flutter-${{ matrix.platform }} + BAAS_DIFFERENTIATOR: ${{ matrix.app }}${{ github.run_id }}${{ github.run_attempt }} needs: - - baas-matrix - deploy-cluster - build-native + - baas-matrix steps: + - name: Checkout uses: actions/checkout@v2 with: submodules: false - name: Setup GTK - if: ${{ matrix.platform == 'linux' }} + if: ${{ matrix.os == 'linux' }} run: | sudo apt-get update -y sudo apt-get install -y libgtk-3-dev xvfb - name: Setup Ninja - if: ${{ matrix.platform == 'linux' }} + if: ${{ matrix.os == 'linux' }} uses: seanmiddleditch/gha-setup-ninja@master - name: Fetch artifacts uses: actions/download-artifact@v2 with: - name: librealm-${{ matrix.platform }} - path: binary/${{ matrix.platform }} + name: librealm-${{ matrix.os }} + path: binary/${{ matrix.os }} - name: Setup Flutter uses: subosito/flutter-action@v2 @@ -338,13 +338,25 @@ jobs: channel: 'stable' - name: Enable Flutter Desktop support - run: flutter config --enable-${{ matrix.platform }}-desktop + run: flutter config --enable-${{ matrix.os }}-desktop - name: Install dependencies run: flutter pub get + # This will be a no-op under normal circumstances since the cluster would have been deployed + # in deploy-cluster. It is needed in case we want to re-run the job after the cluster has been reaped. + - uses: realm/ci-actions/mdb-realm/deployApps@63fb0c1678dd750e92709bb6c78aaafd03c5fade + with: + realmUrl: ${{ env.BAAS_URL }} + atlasUrl: ${{ secrets.ATLAS_QA_URL }} + projectId: ${{ env.BAAS_PROJECT_ID }} + apiKey: ${{ env.BAAS_API_KEY }} + privateApiKey: ${{ env.BAAS_PRIVATE_API_KEY }} + clusterName: ${{ env.BAAS_CLUSTER }} + useExistingCluster: true + - name: Run tests - run: ${{ matrix.platform == 'linux' && 'xvfb-run ' || '' }}flutter drive -d ${{ matrix.platform }} --target=test_driver/app.dart --suppress-analytics --dart-entrypoint-args="" #--verbose #-a="Some test name" + run: ${{ matrix.os == 'linux' && 'xvfb-run' || '' }} flutter drive -d ${{ matrix.os }} --target=test_driver/app.dart --suppress-analytics --dart-entrypoint-args="" #--verbose #-a="Some test name" working-directory: ./flutter/realm_flutter/tests flutter-ios: @@ -352,12 +364,13 @@ jobs: name: Flutter Tests iOS env: BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} - BAAS_DIFFERENTIATOR: flutter-ios + BAAS_DIFFERENTIATOR: fi${{ github.run_id }}${{ github.run_attempt }} needs: - - baas-matrix - deploy-cluster - build-ios-xcframework + - baas-matrix steps: + - name: Checkout uses: actions/checkout@v2 with: @@ -387,6 +400,16 @@ jobs: os: 'iOS' os_version: '>= 14.0' + - uses: realm/ci-actions/mdb-realm/deployApps@63fb0c1678dd750e92709bb6c78aaafd03c5fade + with: + realmUrl: ${{ env.BAAS_URL }} + atlasUrl: ${{ secrets.ATLAS_QA_URL }} + projectId: ${{ env.BAAS_PROJECT_ID }} + apiKey: ${{ env.BAAS_API_KEY }} + privateApiKey: ${{ env.BAAS_PRIVATE_API_KEY }} + clusterName: ${{ env.BAAS_CLUSTER }} + useExistingCluster: true + - name: Run tests on iOS Simulator run: | flutter drive --target=test_driver/app.dart --dart-define=testName="" --suppress-analytics @@ -397,12 +420,13 @@ jobs: name: Flutter Tests Android env: BAAS_CLUSTER: ${{ needs.deploy-cluster.outputs.clusterName }} - BAAS_DIFFERENTIATOR: flutter-android + BAAS_DIFFERENTIATOR: fa${{ github.run_id }}${{ github.run_attempt }} needs: - - baas-matrix - deploy-cluster - build-android-combined + - baas-matrix steps: + - name: Checkout uses: actions/checkout@v2 with: @@ -424,7 +448,7 @@ jobs: # TODO: move this to device farm - name: Setup Android Emulator cache - uses: actions/cache@v2 + uses: actions/cache@v3.0.4 id: avd-cache with: path: | @@ -445,6 +469,16 @@ jobs: cmake: 3.10.2.4988404 script: echo "Generated Emulator snapshot for caching." + - uses: realm/ci-actions/mdb-realm/deployApps@63fb0c1678dd750e92709bb6c78aaafd03c5fade + with: + realmUrl: ${{ env.BAAS_URL }} + atlasUrl: ${{ secrets.ATLAS_QA_URL }} + projectId: ${{ env.BAAS_PROJECT_ID }} + apiKey: ${{ env.BAAS_API_KEY }} + privateApiKey: ${{ env.BAAS_PRIVATE_API_KEY }} + clusterName: ${{ env.BAAS_CLUSTER }} + useExistingCluster: true + - name: Run tests on Android Emulator uses: reactivecircus/android-emulator-runner@v2 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e24dff4..561bd3d1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Enhancements * Added `DisconnectedSyncConfiguration` for opening a synchronized realm in a disconnected state. This configuration allows a synchronized realm to be opened by a secondary process, while a primary process handles synchronization. ([#621](https://github.com/realm/realm-dart/pull/621)) +### Internal +* Added a command to `realm_dart` for deleting Atlas App Services applications. Usage: `dart run realm_dart delete-apps`. By default it will delete apps from `http://localhost:9090` which is the endpoint of the local docker image. If `--atlas-cluster` is provided, it will authenticate, delete the application from the provided cluster. (PR [#663](https://github.com/realm/realm-dart/pull/663)) + ## 0.3.1+beta (2022-06-07) **This project is in the Beta stage. The API should be quite stable, but occasional breaking changes may be made.** diff --git a/flutter/realm_flutter/tests/test_driver/app_test.dart b/flutter/realm_flutter/tests/test_driver/app_test.dart index ef59d7200..3dfa63b20 100644 --- a/flutter/realm_flutter/tests/test_driver/app_test.dart +++ b/flutter/realm_flutter/tests/test_driver/app_test.dart @@ -27,6 +27,7 @@ void main(List args) { testCommandWithArgs += getArgFromEnvVariable("BAAS_API_KEY"); testCommandWithArgs += getArgFromEnvVariable("BAAS_PRIVATE_API_KEY"); testCommandWithArgs += getArgFromEnvVariable("BAAS_PROJECT_ID"); + testCommandWithArgs += getArgFromEnvVariable("BAAS_DIFFERENTIATOR"); String result = await driver!.requestData(testCommandWithArgs, timeout: const Duration(hours: 1)); if (result.isNotEmpty) { diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/atlas_apps/baas_client.dart similarity index 92% rename from lib/src/cli/deployapps/baas_client.dart rename to lib/src/cli/atlas_apps/baas_client.dart index 98959b7b5..fc2860cbd 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/atlas_apps/baas_client.dart @@ -154,7 +154,7 @@ class BaasClient { } Future _createApp(String name, {String? confirmationType}) async { - print('Creating app $name ($name$_appSuffix)'); + print('Creating app $name$_appSuffix'); final dynamic doc = await _post('groups/$_groupId/apps', '{ "name": "$name$_appSuffix" }'); final appId = doc['_id'] as String; @@ -180,10 +180,12 @@ class BaasClient { "runResetFunction": true }'''); + print('Creating database db_$name$_appSuffix'); + await _createMongoDBService(app, '''{ "flexible_sync": { "state": "enabled", - "database_name": "$_differentiator-$name", + "database_name": "db_$name$_appSuffix", "queryable_fields_names": ["differentiator", "stringQueryField", "boolQueryField", "intQueryField"], "permissions": { "rules": {}, @@ -208,7 +210,7 @@ class BaasClient { } Future enableProvider(BaasApp app, String type, [String config = '{}']) async { - print('Enabling provider $type for ${app.name}'); + print('Enabling provider $type for ${app.clientAppId}'); final url = 'groups/$_groupId/apps/$app/auth_providers'; if (type == 'api-key') { @@ -226,6 +228,16 @@ class BaasClient { } } + Future deleteApps() async { + var apps = await _getApps(); + for (final app in apps) { + print('Deleting app ${app.clientAppId}'); + + await _deleteApp(app.appId); + print("App with id='${app.appId}' is deleted."); + } + } + Future _authenticate(String provider, String credentials) async { dynamic response = await _post('auth/providers/$provider/login', credentials); @@ -233,7 +245,7 @@ class BaasClient { } Future _createFunction(BaasApp app, String name, String source) async { - print('Creating function $name for ${app.name}...'); + print('Creating function $name for ${app.clientAppId}...'); final dynamic response = await _post('groups/$_groupId/apps/$app/functions', '''{ "name": "$name", @@ -246,7 +258,7 @@ class BaasClient { } Future _updateFunction(BaasApp app, String name, String functionId, String source) async { - print('Updating function $name for ${app.name}...'); + print('Updating function $name for ${app.clientAppId}...'); await _put('groups/$_groupId/apps/$app/functions/$functionId', '''{ "name": "$name", @@ -285,7 +297,7 @@ class BaasClient { } Future _createService(BaasApp app, String name, String type, String config) async { - print('Creating service $name for ${app.name}'); + print('Creating service $name for ${app.clientAppId}'); final dynamic response = await _post('groups/$_groupId/apps/$app/services', '''{ "name": "$name", @@ -296,6 +308,10 @@ class BaasClient { return response['_id'] as String; } + Future _deleteApp(String appId) async { + await _delete('groups/$_groupId/apps/$appId'); + } + Map _getHeaders([Map? additionalHeaders]) { if (additionalHeaders == null) { return _headers; @@ -329,6 +345,11 @@ class BaasClient { return _decodeResponse(response, payload); } + Future _delete(String relativePath, {String? payload}) async { + var response = await http.delete(_getUri(relativePath), headers: _getHeaders({'Content-Type': 'application/json'}), body: payload); + return _decodeResponse(response, payload); + } + dynamic _decodeResponse(http.Response response, [String? payload]) { if (response.statusCode > 399 || response.statusCode < 200) { throw Exception('Failed to ${response.request?.method} ${response.request?.url}: ${response.statusCode} ${response.body}. Body: $payload'); @@ -344,9 +365,9 @@ class BaasClient { if (input.length < 8) { return input; } - - final hash = md5.convert(utf8.encode(input)).toString(); - return hash.substring(0, 8); + //Take first 4 and last 4 symbols + final result = input.replaceRange(4, input.length - 4, ''); + return result; } } diff --git a/lib/src/cli/atlas_apps/deleteapps_command.dart b/lib/src/cli/atlas_apps/deleteapps_command.dart new file mode 100644 index 000000000..4cd893658 --- /dev/null +++ b/lib/src/cli/atlas_apps/deleteapps_command.dart @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2022 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +import 'dart:async'; +import 'dart:io'; + +import 'package:args/command_runner.dart'; +import 'options.dart'; +import 'baas_client.dart'; + +class DeleteAppsCommand extends Command { + @override + final String description = 'Delete test applications from MongoDB Atlas.'; + + @override + final String name = 'delete-apps'; + + @override + bool get hidden => true; + + late Options options; + + DeleteAppsCommand() { + populateOptionsParser(argParser); + } + + @override + FutureOr? run() async { + options = parseOptionsResult(argResults!); + + if (options.atlasCluster != null) { + if (options.apiKey == null) { + abort('--api-key must be supplied when --atlas-cluster is not set'); + } + + if (options.privateApiKey == null) { + abort('--private-api-key must be supplied when --atlas-cluster is not set'); + } + + if (options.projectId == null) { + abort('--project-id must be supplied when --atlas-cluster is not set'); + } + } + final differentiator = options.differentiator ?? 'local'; + + final client = await (options.atlasCluster == null + ? BaasClient.docker(options.baasUrl, differentiator) + : BaasClient.atlas(options.baasUrl, options.atlasCluster!, options.apiKey!, options.privateApiKey!, options.projectId!, differentiator)); + + await client.deleteApps(); + } + + void abort(String error) { + print(error); + print(usage); + exit(64); //usage error + } +} diff --git a/lib/src/cli/deployapps/deployapps_command.dart b/lib/src/cli/atlas_apps/deployapps_command.dart similarity index 95% rename from lib/src/cli/deployapps/deployapps_command.dart rename to lib/src/cli/atlas_apps/deployapps_command.dart index 561cd736e..cf0db2a9b 100644 --- a/lib/src/cli/deployapps/deployapps_command.dart +++ b/lib/src/cli/atlas_apps/deployapps_command.dart @@ -67,9 +67,13 @@ class DeployAppsCommand extends Command { final apps = await client.getOrCreateApps(); print('App import is complete. There are: ${apps.length} apps on the server:'); + List listApps = []; apps.forEach((_, value) { print(" App '${value.name}': '${value.clientAppId}'"); + listApps.add(value.appId); }); + print("appIds: "); + print(listApps.join(",")); } void abort(String error) { diff --git a/lib/src/cli/deployapps/options.dart b/lib/src/cli/atlas_apps/options.dart similarity index 100% rename from lib/src/cli/deployapps/options.dart rename to lib/src/cli/atlas_apps/options.dart diff --git a/lib/src/cli/deployapps/options.g.dart b/lib/src/cli/atlas_apps/options.g.dart similarity index 100% rename from lib/src/cli/deployapps/options.g.dart rename to lib/src/cli/atlas_apps/options.g.dart diff --git a/lib/src/cli/main.dart b/lib/src/cli/main.dart index bb8d48b8f..9a5ac019c 100644 --- a/lib/src/cli/main.dart +++ b/lib/src/cli/main.dart @@ -25,7 +25,8 @@ import 'install/install_command.dart'; import 'metrics/metrics_command.dart'; import 'archive/archive_command.dart'; import 'extract/extract_command.dart'; -import 'deployapps/deployapps_command.dart'; +import 'atlas_apps/deployapps_command.dart'; +import 'atlas_apps/deleteapps_command.dart'; void main(List arguments) { CommandRunner("dart run realm|realm_dart", 'Realm commands for working with Realm Flutter & Dart SDKs.') @@ -35,6 +36,7 @@ void main(List arguments) { ..addCommand(ArchiveCommand()) ..addCommand(ExtractCommand()) ..addCommand(DeployAppsCommand()) + ..addCommand(DeleteAppsCommand()) ..run(arguments).catchError((Object error) { if (error is UsageException) { print(error); diff --git a/test/README.md b/test/README.md index 0e2dddb43..853bc282f 100644 --- a/test/README.md +++ b/test/README.md @@ -29,15 +29,20 @@ BAAS_PROJECT_ID= ``` 10) Now you can run `dart test` and it should include the integration tests. -If you are a MongoDB employee, you can instead choose to run the tests against [cloud-dev](https://cloud-dev.mongodb.com). +If you are a MongoDB employee, you can instead choose to run the tests against [cloud-qa](https://cloud-qa.mongodb.com). The procedure is the same, except you need to use your qa credentials instead. - + * If you don't have access to [cloud-qa](https://cloud-qa.mongodb.com), please follow these steps: + * Make request for access to Okta Group `10gen-mms-non-prod` using [mana](https://mana.corp.mongodbgov.com/). + * Browse [cloud-qa](https://cloud-qa.mongodb.com/) and try to reset your password using `Forgot password` option. + * Then login into [cloud-qa](https://cloud-qa.mongodb.com/) and you can create your own `Organization` + * The CI workflow is working with `Realm CI QA` organization. In order to have access to this organization you have to be invited. + * `Dart GHA QA` is the name of the project used by CI workflow. ## Run integration tests against the BaaS docker image -MongoDB employees can run a local docker image that hosts baas and a mongodb database. It is the recommended way to -do day-to-day development as it allows you to get into a clean slate with a single command. +MongoDB employees can run a local docker image that hosts BaaS and a MongoDb database. It is the recommended way to +do day-to-day development as it allows you to get into a clean state with a single command. ### Prerequisites @@ -53,7 +58,7 @@ do day-to-day development as it allows you to get into a clean slate with a sing * Don't forget to Copy the new token. * Then run the following commands: - - For MacOS anf Linux: + - For MacOS and Linux: ```sh $ export CR_PAT=YOUR_TOKEN $ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin @@ -67,7 +72,7 @@ do day-to-day development as it allows you to get into a clean slate with a sing - USERNAME is your [GitHub](https://github.com/) username. - YOUR_TOKEN is the token copied from the previous step. - * Enter your [GitHub](https://github.com/) password. And the output should be `> Login Succeeded`. + * Enter your [GitHub](https://github.com/) password. And the output should be `> Login Succeeded`. 4. Take note of your local machine IP address (it has to be the actual IP address, not localhost or 127.0.0.1). 5. Run the docker image: @@ -79,7 +84,7 @@ do day-to-day development as it allows you to get into a clean slate with a sing * `some_empty_folder` is a mount empty folder to /apps. If not done, the docker image will import a sample app which will mess up the test setup. * `baas_version` is the version of the image you'd like to use. See versions at [mongodb-realm-test-server](https://github.com/realm/ci/pkgs/container/ci%2Fmongodb-realm-test-server). - For MacOS anf Linux: + For MacOS and Linux: ```sh baas_hostname="10.0.1.123" baas_access_key="" diff --git a/test/test.dart b/test/test.dart index ec8e596c4..023f3ec0c 100644 --- a/test/test.dart +++ b/test/test.dart @@ -27,7 +27,7 @@ import 'package:test/test.dart' hide test; import 'package:test/test.dart' as testing; import 'package:args/args.dart'; import '../lib/realm.dart'; -import '../lib/src/cli/deployapps/baas_client.dart'; +import '../lib/src/cli/atlas_apps/baas_client.dart'; import '../lib/src/native/realm_core.dart'; import '../lib/src/configuration.dart'; @@ -368,6 +368,8 @@ Future getAppConfig({AppNames appName = AppNames.flexible}) as app.clientAppId, baseUrl: Uri.parse(baasUrl!), baseFilePath: temporaryDir, + maxConnectionTimeout: Duration(minutes: 10), + defaultRequestTimeout: Duration(minutes: 7), ); }