Skip to content

Latest commit

 

History

History
333 lines (247 loc) · 13.5 KB

AGENTS.md

File metadata and controls

333 lines (247 loc) · 13.5 KB

Agents

This guide provides essential information for working within the firebase-android-sdk repository.

Working Agreement

As an agent executing prompts in the repository, it is necessary to execute the following steps first. If a step fails or can't otherwise be completed, ask the user how to proceed. Do not ignore these instructions or failures without prompting the user.

  • If it exists, run .firebase-sdk-skills/setup-firebase-sdk-skills.sh, if the file does not exist, you can ignore this step
  • Before continuing further, ensure that the set of skills you have access to is up to date based on updates caused by the script

Project Overview

This repository contains the source code for the Firebase Android SDKs. It is a large, multi-module Gradle project. The project is written in a mix of Java and Kotlin.

The project is structured as a collection of libraries, each representing a Firebase product or a shared component. These libraries are published as Maven artifacts to Google's Maven Repository.

Project Structure

The subprojects.cfg file lists all the subprojects in this repository. Each line in this file follows the format <project-path> # <project-type>, where project-type can be one of the following:

  • sdk: A public-facing SDK that is published.
  • test: A test application or a test-only module.
  • util: A utility module that is not part of the public API.
  • directory: A directory containing other subprojects.

This file is useful for understanding the role of each subproject in the repository.

Environment Setup

To work with this repository, the Android SDK must be installed. Use the sdkmanager command-line tool for this purpose.

  1. Install Java 17
    • All SDKs require Java 17 to build and run. Earlier or later versions will not suffice. If multiple versions of java are installed, the JAVA_HOME environment variable can be set without modifying system configuration.
  2. Install Android SDK Command-Line Tools:
    • If not already installed, download the command-line tools from the Android Studio page.
    • Create a directory for the Android SDK, e.g., android_sdk.
    • Unzip the downloaded package. This will create a cmdline-tools directory. Move this directory to android_sdk/cmdline-tools/latest.
    • The final structure should be android_sdk/cmdline-tools/latest/.
  3. Install required SDK packages:
    • Use sdkmanager to install the necessary platforms, build tools, and other packages. For example:

      # List all available packages
      sdkmanager --list
      
      # Install platform tools and the SDK for API level 33
      sdkmanager "platform-tools" "platforms;android-33"
      
      # Accept all licenses
      yes | sdkmanager --licenses
    • Refer to the specific requirements of the project to determine which packages to install.

  4. Configure for integration tests:
    • To run integration tests, a google-services.json file is required.
    • Place this file in the root of the repository.
  5. Install NDK for specific projects:
    • Some projects, like firebase-crashlytics-ndk, require a specific version of the Android NDK. You can install it using sdkmanager. For example, to install NDK version 27.2.12479018, you would run sdkmanager "ndk;27.2.12479018". Always refer to the ndkVersion declared in the project's build file for the exact version required.

Building and Running

The project is built using Gradle. The gradlew script is provided in the root directory.

Building

To build the entire project, you can run the following command:

./gradlew build

To build a specific project, you can run:

./gradlew :<firebase-project>:build

Running Tests

The project has three types of tests: unit tests, integration tests, and smoke tests.

Unit Tests

Unit tests run on the local JVM. They can be executed with the following command:

./gradlew :<firebase-project>:check

Running Specific Unit Tests

To run a specific test class or method, use the --tests filter with the appropriate test task (usually testDebugUnitTest for Android library modules, or test for Java library modules):

./gradlew :<firebase-project>:testDebugUnitTest --tests "com.google.firebase.package.ClassName"
./gradlew :<firebase-project>:testDebugUnitTest --tests "com.google.firebase.package.ClassName.methodName"

Integration Tests

Integration tests run on a hardware device or emulator. Before running integration tests, you need to add a google-services.json file to the root of the project.

To run integration tests on a local emulator, use the following command:

./gradlew :<firebase-project>:connectedCheck

To run integration tests on Firebase Test Lab, use the following command:

./gradlew :<firebase-project>:deviceCheck

Publishing

To publish a project locally, you can use the following command:

./gradlew -PprojectsToPublish="<firebase-project>" publishReleasingLibrariesToMavenLocal

By default, the release variant is published. To publish the debug variant instead, use the publishDebugVariant property:

./gradlew -PprojectsToPublish="<firebase-project>" -PpublishDebugVariant=true publishReleasingLibrariesToMavenLocal

Using the debug variant has the advantage of including additional logging information. For example, the ai-logic/firebase-ai SDK logs the request/response information when the debug variant is used.

Gradle Plugins (plugins/ Directory)

All custom build, release, CI, and documentation logic lives in the plugins/ composite build. Its internals (registered plugins, the firebaseLibrary DSL, the publishing pipeline, and Dackka reference documentation generation) are documented in plugins/AGENTS.md. Read that file before modifying anything under plugins/, or when debugging failures in publishing, release, kotlindoc, or Metalava tasks.

The following pitfalls apply when editing the build file of any module:

  • Pure Java/Kotlin modules using firebase-java-library must set firebaseLibrary { publishJavadoc = false }. DackkaPlugin assumes an Android library, so configuring generateDackkaDocumentation or running kotlindoc fails otherwise.
  • ./gradlew :<project>:check runs the Metalava docStubs task, so invalid Javadoc/KDoc syntax or missing classpath references in doc comments fail check.

Development Conventions

Code Formatting

The project uses Spotless for code formatting. To format the code, run the following command:

./gradlew spotlessApply

To format a specific project, run:

./gradlew :<firebase-project>:spotlessApply

API Surface

