Skip to content

Latest commit

 

History

History
304 lines (213 loc) · 12.8 KB

File metadata and controls

304 lines (213 loc) · 12.8 KB

🌳 Ecosia for iOS

Ecosia-iOS Ecosia-iOS Ecosia-iOS

This is the entry point of all-things Ecosia. It contains info on the way we got the project structure, how we interface it with Firefox, how we release and keep localizations aligned.

🧰 Ecosia Framework

The Ecosia Framework aims to be a wrapper of all our Ecosia isolated implementation and logic. Some of the Ecosia codebase still lives under the main project Client/Ecosia but the goal is to bring as much codebase as possible as part of this dedicated framework.

🤝 Getting involved

We encourage you to participate in those open source projects. We love Pull Requests, Issue Reports, Feature Requests or any kind of positive contribution. Please read the Mozilla Community Participation Guidelines and our Contributing guidelines first.

If more information is required or you have any questions then we suggest reaching out to us via:

  • Chat on Element channel #fx-ios and #focus-ios for general discussion, or write DMs to specific teammates for questions.
  • Open a Github discussion which can be used for general questions.

Want to contribute on the codebase but don't know where to start? Here is a list of issues that are contributor friendly, but make sure to read the Contributing guidelines first.

⁒ Update Ecosia Comments

To ensure consistency when commenting code in Firefox for Ecosia updates, you could document the following approach:

Commenting Guidelines for Ecosia Code in Firefox: 1. One-liner Comments: Use // for introducing new code or brief explanations.

// Ecosia: Update appversion predicate
let appVersionPredicate = (appVersionString?.contains("Ecosia") ?? false) == true
2.	Block Comments:

Use /* */ when commenting out existing Firefox code for easier readability and conflict resolution.

/* Ecosia: Update appversion predicate
let appVersionPredicate = (appVersionString?.contains("Firefox") ?? false) == true
*/
let appVersionPredicate = (appVersionString?.contains("Ecosia") ?? false) == true

After cloning (for Ecosians)


🪝 Git Hooks

This project uses custom Git hooks to enforce commit message formatting and other automated tasks. To ensure that these hooks are installed correctly in your local .git/hooks directory, you need to run the provided setup script after cloning the repository.

  • Navigate into the project directory
  • Run the setup script to install the Git hooks: ./setup_hooks.sh

This script will copy all the necessary hooks (such as prepare-commit-msg) to your local .git/hooks directory, ensuring they are executable.

⚙️ Building the code

🧼 SwiftLint

We use SwiftLint to enforce Swift style and conventions. Make sure to install it so that linting runs correctly when building.

brew install swiftlint
  1. Install the latest Xcode developer tools from Apple.
  2. Install, Brew, Node, and a Python3 virtualenv for localization scripts:
    brew update
    brew install node
    pip3 install virtualenv
  3. Clone the repository:
    git clone https://github.com/ecosia/ios-browser
  4. Install Node.js dependencies, build user scripts and update content blocker:
    cd ios-browser
    sh ./bootstrap.sh
  5. Open firefox-ios/Client.xcodeproj in Xcode.
  6. Make sure to select the Ecosia scheme in Xcode.
  7. Select the destination device you want to build on.
  8. Run the app with Cmd + R or by pressing the build and run button.

⚠️ Important: In case you have dependencies issues with SPM, please try the following:

  • Xcode -> File -> Packages -> Reset Package Caches
  • This will also require you to have a working github integration set up in xcode (see Settings > Accounts > Source Control Accounts)

📝 Building User Scripts


User Scripts (JavaScript injected into the WKWebView) are compiled, concatenated, and minified using webpack. User Scripts to be aggregated are placed in the following directories:

/Client
|-- /Frontend
    |-- /UserContent
        |-- /UserScripts
            |-- /AllFrames
            |   |-- /AtDocumentEnd
            |   |-- /AtDocumentStart
            |-- /MainFrame
                |-- /AtDocumentEnd
                |-- /AtDocumentStart

This reduces the total possible number of User Scripts down to four. The compiled output from concatenating and minifying the User Scripts placed in these folders resides in /Client/Assets and are named accordingly:

  • AllFramesAtDocumentEnd.js
  • AllFramesAtDocumentStart.js
  • MainFrameAtDocumentEnd.js
  • MainFrameAtDocumentStart.js

To simplify the build process, these compiled files are checked-in to this repository. When adding or editing User Scripts, these files can be re-compiled with webpack manually. This requires Node.js to be installed, and all required npm packages can be installed by running npm install in the project's root directory. User Scripts can be compiled by running the following npm command in the root directory of the project:

npm run build

The CURRENT_PROJECT_VERSION being set to 0 indicates that it is not being used for local testing. The outcoming build number is updated by the CI, matching the CI run number (e.g. 8023).

