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

Add IDEA provisioning #529

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

Add IDEA provisioning #529

wants to merge 3 commits into from

Conversation

6hundreds
Copy link
Member

This PR integrates ide-starter to Gradle profiler and provide some wrappers around it. In particular, some abstraction for IDE provisioning is introduced alongside with an implementation of IDEA provisioning.

Provisioning does include downloading of an IDE of desired version to a desired directory.

@6hundreds 6hundreds requested a review from asodja January 15, 2024 09:05
@6hundreds 6hundreds self-assigned this Jan 15, 2024
}

repositories {
maven { url = uri("https://www.jetbrains.com/intellij-repository/releases") }
Copy link
Member Author

Choose a reason for hiding this comment

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

These repos are subject to cleanup, I hope not all of them are required. It's just copy-paste from JetBrains example repo

Copy link
Member

Choose a reason for hiding this comment

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

❓Can we clean them now?

info -> null
);

String version = ideInfo.getVersion().isEmpty()
Copy link
Member Author

Choose a reason for hiding this comment

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

Here and below own cache logic was implemented. Why:
IdeDownloader is able to skip downloading, but it's considering a presence of installer(like a .dmg) file.
However, I'm deleting an installer after unpacking of it, because it's quite big (1+ Gb).
At the same time, I don't want to download IDE each time. So simple heuristics was introduced - create new dir like ideaIC/latest/ and assuming that only one file (ide installation, in fact, like a .app) is there. If it there - skip downloading.

Copy link
Member

Choose a reason for hiding this comment

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

Doesn't idea starter do any caching?

Copy link
Member Author

Choose a reason for hiding this comment

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

It does. But it's relying on presence of installer(like a .dmg file). If we want to delete installers after unpacking(I guess we want), then we can't rely on it


public interface Ide {
@NotNull
String getVersion();
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm doubting what data to use for providing. From one perspective version is a good and simple declaration of which release of IDE we want to get. However, there is a buildNumber as well, and it's possible to have a IDE with same version with different buildNumbers(I thinks it's the case for nightlies)

Copy link
Member

@asodja asodja Jan 15, 2024

Choose a reason for hiding this comment

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

We can always change that later, if we have a need to. So I think version is fine for now

import java.util.Arrays;
import java.util.List;

public class TeeOutputStream extends OutputStream {
Copy link
Member Author

Choose a reason for hiding this comment

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

This was copy/pasted from gradle-profiler, but I think we should create some project with test fixtures or so. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we could have some text-fixtures if we share the code

Copy link
Member Author

Choose a reason for hiding this comment

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

TeeOutputStream is a part of common-io, that was already included to gradle-profiler. So decided to remove own implementations and use common one


java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
Copy link
Member

Choose a reason for hiding this comment

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

❓ Note: if we use Java 17 we won't be able to use it in gradle-profiler. Will we keep Java 17?

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh, it seems like ide-starter was compiled using Java 17:
class file has wrong version 61.0, should be 52.0

The public API of ide-provisioning subproject is not contains any classes from ide-starter, so I think it should be possible somehow to configure toolchains in such a way, to use ide-starter with Java 17 internally, but compile ide-provisioning subproject using Java 8. Do you know how to achieve that?

Copy link
Member

@asodja asodja Jan 15, 2024

Choose a reason for hiding this comment

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

The problem is not just compiling, but also running classes compiled with Java17 on JDK < 17. So then we would need gradle-profiler to require to run only on JDK >= 17 or at least require JDK >= 17 when doing sync profiling.

Copy link
Member Author

Choose a reason for hiding this comment

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

@asodja How to do it correctly?

Copy link
Member

Choose a reason for hiding this comment

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

Good question. I believe we still want to profile with gradle-profiler on JDK8 for most scenarions, but maybe we could soften that for sync profiling.

I guess we would need to:

  1. Add a check when user tries to profile sync and they use JDK < 17 we fail
  2. Add some interface to call IDE provisioning
  3. Use multirelease jar or ServiceLoader to implement Java17 implementation

Copy link
Member

Choose a reason for hiding this comment

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

I think we need to put some more thoughts in to that

Copy link
Member Author

Choose a reason for hiding this comment

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

@asodja I think for now we can check JDK < 17 only if user enabled IDE auto-provisioning for sync. In future, when profiler will use ide-starter for sync triggering as well, we could think about it extend scope of that check, yes

Copy link
Member Author

Choose a reason for hiding this comment

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

@asodja Another "possible" option is fork ide-starter and build it from source using 8, right? But supporting a fork can be painful tho.

Copy link
Member Author

Choose a reason for hiding this comment

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

Checked out assemble of ide-starter with 8 - the main issue is using java.lang.ProcessHandle, which is was introduced in 9

Copy link
Member

Choose a reason for hiding this comment

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

I would not fork ide-starter, since that means extra work to maintain it as you mentioned. And I am sure we don't have resources for that.

Theoretically we could also just call that part of code with JDK >= 17 (so user would somehow provide a path to some JDK17 compatbile JDK), but I think having a requirement to use JDK17 for sync is ok.

I would maybe just ask on Slack if anyone has any concern regarding that (or possible if they see any other option).

}

repositories {
maven { url = uri("https://www.jetbrains.com/intellij-repository/releases") }
Copy link
Member

Choose a reason for hiding this comment

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

❓Can we clean them now?

}

dependencies {
implementation("com.jetbrains.intellij.tools:ide-starter-squashed:233.13135.103") {
Copy link
Member

Choose a reason for hiding this comment

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

💅 Maybe we can use version catalog for this one too

import java.util.Arrays;
import java.util.List;

public class TeeOutputStream extends OutputStream {
Copy link
Member

Choose a reason for hiding this comment

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

Yes, we could have some text-fixtures if we share the code


then:
outputContains("Downloading https://")
assert ide.exists()
Copy link
Member

Choose a reason for hiding this comment

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

❓ Do you need assert? If you setup Spock correctly then assert should not be needed here

plugins {
id("profiler.embedded-library")
}

Copy link
Member

Choose a reason for hiding this comment

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

❓How will we use and bundle it in the gradle-profiler? Also how do you plan to publish it in reuse in gradle/gradle.

I think this two things will require some additional work.

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. I thought about regular subproject usage as a dependency.
  2. In fact, we don't need to reuse it in gradle/gradle directly. gradle/gradle will invoke profiler with dedicated options for auto-provisioning.

Signed-off-by: Sergey Opivalov <[email protected]>
Signed-off-by: Sergey Opivalov <[email protected]>
Signed-off-by: Sergey Opivalov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants