Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dataconnect: integrate codegen into the gradle build #2569

Open
wants to merge 81 commits into
base: master
Choose a base branch
from

Conversation

dconeybe
Copy link
Contributor

@dconeybe dconeybe commented Nov 18, 2024

This PR adds a custom gradle plugin to the "dataconnect" project to hook into the gradle build and generate the Data Connect source code automatically as part of the build. There is no longer a requirement to manually download and launch the Data Connect emulator just to build the project. This behaves very similarly to the protobuf gradle plugin (https://github.com/google/protobuf-gradle-plugin) and how it compiles the .proto files to java/kt files on-demand when the project is built. This also unblocks compiling the dataconnect module in GitHub CI.

The plugin first creates a node project directory (by creating an empty directory that contains an empty package.json) and installs the configured version of firebase-tools into it by running npm install. Then, it uses that firebase-tools to run the dataconnect:sdk:generate subcommand. In order to control where the generated code gets placed, a copy of the dataconnect.yaml et al files is made, and the connector.yaml files are modified to only produce kotlin connectors and to put them into the directory of the gradle plugin's choosing. All of this is done in the "build" directory, and, therefore, is wiped out by a "gradle clean".

As a nice side effect, the GitHub Actions CI can now compile dataconnect just fine. Therefore, this PR also removes the hacks that opted dataconnect out of the CI.

The following new tasks are now present in the :dataconnect:app module:

  1. setupFirebaseToolsForDataConnect
    • Creates the directory dataconnect/app/build/dataconnect/firebase-tools with a single file in it, an empty package.json.
    • Runs npm install [email protected] in that directory (the version is configured in build.gradle.kts).
  2. generateDebugDataConnectSources and generateReleaseDataConnectSources
    • Depends on the setupFirebaseToolsForDataConnect task to set up the firebase command
    • Copies the contents of dataconnect/dataconnect into dataconnect/app/build/dataconnect/variants/{debug,release}/config
    • Edits the connector.yaml file(s) to remove all SDKs under the generate section, except for kotlinSdk. This is because since we're building the kotlin SDK, we don't want to generate code for other SDKs.
    • Modifies the outputDir of the kotlinSdk to use the directory specified by the gradle plugin for placing the generated code. This is because gradle dictates where the generated code is to go and this directory can't be known in advance and hardcoded into the file. Moreover, the directories are different for the "debug" and "release" builds.
    • Runs firebase dataconnect:sdk:generate to generate the code into the directory dictated by gradle.

This plugin is configured by a new "extension" added to dataconnect/app/build.gradle.kts. It looks like this:

dataconnect {
    // The version of https://www.npmjs.com/package/firebase-tools to use to perform the
    // Data Connect code generation.
    firebaseToolsVersion = "13.25.0"

    // The directory that contains dataconnect.yaml to use as input when performing
    // the Data Connect code generation.
    dataConnectConfigDir = file("../dataconnect")
}

This gradle plugin is a proof-of-concept and isn't quite production ready. If it proves to be valuable, customers can at least copy/paste it into their own Android projects. Or, we could make it an "official" plugin. There is even a way to remove the need for node altogether, by just calling the data connect toolkit cli binary directly (without needing to install firebase-tools). This plugin was largely based on my experience writing a similar gradle plugin in the dataconnect android sdk itself: https://github.com/firebase/firebase-android-sdk/blob/866e6bd246fde0e54fdeb5f5d0c043632edf4161/firebase-dataconnect/gradleplugin/plugin/src/main/kotlin/com/google/firebase/dataconnect/gradle/plugin/DataConnectGradlePlugin.kt.

@dconeybe dconeybe marked this pull request as ready for review November 19, 2024 04:23
.github/workflows/android.yml Outdated Show resolved Hide resolved
@@ -14,8 +14,10 @@ activityCompose = "1.9.3"
composeBom = "2024.11.00"
googleServices = "4.4.2"
composeNavigation = "2.8.4"
ktfmt = "0.43"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required)

We use ktlint in this repo, but I've considered moving to ktfmt so that it aligns with the SDK formatting.

I'm happy to move forward with ktfmt only applied to dataconnect in this PR and we can apply to other modules and remove ktlint in a follow-up PR.

dataconnect/README.md Outdated Show resolved Hide resolved
Comment on lines 11 to 14
# Use an arbitrary directory for generating the code, as the
# "com.google.firebase.example.dataconnect.gradle" custom Gradle plugin applied by
# app/build.gradle.kts will look after generating the code on-demand into the
# appropriate directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does it generate? I checked out your repo and tried running the ./gradlew generateDebugDataConnectSources command but couldn't see the generated files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update the comment to be more clear about where the code gets generated by gradle.

In the meantime, if you run ./gradlew --info generateDebugDataConnectSources (i.e. add the --info argument) the logs state the directory into which the code is generated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, cool, I see it in quickstart-android/dataconnect/app/build/generated/java/generateDebugDataConnectSources/com/google/firebase/dataconnect/movies

dconeybe and others added 24 commits November 19, 2024 18:54
…mple of the directory into which the code may be generated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants