Skip to content

Contributing

Required

  • macOS
  • CocoaPods
  • Android Studio
  • Python 3 with lxml, for the MapKit reference

MapKit reference

ymk-docs/ holds an offline copy of the Yandex MapKit reference — the source of truth for every signature the wrapper mirrors. It is generated, not stored in the repository, so build it once after cloning:

python3 ymk-docs/_tools/bootstrap.py

It fetches around 2000 pages from yandex.ru/maps-api/docs/mapkit and converts them to Markdown; expect a couple of minutes. The script is idempotent — it does nothing when the copy is already there. Add --validate to run the coverage and link checks, --force to rebuild, --refresh to re-download instead of reusing the cache in ymk-docs/_tools/cache/.

Rebuilding under a new MapKit release is described in ymk-docs/_tools/README.md.

Sample

The sample needs your API key in local.properties:

MAPKIT_API_KEY=<API-KEY>

Branches

main is the only long-lived branch. Branch off it, open a pull request back into it, and let the checks run. release/X.Y.x branches exist only when a fix has to ship without everything else that already landed on main.

Checks

Every pull request runs four jobs in parallel — lint, test-android, test-ios and api-check — and you can reproduce all of them locally:

./gradlew spotlessApply
./gradlew libraryAssemble libraryTests -PskipIosTarget=true
./gradlew libraryCompileIosArm64 libraryIosTests
./gradlew libraryApiCheck

The library* tasks fan out over the four published modules. The iOS ones need Cocoapods, and so does libraryApiCheck — the dumps cover the iOS targets, so it only runs on macOS.

Compose rendering tests wait for a real frame (GraphicsLayerImageBitmap), which the JVM does not produce, so they are excluded from the Android host run and covered by the iOS simulator plus an emulator job. That emulator job runs on pushes to main and again before every release:

./gradlew :yandex-mapkit-kmp-compose:connectedAndroidDeviceTest

Public API

The four published modules keep two dumps of their public API in <module>/api. Any change to a public declaration makes libraryApiCheck fail until both are refreshed:

./gradlew libraryApiDump

Run it on macOS — a dump generated without the iOS targets is incomplete — and commit the result together with the change. Reviewing that diff is the easiest way to see whether a pull request changes the API on purpose.

<module>.klib.api is the Kotlin ABI validator's klib dump and covers commonMain and iosMain. The validator does not pick up the Android target of com.android.kotlin.multiplatform.library, so <module>.android.api is produced separately by dumpAndroidAbi: it runs javap -public over the classes of the Android main compilation and is what guards androidMain-only declarations such as MapKit.initialize(Context) and the ImageProvider factories. Being a javap dump it is sensitive to the JDK it was generated with — use the same JDK version as CI.

Documentation

The site is MkDocs Material. It is built from docs/ and deployed by CI together with the KDoc that Dokka renders into docs/kdoc.

pip install -r docs/requirements.txt
mkdocs serve
./gradlew :dokkaGenerate

Two languages

Every page exists twice, in the suffix layout of mkdocs-static-i18n: wrapper/overview.md is English and wrapper/overview.ru.md is Russian. English is the default language and keeps the bare URLs; Russian is served under /ru/.

A page without its .ru.md twin falls back to the English text rather than 404ing, so a new page can land in one language and be translated later — but a pull request that adds one should add both. Section titles in the nav are translated in mkdocs.yml under nav_translations; a new nav entry needs its line there too.

Versions are substituted, not typed

Never write a version number into a page. docs_hooks/versions.py reads gradle.properties and gradle/libs.versions.toml at build time and replaces these placeholders:

Placeholder Source
{{ version }} library_version in gradle.properties
{{ mapkit_version }} yandex-mapkit in the version catalog
{{ kotlin_version }} kotlin in the version catalog
{{ compose_version }} compose-plugin in the version catalog
{{ min_sdk }} android-minSdk in the version catalog

An unknown placeholder is left alone, so {{ something }} in a code sample survives untouched; a known one can be escaped with a leading backslash, which is how this table is written.

The README is not built by MkDocs, so its versions are kept in sync by Gradle instead:

./gradlew updateDocumentedVersions
./gradlew checkDocumentedVersions

The check runs in the lint job, so a bumped library_version with a stale README fails CI.

Compatibility

Within 1.x the modules guarantee source compatibility, not binary compatibility.

The wrapper follows MapKit, and MapKit adds fields to its structures and constants to its enums in minor releases. The wrapper mirrors those structures as data classes, so a new field changes componentN and copy$default, and a new enum constant makes an exhaustive when over it stop compiling. Both are binary-breaking, and refusing them would mean freezing the wrapper on the MapKit version 1.0.0 shipped with.

In practice this means: recompile against the version you depend on, do not mix wrapper versions in one dependency graph, and expect a when over a wrapper enum to need a new branch after an update. Renames, removals and signature changes are still reserved for a major release.

Releases

Releases are described in RELEASING.md. Notable changes go into the Unreleased section of CHANGELOG.md in the same pull request that makes them.