-
Notifications
You must be signed in to change notification settings - Fork 417
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
KT-64377 - automatically download and setup Android SDK in Gradle Integration Test #3419
KT-64377 - automatically download and setup Android SDK in Gradle Integration Test #3419
Conversation
val integrationTestPreparation by tasks.registering { | ||
description = | ||
"lifecycle task for preparing the project for integration tests (for example, publishing to the test Maven repo)" | ||
group = VERIFICATION_GROUP | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll be using this task more in later PRs to help manage local Maven publishing of the included-builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please clarify a bit: this is needed for cases, where android SDK is not installed locally, right?
I mean, Android SDK can be installed already on users machines. Even so, if someone will want to run Android integration tests locally they are or Dokka developers or doing something with Android - and so most likely they will have Android SDK installed :)
On CI - it's the same, we don't want to download Android SDK on every run - so it will be preinstalled somewhere already.
I'm not against this change, just want to better understand the reasoning, may be f.e. it's better to add a flag which will cause using this SDK, if it's really needed.
With current approach, I think it's just a matter of time when some day (after some changes to tests/build-logic) we will understand, that our CI (or even local machine) downloads Android SDK on every run.
build-logic/src/main/kotlin/dokkabuild/testing/android-setup.gradle.kts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure, just asking - is this ok to store such files in .git
? :)
I mean, if I understand correctly after this any user will automatically agree
to license terms even if they doesn't know about it
May be Im a bit overreacting, just mentioning some thoughts
environment("ANDROID_HOME", androidSdkDir.asFile.invariantSeparatorsPath) | ||
} | ||
|
||
val updateProjectsAndroidLocalProperties by tasks.registering { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be Im missing something, but as we already provide ANDROID_HOME
above as env variable, why do we need to additionally copy local.properties
file to test project?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ANDROID_HOME
is required by the integration tests - possibly it could be removed.
Lines 26 to 27 in 8899834
private val isAndroidSdkInstalled: Boolean = System.getenv("ANDROID_SDK_ROOT") != null || | |
System.getenv("ANDROID_HOME") != null |
local.properties
is useful for if you want to manually open a project (in a temp dir) that's failed a test, and you want to check it manually.
/** | ||
* Create an `local.properties` file so that Android projects will automatically work in integration tests. | ||
*/ | ||
abstract class CreateAndroidLocalPropertiesFile : DefaultTask() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this task, as in the end we will just copy the text from this file? Can't we just have a property androidSdkDirPath
which we will then use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I've updated the task to do both in one. (I originally adapted it from a Dokkatoo task which needed the separate tasks.)
val createAndroidLocalPropertiesFile by tasks.registering(CreateAndroidLocalPropertiesFile::class) { | ||
localPropertiesFile.convention(layout.file(provider { temporaryDir.resolve("local.properties") })) | ||
androidSdkDirPath.convention(providers | ||
// first try getting the SDK installed on via GitHub step setup-android |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to somehow easily add out-of-the-box support for reading this value from local.properties
inside project? As I already have Android SDK installed at my side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea, I'd be happy to do it. I've done something similar in MockK before. However I'm a little bit reluctant because the Android SDK is only needed in integration tests, and scanning/parsing local.properties
files would add some complexity & maintenance.
Since it's possible to set the Android SDK using an environment variable, I'd prefer not to. But what do you think?
So, just to summarise, the reason for this is so that AGP will automatically download the Android SDK when running integration tests. This means that anyone can run the Android tests without needing to manually setup and install the SDK, which is more convenient. Adding the Committing these license files isn't common, but Mozilla and Google have done it. The android-actions/setup-android GitHub action will automatically accept the licenses too.
Good point! I'm pretty sure that the AGP auto-downloader will pick up existing Android SDK dirs, since the Dokkatoo tests on GitHub download the Android SDK which the tests should use. I'm pretty sure it doesn't download the Android SDK every time. But it's been a while since I looked at it... Perhaps there's some logic in Dokkatoo that will defer to the pre-installed SDK. |
…64377/auto-android-sdk
…wrappers' into KT-64377/update-integration-test-build-config
…64377/auto-android-sdk
… the same Android SDK dir in tests and local.properties
Thanks for checking @whyoleg 👍, I've updated the logic so the Android SDK dir will first use and also pass it in as Could you try checking it out and trying again please? |
…64377/auto-android-sdk # Conflicts: # dokka-integration-tests/gradle/.gitignore
…es task, since apparently a FileTree can't contain directories gradle/gradle#27567
Ah okay, there was a bug with the
However, I learned today that a FileTree cannot contain directories I've updated the logic to use |
…64377/auto-android-sdk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the approach to writing something into the repository state and would like to propose the following changes to use build
directory for temporary things:
- configure Android SDK for all integration tests in the
build/android-sdk
directory (if the user does not have it installed) - Generate
local.properties
file into thebuild/android-prepare/local.properties
file and pass via system property the path to the test runner - Add to this logic additionally coping
local.properties
file into test project directory. Maybe this logic could be generalized to be used in other android IT tests.
build-logic/src/main/kotlin/dokkabuild.testing.android-setup.gradle.kts
Outdated
Show resolved
Hide resolved
*/ | ||
abstract class CreateAndroidLocalPropertiesFiles : DefaultTask() { | ||
@get:OutputFiles | ||
val localPropertiesFilesDestinations: List<File> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: could be converted to SetProperty<File>
:
@get:OutputFiles
val localPropertiesFilesDestinations: SetProperty<File> = objects.setProperty<File>()
.value(
androidProjectsDirectories
.elements
.map {
it.map { it.asFile.resolve("local.properties") }.toSet()
}
)
.apply { disallowChanges() }
We should use provider API in our tasks/build configuration to make our transition to Gradle 9 smoother.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing, done. I've updated it to a Provider<Set<File>>
(which SetProperty<File>
implements) because I think using Provider<>
instead of Property<>
makes it more clear that this is a read-only value.
.environmentVariable("ANDROID_SDK_ROOT").map(::File) | ||
.orElse(providers.environmentVariable("ANDROID_HOME").map(::File)) | ||
// else get the project-local SDK | ||
.orElse(templateProjectsDir.dir("ANDROID_SDK").asFile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: could also add here .map { it.invariantSeparatorsPath }
to avoid calling it in other places
templateProjectsDir.asFile.walk() | ||
.filter { it.isDirectory && it.name in androidProjects } | ||
.asIterable() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be simplified to avoid unnecessary computation:
val androidProjects = setOf(
templateProjectsDir.dir("it-android-0"),
)
androidProjectsDirectories.from(androidProjects)
…ions to `Provider<Set<File>>`
Can do, but the set up would be a little more complicated because the license files would have to be copied into
The reason why I added |
I decided not to proceed with this PR.
I'll update the other PRs that depend on this PR. |
Automatically download and setup Android SDK so that the tests can be run on local machines without additional setup.
Downloading the Android SDK requires committing the license files, passing the directory via the ANDROID_SDK env var, and then AGP magic does the rest.
Depends on