The public API surface of each SDK is determined by standard Java and Kotlin visibility rules and tracked with Metalava in the project's api.txt file. There is no marker annotation for public APIs; instead, the following annotations and tags control what is exposed:

  • @hide (doc comment tag): Excludes a public or protected member from the public API surface.
  • @KeepForSdk: Marks APIs that are intended for use by other Firebase SDKs. These APIs will trigger a linter error if used by developers outside of a Firebase package. They must also carry an @hide tag, otherwise they are reported as public API.
  • @Keep: Marks APIs that need to be preserved at runtime, usually due to reflection. This annotation should be used sparingly as it prevents Proguard from removing or renaming the code.

After changing a public API, regenerate api.txt with ./gradlew :<firebase-project>:generateApiTxtFile.

Common Patterns

This repository uses a combination of dependency injection frameworks:

  • firebase-components: This is a custom dependency injection framework used for discovery and dependency injection between different Firebase SDKs. It allows SDKs to register their components and declare dependencies on other components. The initialization is managed by FirebaseApp.

  • Dagger: Dagger is used for internal dependency injection within individual SDKs. This helps to create more testable and maintainable code. Dagger components are typically instantiated within the ComponentRegistrar of an SDK, which allows for the injection of dependencies from firebase-components into the Dagger graph.

Proguarding

The project supports Proguarding. Projects that need consumer Proguard rules declare them in a file (conventionally proguard.txt) registered via consumerProguardFiles in the project's build file.

Code Review

When reviewing code or preparing changes for review, ensure the following requirements are met:

  • No Latin Abbreviations: Do not use Latin abbreviations (such as e.g., i.e., or etc.) in code comments or strings. Use plain English alternatives instead (such as "for example", "that is", or "and so on").
  • API File Updates: When code modifies the public API, the corresponding api.txt file must be updated.
  • Changelog Updates: When changes to a subproject are non-trivial and user-visible, the corresponding CHANGELOG.md file must be updated.
  • API Documentation: All public APIs must be documented properly using standard doc comments (Javadoc or KDoc).

Write a helpful and well-structured CHANGELOG entry

Content

  • Focus on developer impact over technical implementation. Instead of "Refactored AuthManager.kt observer closure", write "Fixed memory leak when detaching authentication listeners."

  • For feature releases, include the common terminology that a developer might use to describe the feature and/or its use case. This helps with discovery of the feature and its related codebase change.

  • Add hyperlinks to relevant Firebase documentation, when possible. These links can be for narrative guides or reference docs. Only link to documentation that directly and accurately applies to the specific feature, API, or execution mode being described (for example, do not link to cloud-model documentation when describing an on-device feature). If no specific documentation exists for the exact feature, omit the link rather than linking to a tangentially related page that could confuse developers.

  • Do not duplicate entries that were already included in a previous release (such as a prior patch or hotfix release). Ensure that only new changes for the current release are listed.

Structure and syntax

  • Use standardized prefix tags from the following list:
    • [changed]
    • [feature]
    • [fixed]
    • [deprecated]
    • [removed]
    • [important]
    • [issue]
    • [unchanged]
  • For breaking changes, add Breaking change: at the beginning of the entry.
  • Start each entry with a past-tense verb. For example, "Fixed", "Added", "Updated", "Replaced", "Increased", "Set", etc.
  • End every entry and sentence with a period, including short phrases (for example, Internal improvements.).
  • Add the relevant PR # or Issue # to the end of each entry, after the period (for example, Fixed a crash. (#1234)).
  • Wrap lines at 80 characters maximum, using a 2-space indent for continuation lines. When writing CHANGELOG.md entries, keep the first line to at most 78 characters so that it remains within 80 characters when - [<tag>] is converted to * {{<tag>}} in generated release notes.
  • For Firebase product brand names, use the appropriate standard names.
    • For an entry that's for the product's own library, use the "short" form of the name (e.g., Crashlytics, instead of Firebase Crashlytics).
      • For an entry that's for another product's library, use the "long" form of the name (e.g., Firebase Crashlytics, instead of Crashlytics).
  • Capitalize with care.
    • Use sentence case.
      • Capitalize the following: the first letter of each sentence, proper nouns/code identifiers, official product and brand names, and abbreviations / initialisms.
      • Do not capitalize the following: every word or feature names
  • Wrap in backticks all strings that are code-like elements, including the following (this list is not exhaustive):
    • API names
    • attribute names and values
    • class names
    • CLI commands and CLI flags
    • code symbols
    • command output
    • data types
    • database elements
    • defined (constant) values for an element or attribute
    • enum names
    • filenames and file paths
    • folder and directory names
    • HTTP status codes
    • HTTP verbs
    • IP addresses
    • language keywords
    • method and function names
    • package names
    • parameters
    • port numbers
    • URL strings or domain names
    • text input or output
  • Use ISO 8601 date formatting (YYYY-MM-DD).

External Dependencies

Do not add, under any circumstance, any new dependency to an SDK that does not already exist in the gradle/libs.versions.toml, and even then, only do it if explicitly asked to do so. The Firebase SDKs are designed to be lightweight, and adding new dependencies can increase the size of the final artifacts.

Contributing

Contributions are welcome. Please read the contribution guidelines to get started.

Iteration Loop

After you make a change, here's the flow you should follow:

  • Format the code using spotless. It can be run with:

    ./gradlew :<firebase-project>:spotlessApply
  • Run unit tests:

    ./gradlew :<firebase-project>:check
  • If necessary, run integration tests based on the instructions above.

Updating this Guide

If new patterns or conventions are discovered, update this guide to ensure it remains a useful resource.