From 76b9805b1e2ee9b9d12e02b03a216cf2f5805de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Wed, 21 Feb 2024 09:52:20 +0100 Subject: [PATCH] Updating `CONTRIBUTING.md` (#6496) * Deleting an outdated guide around watchman * Bringing CONTRIBUTING.md up to date * Updated wording --- CONTRIBUTING.md | 185 ++++++-------------------------------- contrib/guide-watchman.md | 41 --------- 2 files changed, 26 insertions(+), 200 deletions(-) delete mode 100644 contrib/guide-watchman.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a904765429..c4bb56f7dda 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,182 +29,49 @@ Moreover, indicate how you would like us to support you. We will happily guide y If you’re working on a long-living branch, keep it updated with upstream changes by rebasing it on the target branch on a regular basis. This requires a force-push, so you should coordinate with anyone working on the same branch team when doing that. -### Commit Messages - -Although we don’t enforce a strict format for commit messages, we prefer that you follow the guidelines below, which are common among open source projects. Following these guidelines helps with the review process, searching commit logs and documentation of implementation details. At a high level, the contents of the commit message should convey the rationale of the change, without delving into much detail. For example, `setter names were not set right` leaves the reviewer wondering about which bits and why they weren’t “right”. In contrast, `[RLMProperty] Correctly capitalize setterName` conveys almost all there is to the change. - -Below are some guidelines about the format of the commit message itself: - -* Separate the commit message into a single-line title and a separate body that describes the change. -* Make the title concise to be easily read within a commit log. -* Make the body concise, while including the complete reasoning. Unless required to understand the change, additional code examples or other details should be left to the pull request. -* If the commit fixes a bug, include the number of the issue in the message. -* Use the first person present tense - for example "Fix …" instead of "Fixes …" or "Fixed …". -* For text formatting and spelling, follow the same rules as documentation and in-code comments — for example, the use of capitalization and periods. -* If the commit is a bug fix on top of another recently committed change, or a revert or reapply of a patch, include the Git revision number of the prior related commit, e.g. `Revert abcd3fg because it caused #1234`. - ### CLA Realm welcomes all contributions! The only requirement we have is that, like many other projects, we need to have a [Contributor License Agreement](https://en.wikipedia.org/wiki/Contributor_License_Agreement) (CLA) in place before we can accept any external code. Our own CLA is a modified version of the Apache Software Foundation’s CLA. [Please submit your CLA electronically using our Google form](https://docs.google.com/forms/d/e/1FAIpQLSeQ9ROFaTu9pyrmPhXc-dEnLD84DbLuT_-tPNZDOL9J10tOKQ/viewform) so we can accept your submissions. The GitHub username you file there will need to match that of your Pull Requests. If you have any questions or cannot file the CLA electronically, you can email . -### How To: Add a new function - -Adding new functionality to Realm JavaScript requires that you modify a few places in the repository. As an example, consider adding a function `crashOnStart()` to the class `Realm`. The subsections below guides you through where and what to add. - -#### Add the function - -First, add a prototype of function to `src/js_realm.hpp`; look for a section marked by the comment `// method`. The prototype looks like: - -``` -static void crashOnStart(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &); -``` - -You have to implement the function. Find a place in `src/js_realm.hpp` to add it (maybe at the end): - -``` -template -void RealmClass::crashOnStart(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) { - validate_argument_count(argc, 0); // <- the function doesn't take any arguments - - SharedRealm realm = *get_internal>(this_object); // <- unwrap the Realm instance - - // add the actual implement ... -} -``` - -Testing is important, and in `tests/js/realm-tests.js` you can add the tests you need. - -Note: If your new API and/or test cases are not getting picked up when running the Android or iOS tests, remove the corresponding installed package from ReactTestApp and try again. - -``` -rm -rf tests/ReactTestApp/node_modules/realm -rm -rf tests/ReactTestApp/node_modules/realm-tests -``` +## Getting started contributing -#### Wrap the function +Browse the [contrib](./contrib/) directory for detailed guides on building and testing the library. -In order to call the C++ implementation, the JavaScript engine has to know about the function. You must simply add it to the map of methods/functions. Find `MethodMap const methods` declaration in `src/js_realm.hpp` and add your function to it: +TLDR; We have an NPM workspace mono-repo, orchestrated by [Wireit](https://github.com/google/wireit). +```shell +# Clone the repository (with submodules) +git clone --recurse-submodules git@github.com:realm/realm-js.git +# Change directory into the git repo +cd realm-js +# Install dependencies +npm install +# Run the node tests (which will transitively generate the binding, build the SDK, etc.) +npm test --workspace @realm/node-tests ``` -{"crashOnStart", wrap}, -``` - -#### Update the RPC protocol -This is required for the Chrome Debugger to work with React Native. If the method added is a pure Javascript function, -you can skip this step as it will work automatically. If the method is a C++ method you will -need to manually update the RPC protocol. +## Running the "sync test" (requires running the sync server, a.k.a. baas) -If the method is an instance method you need to: +Due to its proprietary license, we're not able to publish docker images for the server, so the following steps are only available to MongoDB employees. -* Add your function to the relevant list of methods in `lib/browser/index.js` or one of the subclasses in `lib/browser/`. +First, you need to follow the guide on ["Using Docker to run a BAAS server instance"](https://wiki.corp.mongodb.com/display/10GEN/%28Device+Sync%29+Using+Docker+to+run+a+BAAS+server+instance). -If the method is static method you need to: - -* Add function name to `lib/browser/index.js` or the relevant class under `lib/browser/`. It should forward the method - call to an RPC method, e.g like: +Create an `.env` file in the `integration-tests/baas-test-server` directory, with the following content (replacing `...` with values from the guide above): ``` -const Sync = { - "_myMethod": function(arg) { - rpc._myMethod(arg); - }, - // ... -}; +AWS_PROFILE="..." +AWS_ACCESS_KEY_ID="..." +AWS_SECRET_ACCESS_KEY="..." +BAASAAS_KEY="..." ``` -* Add the RPC sender method to `/lib/browser/rpc.js`. -* Add the RPC receiver endpoint in `/src/rpc.cpp`. - -#### The final details - -To finish adding your new function, you will have to add your function a few places: - -* In `lib/index.d.ts` you add the TypeScript declaration -* Documentation is added in `docs/realm.js` -* Add an entry to `CHANGELOG.md` if applicable (Breaking changes/Enhancements/Bug fixes) - -### How To: Update Object Store - -[Object Store](https://github.com/realm/realm-object-store) is the cross platform abstraction shared between all SDKs supported by Realm. - -It is included in Realm JS as a Git submodule under `src/object-store`. - -In order to pull in new versions checkout the appropriate commit and add the commit to the `### Internal` -section of the changelog. - -If the Object Store commit contains new files, it is necessary to update some Realm JS files due to how the project -is built. These files are: - -* Android: `/react-native/android/src/main/jni/Android.mk` -* iOS: `/Realm.xcodeworkspace`: Open in XCode and add the files to RealmJS under `Build Phases` -* Node: `/realm.gypi` - -### How To: Debug Node Unit tests - -Building and running the full test suite can be done on macOS or Linux by running `./scripts/test.sh node Debug` (or `node Release`) from the root directory of the repository. This will install all dependencies, build the library, and run the tests. - -Iterative development requires performing more of the steps manually: - -1. Run `npm ci --ignore-scripts` in the repository root directory to install the library dependencies (but skip building Realm). -2. Run `npm ci` in the `tests` directory to install test dependencies. -3. Run `npm run build-changes` to build a debug copy of the library. -4. Run `npm run start-ros` to launch a ROS instance which the sync tests can run against. By default this has logging disabled, but you can change the log level by setting the `ROS_LOG_LEVEL` environment variable. When this starts, it'll print `Started: /path/to/tmp/dir`. Take note of this path for future steps. -5. In the `tests` directory, run `ROS_DATA_DIR=/path/to/temp/dir npm run js-tests` to run all of the tests, with `ROS_DATA_DIR` set to the directory printed during ROS startup. Run `npm run js-tests -- --filter=NotificationTests` to run only tests matching the filter (either suite name or test name). To debug the tests using the Chrome debugger, run `node --inspect-brk ./node_modules/.bin/jasmine` and then open `chrome://inspect` and select the appropriate Node process. The native side of things can be debugged by instead (or additionally) attaching lldb/gdb to the process. - -After making changes to the C++ source files rerun `npm run build-changes` to rebuild the files which have changed. Changes to JS or TS files don't require any manual steps beyond rerunning the tests. - -If you want the Realm JS Sync client's logs in the console, run your command with the `DEBUG=realm` environment variable set (i.e. `DEBUG=realm npm run js-tests`) -To adjust the lowest log level set the `REALM_LOG_LEVEL` environment variable (defaults to `info`). - -Some tests have been instrumented with detailed logging, run your command with the `DEBUG=tests:*` environment variable set to see these (i.e. `DEBUG=tests:* npm run js-tests`) - -### How To: Debug React Native Unit tests - -This guide assumes that development is happening on a Mac. - -When developing new functionality, unit- and integration tests are being run on many different platforms. One of them being React Native. -If a bug occurs on this platform, it is, unfortunately, rather difficult to debug due to the complex nature of this repository and the React Native build system. - -Debugging and working with the unit tests in an iterative mannner is done the following way: - -1. Run `./scripts/test.sh react-tests` to install all the dependencies. -2. Run `npm run ros-start` in one terminal window. -3. `cd tests/ReactTestApp && npm start` in another terminal window -4. Open `tests/ReactTestApp/ios/ReactTests.xcworkspace` (note: not the xcodeproj) in Xcode. -5. Hit Cmd-U to run the tests. - -If you want to modify the Javascript in an iterative manner or enable break points you need to do it on the files located in `tests/ReactTestApp/node_modules/realm-tests`. These files are a copy of the original files located in `tests/js` so any changes must manually be copied back. The reason for this is that the React Native Metro Bundler doesn't support symlinks. - -The Javascript tests are run twice: once directly in the simulator, and once in Chrome, talking to the simulator via the RPC bridge used for Chrome debugging. When running the Chrome tests you can open the Chrome Developer Tools on the tab that they open to debug the tests themselves. The JS engine running inside the simulator (for both the RPC server and the tests themselves in the non-Chrome test suite) can be debugged using the Safari developer tools. - -Note that it isn't possible to easily run a single unit test from Xcode. Instead you should disable the tests manually by modifying `tests/ReactTestApp/node_modules/realm-tests/index.js`. - -### How To: Debug React Native Podspec - -The [Podspec](./RealmJS.podspec) file follows [the CocoaPods Podspec syntax](https://guides.cocoapods.org/syntax/podspec.html). It describes how Realm JS is build for React Native apps on iOS and is automatically discovered by the React Native CLI when running `pod install` from a users project. - -The Podspec file expects to be located in the `./node_modules/realm/` folder of a React Native project with a `./ios/Podfile` file. The easiest way to verify that changes to the Podspec is not breaking installing the library, install Realm JS in a new React Native app, make the changes to the `./node_modules/realm/RealmJS.podspec` and build the app. - -It's also possible to run `pod lib lint --verbose` from the `./node_modules/realm/` directory, but then it's required that `'#{app_path}/ios/Pods/Headers/Public/React-Core'` is added to the `HEADER_SEARCH_PATHS` of `s.pod_target_xcconfig`. -Consider adding `--no-clean` to prevent the CocoaPods CLI from deleting the temporary project created during linting. Once linting passes, try installing the pod and running the consuming app on an iOS device. - -### How To: Login to the GitHub docker container registry - -Testing against the Atlas Device Sync server locally requires that you have access to the Atlas App Services docker image (`ghcr.io/realm/ci/mongodb-realm-test-server`). To provide your local docker deamon with the credentials necessary to pull the image, you must first authenticate using you GitHub username and an API token. - -First navigate to https://github.com/settings/tokens to generate a token - it just needs the `read:packages` scope. - -Then run the following to log into the GitHub container registry, entering your GitHub username and the API token that you've just created as password. - +```shell +# Start the server +npm start --workspace @realm/baas-test-server +# Run the tests (which will no longer skip sync tests) +npm test --workspace @realm/node-tests ``` -docker login ghcr.io -``` - -### How to: Run the BaaS server locally - -It can be useful to run the BaaS server directly, rather than in the docker container, for example to use the latest version from a branch or for debugging. -You can do this by running: `AWS_ACCESS_KEY_ID="???" AWS_SECRET_ACCESS_KEY="???" ./vendor/realm-core/evergreen/install_baas.sh -w ../baas-work-dir -b master` from the `realm-js` root directory. Logs can be accessed in `../baas-work-dir/baas_server.log` (the `baas-work-dir` is kept one level up from the `realm-js` repo). \ No newline at end of file + diff --git a/contrib/guide-watchman.md b/contrib/guide-watchman.md deleted file mode 100644 index e5fbd54f120..00000000000 --- a/contrib/guide-watchman.md +++ /dev/null @@ -1,41 +0,0 @@ -# Guide: Setting up watchman to copy changes from this package to an app - -You're debugging an issue reproduced in a React Native app, which uses Realm JS. You want to iterate fast, such that a change in the Realm JS source code gets reflected in the library used in the app, as fast as possible. - -## Prerequisites - -You'll need "watchman" and "rsync" installed on your system. - -## Why is this even needed - -1. React Native's Metro bundler has the long standing issue that it's not following symbolic links: https://github.com/facebook/metro/issues/1. -2. The CocoaPod "`pod install`" command won't consider source files that are symbolically linked into the project, when generating XCode projects for a development pod. - -For these reasons we cannot rely on a simple `npm link` but have to copy files from Realm JS to the app's `node_modules/realm` directory as we iterate on our code. - -## The `watch-from-dependency` script - -The script is located in `scripts/watch-from-dependency.js` (relative to the root of this repository) and it takes a single runtime option: The path of the React Native application package that depends on the `realm` package. - -``` -./scripts/watch-from-dependency.js ~/Projects/my-awesome-app -``` - -In the example above we're setting up a project-wide watch of our Realm JS repository and registering a subscription on all files exported by the Realm JS `package.json` which will execute an "rsync" command to ultimately, incrementally (not a full copy every time) synchronize changes made our Realm JS repository into the app's `node_modules/realm` directory. - -When you the process is interrupted (Ctrl+C) the subscription is removed and the files are no longer being copied. - -## The order of execution is important - -In order for the CocoaPods to generate the right XCode project files, you'll need to run the watcher after `npm install` in the application but *before* running `pod install` in the `/ios` directory. If you mess this up, you'll have to re-run `pod install` after starting the `watch-from-dependency.js` script. - -## Removing the project watch completely - -After exiting the script, a project watch on the Realm JS project will still exist. -It won't be performing any operations on file change, so it's not a huge waste of resources, but if you see a need for it you might want to completely remove the watch on the project. - -Simply run this in the root of this repository: - -``` -watchman watch-del . -```