mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 03:21:44 +03:00
Add Python and R to the GraalVM Bundle (#1644)
CI release pipeline is updated to install python and R GraalVM components
This commit is contained in:
parent
8b0588939e
commit
65e9cca5a4
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@ -142,7 +142,8 @@ jobs:
|
|||||||
working-directory: repo
|
working-directory: repo
|
||||||
shell: bash
|
shell: bash
|
||||||
run: >
|
run: >
|
||||||
DIST_OS=$(echo ${{ runner.os }} | awk '{print tolower($0)}') bash
|
GRAAL_VERSION=$(echo ${{ env.graalVersion }}) DIST_OS=$(echo
|
||||||
|
${{runner.os }} | awk '{print tolower($0)}') bash
|
||||||
tools/ci/prepare-distribution-env.sh
|
tools/ci/prepare-distribution-env.sh
|
||||||
|
|
||||||
- name: Prepare Launcher Distribution
|
- name: Prepare Launcher Distribution
|
||||||
@ -163,6 +164,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sleep 1
|
sleep 1
|
||||||
sbt buildProjectManagerDistribution
|
sbt buildProjectManagerDistribution
|
||||||
|
- name: Prepare GraalVM Distribution
|
||||||
|
working-directory: repo
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sleep 1
|
||||||
|
sbt buildGraalDistribution
|
||||||
|
|
||||||
# Ensure that the versions encoded in the binary and in the release match
|
# Ensure that the versions encoded in the binary and in the release match
|
||||||
- name: Check Versions (Unix)
|
- name: Check Versions (Unix)
|
||||||
@ -216,6 +223,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: ${{ env.PROJECTMANAGER_DIST_NAME }}
|
name: ${{ env.PROJECTMANAGER_DIST_NAME }}
|
||||||
path: repo/${{ env.PROJECTMANAGER_DIST_ROOT }}
|
path: repo/${{ env.PROJECTMANAGER_DIST_ROOT }}
|
||||||
|
- name: Upload the GraalVM Artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ env.GRAAL_DIST_NAME }}
|
||||||
|
path: repo/${{ env.GRAAL_DIST_ROOT }}
|
||||||
- name: Upload the Manifest Artifact
|
- name: Upload the Manifest Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
|
25
build.sbt
25
build.sbt
@ -1362,3 +1362,28 @@ buildProjectManagerDistribution := {
|
|||||||
DistributionPackage.createProjectManagerPackage(root, cacheFactory)
|
DistributionPackage.createProjectManagerPackage(root, cacheFactory)
|
||||||
log.info(s"Project Manager package created at $root")
|
log.info(s"Project Manager package created at $root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy val buildGraalDistribution =
|
||||||
|
taskKey[Unit]("Builds the GraalVM distribution")
|
||||||
|
buildGraalDistribution := {
|
||||||
|
val log = streams.value.log
|
||||||
|
val distOs = "DIST_OS"
|
||||||
|
val osName = "os.name"
|
||||||
|
val distName = sys.env.get(distOs).getOrElse {
|
||||||
|
val name = sys.props(osName).takeWhile(!_.isWhitespace)
|
||||||
|
if (sys.env.contains("CI")) {
|
||||||
|
log.warn(
|
||||||
|
s"$distOs env var is empty. Fallback to system property $osName=$name."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
name
|
||||||
|
}
|
||||||
|
val os = DistributionPackage.OS(distName).getOrElse {
|
||||||
|
throw new RuntimeException(s"Failed to determine OS: $distName.")
|
||||||
|
}
|
||||||
|
packageBuilder.createGraalPackage(
|
||||||
|
log,
|
||||||
|
os,
|
||||||
|
DistributionPackage.Architecture.X64
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -6,6 +6,36 @@ import sbt.util.{CacheStore, CacheStoreFactory, FileInfo, Tracked}
|
|||||||
import scala.sys.process._
|
import scala.sys.process._
|
||||||
|
|
||||||
object DistributionPackage {
|
object DistributionPackage {
|
||||||
|
|
||||||
|
/** File extensions. */
|
||||||
|
implicit class FileExtensions(file: File) {
|
||||||
|
|
||||||
|
/** Get the outermost directory of this file. For absolute paths this
|
||||||
|
* function always returns root.
|
||||||
|
*
|
||||||
|
* == Example ==
|
||||||
|
* Get top directory of the relative path.
|
||||||
|
* {{{
|
||||||
|
* file("foo/bar/baz").getTopDirectory == file("foo")
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* Get top directory of the absolute path.
|
||||||
|
* {{{
|
||||||
|
* file(/foo/bar/baz").getTopDirectory == file("/")
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* @return the outermost directory of this file.
|
||||||
|
*/
|
||||||
|
def getTopDirectory: File = {
|
||||||
|
@scala.annotation.tailrec
|
||||||
|
def go(path: File): File = {
|
||||||
|
val parent = path.getParentFile
|
||||||
|
if (parent == null) path else go(parent)
|
||||||
|
}
|
||||||
|
go(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def copyDirectoryIncremental(
|
def copyDirectoryIncremental(
|
||||||
source: File,
|
source: File,
|
||||||
destination: File,
|
destination: File,
|
||||||
@ -150,6 +180,7 @@ object DistributionPackage {
|
|||||||
|
|
||||||
sealed trait OS {
|
sealed trait OS {
|
||||||
def name: String
|
def name: String
|
||||||
|
def hasSupportForSulong: Boolean
|
||||||
def graalName: String = name
|
def graalName: String = name
|
||||||
def executableName(base: String): String = base
|
def executableName(base: String): String = base
|
||||||
def archiveExt: String = ".tar.gz"
|
def archiveExt: String = ".tar.gz"
|
||||||
@ -157,20 +188,31 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
object OS {
|
object OS {
|
||||||
case object Linux extends OS {
|
case object Linux extends OS {
|
||||||
override def name: String = "linux"
|
override val name: String = "linux"
|
||||||
|
override val hasSupportForSulong: Boolean = true
|
||||||
}
|
}
|
||||||
case object MacOS extends OS {
|
case object MacOS extends OS {
|
||||||
override def name: String = "macos"
|
override val name: String = "macos"
|
||||||
|
override val hasSupportForSulong: Boolean = true
|
||||||
override def graalName: String = "darwin"
|
override def graalName: String = "darwin"
|
||||||
}
|
}
|
||||||
case object Windows extends OS {
|
case object Windows extends OS {
|
||||||
override def name: String = "windows"
|
override val name: String = "windows"
|
||||||
|
override val hasSupportForSulong: Boolean = false
|
||||||
override def executableName(base: String): String = base + ".exe"
|
override def executableName(base: String): String = base + ".exe"
|
||||||
override def archiveExt: String = ".zip"
|
override def archiveExt: String = ".zip"
|
||||||
override def isUNIX: Boolean = false
|
override def isUNIX: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
val platforms = Seq(Linux, MacOS, Windows)
|
val platforms = Seq(Linux, MacOS, Windows)
|
||||||
|
|
||||||
|
def apply(name: String): Option[OS] =
|
||||||
|
name.toLowerCase match {
|
||||||
|
case Linux.`name` => Some(Linux)
|
||||||
|
case MacOS.`name` => Some(MacOS)
|
||||||
|
case Windows.`name` => Some(Windows)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait Architecture {
|
sealed trait Architecture {
|
||||||
@ -213,6 +255,14 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def listZip(archive: File): Seq[File] = {
|
||||||
|
val suppressStdErr = ProcessLogger(_ => ())
|
||||||
|
val zipList = Process(
|
||||||
|
Seq("zip", "-l", archive.toPath.toAbsolutePath.normalize.toString)
|
||||||
|
)
|
||||||
|
zipList.lineStream(suppressStdErr).map(file)
|
||||||
|
}
|
||||||
|
|
||||||
private def extractTarGz(archive: File, root: File): Unit = {
|
private def extractTarGz(archive: File, root: File): Unit = {
|
||||||
IO.createDirectory(root)
|
IO.createDirectory(root)
|
||||||
val exitCode = Process(
|
val exitCode = Process(
|
||||||
@ -228,6 +278,13 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def listTarGz(archive: File): Seq[File] = {
|
||||||
|
val suppressStdErr = ProcessLogger(_ => ())
|
||||||
|
val tarList =
|
||||||
|
Process(Seq("tar", "tf", archive.toPath.toAbsolutePath.toString))
|
||||||
|
tarList.lineStream(suppressStdErr).map(file)
|
||||||
|
}
|
||||||
|
|
||||||
private def extract(archive: File, root: File): Unit = {
|
private def extract(archive: File, root: File): Unit = {
|
||||||
if (archive.getName.endsWith("zip")) {
|
if (archive.getName.endsWith("zip")) {
|
||||||
extractZip(archive, root)
|
extractZip(archive, root)
|
||||||
@ -236,15 +293,31 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def copyGraal(
|
private def list(archive: File): Seq[File] = {
|
||||||
|
if (archive.getName.endsWith("zip")) {
|
||||||
|
listZip(archive)
|
||||||
|
} else {
|
||||||
|
listTarGz(archive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def graalArchive(os: OS, architecture: Architecture): File = {
|
||||||
|
val packageDir =
|
||||||
|
artifactRoot / s"graalvm-$graalVersion-${os.name}-${architecture.name}"
|
||||||
|
if (!packageDir.exists()) {
|
||||||
|
IO.createDirectory(packageDir)
|
||||||
|
}
|
||||||
|
val archiveName = s"graalvm-${os.name}-${architecture.name}-" +
|
||||||
|
s"$graalVersion-$graalJavaVersion"
|
||||||
|
packageDir / (archiveName + os.archiveExt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def downloadGraal(
|
||||||
log: ManagedLogger,
|
log: ManagedLogger,
|
||||||
os: OS,
|
os: OS,
|
||||||
architecture: Architecture,
|
architecture: Architecture
|
||||||
runtimeDir: File
|
): File = {
|
||||||
): Unit = {
|
val archive = graalArchive(os, architecture)
|
||||||
val packageName = s"graalvm-${os.name}-${architecture.name}-" +
|
|
||||||
s"$graalVersion-$graalJavaVersion"
|
|
||||||
val archive = artifactRoot / (packageName + os.archiveExt)
|
|
||||||
if (!archive.exists()) {
|
if (!archive.exists()) {
|
||||||
log.info(
|
log.info(
|
||||||
s"Downloading GraalVM $graalVersion Java $graalJavaVersion " +
|
s"Downloading GraalVM $graalVersion Java $graalJavaVersion " +
|
||||||
@ -261,9 +334,94 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
archive
|
||||||
|
}
|
||||||
|
|
||||||
|
private def copyGraal(
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture,
|
||||||
|
runtimeDir: File
|
||||||
|
): Unit = {
|
||||||
|
val archive = graalArchive(os, architecture)
|
||||||
extract(archive, runtimeDir)
|
extract(archive, runtimeDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prepare the GraalVM package.
|
||||||
|
*
|
||||||
|
* @param log the logger
|
||||||
|
* @param os the system type
|
||||||
|
* @param architecture the architecture type
|
||||||
|
* @return the path to the created GraalVM package
|
||||||
|
*/
|
||||||
|
def createGraalPackage(
|
||||||
|
log: ManagedLogger,
|
||||||
|
os: OS,
|
||||||
|
architecture: Architecture
|
||||||
|
): File = {
|
||||||
|
log.info("Building GraalVM distribution")
|
||||||
|
val archive = downloadGraal(log, os, architecture)
|
||||||
|
|
||||||
|
if (os.hasSupportForSulong) {
|
||||||
|
val packageDir = archive.getParentFile
|
||||||
|
val archiveRootDir = list(archive).head.getTopDirectory.getName
|
||||||
|
val extractedGraalDir = packageDir / archiveRootDir
|
||||||
|
if (extractedGraalDir.exists()) {
|
||||||
|
IO.delete(extractedGraalDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(s"Extracting $archive to $packageDir")
|
||||||
|
extract(archive, packageDir)
|
||||||
|
|
||||||
|
log.info("Installing components")
|
||||||
|
gu(log, os, extractedGraalDir, "install", "python", "R")
|
||||||
|
|
||||||
|
log.info(s"Re-creating $archive")
|
||||||
|
IO.delete(archive)
|
||||||
|
makeArchive(packageDir, archiveRootDir, archive)
|
||||||
|
|
||||||
|
log.info(s"Cleaning up $extractedGraalDir")
|
||||||
|
IO.delete(extractedGraalDir)
|
||||||
|
}
|
||||||
|
archive
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Run the `gu` executable from the GraalVM distribution.
|
||||||
|
*
|
||||||
|
* @param log the logger
|
||||||
|
* @param os the system type
|
||||||
|
* @param graalDir the directory with a GraalVM distribution
|
||||||
|
* @param arguments the command arguments
|
||||||
|
*/
|
||||||
|
def gu(
|
||||||
|
log: ManagedLogger,
|
||||||
|
os: OS,
|
||||||
|
graalDir: File,
|
||||||
|
arguments: String*
|
||||||
|
): Unit = {
|
||||||
|
val executableFile = os match {
|
||||||
|
case OS.Linux =>
|
||||||
|
graalDir / "bin" / "gu"
|
||||||
|
case OS.MacOS =>
|
||||||
|
graalDir / "Contents" / "Home" / "bin" / "gu"
|
||||||
|
case OS.Windows =>
|
||||||
|
graalDir / "bin" / "gu.cmd"
|
||||||
|
}
|
||||||
|
val javaHomeFile = executableFile.getParentFile.getParentFile
|
||||||
|
val command =
|
||||||
|
executableFile.toPath.toAbsolutePath.toString +: arguments
|
||||||
|
val exitCode = Process(
|
||||||
|
command,
|
||||||
|
Some(graalDir),
|
||||||
|
("JAVA_HOME", javaHomeFile.toPath.toAbsolutePath.toString),
|
||||||
|
("GRAALVM_HOME", javaHomeFile.toPath.toAbsolutePath.toString)
|
||||||
|
).!
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
s"Failed to run '${command.mkString(" ")}'"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def copyEngine(os: OS, architecture: Architecture, distDir: File): Unit = {
|
def copyEngine(os: OS, architecture: Architecture, distDir: File): Unit = {
|
||||||
val engine = builtArtifact("engine", os, architecture)
|
val engine = builtArtifact("engine", os, architecture)
|
||||||
if (!engine.exists()) {
|
if (!engine.exists()) {
|
||||||
@ -351,6 +509,12 @@ object DistributionPackage {
|
|||||||
architecture
|
architecture
|
||||||
) + os.archiveExt)
|
) + os.archiveExt)
|
||||||
|
|
||||||
|
private def cleanDirectory(dir: File): Unit = {
|
||||||
|
for (f <- IO.listFiles(dir)) {
|
||||||
|
IO.delete(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Creates compressed and ready for release packages for the launcher and
|
/** Creates compressed and ready for release packages for the launcher and
|
||||||
* engine.
|
* engine.
|
||||||
*
|
*
|
||||||
@ -390,12 +554,6 @@ object DistributionPackage {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
private def cleanDirectory(dir: File): Unit = {
|
|
||||||
for (f <- IO.listFiles(dir)) {
|
|
||||||
IO.delete(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates launcher and project-manager bundles that include the component
|
/** Creates launcher and project-manager bundles that include the component
|
||||||
* itself, the engine and a Graal runtime.
|
* itself, the engine and a Graal runtime.
|
||||||
*
|
*
|
||||||
@ -418,7 +576,7 @@ object DistributionPackage {
|
|||||||
if (launcher.exists()) {
|
if (launcher.exists()) {
|
||||||
fixLauncher(launcher, os)
|
fixLauncher(launcher, os)
|
||||||
copyEngine(os, arch, launcher / "enso" / "dist")
|
copyEngine(os, arch, launcher / "enso" / "dist")
|
||||||
copyGraal(log, os, arch, launcher / "enso" / "runtime")
|
copyGraal(os, arch, launcher / "enso" / "runtime")
|
||||||
|
|
||||||
val archive = builtArchive("bundle", os, arch)
|
val archive = builtArchive("bundle", os, arch)
|
||||||
makeArchive(launcher, "enso", archive)
|
makeArchive(launcher, "enso", archive)
|
||||||
@ -436,7 +594,8 @@ object DistributionPackage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copyEngine(os, arch, pm / "enso" / "dist")
|
copyEngine(os, arch, pm / "enso" / "dist")
|
||||||
copyGraal(log, os, arch, pm / "enso" / "runtime")
|
copyGraal(os, arch, pm / "enso" / "runtime")
|
||||||
|
|
||||||
IO.copyFile(
|
IO.copyFile(
|
||||||
file("distribution/enso.bundle.template"),
|
file("distribution/enso.bundle.template"),
|
||||||
pm / "enso" / ".enso.bundle"
|
pm / "enso" / ".enso.bundle"
|
||||||
|
6
tools/ci/prepare-distribution-env.sh
Normal file → Executable file
6
tools/ci/prepare-distribution-env.sh
Normal file → Executable file
@ -10,6 +10,10 @@ ENGINE_DIST_DIR=$ENGINE_DIST_ROOT/enso-$DIST_VERSION
|
|||||||
PROJECTMANAGER_DIST_NAME=enso-project-manager-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
PROJECTMANAGER_DIST_NAME=enso-project-manager-$DIST_VERSION-$DIST_OS-$DIST_ARCH
|
||||||
PROJECTMANAGER_DIST_ROOT=$BUILD_ROOT/$PROJECTMANAGER_DIST_NAME
|
PROJECTMANAGER_DIST_ROOT=$BUILD_ROOT/$PROJECTMANAGER_DIST_NAME
|
||||||
PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_ROOT/enso
|
PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_ROOT/enso
|
||||||
|
GRAAL_DIST_NAME=graalvm-$GRAAL_VERSION-$DIST_OS-$DIST_ARCH
|
||||||
|
GRAAL_DIST_ROOT=$BUILD_ROOT/$GRAAL_DIST_NAME
|
||||||
|
echo "DIST_OS=$DIST_OS" >> $GITHUB_ENV
|
||||||
|
echo "DIST_ARCH=$DIST_ARCH" >> $GITHUB_ENV
|
||||||
echo "LAUNCHER_DIST_NAME=$LAUNCHER_DIST_NAME" >> $GITHUB_ENV
|
echo "LAUNCHER_DIST_NAME=$LAUNCHER_DIST_NAME" >> $GITHUB_ENV
|
||||||
echo "LAUNCHER_DIST_DIR=$LAUNCHER_DIST_DIR" >> $GITHUB_ENV
|
echo "LAUNCHER_DIST_DIR=$LAUNCHER_DIST_DIR" >> $GITHUB_ENV
|
||||||
echo "LAUNCHER_DIST_ROOT=$LAUNCHER_DIST_ROOT" >> $GITHUB_ENV
|
echo "LAUNCHER_DIST_ROOT=$LAUNCHER_DIST_ROOT" >> $GITHUB_ENV
|
||||||
@ -19,3 +23,5 @@ echo "ENGINE_DIST_ROOT=$ENGINE_DIST_ROOT" >> $GITHUB_ENV
|
|||||||
echo "PROJECTMANAGER_DIST_NAME=$PROJECTMANAGER_DIST_NAME" >> $GITHUB_ENV
|
echo "PROJECTMANAGER_DIST_NAME=$PROJECTMANAGER_DIST_NAME" >> $GITHUB_ENV
|
||||||
echo "PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_DIR" >> $GITHUB_ENV
|
echo "PROJECTMANAGER_DIST_DIR=$PROJECTMANAGER_DIST_DIR" >> $GITHUB_ENV
|
||||||
echo "PROJECTMANAGER_DIST_ROOT=$PROJECTMANAGER_DIST_ROOT" >> $GITHUB_ENV
|
echo "PROJECTMANAGER_DIST_ROOT=$PROJECTMANAGER_DIST_ROOT" >> $GITHUB_ENV
|
||||||
|
echo "GRAAL_DIST_NAME=$GRAAL_DIST_NAME" >> $GITHUB_ENV
|
||||||
|
echo "GRAAL_DIST_ROOT=$GRAAL_DIST_ROOT" >> $GITHUB_ENV
|
||||||
|
Loading…
Reference in New Issue
Block a user