This repository has been archived by the owner on Aug 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feature] Install bazelisk if bazel is not found
Adds a new e2e test Merge-request: BAZEL-MR-479 Merged-by: Andrzej Gluszak <[email protected]>
- Loading branch information
Showing
16 changed files
with
235 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
commons/src/main/kotlin/org/jetbrains/bsp/bazel/commons/FileUtils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package org.jetbrains.bsp.bazel.commons | ||
|
||
import java.io.File | ||
|
||
object FileUtils { | ||
fun getCacheDirectory(subfolder: String): File? { | ||
val path = System.getenv("XDG_CACHE_HOME") ?: run { | ||
val os = System.getProperty("os.name").lowercase() | ||
when { | ||
os.startsWith("windows") -> | ||
System.getenv("LOCALAPPDATA") ?: System.getenv("APPDATA") | ||
os.startsWith("linux") -> | ||
System.getenv("HOME") + "/.cache" | ||
os.startsWith("mac") -> | ||
System.getenv("HOME") + "/Library/Caches" | ||
else -> return null | ||
} | ||
} | ||
val file = File(path, subfolder) | ||
try { | ||
file.mkdirs() | ||
} catch (e: Exception) { | ||
return null | ||
} | ||
if (!file.exists() || !file.isDirectory) { | ||
return null | ||
} | ||
return file | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
e2e/src/main/kotlin/org/jetbrains/bsp/bazel/ServerDownloadsBazeliskTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package org.jetbrains.bsp.bazel | ||
|
||
import org.jetbrains.bsp.bazel.base.BazelBspTestBaseScenario | ||
import org.jetbrains.bsp.bazel.base.BazelBspTestScenarioStep | ||
import org.jetbrains.bsp.bazel.install.Install | ||
import java.time.Duration | ||
|
||
object ServerDownloadsBazeliskTest : BazelBspTestBaseScenario() { | ||
@JvmStatic | ||
fun main(args: Array<String>) = executeScenario() | ||
|
||
override fun installServer() { | ||
// DO NOT supply the -b flag to test whether bazelisk is downloaded | ||
Install.main( | ||
arrayOf( | ||
"-d", workspaceDir, | ||
"-t", "//...", | ||
"--produce-trace-log" | ||
) | ||
) | ||
} | ||
|
||
override fun scenarioSteps(): List<BazelBspTestScenarioStep> = listOf(resolveProject()) | ||
|
||
private fun resolveProject(): BazelBspTestScenarioStep = BazelBspTestScenarioStep( | ||
"resolve project" | ||
) { testClient.testResolveProject(Duration.ofMinutes(2)) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 81 additions & 31 deletions
112
...kspacecontext/src/main/kotlin/org/jetbrains/bsp/bazel/workspacecontext/BazelBinarySpec.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,106 @@ | ||
package org.jetbrains.bsp.bazel.workspacecontext | ||
|
||
import org.apache.logging.log4j.LogManager | ||
import org.jetbrains.bsp.bazel.commons.FileUtils | ||
import org.jetbrains.bsp.bazel.executioncontext.api.ExecutionContextSingletonEntity | ||
import org.jetbrains.bsp.bazel.executioncontext.api.ExecutionContextEntityExtractor | ||
import org.jetbrains.bsp.bazel.executioncontext.api.ExecutionContextEntityExtractorException | ||
import org.jetbrains.bsp.bazel.projectview.model.ProjectView | ||
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewBazelBinarySection | ||
import java.io.File | ||
import java.net.URI | ||
import java.nio.file.Path | ||
|
||
data class BazelBinarySpec( | ||
override val value: Path | ||
override val value: Path, | ||
) : ExecutionContextSingletonEntity<Path>() | ||
|
||
private val log = LogManager.getLogger(BazelBinarySpec::class.java) | ||
|
||
// TODO(abrams): update tests for the whole flow and mock different OSes | ||
internal object BazelBinarySpecExtractor : ExecutionContextEntityExtractor<BazelBinarySpec> { | ||
|
||
override fun fromProjectView(projectView: ProjectView): BazelBinarySpec = | ||
when (projectView.bazelBinary) { | ||
null -> findBazelOnPath() | ||
else -> map(projectView.bazelBinary!!) | ||
override fun fromProjectView(projectView: ProjectView): BazelBinarySpec { | ||
val extracted = projectView.bazelBinary?.value | ||
return if (extracted != null) { | ||
BazelBinarySpec(extracted) | ||
} else { | ||
val path = findBazelOnPathOrNull() ?: downloadBazelisk() | ||
?: throw ExecutionContextEntityExtractorException( | ||
"bazel path", | ||
"Could not find bazel on your PATH nor download bazelisk" | ||
) | ||
BazelBinarySpec(path) | ||
} | ||
} | ||
|
||
|
||
private fun findBazelOnPath(): BazelBinarySpec = | ||
findBazelOnPathOrNull() | ||
?: throw | ||
ExecutionContextEntityExtractorException( | ||
"bazel path", | ||
"Could not find bazel on your PATH" | ||
) | ||
private fun downloadBazelisk(): Path? { | ||
log.info("Downloading bazelisk") | ||
val downloadLink = calculateBazeliskDownloadLink()?.let { | ||
try { | ||
URI(it).toURL() | ||
} catch (e: Exception) { | ||
log.error("Could not parse bazelisk download link: $it") | ||
return null | ||
} | ||
} | ||
if (downloadLink == null) { | ||
log.error("Could not calculate bazelisk download link (your OS should be one of: windows-amd64, linux-amd64, linux-arm64, darwin)") | ||
return null | ||
} | ||
val cache = FileUtils.getCacheDirectory("bazelbsp") | ||
if (cache == null) { | ||
log.error("Could not find cache directory") | ||
return null | ||
} | ||
// Download bazelisk to the cache folder | ||
val bazeliskFile = File(cache, "bazelisk") | ||
if (bazeliskFile.exists()) { | ||
log.info("Bazelisk already exists in the cache folder: ${bazeliskFile.path}") | ||
} else { | ||
log.info("Downloading bazelisk to the cache folder: ${bazeliskFile.path}") | ||
org.apache.commons.io.FileUtils.copyURLToFile(downloadLink, | ||
bazeliskFile, | ||
60 * 1000, | ||
60 * 1000) | ||
log.info("Downloaded bazelisk") | ||
} | ||
return bazeliskFile.toPath() | ||
} | ||
|
||
private fun findBazelOnPathOrNull(): BazelBinarySpec? = | ||
private fun calculateBazeliskDownloadLink(): String? { | ||
// TODO: https://youtrack.jetbrains.com/issue/BAZEL-743 | ||
val base = "https://github.com/bazelbuild/bazelisk/releases/download/v1.18.0/bazelisk-" | ||
val os = System.getProperty("os.name").lowercase() | ||
val arch = System.getProperty("os.arch").lowercase() | ||
val suffix = when { | ||
os.startsWith("windows") && arch == "amd64" -> base + "windows-amd64.exe" | ||
os.startsWith("linux") && arch == "amd64" -> base + "linux-amd64" | ||
os.startsWith("linux") && arch == "arm64" -> base + "linux-arm64" | ||
os.startsWith("mac") -> base + "darwin" | ||
else -> null | ||
} | ||
if (suffix == null) { | ||
log.error("Could not calculate bazelisk download link (your OS should be one of: windows-amd64, linux-amd64, linux-arm64, darwin)") | ||
} | ||
return base + suffix | ||
} | ||
|
||
private fun findBazelOnPathOrNull(): Path? = | ||
splitPath() | ||
.map { mapToBazel(it) } | ||
.firstOrNull { it.canExecute() } | ||
?.toPath() | ||
?.let { BazelBinarySpec(it) } | ||
.flatMap { listOf(bazelFile(it, "bazel"), bazelFile(it, "bazelisk")) } | ||
.firstOrNull() | ||
|
||
private fun splitPath(): List<String> = System.getenv("PATH").split(File.pathSeparator) | ||
|
||
private fun mapToBazel(path: String): File = File(path, calculateBazeliskExecName()) | ||
|
||
// TODO: update tests for the whole flow and mock different OSes | ||
private fun calculateBazeliskExecName(): String { | ||
val osName = System.getProperty("os.name").lowercase() | ||
return with(osName) { | ||
when { | ||
startsWith("windows") -> "bazel.exe" | ||
else -> "bazel" | ||
} | ||
} | ||
private fun bazelFile(path: String, executable: String): Path? { | ||
val file = File(path, calculateExecutableName(executable)) | ||
return if (file.exists() && file.canExecute()) file.toPath() else null | ||
} | ||
|
||
private fun map(bazelBinarySection: ProjectViewBazelBinarySection): BazelBinarySpec = | ||
BazelBinarySpec(bazelBinarySection.value) | ||
private fun calculateExecutableName(name: String): String = when { | ||
System.getProperty("os.name").lowercase().startsWith("windows") -> "$name.exe" | ||
else -> name | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 0 additions & 43 deletions
43
server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bsp/BazelBspServerLifetime.java
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.