From 89c8c45e551384571cff7e29b09c69a7e8cd51b1 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 16:55:34 +0100 Subject: [PATCH 01/24] Add jobs to deploy and cleanup baas on cloud-dev --- .github/workflows/realm-dart-linux.yml | 39 ++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml index c8fb5d226..0be8e8f9d 100644 --- a/.github/workflows/realm-dart-linux.yml +++ b/.github/workflows/realm-dart-linux.yml @@ -9,11 +9,28 @@ on: pull_request: jobs: + deploy-baas: + runs-on: ubuntu-latest + name: Deploy BaaS + outputs: + clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} + timeout-minutes: 20 + steps: + - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 + id: deploy-mdb-apps + with: + projectId: ${{ secrets.ATLAS_PROJECT_ID}} + realmUrl: ${{ secrets.REALM_BASE_URL }} + atlasUrl: ${{ secrets.ATLAS_BASE_URL}} + apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + differentiator: dart-linux CI: runs-on: ubuntu-latest env: REALM_CI: true - + needs: + - deploy-baas steps: - name: Checkout uses: actions/checkout@v2 @@ -38,7 +55,7 @@ jobs: run: | dart test -r expanded -j 1 --test-randomize-ordering-seed random echo "ARCHIVE_PATH=$(pwd)/binary/linux.tar.gz" >> $GITHUB_ENV - + - name: Archive binary if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} run: | @@ -57,4 +74,20 @@ jobs: artifacts: ${{ env.ARCHIVE_PATH }} body: "ADD RELEASE NOTES" omitBodyDuringUpdate: true - token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + token: ${{ secrets.GITHUB_TOKEN }} + cleanup-baas: + runs-on: ubuntu-latest + name: Cleanup BaaS + needs: + - CI + if: always() + timeout-minutes: 5 + steps: + - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 + with: + projectId: ${{ secrets.ATLAS_PROJECT_ID}} + realmUrl: ${{ secrets.REALM_BASE_URL }} + atlasUrl: ${{ secrets.ATLAS_BASE_URL}} + apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + differentiator: dart-linux From 458d34d6ef23a9c44cc6bb27bb236c230bb5619b Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 19:51:14 +0100 Subject: [PATCH 02/24] Trigger a build --- .github/workflows/realm-dart-linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml index 0be8e8f9d..854254ab4 100644 --- a/.github/workflows/realm-dart-linux.yml +++ b/.github/workflows/realm-dart-linux.yml @@ -25,6 +25,7 @@ jobs: apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux + CI: runs-on: ubuntu-latest env: From e4309bfa07ae10d21dadad33a1dd85ebe7441f6b Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 20:02:07 +0100 Subject: [PATCH 03/24] Don't be so secretive about the urls --- .github/workflows/realm-dart-linux.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml index 854254ab4..eafbdd931 100644 --- a/.github/workflows/realm-dart-linux.yml +++ b/.github/workflows/realm-dart-linux.yml @@ -20,8 +20,8 @@ jobs: id: deploy-mdb-apps with: projectId: ${{ secrets.ATLAS_PROJECT_ID}} - realmUrl: ${{ secrets.REALM_BASE_URL }} - atlasUrl: ${{ secrets.ATLAS_BASE_URL}} + realmUrl: https://realm-dev.mongodb.com + atlasUrl: https://cloud-dev.mongodb.com apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux @@ -87,8 +87,8 @@ jobs: - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 with: projectId: ${{ secrets.ATLAS_PROJECT_ID}} - realmUrl: ${{ secrets.REALM_BASE_URL }} - atlasUrl: ${{ secrets.ATLAS_BASE_URL}} + realmUrl: https://realm-dev.mongodb.com + atlasUrl: https://cloud-dev.mongodb.com apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux From 7eeb93e4ea9213939868bba6491c7eb09c7f2d8d Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 20:26:26 +0100 Subject: [PATCH 04/24] Add a PR build --- .github/workflows/pr.yml | 112 ++++++++++++++++++++ .github/workflows/realm-dart-linux.yml | 1 - .github/workflows/realm-dart-macos.yml | 1 - .github/workflows/realm-dart-windows.yml | 1 - .github/workflows/realm-flutter-android.yml | 1 - .github/workflows/realm-flutter-ios.yml | 5 +- .github/workflows/realm-flutter-linux.yml | 1 - .github/workflows/realm-flutter-macos.yml | 3 +- .github/workflows/realm-flutter-windows.yml | 1 - .github/workflows/realm-generator.yml | 1 - 10 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/pr.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 000000000..6ff5651e3 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,112 @@ +name: PR Build + +on: + push: + branches: + - master + tags: + - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: +env: + REALM_CI: true + +jobs: + # deploy-baas: + # runs-on: ubuntu-latest + # name: Deploy BaaS + # outputs: + # clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} + # timeout-minutes: 20 + # steps: + # - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 + # id: deploy-mdb-apps + # with: + # projectId: ${{ secrets.ATLAS_PROJECT_ID}} + # realmUrl: https://realm-dev.mongodb.com + # atlasUrl: https://cloud-dev.mongodb.com + # apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + # privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + # differentiator: dart-linux + + build-linux: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@master + - name: Build Realm Dart for Linux + run: ./scripts/build-linux.sh + - name: Store artifacts + uses: actions/upload-artifact@v2 + with: + name: librealm-linux + path: binary/** + retention-days: 1 + + tests-linux: + runs-on: ubuntu-latest + needs: + # - deploy-baas + - build-linux + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: Fetch artifacts + uses: actions/download-artifact@v2 + with: + name: librealm-linux + path: binary + + - name : Setup Dart SDK + uses: dart-lang/setup-dart@main + with: + sdk: stable + + - name: Install dependencies + run: dart pub get + + - name: Run tests + run: | + dart test -r expanded -j 1 --test-randomize-ordering-seed random + echo "ARCHIVE_PATH=$(pwd)/binary/linux.tar.gz" >> $GITHUB_ENV + + - name: Archive binary + if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} + run: | + dart run realm_dart archive --source-dir $(pwd)/binary/linux --output-file $ARCHIVE_PATH + + - name: Release artifacts + if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifactErrorsFailBuild: true + draft: true + omitNameDuringUpdate: true + prerelease: false + omitPrereleaseDuringUpdate: true + artifacts: ${{ env.ARCHIVE_PATH }} + body: "ADD RELEASE NOTES" + omitBodyDuringUpdate: true + token: ${{ secrets.GITHUB_TOKEN }} + # cleanup-baas: + # runs-on: ubuntu-latest + # name: Cleanup BaaS + # needs: + # - CI + # if: always() + # timeout-minutes: 5 + # steps: + # - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 + # with: + # projectId: ${{ secrets.ATLAS_PROJECT_ID}} + # realmUrl: https://realm-dev.mongodb.com + # atlasUrl: https://cloud-dev.mongodb.com + # apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + # privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + # differentiator: dart-linux diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml index eafbdd931..a6341d738 100644 --- a/.github/workflows/realm-dart-linux.yml +++ b/.github/workflows/realm-dart-linux.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: deploy-baas: diff --git a/.github/workflows/realm-dart-macos.yml b/.github/workflows/realm-dart-macos.yml index 3f3837f8e..84bbecbe2 100644 --- a/.github/workflows/realm-dart-macos.yml +++ b/.github/workflows/realm-dart-macos.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: diff --git a/.github/workflows/realm-dart-windows.yml b/.github/workflows/realm-dart-windows.yml index 9aa017692..68bd5c212 100644 --- a/.github/workflows/realm-dart-windows.yml +++ b/.github/workflows/realm-dart-windows.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-android.yml b/.github/workflows/realm-flutter-android.yml index 4adcfd10d..af23fc4b6 100644 --- a/.github/workflows/realm-flutter-android.yml +++ b/.github/workflows/realm-flutter-android.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-ios.yml b/.github/workflows/realm-flutter-ios.yml index faac106a3..76af0eedd 100644 --- a/.github/workflows/realm-flutter-ios.yml +++ b/.github/workflows/realm-flutter-ios.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: @@ -48,7 +47,7 @@ jobs: uses: subosito/flutter-action@v2 with: channel: 'stable' - + - name: Install dependencies run: flutter pub get @@ -87,5 +86,5 @@ jobs: artifacts: ${{ env.ARCHIVE_PATH }} body: "ADD RELEASE NOTES" omitBodyDuringUpdate: true - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/realm-flutter-linux.yml b/.github/workflows/realm-flutter-linux.yml index 5116106d9..7bb110e10 100644 --- a/.github/workflows/realm-flutter-linux.yml +++ b/.github/workflows/realm-flutter-linux.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-macos.yml b/.github/workflows/realm-flutter-macos.yml index e882a093e..a0e3f8f37 100644 --- a/.github/workflows/realm-flutter-macos.yml +++ b/.github/workflows/realm-flutter-macos.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: @@ -37,4 +36,4 @@ jobs: - name: Run tests run: flutter drive -d macos --target=test_driver/app.dart --suppress-analytics --dart-entrypoint-args="" #--verbose #-a="Some test name" working-directory: ./flutter/realm_flutter/tests - + diff --git a/.github/workflows/realm-flutter-windows.yml b/.github/workflows/realm-flutter-windows.yml index 552328081..46627e84a 100644 --- a/.github/workflows/realm-flutter-windows.yml +++ b/.github/workflows/realm-flutter-windows.yml @@ -6,7 +6,6 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: jobs: CI: diff --git a/.github/workflows/realm-generator.yml b/.github/workflows/realm-generator.yml index 3f61acd79..31b1a8af9 100644 --- a/.github/workflows/realm-generator.yml +++ b/.github/workflows/realm-generator.yml @@ -4,7 +4,6 @@ on: push: branches: - master - pull_request: jobs: CI: From a47a3f87e310cb13bf43674e8d6de7ceaaadb116 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 20:49:24 +0100 Subject: [PATCH 05/24] Bring back baas --- .github/workflows/pr.yml | 91 +++++++++++++++------------------------- bin/README.md | 14 +++---- 2 files changed, 41 insertions(+), 64 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6ff5651e3..eb6b2418a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,32 +4,31 @@ on: push: branches: - master - tags: - - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta pull_request: env: REALM_CI: true jobs: - # deploy-baas: - # runs-on: ubuntu-latest - # name: Deploy BaaS - # outputs: - # clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} - # timeout-minutes: 20 - # steps: - # - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 - # id: deploy-mdb-apps - # with: - # projectId: ${{ secrets.ATLAS_PROJECT_ID}} - # realmUrl: https://realm-dev.mongodb.com - # atlasUrl: https://cloud-dev.mongodb.com - # apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} - # privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} - # differentiator: dart-linux + baas-linux: + runs-on: ubuntu-latest + name: BaaS Linux + outputs: + clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} + timeout-minutes: 20 + steps: + - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 + id: deploy-mdb-apps + with: + projectId: ${{ secrets.ATLAS_PROJECT_ID}} + realmUrl: https://realm-dev.mongodb.com + atlasUrl: https://cloud-dev.mongodb.com + apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + differentiator: dart-linux build-linux: runs-on: ubuntu-latest + name: Build Linux steps: - name: Checkout uses: actions/checkout@v2 @@ -48,8 +47,9 @@ jobs: tests-linux: runs-on: ubuntu-latest + name: Tests Linux needs: - # - deploy-baas + - baas-linux - build-linux steps: - name: Checkout @@ -61,52 +61,29 @@ jobs: with: name: librealm-linux path: binary - - name : Setup Dart SDK uses: dart-lang/setup-dart@main with: sdk: stable - - name: Install dependencies run: dart pub get - - name: Run tests run: | dart test -r expanded -j 1 --test-randomize-ordering-seed random - echo "ARCHIVE_PATH=$(pwd)/binary/linux.tar.gz" >> $GITHUB_ENV - - name: Archive binary - if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} - run: | - dart run realm_dart archive --source-dir $(pwd)/binary/linux --output-file $ARCHIVE_PATH - - - name: Release artifacts - if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} - uses: ncipollo/release-action@v1 + cleanup-baas: + runs-on: ubuntu-latest + name: Cleanup Linux + needs: + - tests-linux + if: always() + timeout-minutes: 5 + steps: + - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 with: - allowUpdates: true - artifactErrorsFailBuild: true - draft: true - omitNameDuringUpdate: true - prerelease: false - omitPrereleaseDuringUpdate: true - artifacts: ${{ env.ARCHIVE_PATH }} - body: "ADD RELEASE NOTES" - omitBodyDuringUpdate: true - token: ${{ secrets.GITHUB_TOKEN }} - # cleanup-baas: - # runs-on: ubuntu-latest - # name: Cleanup BaaS - # needs: - # - CI - # if: always() - # timeout-minutes: 5 - # steps: - # - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 - # with: - # projectId: ${{ secrets.ATLAS_PROJECT_ID}} - # realmUrl: https://realm-dev.mongodb.com - # atlasUrl: https://cloud-dev.mongodb.com - # apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} - # privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} - # differentiator: dart-linux + projectId: ${{ secrets.ATLAS_PROJECT_ID}} + realmUrl: https://realm-dev.mongodb.com + atlasUrl: https://cloud-dev.mongodb.com + apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + differentiator: dart-linux diff --git a/bin/README.md b/bin/README.md index cadb536c3..45e26943a 100644 --- a/bin/README.md +++ b/bin/README.md @@ -1,10 +1,10 @@ -Dart packages should distribute their prebuilt native extension binaries (if any) in the lib directory of the package. -This is where Dart VM looks for the binary when an application loads the Dart package. -On Windows Dart VM have a bug which looks for the package with incorrect path. -For Realm Dart this is something like C:\C:\\realm_dart\lib\src\realm_dart.dartrealm_dart_extension.dll. -The name of the native extension binary and the device letter is incorreth path on Windows. +Dart packages should distribute their prebuilt native extension binaries (if any) in the lib directory of the package. +This is where Dart VM looks for the binary when an application loads the Dart package. +On Windows Dart VM have a bug which looks for the package with incorrect path. +For Realm Dart this is something like C:\C:\\realm_dart\lib\src\realm_dart.dartrealm_dart_extension.dll. +The name of the native extension binary and the device letter is incorrect path on Windows. To workaround this bug Realm Dart package has a script in its binary directory which copies the native extension to the correct place on Windows -When the Dart VM bug is fixed Realm Dart package should move the native extension dll to its lib directory and this script will not be needed. +When the Dart VM bug is fixed Realm Dart package should move the native extension dll to its lib directory and this script will not be needed. -In order to use the Realm Dart package application developers should execute `pub run realm_dart install` from the root directory of their Dart application. \ No newline at end of file +In order to use the Realm Dart package application developers should execute `pub run realm_dart install` from the root directory of their Dart application. \ No newline at end of file From 319cd2d15182c040884500f0fd2bcdf045bbab8f Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Wed, 23 Mar 2022 22:17:59 +0100 Subject: [PATCH 06/24] Baas client WIP --- pubspec.yaml | 5 +- test/baas_client.dart | 89 ++++++++++++++++++++++++++++++++++++ test/configuration_test.dart | 7 ++- test/list_test.dart | 2 +- test/realm_object_test.dart | 2 +- test/realm_test.dart | 2 +- test/results_test.dart | 2 +- test/test.dart | 33 +++++++++++-- 8 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 test/baas_client.dart diff --git a/pubspec.yaml b/pubspec.yaml index b9089585a..d7912cdea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: pub_semver: ^2.1.0 realm_common: path: ./common - realm_generator: + realm_generator: path: ./generator tar: ^0.5.4 build_runner: ^2.1.0 @@ -35,8 +35,9 @@ dev_dependencies: json_serializable: ^6.1.0 lints: ^1.0.1 test: ^1.14.3 + http: ^0.13.4 -platforms: +platforms: windows: linux: macos: \ No newline at end of file diff --git a/test/baas_client.dart b/test/baas_client.dart new file mode 100644 index 000000000..48c34f8e4 --- /dev/null +++ b/test/baas_client.dart @@ -0,0 +1,89 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2021 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 'package:http/http.dart' as http; +import 'dart:convert'; + +class BaasClient { + final String _baseUrl; + final Map _headers; + + late String _groupId; + + BaasClient._(String baseUrl) + : _baseUrl = "$baseUrl/api/admin/v3.0", + _headers = {'Accept': 'application/json'}; + + static Future docker(String baseUrl) async { + final BaasClient result = BaasClient._(baseUrl); + + await result._authenticate("local-userpass", {'username': "unique_user@domain.com", 'password': "password"}); + + dynamic groupDoc = await result._get("auth/profile"); + result._groupId = (groupDoc['roles'] as List)[0]['group_id'] as String; + + print("Current GroupID ${result._groupId}"); + + return result; + } + + static Future atlas(String baseUrl, String cluster, String apiKey, String privateApiKey, String groupId) async { + final BaasClient result = BaasClient._(baseUrl); + + return result; + } + + Future _authenticate(String provider, Object credentials) async { + dynamic response = await _post("auth/providers/$provider/login", credentials); + + _headers['Authorization'] = "Bearer ${response['access_token']}"; + } + + Map _getHeaders([Map? additionalHeaders]) { + if (additionalHeaders == null) { + return _headers; + } + + additionalHeaders.addAll(_headers); + return additionalHeaders; + } + + Uri _getUri(String relativePath) { + return Uri.parse("$_baseUrl/$relativePath"); + } + + Future _post(String relativePath, Object object) async { + var response = await http.post(_getUri(relativePath), headers: _getHeaders({'Content-Type': 'application/json'}), body: jsonEncode(object)); + + if (response.statusCode > 399 || response.statusCode < 200) { + throw Exception("Failed to post $relativePath: ${response.statusCode} ${response.body}"); + } + + return jsonDecode(response.body); + } + + Future _get(String relativePath) async { + var response = await http.get(_getUri(relativePath), headers: _getHeaders()); + + if (response.statusCode > 399 || response.statusCode < 200) { + throw Exception("Failed to get $relativePath: ${response.statusCode} ${response.body}"); + } + + return jsonDecode(response.body); + } +} diff --git a/test/configuration_test.dart b/test/configuration_test.dart index 396647335..0e254882e 100644 --- a/test/configuration_test.dart +++ b/test/configuration_test.dart @@ -25,7 +25,7 @@ import 'test.dart'; Future main([List? args]) async { print("Current PID $pid"); - setupTests(args); + await setupTests(args); test('Configuration can be created', () { Configuration([Car.schema]); @@ -108,7 +108,7 @@ Future main([List? args]) async { expect(() => realm.write(() {}), throws("Can't perform transactions on read-only Realms.")); realm.close(); }); - + test('Configuration inMemory - no files after closing realm', () { Configuration config = Configuration([Car.schema], inMemory: true); var realm = Realm(config); @@ -125,11 +125,10 @@ Future main([List? args]) async { expect(() => Realm(config), throws("Realm at path '${config.path}' already opened with different read permissions")); realm.close(); }); - + test('Configuration - FIFO files fallback path', () { Configuration config = Configuration([Car.schema], fifoFilesFallbackPath: "./fifo_folder"); var realm = Realm(config); realm.close(); }); - } diff --git a/test/list_test.dart b/test/list_test.dart index 487aa3c3d..ba7376af4 100644 --- a/test/list_test.dart +++ b/test/list_test.dart @@ -26,7 +26,7 @@ import 'test.dart'; Future main([List? args]) async { print("Current PID $pid"); - setupTests(args); + await setupTests(args); test('Lists add object with a list property', () { var config = Configuration([Team.schema, Person.schema]); diff --git a/test/realm_object_test.dart b/test/realm_object_test.dart index 854c8a117..de8927710 100644 --- a/test/realm_object_test.dart +++ b/test/realm_object_test.dart @@ -27,7 +27,7 @@ import 'test.dart'; Future main([List? args]) async { print("Current PID $pid"); - setupTests(args); + await setupTests(args); test('RealmObject get property', () { var config = Configuration([Car.schema]); diff --git a/test/realm_test.dart b/test/realm_test.dart index 84bc66213..a06cda829 100644 --- a/test/realm_test.dart +++ b/test/realm_test.dart @@ -27,7 +27,7 @@ import 'test.dart'; Future main([List? args]) async { print("Current PID $pid"); - setupTests(args); + await setupTests(args); test('Realm can be created', () { var config = Configuration([Car.schema]); diff --git a/test/results_test.dart b/test/results_test.dart index 02c387104..cf7633518 100644 --- a/test/results_test.dart +++ b/test/results_test.dart @@ -26,7 +26,7 @@ import 'test.dart'; Future main([List? args]) async { print("Current PID $pid"); - setupTests(args); + await setupTests(args); test('Results all should not return null', () { var config = Configuration([Car.schema]); diff --git a/test/test.dart b/test/test.dart index 3f56b4495..cc68cf33d 100644 --- a/test/test.dart +++ b/test/test.dart @@ -22,6 +22,7 @@ import 'package:path/path.dart' as _path; import 'package:test/test.dart' hide test; import 'package:test/test.dart' as testing; import '../lib/realm.dart'; +import './baas_client.dart'; part 'test.g.dart'; @@ -73,6 +74,8 @@ class _School { } String? testName; +List? baasApps; + //Overrides test method so we can filter tests void test(String? name, dynamic Function() testFunction, {dynamic skip}) { if (testName != null && !name!.contains(testName!)) { @@ -92,9 +95,11 @@ void xtest(String? name, dynamic Function() testFunction) { testing.test(name, testFunction, skip: "Test is disabled"); } -void setupTests(List? args) { +Future setupTests(List? args) async { parseTestNameFromArguments(args); + await setupBaas(); + setUp(() { String path = "${generateRandomString(10)}.realm"; if (Platform.isAndroid || Platform.isIOS) { @@ -153,8 +158,28 @@ void parseTestNameFromArguments(List? arguments) { return; } - int nameArgIndex = arguments.indexOf("--name"); - if (nameArgIndex >= 0 && arguments.length > 1) { - testName = arguments[nameArgIndex + 1]; + testName = getArg("name", arguments); +} + +Future setupBaas() async { + var baasUrl = Platform.environment['BAAS_URL']; + var cluster = Platform.environment['BAAS_CLUSTER']; + var apiKey = Platform.environment['BAAS_API_KEY']; + var privateApiKey = Platform.environment['BAAS_PRIVATE_API_KEY']; + var projectId = Platform.environment['BAAS_PROJECT_ID']; + + if (baasUrl == null) { + return; } + + final BaasClient client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); +} + +String? getArg(String name, List arguments) { + int argIndex = arguments.indexOf("--$name"); + if (argIndex >= 0 && arguments.length > argIndex) { + return arguments[argIndex + 1]; + } + + return null; } From 9ace801ec495f9cc7d538147d78e22624d3700f8 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 15:33:59 +0100 Subject: [PATCH 07/24] Wrap up the baas client --- .github/workflows/pr.yml | 6 ++ test/baas_client.dart | 217 ++++++++++++++++++++++++++++++++++++--- test/test.dart | 12 ++- 3 files changed, 220 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index eb6b2418a..2943215cf 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -48,6 +48,12 @@ jobs: tests-linux: runs-on: ubuntu-latest name: Tests Linux + env: + BAAS_URL: https://realm-dev.mongodb.com + BAAS_CLUSTER: ${{ needs.baas-linux.outputs.clusterName }} + BAAS_API_KEY: ${{ secrets.ATLAS_PUBLIC_API_KEY }} + BAAS_PRIVATE_API_KEY: ${{ secrets.ATLAS_PRIVATE_API_KEY }} + BAAS_PROJECT_ID: ${{ secrets.ATLAS_PROJECT_ID}} needs: - baas-linux - build-linux diff --git a/test/baas_client.dart b/test/baas_client.dart index 48c34f8e4..5857e1ebd 100644 --- a/test/baas_client.dart +++ b/test/baas_client.dart @@ -20,19 +20,40 @@ import 'package:http/http.dart' as http; import 'dart:convert'; class BaasClient { + static const String _confirmFuncSource = '''exports = ({ token, tokenId, username }) => { + // process the confirm token, tokenId and username + if (username.includes("realm_tests_do_autoverify")) { + return { status: 'success' } + } + // do not confirm the user + return { status: 'fail' }; + };'''; + + static const String _resetFuncSource = '''exports = ({ token, tokenId, username, password }) => { + // process the reset token, tokenId, username and password + if (password.includes("realm_tests_do_reset")) { + return { status: 'success' }; + } + // will not reset the password + return { status: 'fail' }; + };'''; + final String _baseUrl; + final String? _clusterName; + final String _appSuffix; final Map _headers; late String _groupId; - BaasClient._(String baseUrl) + BaasClient._(String baseUrl, [this._clusterName]) : _baseUrl = "$baseUrl/api/admin/v3.0", - _headers = {'Accept': 'application/json'}; + _headers = {'Accept': 'application/json'}, + _appSuffix = "-$_clusterName"; static Future docker(String baseUrl) async { final BaasClient result = BaasClient._(baseUrl); - await result._authenticate("local-userpass", {'username': "unique_user@domain.com", 'password': "password"}); + await result._authenticate("local-userpass", '{ "username": "unique_user@domain.com", "password": "password" }'); dynamic groupDoc = await result._get("auth/profile"); result._groupId = (groupDoc['roles'] as List)[0]['group_id'] as String; @@ -43,17 +64,161 @@ class BaasClient { } static Future atlas(String baseUrl, String cluster, String apiKey, String privateApiKey, String groupId) async { - final BaasClient result = BaasClient._(baseUrl); + final BaasClient result = BaasClient._(baseUrl, cluster); + + await result._authenticate("mongodb-cloud", '{ "username": "$apiKey", "apiKey": "$privateApiKey" }'); + + result._groupId = groupId; return result; } - Future _authenticate(String provider, Object credentials) async { + Future> getApps() async { + final apps = await _get("groups/$_groupId/apps") as List; + return apps + .map((dynamic doc) { + final name = doc['name'] as String; + if (!name.endsWith(_appSuffix)) { + return null; + } + + final appName = name.substring(0, name.length - _appSuffix.length); + return BaasApp(doc['_id'] as String, doc['client_app_id'] as String, appName); + }) + .where((doc) => doc != null) + .map((doc) => doc!) + .toList(); + } + + Future createApp(String name) async { + print("Creating app $name"); + + final dynamic doc = await _post("groups/$_groupId/apps", '{ "name": "$name$_appSuffix" }'); + final appId = doc['_id'] as String; + final clientAppId = doc['client_app_id'] as String; + + final app = BaasApp(appId, clientAppId, name); + + final confirmFuncId = await _createFunction(app, "confirmFunc", _confirmFuncSource); + final resetFuncId = await _createFunction(app, "resetFunc", _resetFuncSource); + + enableProvider(app, "anon-user"); + enableProvider(app, "local-userpass", '''{ + "autoConfirm": false, + "confirmEmailSubject": "", + "confirmationFunctionName": "confirmFunc", + "confirmationFunctionId": "$confirmFuncId", + "emailConfirmationUrl": "http://localhost/confirmEmail", + "resetFunctionName": "resetFunc", + "resetFunctionId": "$resetFuncId", + "resetPasswordSubject": "", + "resetPasswordUrl": "http://localhost/resetPassword", + "runConfirmationFunction": true, + "runResetFunction": true + }'''); + + await _createMongoDBService(app, '''{ + "flexible_sync": { + "state": "enabled", + "database_name": "flexible_sync_data", + "queryable_fields_names": ["TODO"], + "permissions": { + "rules": {}, + "defaultRoles": [ + { + "name": "all", + "applyWhen": {}, + "read": true, + "write": true + } + ] + } + } + }'''); + + await _put("groups/$_groupId/apps/$app/sync/config", '{ "development_mode_enabled": true }'); + + return app; + } + + Future enableProvider(BaasApp app, String type, [String config = '{}']) async { + print("Enabling provider $type for ${app.name}"); + + final url = "groups/$_groupId/apps/$app/auth_providers"; + if (type == 'api-key') { + final providers = await _get(url) as List; + final apiKeyProviderId = providers.singleWhere((dynamic doc) => doc['type'] == 'api-key')['_id'] as String; + + await _put("$url/$apiKeyProviderId/enable", "{}"); + } else { + await _post(url, '''{ + "name": "$type", + "type": "$type", + "disabled": false, + "config": $config + }'''); + } + } + + Future _authenticate(String provider, String credentials) async { dynamic response = await _post("auth/providers/$provider/login", credentials); _headers['Authorization'] = "Bearer ${response['access_token']}"; } + Future _createFunction(BaasApp app, String name, String source) async { + print("Creating function $name for ${app.name}..."); + + final dynamic response = await _post("groups/$_groupId/apps/$app/functions", '''{ + "name": "$name", + "source": ${jsonEncode(source)}, + "private": false, + "can_evaluate": {} + }'''); + + return response['_id'] as String; + } + + Future _createMongoDBService(BaasApp app, String syncConfig) async { + final serviceName = _clusterName == null ? 'mongodb' : 'mongodb-atlas'; + final mongoConfig = _clusterName == null ? '{ "uri": "mongodb://localhost:26000" }' : '{ "clusterName": "$_clusterName" }'; + final mongoServiceId = await createService(app, 'BackingDB', serviceName, mongoConfig); + + // The cluster linking must be separated from enabling sync because Atlas + // takes a few seconds to provision a user for BaaS, meaning enabling sync + // will fail if we attempt to do it with the same request. It's nondeterministic + // how long it'll take, so we must retry for a while. + var attempt = 0; + while (true) { + try { + await _patch("groups/$_groupId/apps/$app/services/$mongoServiceId/config", syncConfig); + break; + } catch (err) { + if (attempt++ < 1) { + print("Failed to update service after ${attempt * 5} seconds. Will keep retrying ..."); + + await Future.delayed(Duration(seconds: 5)); + } else { + rethrow; + } + } + } + + return mongoServiceId; + } + + Future createService(BaasApp app, String name, String type, String config) async { + print("Creating service $name for ${app.name}"); + + final dynamic response = await _post("groups/$_groupId/apps/$app/services", '''{ + "name": "$name", + "type": "$type", + "config": $config + }'''); + + return response['_id'] as String; + } + Map _getHeaders([Map? additionalHeaders]) { if (additionalHeaders == null) { return _headers; @@ -67,23 +232,47 @@ class BaasClient { return Uri.parse("$_baseUrl/$relativePath"); } - Future _post(String relativePath, Object object) async { - var response = await http.post(_getUri(relativePath), headers: _getHeaders({'Content-Type': 'application/json'}), body: jsonEncode(object)); - - if (response.statusCode > 399 || response.statusCode < 200) { - throw Exception("Failed to post $relativePath: ${response.statusCode} ${response.body}"); - } - - return jsonDecode(response.body); + Future _post(String relativePath, String payload) async { + var response = await http.post(_getUri(relativePath), headers: _getHeaders({'Content-Type': 'application/json'}), body: payload); + return _decodeResponse(response, payload); } Future _get(String relativePath) async { var response = await http.get(_getUri(relativePath), headers: _getHeaders()); + return _decodeResponse(response); + } + + Future _put(String relativePath, String payload) async { + var response = await http.put(_getUri(relativePath), headers: _getHeaders({'Content-Type': 'application/json'}), body: payload); + return _decodeResponse(response, payload); + } + + Future _patch(String relativePath, String payload) async { + var response = await http.patch(_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 get $relativePath: ${response.statusCode} ${response.body}"); + throw Exception("Failed to ${response.request?.method} ${response.request?.url}: ${response.statusCode} ${response.body}. Body: $payload"); } + if (response.body.isEmpty) { + return {}; + } return jsonDecode(response.body); } } + +class BaasApp { + final String appId; + final String clientAppId; + final String name; + + BaasApp(this.appId, this.clientAppId, this.name); + + @override + String toString() { + return appId; + } +} diff --git a/test/test.dart b/test/test.dart index cc68cf33d..23b8808ed 100644 --- a/test/test.dart +++ b/test/test.dart @@ -74,7 +74,7 @@ class _School { } String? testName; -List? baasApps; +Map baasApps = {}; //Overrides test method so we can filter tests void test(String? name, dynamic Function() testFunction, {dynamic skip}) { @@ -173,6 +173,16 @@ Future setupBaas() async { } final BaasClient client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); + var apps = await client.getApps(); + if (apps.isNotEmpty) { + for (var app in apps) { + baasApps[app.name] = app; + } + } else { + final defaultApp = await client.createApp("flexible"); + + baasApps[defaultApp.name] = defaultApp; + } } String? getArg(String name, List arguments) { From ea9d9c1da9ec35c91c2dfff8b8d931bbd38ad035 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 16:32:01 +0100 Subject: [PATCH 08/24] Try to deploy apps earlier --- .github/workflows/pr.yml | 11 ++- .../src/cli/deployapps}/baas_client.dart | 20 ++++- .../cli/deployapps/deployapps_command.dart | 78 +++++++++++++++++++ lib/src/cli/deployapps/options.dart | 47 +++++++++++ lib/src/cli/deployapps/options.g.dart | 48 ++++++++++++ lib/src/cli/main.dart | 2 + test/test.dart | 12 +-- 7 files changed, 203 insertions(+), 15 deletions(-) rename {test => lib/src/cli/deployapps}/baas_client.dart (95%) create mode 100644 lib/src/cli/deployapps/deployapps_command.dart create mode 100644 lib/src/cli/deployapps/options.dart create mode 100644 lib/src/cli/deployapps/options.g.dart diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 2943215cf..79b7f6547 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,13 +19,18 @@ jobs: - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 id: deploy-mdb-apps with: - projectId: ${{ secrets.ATLAS_PROJECT_ID}} + projectId: ${{ secrets.ATLAS_PROJECT_ID }} realmUrl: https://realm-dev.mongodb.com atlasUrl: https://cloud-dev.mongodb.com - apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} + apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY }} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux - + - name : Setup Dart SDK + uses: dart-lang/setup-dart@main + with: + sdk: stable + - name: Deploy Apps + run: dart run realm_dart deploy-apps --baas-url https://realm-dev.mongodb.com --atlas-cluster ${{ steps.deploy-mdb-apps.outputs.clusterName }} --api-key ${{ secrets.ATLAS_PUBLIC_API_KEY }} --private-api-key ${{ secrets.ATLAS_PRIVATE_API_KEY }} --project-id ${{ secrets.ATLAS_PROJECT_ID }} build-linux: runs-on: ubuntu-latest name: Build Linux diff --git a/test/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart similarity index 95% rename from test/baas_client.dart rename to lib/src/cli/deployapps/baas_client.dart index 5857e1ebd..d7f7552f3 100644 --- a/test/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -73,7 +73,23 @@ class BaasClient { return result; } - Future> getApps() async { + Future> getOrCreateApps() async { + final result = {}; + var apps = await _getApps(); + if (apps.isNotEmpty) { + for (var app in apps) { + result[app.name] = app; + } + } else { + final defaultApp = await _createApp("flexible"); + + result[defaultApp.name] = defaultApp; + } + + return result; + } + + Future> _getApps() async { final apps = await _get("groups/$_groupId/apps") as List; return apps .map((dynamic doc) { @@ -90,7 +106,7 @@ class BaasClient { .toList(); } - Future createApp(String name) async { + Future _createApp(String name) async { print("Creating app $name"); final dynamic doc = await _post("groups/$_groupId/apps", '{ "name": "$name$_appSuffix" }'); diff --git a/lib/src/cli/deployapps/deployapps_command.dart b/lib/src/cli/deployapps/deployapps_command.dart new file mode 100644 index 000000000..05e418158 --- /dev/null +++ b/lib/src/cli/deployapps/deployapps_command.dart @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 DeployAppsCommand extends Command { + @override + final String description = 'Deploys test applications to a MongoDB Realm server.'; + + @override + final String name = 'deploy-apps'; + + @override + bool get hidden => true; + + late Options options; + + DeployAppsCommand() { + 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 BaasClient client = await (options.atlasCluster == null + ? BaasClient.docker(options.baasUrl) + : BaasClient.atlas(options.baasUrl, options.atlasCluster!, options.apiKey!, options.privateApiKey!, options.projectId!)); + + final apps = await client.getOrCreateApps(); + + print('App import is complete. There are: ${apps.length} apps on the server:'); + apps.forEach((_, value) { + print(" App '${value.name}': '${value.clientAppId}'"); + }); + } + + void abort(String error) { + print(error); + print(usage); + exit(64); //usage error + } +} diff --git a/lib/src/cli/deployapps/options.dart b/lib/src/cli/deployapps/options.dart new file mode 100644 index 000000000..35628da41 --- /dev/null +++ b/lib/src/cli/deployapps/options.dart @@ -0,0 +1,47 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 'package:build_cli_annotations/build_cli_annotations.dart'; + +part 'options.g.dart'; + +@CliOptions() +class Options { + @CliOption(help: "Url for MongoDB Realm.", defaultsTo: "http://localhost:9090") + final String baasUrl; + + @CliOption(help: "Atlas Cluster to link in the application.") + final String? atlasCluster; + + @CliOption(help: "Atlas API key to use for the import. Only used if atlas-cluster is specified.") + final String? apiKey; + + @CliOption(help: "The private Atlas API key to use for the import. Only used if atlas-cluster is specified.") + final String? privateApiKey; + + @CliOption(help: "The Atlas project id to use for the import. Only used if atlas-cluster is specified.") + final String? projectId; + + Options(this.baasUrl, {this.atlasCluster, this.apiKey, this.privateApiKey, this.projectId}); +} + +String get usage => _$parserForOptions.usage; + +ArgParser populateOptionsParser(ArgParser p) => _$populateOptionsParser(p); + +Options parseOptionsResult(ArgResults results) => _$parseOptionsResult(results); diff --git a/lib/src/cli/deployapps/options.g.dart b/lib/src/cli/deployapps/options.g.dart new file mode 100644 index 000000000..6a10e9101 --- /dev/null +++ b/lib/src/cli/deployapps/options.g.dart @@ -0,0 +1,48 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'options.dart'; + +// ************************************************************************** +// CliGenerator +// ************************************************************************** + +Options _$parseOptionsResult(ArgResults result) => Options( + result['baas-url'] as String, + atlasCluster: result['atlas-cluster'] as String?, + apiKey: result['api-key'] as String?, + privateApiKey: result['private-api-key'] as String?, + projectId: result['project-id'] as String?, + ); + +ArgParser _$populateOptionsParser(ArgParser parser) => parser + ..addOption( + 'baas-url', + help: 'Url for MongoDB Realm.', + defaultsTo: 'http://localhost:9090', + ) + ..addOption( + 'atlas-cluster', + help: 'Atlas Cluster to link in the application.', + ) + ..addOption( + 'api-key', + help: + 'Atlas API key to use for the import. Only used if atlas-cluster is specified.', + ) + ..addOption( + 'private-api-key', + help: + 'The private Atlas API key to use for the import. Only used if atlas-cluster is specified.', + ) + ..addOption( + 'project-id', + help: + 'The Atlas project id to use for the import. Only used if atlas-cluster is specified.', + ); + +final _$parserForOptions = _$populateOptionsParser(ArgParser()); + +Options parseOptions(List args) { + final result = _$parserForOptions.parse(args); + return _$parseOptionsResult(result); +} diff --git a/lib/src/cli/main.dart b/lib/src/cli/main.dart index 080015b47..bb8d48b8f 100644 --- a/lib/src/cli/main.dart +++ b/lib/src/cli/main.dart @@ -25,6 +25,7 @@ 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'; void main(List arguments) { CommandRunner("dart run realm|realm_dart", 'Realm commands for working with Realm Flutter & Dart SDKs.') @@ -33,6 +34,7 @@ void main(List arguments) { ..addCommand(InstallCommand()) ..addCommand(ArchiveCommand()) ..addCommand(ExtractCommand()) + ..addCommand(DeployAppsCommand()) ..run(arguments).catchError((Object error) { if (error is UsageException) { print(error); diff --git a/test/test.dart b/test/test.dart index 23b8808ed..bfabbee84 100644 --- a/test/test.dart +++ b/test/test.dart @@ -22,7 +22,7 @@ import 'package:path/path.dart' as _path; import 'package:test/test.dart' hide test; import 'package:test/test.dart' as testing; import '../lib/realm.dart'; -import './baas_client.dart'; +import '../lib/src/cli/deployapps/baas_client.dart'; part 'test.g.dart'; @@ -173,16 +173,8 @@ Future setupBaas() async { } final BaasClient client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); - var apps = await client.getApps(); - if (apps.isNotEmpty) { - for (var app in apps) { - baasApps[app.name] = app; - } - } else { - final defaultApp = await client.createApp("flexible"); - baasApps[defaultApp.name] = defaultApp; - } + baasApps.addAll(await client.getOrCreateApps()); } String? getArg(String name, List arguments) { From e29f855f22194448a9f4358d042fc98a36e0dba4 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 17:42:42 +0100 Subject: [PATCH 09/24] Trigger build --- lib/src/cli/deployapps/baas_client.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index d7f7552f3..b162a0872 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2021 Realm Inc. +// 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. From 3a837112a00ccc1b19db844e7dca9018c9e6962d Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 18:10:09 +0100 Subject: [PATCH 10/24] Do a proper checkout --- .github/workflows/pr.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 79b7f6547..81990e6c1 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -16,6 +16,10 @@ jobs: clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} timeout-minutes: 20 steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: false - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 id: deploy-mdb-apps with: From b89715fc9f9d4f02b50c32530ba92c61d5ae4e48 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 18:13:25 +0100 Subject: [PATCH 11/24] Revert unrelated change --- test/test.dart | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/test/test.dart b/test/test.dart index bfabbee84..f1d9f8779 100644 --- a/test/test.dart +++ b/test/test.dart @@ -158,7 +158,10 @@ void parseTestNameFromArguments(List? arguments) { return; } - testName = getArg("name", arguments); + int nameArgIndex = arguments.indexOf("--name"); + if (nameArgIndex >= 0 && arguments.length > nameArgIndex) { + testName = arguments[nameArgIndex + 1]; + } } Future setupBaas() async { @@ -176,12 +179,3 @@ Future setupBaas() async { baasApps.addAll(await client.getOrCreateApps()); } - -String? getArg(String name, List arguments) { - int argIndex = arguments.indexOf("--$name"); - if (argIndex >= 0 && arguments.length > argIndex) { - return arguments[argIndex + 1]; - } - - return null; -} From 8ae6ab1f7c8fe8880286b3ad03ed0b2f7e5962ac Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 19:19:42 +0100 Subject: [PATCH 12/24] Revert linux workflow --- .github/workflows/realm-dart-linux.yml | 35 -------------------------- 1 file changed, 35 deletions(-) diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml index a6341d738..32566eee5 100644 --- a/.github/workflows/realm-dart-linux.yml +++ b/.github/workflows/realm-dart-linux.yml @@ -8,29 +8,10 @@ on: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta jobs: - deploy-baas: - runs-on: ubuntu-latest - name: Deploy BaaS - outputs: - clusterName: ${{ steps.deploy-mdb-apps.outputs.clusterName }} - timeout-minutes: 20 - steps: - - uses: realm/ci-actions/mdb-realm/deployApps@fac1d6958f03d71de743305ce3ab27594efbe7b7 - id: deploy-mdb-apps - with: - projectId: ${{ secrets.ATLAS_PROJECT_ID}} - realmUrl: https://realm-dev.mongodb.com - atlasUrl: https://cloud-dev.mongodb.com - apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} - privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} - differentiator: dart-linux - CI: runs-on: ubuntu-latest env: REALM_CI: true - needs: - - deploy-baas steps: - name: Checkout uses: actions/checkout@v2 @@ -75,19 +56,3 @@ jobs: body: "ADD RELEASE NOTES" omitBodyDuringUpdate: true token: ${{ secrets.GITHUB_TOKEN }} - cleanup-baas: - runs-on: ubuntu-latest - name: Cleanup BaaS - needs: - - CI - if: always() - timeout-minutes: 5 - steps: - - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 - with: - projectId: ${{ secrets.ATLAS_PROJECT_ID}} - realmUrl: https://realm-dev.mongodb.com - atlasUrl: https://cloud-dev.mongodb.com - apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} - privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} - differentiator: dart-linux From b452e1fd8c8ef519654af7ab3d8aed21fe20bf00 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 19:42:45 +0100 Subject: [PATCH 13/24] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kasper Overgård Nielsen --- lib/src/cli/deployapps/baas_client.dart | 2 +- lib/src/cli/deployapps/deployapps_command.dart | 2 +- test/test.dart | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index b162a0872..2654f0951 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -51,7 +51,7 @@ class BaasClient { _appSuffix = "-$_clusterName"; static Future docker(String baseUrl) async { - final BaasClient result = BaasClient._(baseUrl); + final result = BaasClient._(baseUrl); await result._authenticate("local-userpass", '{ "username": "unique_user@domain.com", "password": "password" }'); diff --git a/lib/src/cli/deployapps/deployapps_command.dart b/lib/src/cli/deployapps/deployapps_command.dart index 05e418158..ebdecb9da 100644 --- a/lib/src/cli/deployapps/deployapps_command.dart +++ b/lib/src/cli/deployapps/deployapps_command.dart @@ -58,7 +58,7 @@ class DeployAppsCommand extends Command { } } - final BaasClient client = await (options.atlasCluster == null + final client = await (options.atlasCluster == null ? BaasClient.docker(options.baasUrl) : BaasClient.atlas(options.baasUrl, options.atlasCluster!, options.apiKey!, options.privateApiKey!, options.projectId!)); diff --git a/test/test.dart b/test/test.dart index f1d9f8779..5e1165401 100644 --- a/test/test.dart +++ b/test/test.dart @@ -165,17 +165,17 @@ void parseTestNameFromArguments(List? arguments) { } Future setupBaas() async { - var baasUrl = Platform.environment['BAAS_URL']; - var cluster = Platform.environment['BAAS_CLUSTER']; - var apiKey = Platform.environment['BAAS_API_KEY']; - var privateApiKey = Platform.environment['BAAS_PRIVATE_API_KEY']; - var projectId = Platform.environment['BAAS_PROJECT_ID']; + final baasUrl = Platform.environment['BAAS_URL']; + final cluster = Platform.environment['BAAS_CLUSTER']; + final apiKey = Platform.environment['BAAS_API_KEY']; + final privateApiKey = Platform.environment['BAAS_PRIVATE_API_KEY']; + final projectId = Platform.environment['BAAS_PROJECT_ID']; if (baasUrl == null) { return; } - final BaasClient client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); + final client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); baasApps.addAll(await client.getOrCreateApps()); } From b083f338ac4574a18f09a09aabc7f0789989fb4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 24 Mar 2022 20:01:56 +0100 Subject: [PATCH 14/24] Nitpicking suggestions --- lib/src/cli/deployapps/baas_client.dart | 56 ++++++++++++------------- lib/src/cli/deployapps/options.dart | 10 ++--- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index 2654f0951..df0d09577 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -46,19 +46,19 @@ class BaasClient { late String _groupId; BaasClient._(String baseUrl, [this._clusterName]) - : _baseUrl = "$baseUrl/api/admin/v3.0", + : _baseUrl = '$baseUrl/api/admin/v3.0', _headers = {'Accept': 'application/json'}, - _appSuffix = "-$_clusterName"; + _appSuffix = '-$_clusterName'; static Future docker(String baseUrl) async { final result = BaasClient._(baseUrl); - await result._authenticate("local-userpass", '{ "username": "unique_user@domain.com", "password": "password" }'); + await result._authenticate('local-userpass', '{ "username": "unique_user@domain.com", "password": "password" }'); - dynamic groupDoc = await result._get("auth/profile"); + dynamic groupDoc = await result._get('auth/profile'); result._groupId = (groupDoc['roles'] as List)[0]['group_id'] as String; - print("Current GroupID ${result._groupId}"); + print('Current GroupID ${result._groupId}'); return result; } @@ -66,7 +66,7 @@ class BaasClient { static Future atlas(String baseUrl, String cluster, String apiKey, String privateApiKey, String groupId) async { final BaasClient result = BaasClient._(baseUrl, cluster); - await result._authenticate("mongodb-cloud", '{ "username": "$apiKey", "apiKey": "$privateApiKey" }'); + await result._authenticate('mongodb-cloud', '{ "username": "$apiKey", "apiKey": "$privateApiKey" }'); result._groupId = groupId; @@ -77,11 +77,11 @@ class BaasClient { final result = {}; var apps = await _getApps(); if (apps.isNotEmpty) { - for (var app in apps) { + for (final app in apps) { result[app.name] = app; } } else { - final defaultApp = await _createApp("flexible"); + final defaultApp = await _createApp('flexible'); result[defaultApp.name] = defaultApp; } @@ -90,7 +90,7 @@ class BaasClient { } Future> _getApps() async { - final apps = await _get("groups/$_groupId/apps") as List; + final apps = await _get('groups/$_groupId/apps') as List; return apps .map((dynamic doc) { final name = doc['name'] as String; @@ -107,19 +107,19 @@ class BaasClient { } Future _createApp(String name) async { - print("Creating app $name"); + print('Creating app $name'); - final dynamic doc = await _post("groups/$_groupId/apps", '{ "name": "$name$_appSuffix" }'); + final dynamic doc = await _post('groups/$_groupId/apps', '{ "name": "$name$_appSuffix" }'); final appId = doc['_id'] as String; final clientAppId = doc['client_app_id'] as String; final app = BaasApp(appId, clientAppId, name); - final confirmFuncId = await _createFunction(app, "confirmFunc", _confirmFuncSource); - final resetFuncId = await _createFunction(app, "resetFunc", _resetFuncSource); + final confirmFuncId = await _createFunction(app, 'confirmFunc', _confirmFuncSource); + final resetFuncId = await _createFunction(app, 'resetFunc', _resetFuncSource); - enableProvider(app, "anon-user"); - enableProvider(app, "local-userpass", '''{ + enableProvider(app, 'anon-user'); + enableProvider(app, 'local-userpass', '''{ "autoConfirm": false, "confirmEmailSubject": "", "confirmationFunctionName": "confirmFunc", @@ -152,20 +152,20 @@ class BaasClient { } }'''); - await _put("groups/$_groupId/apps/$app/sync/config", '{ "development_mode_enabled": true }'); + await _put('groups/$_groupId/apps/$app/sync/config', '{ "development_mode_enabled": true }'); return app; } Future enableProvider(BaasApp app, String type, [String config = '{}']) async { - print("Enabling provider $type for ${app.name}"); + print('Enabling provider $type for ${app.name}'); - final url = "groups/$_groupId/apps/$app/auth_providers"; + final url = 'groups/$_groupId/apps/$app/auth_providers'; if (type == 'api-key') { final providers = await _get(url) as List; final apiKeyProviderId = providers.singleWhere((dynamic doc) => doc['type'] == 'api-key')['_id'] as String; - await _put("$url/$apiKeyProviderId/enable", "{}"); + await _put('$url/$apiKeyProviderId/enable', '{}'); } else { await _post(url, '''{ "name": "$type", @@ -177,15 +177,15 @@ class BaasClient { } Future _authenticate(String provider, String credentials) async { - dynamic response = await _post("auth/providers/$provider/login", credentials); + dynamic response = await _post('auth/providers/$provider/login', credentials); _headers['Authorization'] = "Bearer ${response['access_token']}"; } Future _createFunction(BaasApp app, String name, String source) async { - print("Creating function $name for ${app.name}..."); + print('Creating function $name for ${app.name}...'); - final dynamic response = await _post("groups/$_groupId/apps/$app/functions", '''{ + final dynamic response = await _post('groups/$_groupId/apps/$app/functions', '''{ "name": "$name", "source": ${jsonEncode(source)}, "private": false, @@ -207,11 +207,11 @@ class BaasClient { var attempt = 0; while (true) { try { - await _patch("groups/$_groupId/apps/$app/services/$mongoServiceId/config", syncConfig); + await _patch('groups/$_groupId/apps/$app/services/$mongoServiceId/config', syncConfig); break; } catch (err) { if (attempt++ < 1) { - print("Failed to update service after ${attempt * 5} seconds. Will keep retrying ..."); + print('Failed to update service after ${attempt * 5} seconds. Will keep retrying ...'); await Future.delayed(Duration(seconds: 5)); } else { @@ -224,9 +224,9 @@ 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.name}'); - final dynamic response = await _post("groups/$_groupId/apps/$app/services", '''{ + final dynamic response = await _post('groups/$_groupId/apps/$app/services', '''{ "name": "$name", "type": "$type", "config": $config @@ -245,7 +245,7 @@ class BaasClient { } Uri _getUri(String relativePath) { - return Uri.parse("$_baseUrl/$relativePath"); + return Uri.parse('$_baseUrl/$relativePath'); } Future _post(String relativePath, String payload) async { @@ -270,7 +270,7 @@ class BaasClient { 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"); + throw Exception('Failed to ${response.request?.method} ${response.request?.url}: ${response.statusCode} ${response.body}. Body: $payload'); } if (response.body.isEmpty) { diff --git a/lib/src/cli/deployapps/options.dart b/lib/src/cli/deployapps/options.dart index 35628da41..7df2e88c1 100644 --- a/lib/src/cli/deployapps/options.dart +++ b/lib/src/cli/deployapps/options.dart @@ -22,19 +22,19 @@ part 'options.g.dart'; @CliOptions() class Options { - @CliOption(help: "Url for MongoDB Realm.", defaultsTo: "http://localhost:9090") + @CliOption(help: 'Url for MongoDB Realm.', defaultsTo: 'http://localhost:9090') final String baasUrl; - @CliOption(help: "Atlas Cluster to link in the application.") + @CliOption(help: 'Atlas Cluster to link in the application.') final String? atlasCluster; - @CliOption(help: "Atlas API key to use for the import. Only used if atlas-cluster is specified.") + @CliOption(help: 'Atlas API key to use for the import. Only used if atlas-cluster is specified.') final String? apiKey; - @CliOption(help: "The private Atlas API key to use for the import. Only used if atlas-cluster is specified.") + @CliOption(help: 'The private Atlas API key to use for the import. Only used if atlas-cluster is specified.') final String? privateApiKey; - @CliOption(help: "The Atlas project id to use for the import. Only used if atlas-cluster is specified.") + @CliOption(help: 'The Atlas project id to use for the import. Only used if atlas-cluster is specified.') final String? projectId; Options(this.baasUrl, {this.atlasCluster, this.apiKey, this.privateApiKey, this.projectId}); From fd7f6af1e43f93f654b4822b0bc9b5cf6fcec4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Thu, 24 Mar 2022 20:15:29 +0100 Subject: [PATCH 15/24] Prefer const ctors --- lib/src/cli/deployapps/baas_client.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index df0d09577..8030b4e64 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -213,7 +213,7 @@ class BaasClient { if (attempt++ < 1) { print('Failed to update service after ${attempt * 5} seconds. Will keep retrying ...'); - await Future.delayed(Duration(seconds: 5)); + await Future.delayed(const Duration(seconds: 5)); } else { rethrow; } From 699ee86db453a02d1e36019fa3381bbe986c7665 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 20:15:48 +0100 Subject: [PATCH 16/24] Fix workflow --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 81990e6c1..4c6af7fda 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -86,7 +86,7 @@ jobs: run: | dart test -r expanded -j 1 --test-randomize-ordering-seed random - cleanup-baas: + cleanup-linux: runs-on: ubuntu-latest name: Cleanup Linux needs: From c2aa08b9352c8d6198eabdae5dfef99df9643c81 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 20:30:47 +0100 Subject: [PATCH 17/24] Remove some default args --- .github/workflows/pr.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4c6af7fda..47f7bc5de 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -24,8 +24,6 @@ jobs: id: deploy-mdb-apps with: projectId: ${{ secrets.ATLAS_PROJECT_ID }} - realmUrl: https://realm-dev.mongodb.com - atlasUrl: https://cloud-dev.mongodb.com apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY }} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux @@ -97,8 +95,6 @@ jobs: - uses: realm/ci-actions/mdb-realm/cleanup@fac1d6958f03d71de743305ce3ab27594efbe7b7 with: projectId: ${{ secrets.ATLAS_PROJECT_ID}} - realmUrl: https://realm-dev.mongodb.com - atlasUrl: https://cloud-dev.mongodb.com apiKey: ${{ secrets.ATLAS_PUBLIC_API_KEY}} privateApiKey: ${{ secrets.ATLAS_PRIVATE_API_KEY }} differentiator: dart-linux From eec8649fa940931cd2f024c61afb25930b4bfbd2 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 21:03:02 +0100 Subject: [PATCH 18/24] Clean up the PR --- .github/workflows/pr.yml | 20 +++++++ .github/workflows/realm-dart-linux.yml | 58 --------------------- .github/workflows/realm-dart-macos.yml | 1 + .github/workflows/realm-dart-windows.yml | 1 + .github/workflows/realm-flutter-android.yml | 1 + .github/workflows/realm-flutter-ios.yml | 1 + .github/workflows/realm-flutter-linux.yml | 1 + .github/workflows/realm-flutter-macos.yml | 1 + .github/workflows/realm-flutter-windows.yml | 1 + .github/workflows/realm-generator.yml | 1 + CHANGELOG.md | 38 ++++++++++---- lib/src/cli/deployapps/baas_client.dart | 8 +++ 12 files changed, 64 insertions(+), 68 deletions(-) delete mode 100644 .github/workflows/realm-dart-linux.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 47f7bc5de..e4dad3921 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -84,6 +84,26 @@ jobs: run: | dart test -r expanded -j 1 --test-randomize-ordering-seed random + # TODO: these should go away once we have a proper release workflow + - name: Archive binary + if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} + run: | + dart run realm_dart archive --source-dir $(pwd)/binary/linux --output-file $ARCHIVE_PATH + - name: Release artifacts + if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifactErrorsFailBuild: true + draft: true + omitNameDuringUpdate: true + prerelease: false + omitPrereleaseDuringUpdate: true + artifacts: ${{ env.ARCHIVE_PATH }} + body: "ADD RELEASE NOTES" + omitBodyDuringUpdate: true + token: ${{ secrets.GITHUB_TOKEN }} + cleanup-linux: runs-on: ubuntu-latest name: Cleanup Linux diff --git a/.github/workflows/realm-dart-linux.yml b/.github/workflows/realm-dart-linux.yml deleted file mode 100644 index 32566eee5..000000000 --- a/.github/workflows/realm-dart-linux.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Realm Dart for Linux - -on: - push: - branches: - - master - tags: - - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - -jobs: - CI: - runs-on: ubuntu-latest - env: - REALM_CI: true - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: Setup Ninja - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Build Realm Dart for Linux - run: ./scripts/build-linux.sh - - - name : Setup Dart SDK - uses: dart-lang/setup-dart@main - with: - sdk: stable - - - name: Install dependencies - run: dart pub get - - - name: Run tests - run: | - dart test -r expanded -j 1 --test-randomize-ordering-seed random - echo "ARCHIVE_PATH=$(pwd)/binary/linux.tar.gz" >> $GITHUB_ENV - - - name: Archive binary - if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} - run: | - dart run realm_dart archive --source-dir $(pwd)/binary/linux --output-file $ARCHIVE_PATH - - - name: Release artifacts - if: ${{ success() && github.event_name == 'push' && github.ref_type == 'tag' }} - uses: ncipollo/release-action@v1 - with: - allowUpdates: true - artifactErrorsFailBuild: true - draft: true - omitNameDuringUpdate: true - prerelease: false - omitPrereleaseDuringUpdate: true - artifacts: ${{ env.ARCHIVE_PATH }} - body: "ADD RELEASE NOTES" - omitBodyDuringUpdate: true - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/realm-dart-macos.yml b/.github/workflows/realm-dart-macos.yml index 84bbecbe2..86bdf1860 100644 --- a/.github/workflows/realm-dart-macos.yml +++ b/.github/workflows/realm-dart-macos.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-dart-windows.yml b/.github/workflows/realm-dart-windows.yml index 68bd5c212..f479b98e4 100644 --- a/.github/workflows/realm-dart-windows.yml +++ b/.github/workflows/realm-dart-windows.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-android.yml b/.github/workflows/realm-flutter-android.yml index af23fc4b6..6bc1504f6 100644 --- a/.github/workflows/realm-flutter-android.yml +++ b/.github/workflows/realm-flutter-android.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-ios.yml b/.github/workflows/realm-flutter-ios.yml index 76af0eedd..9bf878d9b 100644 --- a/.github/workflows/realm-flutter-ios.yml +++ b/.github/workflows/realm-flutter-ios.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-linux.yml b/.github/workflows/realm-flutter-linux.yml index 7bb110e10..4648da5cf 100644 --- a/.github/workflows/realm-flutter-linux.yml +++ b/.github/workflows/realm-flutter-linux.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-macos.yml b/.github/workflows/realm-flutter-macos.yml index a0e3f8f37..54f13bcf8 100644 --- a/.github/workflows/realm-flutter-macos.yml +++ b/.github/workflows/realm-flutter-macos.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-windows.yml b/.github/workflows/realm-flutter-windows.yml index 46627e84a..768bc0ea8 100644 --- a/.github/workflows/realm-flutter-windows.yml +++ b/.github/workflows/realm-flutter-windows.yml @@ -6,6 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta + pull_request: jobs: CI: diff --git a/.github/workflows/realm-generator.yml b/.github/workflows/realm-generator.yml index 31b1a8af9..e526c553d 100644 --- a/.github/workflows/realm-generator.yml +++ b/.github/workflows/realm-generator.yml @@ -4,6 +4,7 @@ on: push: branches: - master + pull_request: jobs: CI: diff --git a/CHANGELOG.md b/CHANGELOG.md index b7ba5b7e1..7e069cad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +x.x.x Release notes (yyyy-MM-dd) +============================================================== + +**This project is in the Alpha stage. All API's might change without warning and no guarantees are given about stability. Do not use it in production.** + +### Enhancements +* None + +### Fixed +* Fix running package commands. + +### Compatibility +* Dart ^2.15 on Windows, MacOS and Linux + +### Internal +* Added a command to deploy a MongoDB Realm app to `realm_dart`. Usage: `dart run realm_dart deploy-apps`. By default it will deploy apps to `http://localhost:9090` which is the endpoint of the local docker image. If `--atlas-cluster` is provided, it will authenticate, create an application and link the provided cluster to it. (PR [#309](https://github.com/realm/realm-dart/pull/309)) +* Unit tests will now attempt to lookup and create if necessary MongoDB applications (similarly to the above mentioned command). See `test.dart/setupBaas()` for the environment variables that control the Url and Atlas Cluster that will be used. If the `BAAS_URL` environment variable is not set, no apps will be imported and sync tests will not run. (PR [#309](https://github.com/realm/realm-dart/pull/309)) + 0.2.1+alpha Release notes (2022-03-20) ============================================================== @@ -5,7 +23,7 @@ ### Enhancements * Support change notifications on query results. ([#208](https://github.com/realm/realm-dart/pull/208)) - + Every `RealmResults` object now has a `changes` method returning a `Stream>` which can be listened to. ```dart @@ -70,7 +88,7 @@ * Added support for opening in-memory realms. ([#280](https://github.com/realm/realm-dart/pull/280)) * Primary key fields no longer required to be `final` in data model classes ([#240](https://github.com/realm/realm-dart/pull/240)) - Previously primary key fields needed to be `final`. + Previously primary key fields needed to be `final`. ```dart @RealmModel() @@ -93,7 +111,7 @@ * List fields no longer required to be `final` in data model classes. ([#253](https://github.com/realm/realm-dart/pull/253)) - Previously list fields needed to be `final`. + Previously list fields needed to be `final`. ```dart @RealmModel() @@ -127,7 +145,7 @@ **This project is in the Alpha stage. All API's might change without warning and no guarantees are given about stability. Do not use it in production.** -### Enhancements +### Enhancements * Completely rewritten from the ground up with sound null safety and using Dart FFI ### Compatibility @@ -136,9 +154,9 @@ 0.2.0-alpha.2 Release notes (2022-01-29) ============================================================== -Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. +Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. -### Enhancements +### Enhancements * Completеly rewritten from the ground up with sound null safety and using Dart FFI ### Fixed @@ -150,9 +168,9 @@ Notes: This release is a prerelease version. All API's might change without warn 0.2.0-alpha.1 Release notes (2022-01-29) ============================================================== -Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. +Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. -### Enhancements +### Enhancements * Completеly rewritten from the ground up with sound null safety and using Dart FFI ### Fixed @@ -167,9 +185,9 @@ Notes: This release is a prerelease version. All API's might change without warn 0.2.0-alpha Release notes (2022-01-27) ============================================================== -Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. +Notes: This release is a prerelease version. All API's might change without warning and no guarantees are given about stability. -### Enhancements +### Enhancements * Completеly rewritten from the ground up with sound null safety and using Dart FFI ### Compatibility diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index 8030b4e64..4e5024e47 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -50,6 +50,8 @@ class BaasClient { _headers = {'Accept': 'application/json'}, _appSuffix = '-$_clusterName'; + /// A client that imports apps in a MongoDB Realm docker image. See https://github.com/realm/ci/tree/master/realm/docker/mongodb-realm + /// for instructions on how to set it up. static Future docker(String baseUrl) async { final result = BaasClient._(baseUrl); @@ -63,6 +65,7 @@ class BaasClient { return result; } + /// A client that imports apps to an MongoDB Realm environment (typically realm-dev or realm-qa). static Future atlas(String baseUrl, String cluster, String apiKey, String privateApiKey, String groupId) async { final BaasClient result = BaasClient._(baseUrl, cluster); @@ -73,6 +76,9 @@ class BaasClient { return result; } + /// Tries to look up the applications for the specified cluster. For [docker] client, returns all apps, + /// for [atlas] one, it will return only apps with suffix equal to the cluster name. If no apps exist, + /// then it will create the test applications and return them. Future> getOrCreateApps() async { final result = {}; var apps = await _getApps(); @@ -84,6 +90,8 @@ class BaasClient { final defaultApp = await _createApp('flexible'); result[defaultApp.name] = defaultApp; + + // Add more types of apps as we add more tests here. } return result; From fd01fce64939559fefe077bac0c7c09235373c79 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 21:41:25 +0100 Subject: [PATCH 19/24] Fix indents --- .github/workflows/realm-dart-macos.yml | 2 +- .github/workflows/realm-dart-windows.yml | 2 +- .github/workflows/realm-flutter-android.yml | 2 +- .github/workflows/realm-flutter-ios.yml | 2 +- .github/workflows/realm-flutter-linux.yml | 2 +- .github/workflows/realm-flutter-macos.yml | 2 +- .github/workflows/realm-flutter-windows.yml | 2 +- .github/workflows/realm-generator.yml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/realm-dart-macos.yml b/.github/workflows/realm-dart-macos.yml index 86bdf1860..3f3837f8e 100644 --- a/.github/workflows/realm-dart-macos.yml +++ b/.github/workflows/realm-dart-macos.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-dart-windows.yml b/.github/workflows/realm-dart-windows.yml index f479b98e4..9aa017692 100644 --- a/.github/workflows/realm-dart-windows.yml +++ b/.github/workflows/realm-dart-windows.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-android.yml b/.github/workflows/realm-flutter-android.yml index 6bc1504f6..4adcfd10d 100644 --- a/.github/workflows/realm-flutter-android.yml +++ b/.github/workflows/realm-flutter-android.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-ios.yml b/.github/workflows/realm-flutter-ios.yml index 9bf878d9b..845dea4c7 100644 --- a/.github/workflows/realm-flutter-ios.yml +++ b/.github/workflows/realm-flutter-ios.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-linux.yml b/.github/workflows/realm-flutter-linux.yml index 4648da5cf..5116106d9 100644 --- a/.github/workflows/realm-flutter-linux.yml +++ b/.github/workflows/realm-flutter-linux.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-macos.yml b/.github/workflows/realm-flutter-macos.yml index 54f13bcf8..b5ded4885 100644 --- a/.github/workflows/realm-flutter-macos.yml +++ b/.github/workflows/realm-flutter-macos.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-flutter-windows.yml b/.github/workflows/realm-flutter-windows.yml index 768bc0ea8..552328081 100644 --- a/.github/workflows/realm-flutter-windows.yml +++ b/.github/workflows/realm-flutter-windows.yml @@ -6,7 +6,7 @@ on: - master tags: - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: + pull_request: jobs: CI: diff --git a/.github/workflows/realm-generator.yml b/.github/workflows/realm-generator.yml index e526c553d..3f61acd79 100644 --- a/.github/workflows/realm-generator.yml +++ b/.github/workflows/realm-generator.yml @@ -4,7 +4,7 @@ on: push: branches: - master - pull_request: + pull_request: jobs: CI: From f076c96ea31838fe1b5b961eb9d5fab2dee09696 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 22:00:30 +0100 Subject: [PATCH 20/24] Add http to flutter dev dependencies --- .github/workflows/pr.yml | 34 +++++++++++++++++++++++++++++- flutter/realm_flutter/pubspec.yaml | 3 ++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e4dad3921..4752d48cf 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -68,7 +68,7 @@ jobs: - name: Checkout uses: actions/checkout@v2 with: - submodules: 'recursive' + submodules: false - name: Fetch artifacts uses: actions/download-artifact@v2 with: @@ -104,6 +104,38 @@ jobs: omitBodyDuringUpdate: true token: ${{ secrets.GITHUB_TOKEN }} + flutter-linux: + runs-on: ubuntu-latest + name: Flutter Tests Linux + needs: + - build-linux + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: false + - name: Setup GTK + run: | + sudo apt-get update -y + sudo apt-get install -y libgtk-3-dev xvfb + - name: Fetch artifacts + uses: actions/download-artifact@v2 + with: + name: librealm-linux + path: binary + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: 'stable' + - name: Enable Flutter Desktop support + run: flutter config --enable-linux-desktop + - name: Install dependencies + run: flutter pub get + - name: Run tests + run: xvfb-run flutter drive -d linux --target=test_driver/app.dart --suppress-analytics --dart-entrypoint-args="" #--verbose #-a="Some test name" + working-directory: ./flutter/realm_flutter/tests + + cleanup-linux: runs-on: ubuntu-latest name: Cleanup Linux diff --git a/flutter/realm_flutter/pubspec.yaml b/flutter/realm_flutter/pubspec.yaml index eaf216173..4f06f64eb 100644 --- a/flutter/realm_flutter/pubspec.yaml +++ b/flutter/realm_flutter/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: pub_semver: ^2.1.0 realm_common: path: ../../common - realm_generator: + realm_generator: path: ../../generator tar: ^0.5.4 build_runner: ^2.1.0 @@ -39,6 +39,7 @@ dev_dependencies: build_cli: ^2.1.3 json_serializable: ^6.1.0 lints: ^1.0.1 + http: ^0.13.4 flutter: plugin: From 8f914c4a572f55d0fa9f74ec2b80586d20a69467 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 22:16:59 +0100 Subject: [PATCH 21/24] Try to fix build again --- .github/workflows/pr.yml | 2 ++ flutter/realm_flutter/tests/pubspec.yaml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4752d48cf..35550b591 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -118,6 +118,8 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y libgtk-3-dev xvfb + - name: Setup Ninja + uses: seanmiddleditch/gha-setup-ninja@master - name: Fetch artifacts uses: actions/download-artifact@v2 with: diff --git a/flutter/realm_flutter/tests/pubspec.yaml b/flutter/realm_flutter/tests/pubspec.yaml index 648629ca4..9aa733a92 100644 --- a/flutter/realm_flutter/tests/pubspec.yaml +++ b/flutter/realm_flutter/tests/pubspec.yaml @@ -26,9 +26,10 @@ dev_dependencies: flutter_lints: ^1.0.4 build_runner: ^2.1.2 test: ^1.20.1 + http: ^0.13.4 # Remove once flutter_driver from sdk is updated -dependency_overrides: +dependency_overrides: test_api: ^0.4.9 flutter: From c25053bad6c6d5ef2158aeb996440baa8a2f42fe Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Thu, 24 Mar 2022 22:27:31 +0100 Subject: [PATCH 22/24] Remove flutter linux workflow --- .github/workflows/realm-flutter-linux.yml | 47 ----------------------- 1 file changed, 47 deletions(-) delete mode 100644 .github/workflows/realm-flutter-linux.yml diff --git a/.github/workflows/realm-flutter-linux.yml b/.github/workflows/realm-flutter-linux.yml deleted file mode 100644 index 5116106d9..000000000 --- a/.github/workflows/realm-flutter-linux.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Realm Flutter for Linux - -on: - push: - branches: - - master - tags: - - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta - pull_request: - -jobs: - CI: - runs-on: ubuntu-latest - env: - REALM_CI: true - - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: Setup GTK - run: | - sudo apt-get update -y - sudo apt-get install -y libgtk-3-dev xvfb - - - name: Setup Ninja - uses: seanmiddleditch/gha-setup-ninja@master - - - name: Build Realm Flutter for Linux - run: ./scripts/build-linux.sh - - - name: Setup Flutter - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - - - name: Enable Flutter Desktop support - run: flutter config --enable-linux-desktop - - - name: Install dependencies - run: flutter pub get - - - name: Run tests - run: xvfb-run flutter drive -d linux --target=test_driver/app.dart --suppress-analytics --dart-entrypoint-args="" #--verbose #-a="Some test name" - working-directory: ./flutter/realm_flutter/tests From 2c43087906deef2c1d25aa6546afc329b70271ae Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Fri, 25 Mar 2022 10:15:52 +0100 Subject: [PATCH 23/24] Update .github/workflows/pr.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kasper Overgård Nielsen --- .github/workflows/pr.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 35550b591..0217cff36 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -32,7 +32,13 @@ jobs: with: sdk: stable - name: Deploy Apps - run: dart run realm_dart deploy-apps --baas-url https://realm-dev.mongodb.com --atlas-cluster ${{ steps.deploy-mdb-apps.outputs.clusterName }} --api-key ${{ secrets.ATLAS_PUBLIC_API_KEY }} --private-api-key ${{ secrets.ATLAS_PRIVATE_API_KEY }} --project-id ${{ secrets.ATLAS_PROJECT_ID }} + run: | + dart run realm_dart deploy-apps \ + --baas-url https://realm-dev.mongodb.com \ + --atlas-cluster ${{ steps.deploy-mdb-apps.outputs.clusterName }} \ + --api-key ${{ secrets.ATLAS_PUBLIC_API_KEY }} \ + --private-api-key ${{ secrets.ATLAS_PRIVATE_API_KEY }} \ + --project-id ${{ secrets.ATLAS_PROJECT_ID }} build-linux: runs-on: ubuntu-latest name: Build Linux From 938c7f2b6bc1eb84531a9e5ab45073eae076433f Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Mon, 28 Mar 2022 11:15:25 +0200 Subject: [PATCH 24/24] Code review fixes --- .github/workflows/pr.yml | 2 ++ lib/src/cli/deployapps/baas_client.dart | 9 ++++++--- test/test.dart | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0217cff36..d17cf058d 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,6 +4,8 @@ on: push: branches: - master + tags: + - '[0-9]+.[0-9]+.[0-9]+**' # matches tags like number(s).number(s).number(s)(any) for ex: 1.0.0 and also 1.0.0+beta pull_request: env: REALM_CI: true diff --git a/lib/src/cli/deployapps/baas_client.dart b/lib/src/cli/deployapps/baas_client.dart index 4e5024e47..0ea01bfa0 100644 --- a/lib/src/cli/deployapps/baas_client.dart +++ b/lib/src/cli/deployapps/baas_client.dart @@ -52,6 +52,7 @@ class BaasClient { /// A client that imports apps in a MongoDB Realm docker image. See https://github.com/realm/ci/tree/master/realm/docker/mongodb-realm /// for instructions on how to set it up. + /// @nodoc static Future docker(String baseUrl) async { final result = BaasClient._(baseUrl); @@ -66,6 +67,7 @@ class BaasClient { } /// A client that imports apps to an MongoDB Realm environment (typically realm-dev or realm-qa). + /// @nodoc static Future atlas(String baseUrl, String cluster, String apiKey, String privateApiKey, String groupId) async { final BaasClient result = BaasClient._(baseUrl, cluster); @@ -79,6 +81,7 @@ class BaasClient { /// Tries to look up the applications for the specified cluster. For [docker] client, returns all apps, /// for [atlas] one, it will return only apps with suffix equal to the cluster name. If no apps exist, /// then it will create the test applications and return them. + /// @nodoc Future> getOrCreateApps() async { final result = {}; var apps = await _getApps(); @@ -206,7 +209,7 @@ class BaasClient { Future _createMongoDBService(BaasApp app, String syncConfig) async { final serviceName = _clusterName == null ? 'mongodb' : 'mongodb-atlas'; final mongoConfig = _clusterName == null ? '{ "uri": "mongodb://localhost:26000" }' : '{ "clusterName": "$_clusterName" }'; - final mongoServiceId = await createService(app, 'BackingDB', serviceName, mongoConfig); + final mongoServiceId = await _createService(app, 'BackingDB', serviceName, mongoConfig); // The cluster linking must be separated from enabling sync because Atlas // takes a few seconds to provision a user for BaaS, meaning enabling sync @@ -218,7 +221,7 @@ class BaasClient { await _patch('groups/$_groupId/apps/$app/services/$mongoServiceId/config', syncConfig); break; } catch (err) { - if (attempt++ < 1) { + if (attempt++ < 24) { print('Failed to update service after ${attempt * 5} seconds. Will keep retrying ...'); await Future.delayed(const Duration(seconds: 5)); @@ -231,7 +234,7 @@ class BaasClient { return mongoServiceId; } - Future createService(BaasApp app, String name, String type, String config) async { + Future _createService(BaasApp app, String name, String type, String config) async { print('Creating service $name for ${app.name}'); final dynamic response = await _post('groups/$_groupId/apps/$app/services', '''{ diff --git a/test/test.dart b/test/test.dart index 5e1165401..a74b8d064 100644 --- a/test/test.dart +++ b/test/test.dart @@ -166,15 +166,15 @@ void parseTestNameFromArguments(List? arguments) { Future setupBaas() async { final baasUrl = Platform.environment['BAAS_URL']; + if (baasUrl == null) { + return; + } + final cluster = Platform.environment['BAAS_CLUSTER']; final apiKey = Platform.environment['BAAS_API_KEY']; final privateApiKey = Platform.environment['BAAS_PRIVATE_API_KEY']; final projectId = Platform.environment['BAAS_PROJECT_ID']; - if (baasUrl == null) { - return; - } - final client = await (cluster == null ? BaasClient.docker(baasUrl) : BaasClient.atlas(baasUrl, cluster, apiKey!, privateApiKey!, projectId!)); baasApps.addAll(await client.getOrCreateApps());