Skip to main content
If you’re thinking about contributing to Patrol, thank you! We appreciate your help. Before you get started, we encourage you to read this document to make your contributing experience better.

Ways to Contribute

There are many ways to contribute to Patrol:
  • Report bugs: Found a bug? Open an issue
  • Request features: Have an idea? Start a discussion
  • Improve documentation: Fix typos, clarify sections, or add examples
  • Write code: Fix bugs, implement features, or improve performance
  • Help others: Answer questions on Discord or GitHub

Opening a Pull Request

Before opening a PR with your changes, please ensure:
  1. Update the changelog for the package you modified
  2. Mention the related issue in the PR description. If no issue exists, create one or describe the changes in detail
  3. Use ## Unreleased title in the changelog if you’re not sure what the next version number should be
  4. Be aware that test android emulator and test android emulator webview workflows will fail due to insufficient permissions for contributors. These will need to be re-run by someone with write access to the repository

Development Setup

Prerequisites

  • Flutter SDK (latest stable version)
  • Dart SDK (comes with Flutter)
  • Android Studio or VS Code
  • Xcode (for iOS/macOS development)
  • Git

Clone the Repository

git clone https://github.com/leancodepl/patrol.git
cd patrol

Repository Structure

Patrol is a monorepo containing multiple packages:
patrol/
├── packages/
│   ├── patrol/              # Main Patrol package
│   ├── patrol_cli/          # CLI tool
│   ├── patrol_finders/      # Custom finders
│   ├── patrol_log/          # Logging utilities
│   ├── patrol_devtools_extension/  # DevTools extension
│   └── adb/                 # ADB utilities
└── dev/
    └── e2e_app/             # Example app for testing

Running patrol_cli Locally

If you want to work with a local version of patrol_cli, you have two options:

Option 1: Global Activation

Activate patrol_cli locally:
dart pub global activate --source path packages/patrol_cli
After that, you can use the patrol command exactly as you would with a published version.

Option 2: Direct Execution

Run commands directly:
dart run packages/patrol_cli <command you want to test>

Debugging patrol_cli

Changes to Patrol CLI can be debugged using the following configurations:

Visual Studio Code

Use the .vscode/launch.json configuration, changing the cwd value to the path of the project you want to test and updating paths to the target tests in args:
{
  "version": "0.1.0",
  "configurations": [
    {
      "name": "Patrol CLI",
      "request": "launch",
      "type": "dart",
      "program": "patrol/packages/patrol_cli/bin/main.dart",
      "cwd": "dev/e2e_app",
      "args": ["test", "-t", "patrol_test/example_test.dart"]
    }
  ]
}

Android Studio / IntelliJ IDEA

Use the .run/patrol_cli.run.xml configuration, changing the working directory value to the path of the project you want to test and updating paths to the target tests in arguments:
<component name="ProjectRunConfigurationManager">
  <configuration default="false" name="patrol_cli" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application">
    <option name="arguments" value="test -t patrol_test/example_test.dart" />
    <option name="filePath" value="$PROJECT_DIR$/packages/patrol_cli/bin/main.dart" />
    <option name="workingDirectory" value="$PROJECT_DIR$/dev/e2e_app" />
    <method v="2" />
  </configuration>
</component>

Implementing Native Interactions

Native methods API is generated from a schema. If you wish to modify any of these methods:
1

Edit the schema

Go to schema.dart in the root directory of the repository. Add or modify methods as needed.
2

Regenerate contracts

Run the ./gen_from_schema script to regenerate the contracts:
./gen_from_schema
3

Implement native side

Implement the methods on the native side (Kotlin for Android, Swift for iOS).
iOS Development Tip: During development, you should remove #if PATROL_ENABLED from AutomatorServer.swift and Automator.swift to make code completion work.

Working with patrol_devtools_extension

If you plan to use the local version of Patrol to test/modify the Patrol DevTools extension:
  1. Navigate to the patrol_devtools_extension folder
  2. Run the publish script:
    ./publish_to_patrol_extension
    
This deploys the extension locally for testing.

Adding Localization for Native Interactions

Patrol supports multiple languages for native OS interactions (like permission dialogs).

Adding iOS Localization

1

Create or update language folder

Go to packages/patrol/darwin/Resources/ and add a new language folder (e.g., es.lproj for Spanish) or use an existing one.
2

Add strings file

Create or update Localizable.strings in the language folder:
"allow_once" = "Permitir una vez";
"allow_while_using" = "Permitir mientras se usa la app";
3

Update getLocalizedStrings function

Add the new language to the getLocalizedStrings function in IOSAutomator.swift.
4

Update function usage

Find all functions where these strings are used and add them. For example, “labels” in allowPermissionOnce() in IOSAutomator.swift.
5

Register language

Add the new language to the supportedLanguages array in Localization.swift.

Adding Android Localization

1

Create or update values folder

Go to packages/patrol/android/src/main/res/ and create values-<language>/ folder (e.g., values-es/ for Spanish).
2

Add strings file

Create or update strings.xml in the values folder:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="allow_once">Permitir una vez</string>
    <string name="allow_while_using">Permitir mientras se usa la app</string>
</resources>
3

Update function usage

If you added new strings, add them to the proper function in Automator.kt. For example, look at the toggleAirplaneMode() function.
4

Register language

Add the new language to the getLocalizedString function in Localization.kt.

Supported Languages

Patrol currently supports the following languages for native interactions:
  • English (en)
  • German (de)
  • French (fr)
  • Polish (pl)
  • Spanish (es)

Code Style

We use leancode_lint for Dart code style. The linter runs automatically on PRs.

Dart/Flutter Code

  • Follow Effective Dart guidelines
  • Use leancode_lint rules
  • Format code with dart format
  • Run analysis with flutter analyze

Native Code

Kotlin (Android): Swift (iOS):

Testing

Before submitting a PR, ensure all tests pass:
# Run Dart tests
dart test

# Run Flutter tests
flutter test

# Run Patrol tests in example app
cd dev/e2e_app
patrol test

Documentation

When adding new features:
  1. Update relevant documentation in the docs/ folder
  2. Add code examples demonstrating usage
  3. Update the changelog in the affected package
  4. Add inline code comments for complex logic

Commit Messages

We don’t enforce a strict commit message format, but please:
  • Write clear, descriptive commit messages
  • Reference related issues (e.g., “Fix #123: Description”)
  • Keep commits focused on a single change when possible

Release Process

Releases are handled by maintainers. Contributors don’t need to worry about versioning, but should update the changelog with ## Unreleased for their changes.

Questions?

If you have questions about contributing:

Code of Conduct

We expect all contributors to follow our code of conduct:
  • Be respectful and inclusive
  • Focus on constructive feedback
  • Help create a welcoming environment
  • Respect differing viewpoints and experiences

License

By contributing to Patrol, you agree that your contributions will be licensed under the Apache License 2.0.

Recognition

Contributors are recognized in:
  • GitHub contributors page
  • Release notes for significant contributions
  • Our documentation (for major features)
Thank you for contributing to Patrol! 🚀

Build docs developers (and LLMs) love