- Xcode 13 or above
- Android and iOS environment setup described in the RN docs
- Run
npm install
- Run
npx pod-install ios
orcd ios && pod install
from the root directory cp env.example .env
and fill in appropriate values. This is not part of the code repo (contains secrets, such as OAuth client ID).
- We're using Husky to automatically run
eslint
before each commit. Runnpm run prepare
to install Husky locally.
- Run
npm start -- --reset-cache
(npm start
works too, but resetting the cache each time makes for a lot less build issues) - Run
npm run ios
ornpm run android
# Run all tests
npm test
# Run test paths matching a pattern
npx jest MyObs
# Run individual tests matching a pattern
npx jest -t accessibility
We currently have two kinds of tests:
tests/integration
: Tests the test the integration of multiple modules, e.g. a list of observation that makes requests to a mocked API, persists the response data in local storage, retrieves the data from local storage and renders components.tests/unit
: Tests that only test specific modules, like a single component, or a hook.
We're using Jest and React Native Testing Library for most of our tests, factoria and faker.js to generate test data for use with mocks. Local*
model factories represent locally persisted data, while Remote*
factories represent that kinds of records we get from an API or external package.
- Override
API_URL
to a staging API domain - either using a local.env
file, or overriding the environment variable when callingnpm start
- e.g.API_URL=http://example.com npm start -- --reset-cache
- Add new strings in English to
src/i18n/strings.ftl
using Fluent syntax, e.g.Try to match case and strike a balance between specificity and reusability when choosing a key. Please add context comments to help translators understand how the text is used, avoid variables whenever possible, and try to keep# Header for a paragraph describing projects ABOUT-PROJECTS = ABOUT # Text describing what projects are projects-description = Projects are really great, probably iNat's best feature.
strings.ftl
alphabetized by key. - Run
node src/i18n/i18ncli.js build
to build the JSON files i18next needs to access text in the app - In a commponent, use the
useTranslation
hook to reference your new string, e.g.import { useTranslation } from "react-i18next"; const MyComponent = ( ) => { const { t } = useTranslation(); return ( <View> <Text>{ t( "ABOUT-PROJECTS" ) }</Text> <Text>{ t( "projects-description" ) }</Text> </View> ); };
We manage translations through Crowdin. Actually updating the translation files should be largely automated, but this is what it looks like to do it manually (you must have the Crowdin CLI installed and have an access token associated with a Crowdin user that can post files to the specified project):
# Upload new strings. Source and destination paths are specified in crowdin.yml
crowdin upload --token YOUR_ACCESS_TOKEN --project-id YOUR_PROJECT_ID
# Download new translations and build for use in the app
crowdin download --token YOUR_ACCESS_TOKEN --project-id YOUR_PROJECT_ID
node src/i18n/i18ncli.js build
git add src/i18n/l10n/*
git commit -a -m "Updated translations"
- Run
react-native clean-project
. This will give you options to clean caches, clean builds, reinstall pods, and reinstall node_modules. Using this eliminates a lot of hard-to-diagnose build issues. - If you're running on an M series chip, you may need to install a specific version of NDK to the app to build for Android. See
android/build.gradle
We use fastlane to help automate parts of the deployment process, which requires some additional setup.
- Make a Github personal access token with repo access in the
GITHUB_TOKEN
environmental variable. cp android/example-keystore.properties android/keystore.properties
and fill in the relevant values provided by another member of iNat staff.cp fastlane/example-Appfile fastlane/Appfile
and fill in the relevant values provided by another member of iNat staff.- Work with iNat staff to either get a new Apple ID or associate an existing one with the iNat Apple development team
- Sign in to Xcode with your Apple ID
- Manage Certificates and add an Apple Distribution certificate associated with the iNaturalist team
The current expectation is that you we tag to freeze the code, bump the version, and describe the changes represented by the tag. Then we release to make builds and publish on Github. Later, presumably when some of the change logs have been translated, we push builds for internal testing. If that looks ok, we push to public testing, and later to production release.
# Make a git tag. This will bump the build number and prompt you to describe
# what changed, which will be used for the eventual github release
# description and changelogs uploaded to the app stores.
fastlane tag
# Make a github release. This will make relevant builds, a github release, and
# add build files to the release
fastlane release
# Upload the build for the latest tag for internal testing
fastlane internal
# Upload the build for the latest tag for public testing (promotes latest
# internal build to open testing)
fastlane beta
# Upload the build for the latest tag to production release. In Android, this
# should just promote the last beta to prod.
fastlane prod