From 291cbfa6ee6be0d39dc1d21180c3e32dec07b2d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Olczak?= Date: Wed, 23 Dec 2020 18:56:30 +0100 Subject: [PATCH] Runtime Containerisation (#1345) --- .github/workflows/release.yml | 38 ++++++++----------- .../org/enso/runner/LanguageServerApp.scala | 22 ++++++++--- .../src/main/scala/org/enso/runner/Main.scala | 18 +++++++-- .../jsonrpc/test/JsonRpcServerTestKit.scala | 4 +- .../src/test/resources/application.conf | 2 +- .../projectmanager/ProjectManagementOps.scala | 2 +- .../protocol/ProjectManagementApiSpec.scala | 5 ++- tools/ci/docker/Dockerfile | 30 +++++++++++++++ 8 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 tools/ci/docker/Dockerfile diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1a92a7205..67f3ef2f3b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -186,36 +186,16 @@ jobs: test $engineversion = $refversion || (echo "Tag version $refversion and the engine version $engineversion do not match" && false) # Verify License Packages in Distributions - - name: Verify Engine Licenses Package + - name: Verify Distributed Licenses Package working-directory: repo + if: runner.os != 'Windows' # TODO [RW] CRLF handling in licenses task shell: bash run: | sleep 1 sbt "enso/verifyGeneratedPackage engine ${{ env.ENGINE_DIST_DIR }}/THIRD-PARTY" - - name: Verify Launcher Licenses Package - working-directory: repo - shell: bash - run: | - sleep 1 sbt "enso/verifyGeneratedPackage launcher ${{ env.LAUNCHER_DIST_DIR }}/THIRD-PARTY" - - name: Verify Project Manager Licenses Package - working-directory: repo - shell: bash - run: | - sleep 1 sbt "enso/verifyGeneratedPackage project-manager ${{ env.PROJECTMANAGER_DIST_DIR }}/THIRD-PARTY" - - - name: Verify std-lib-Base Licenses Package - working-directory: repo - shell: bash - run: | - sleep 1 sbt "enso/verifyGeneratedPackage std-lib-Base ${{ env.ENGINE_DIST_DIR }}/std-lib/Base/THIRD-PARTY" - - name: Verify std-lib-Table Licenses Package - working-directory: repo - shell: bash - run: | - sleep 1 sbt "enso/verifyGeneratedPackage std-lib-Table ${{ env.ENGINE_DIST_DIR }}/std-lib/Table/THIRD-PARTY" # Publish @@ -366,6 +346,20 @@ jobs: draft: true prerelease: true + - name: Login to ACR + uses: docker/login-action@v1.6 + with: + registry: ensosharedwus2acr.azurecr.io + username: ${{ secrets.ACR_PUSH_CLIENT_ID }} + password: ${{ secrets.ACR_PUSH_CLIENT_SECRET }} + + - name: Publish Runtime Docker Image + shell: bash + run: | + sleep 1 + docker build -t ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }} -f ./repo/tools/ci/docker/Dockerfile ./artifacts/enso-engine-${{ env.DIST_VERSION }}-linux-amd64/enso-${{ env.DIST_VERSION }}/component + docker push ensosharedwus2acr.azurecr.io/runtime:${{ env.DIST_VERSION }} + # Publish the launcher packages to the backup/fallback S3 bucket - name: Prepare AWS Session shell: bash diff --git a/engine/runner/src/main/scala/org/enso/runner/LanguageServerApp.scala b/engine/runner/src/main/scala/org/enso/runner/LanguageServerApp.scala index 66dc65e0a4..85e54dc0bd 100644 --- a/engine/runner/src/main/scala/org/enso/runner/LanguageServerApp.scala +++ b/engine/runner/src/main/scala/org/enso/runner/LanguageServerApp.scala @@ -19,12 +19,24 @@ object LanguageServerApp { * @param config a config * @param logLevel log level */ - def run(config: LanguageServerConfig, logLevel: LogLevel): Unit = { - println("Starting Language Server...") + def run( + config: LanguageServerConfig, + logLevel: LogLevel, + deamonize: Boolean + ): Unit = { val server = new LanguageServerComponent(config, logLevel) - Await.result(server.start(), 10.seconds) - StdIn.readLine() - Await.result(server.stop(), 10.seconds) + Runtime.getRuntime.addShutdownHook(new Thread(() => { + Await.result(server.stop(), 20.seconds) + })) + Await.result(server.start(), 20.seconds) + if (deamonize) { + val lock = new AnyRef + lock.synchronized { + lock.wait() + } + } else { + StdIn.readLine() + } } } diff --git a/engine/runner/src/main/scala/org/enso/runner/Main.scala b/engine/runner/src/main/scala/org/enso/runner/Main.scala index bf67385194..3a2cce42ba 100644 --- a/engine/runner/src/main/scala/org/enso/runner/Main.scala +++ b/engine/runner/src/main/scala/org/enso/runner/Main.scala @@ -28,6 +28,7 @@ object Main { private val PROJECT_AUTHOR_EMAIL_OPTION = "new-project-author-email" private val REPL_OPTION = "repl" private val LANGUAGE_SERVER_OPTION = "server" + private val DAEMONIZE_OPTION = "daemon" private val INTERFACE_OPTION = "interface" private val RPC_PORT_OPTION = "rpc-port" private val DATA_PORT_OPTION = "data-port" @@ -100,6 +101,10 @@ object Main { .longOpt(LANGUAGE_SERVER_OPTION) .desc("Runs Language Server") .build() + val deamonizeOption = CliOption.builder + .longOpt(DAEMONIZE_OPTION) + .desc("Deamonize Language Server") + .build() val interfaceOption = CliOption.builder .longOpt(INTERFACE_OPTION) .hasArg(true) @@ -181,6 +186,7 @@ object Main { .addOption(newProjectAuthorNameOpt) .addOption(newProjectAuthorEmailOpt) .addOption(lsOption) + .addOption(deamonizeOption) .addOption(interfaceOption) .addOption(rpcPortOption) .addOption(dataPortOption) @@ -433,7 +439,11 @@ object Main { exitFail() case Right(config) => - LanguageServerApp.run(config, logLevel) + LanguageServerApp.run( + config, + logLevel, + line.hasOption(DAEMONIZE_OPTION) + ) exitSuccess() } } @@ -554,7 +564,9 @@ object Main { if (line.hasOption(LANGUAGE_SERVER_OPTION)) { runLanguageServer(line, logLevel) } - printHelp(options) - exitFail() + if (line.getOptions.isEmpty) { + printHelp(options) + exitFail() + } } } diff --git a/lib/scala/json-rpc-server-test/src/main/scala/org/enso/jsonrpc/test/JsonRpcServerTestKit.scala b/lib/scala/json-rpc-server-test/src/main/scala/org/enso/jsonrpc/test/JsonRpcServerTestKit.scala index a7d0b74549..5114d5c375 100644 --- a/lib/scala/json-rpc-server-test/src/main/scala/org/enso/jsonrpc/test/JsonRpcServerTestKit.scala +++ b/lib/scala/json-rpc-server-test/src/main/scala/org/enso/jsonrpc/test/JsonRpcServerTestKit.scala @@ -104,7 +104,7 @@ abstract class JsonRpcServerTestKit def send(json: Json): Unit = send(json.noSpaces) - def expectMessage(timeout: FiniteDuration = 3.seconds.dilated): String = { + def expectMessage(timeout: FiniteDuration = 5.seconds.dilated): String = { val message = outActor.expectMsgClass[String](timeout, classOf[String]) if (debugMessages) println(message) message @@ -112,7 +112,7 @@ abstract class JsonRpcServerTestKit def expectJson( json: Json, - timeout: FiniteDuration = 3.seconds.dilated + timeout: FiniteDuration = 5.seconds.dilated ): Assertion = { val parsed = parse(expectMessage(timeout)) parsed shouldEqual Right(json) diff --git a/lib/scala/project-manager/src/test/resources/application.conf b/lib/scala/project-manager/src/test/resources/application.conf index c34b080c63..182ea3272e 100644 --- a/lib/scala/project-manager/src/test/resources/application.conf +++ b/lib/scala/project-manager/src/test/resources/application.conf @@ -44,7 +44,7 @@ project-manager { request-timeout = 10 seconds boot-timeout = 30 seconds shutdown-timeout = 20 seconds - socket-close-timeout = 2 seconds + socket-close-timeout = 10 seconds } tutorials { diff --git a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/ProjectManagementOps.scala b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/ProjectManagementOps.scala index cf26e68888..e5df9563a9 100644 --- a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/ProjectManagementOps.scala +++ b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/ProjectManagementOps.scala @@ -90,7 +90,7 @@ trait ProjectManagementOps { this: BaseServerSpec => "result": null } """, - 10.seconds.dilated + 20.seconds.dilated ) } diff --git a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/protocol/ProjectManagementApiSpec.scala b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/protocol/ProjectManagementApiSpec.scala index 9a2746ba47..e33959004e 100644 --- a/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/protocol/ProjectManagementApiSpec.scala +++ b/lib/scala/project-manager/src/test/scala/org/enso/projectmanager/protocol/ProjectManagementApiSpec.scala @@ -9,13 +9,14 @@ import nl.gn0s1s.bump.SemVer import org.apache.commons.io.FileUtils import org.enso.projectmanager.test.Net.tryConnect import org.enso.projectmanager.{BaseServerSpec, ProjectManagementOps} -import org.enso.testkit.FlakySpec +import org.enso.testkit.{FlakySpec, RetrySpec} import scala.io.Source class ProjectManagementApiSpec extends BaseServerSpec with FlakySpec + with RetrySpec with ProjectManagementOps { override def beforeEach(): Unit = { @@ -577,7 +578,7 @@ class ProjectManagementApiSpec deleteProject(projectId) } - "move project dir on project close" taggedAs Flaky in { + "move project dir on project close".taggedAs(Retry, Flaky) in { implicit val client = new WsTestClient(address) //given val projectId = createProject("foo") diff --git a/tools/ci/docker/Dockerfile b/tools/ci/docker/Dockerfile new file mode 100644 index 0000000000..625bb786f8 --- /dev/null +++ b/tools/ci/docker/Dockerfile @@ -0,0 +1,30 @@ +FROM oracle/graalvm-ce:20.2.0-java11 + +USER root + +RUN groupadd -g 1001 enso +RUN useradd --system --create-home --uid 1001 --gid 1001 enso + +ADD runner.jar /opt/enso/runner.jar +ADD runtime.jar /opt/enso/runtime.jar + +RUN chown -hR enso:enso /opt/enso +RUN chmod -R u=rX,g=rX /opt/enso + +RUN mkdir -p /home/enso/workspace +RUN chown -hR enso:enso /home/enso/workspace +RUN chmod -R u=rwX,g=rwX /home/enso/workspace + +USER enso:enso + +WORKDIR /opt/enso + +ENTRYPOINT ["java", "-jar", "-Dtruffle.class.path.append=runtime.jar", "-Dpolyglot.engine.IterativePartialEscape=true", "runner.jar" ] + +EXPOSE 30001 +EXPOSE 30002 + +VOLUME /home/enso/workspace + +CMD ["--server", "--rpc-port", "30001", "--data-port", "30002", "--root-id", "00000000-0000-0000-0000-000000000001", "--path", "/home/enso/workspace", "--interface", "0.0.0.0"] +