🏅 Get certificates and profiles

brew install fastlane

Our certs and profiles are managed centrally by fastlane match. Find the repo here

You might need to set up your Ruby stack:

sudo gem install bundler:2.3.4
bundle install

# you may need to link your ruby if you have a ruby from brew
echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc

# you may need to install a ruby <4
# https://formulae.brew.sh/formula/rbenv
brew install rbenv
echo 'eval "$(rbenv init -)"' >> ~/.zshrc
source ~/.zshrc

rbenv install 3.2.2
rbenv global 3.2.2

Run bundle exec fastlane match --readonly to add certs and profiles to your system. You can append -p "keychain password" to avoid keychain prompts during the process. The passphrase to decrypt the repo can be found in LastPass.

Command:

bundle exec fastlane match --readonly

Expected output:

[...]
[14:22:17]: Passphrase for Match storage: [get the password from the password manager]

Registering new devices

To run the app on a new device, register it on the Apple Developer Portal and re-generate the provisioning profiles using fastlane match.

  1. Plug in your device and register it via the register_devices action. You will be prompted for the device name and UDID:
    bundle exec fastlane run register_devices
  2. Re-generate the provisioning profiles to include the new device by running match with --force_for_new_devices for both development (for local development) and ad hoc (for Firebase releases):
    bundle exec fastlane match development --force_for_new_devices
    bundle exec fastlane match adhoc --force_for_new_devices
    This flag makes match check whether the device count has changed since the last run and automatically re-generate the provisioning profiles if necessary. See the fastlane match docs for more details.
  3. Open Xcode, select the EcosiaBeta (or Ecosia) scheme, choose your device and run (Cmd + R).

🗣️ Translations

We are using Transifex for managing our translations.

Install the transifex client using pip

curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash

Configure your ~/.transifexrc file

[https://www.transifex.com]
api_hostname  = https://api.transifex.com
hostname      = https://www.transifex.com
username      = <vault secret>
password      = <vault secret>
rest_hostname = https://rest.api.transifex.com
token         = <vault secret>

Translations need to be pulled and commited manually

Pulling translation from the web

tx pull -fs

Test and commit the new translations. There exists schemes for testing other languages in the simulator.

Adding new strings

Via CLI

  1. Pull the source file
  2. Add the new strings to the English source file Client/Ecosia/L10N/en.lproj/Ecosia.strings
  3. Push it to Transifex
tx pull -fs
tx push -s

Ecosify Mozilla Strings (only needed after upgrade)

We do a rebrand of the Strings from Mozilla. Usually this step is only needed after an upgrade as we keep our changes in version control (as of opposite to Mozilla). Firefox already imports and versions their strings, which means they will have been added to our codebase once we rebase. After that, you can use the existing python script to update all strings on the folder containing the project file.

# brand all the files as they contain the term 'Firefox' a lot
python3 ecosify-strings.py firefox-ios

🚀 Release

Follow the instructions from our confluence page

How to update the release notes

Make sure that fastlane and transifex-cli is installed.

Add source release notes to transifex (en-US)

ℹ️ Updating the source file in the project and merging it into main will automatically push it to Transifex as well since the Github integration is in place.

🔔 Make sure that an inflight version exists in AppStore Connect. If not, create one.

  • Create a new branch off main and modify the English release notes here
  • Open a PR with the modified English release note text file against main branch
  • Once approved, Squash and Merge the code to main. (The transifex integration will pick up the push)
  • Transifex will create a PR and update it with the release notes in all available languages ⏳
  • Squash and Merge the code to main via a PR and a GitHubAction workflow will be triggered to upload the newly translated release notes

Add language translations

  • Make sure that all languages are translated in the transifex web interface and found their way to main

  • Verify the translations in the Transifex-made PR

  • Squash and Merge the PR

  • The GitHub Action Workflow Upload release notes to AppStore will take care of the upload

In case you need a manual update

  • Push via the update translation via deliver to the AppStore

    bundle exec fastlane deliver --app-version 8.2.0

🧪 Unit tests

  • Run tests against EcosiaBeta scheme. With the standard CMD+U it picks the test plan (Xcode)

✅ Acceptance testing

Check https://github.com/ecosia/mobile-acceptance-testing for details

📸 Snapshot Testing

We built our snapshot testing setup with SnapshotTestHelper to streamline UI checks. Here’s the gist:

  • Dynamic Setup: We create UI components on-the-fly for testing, ensuring they're set up with current data and state.

  • Config Flexibility: The tool handles multiple themes and devices, simulating how UI looks across different environments.

  • Localization: It supports testing in various languages by adjusting the app’s locale dynamically, crucial for ensuring the UI displays correctly in all supported languages.

  • Comparison: We capture snapshots of the UI and compare them to reference images to spot any unintended changes.

More details here