From 1e1fd25a1b86a486264a30049854044da67c2ba8 Mon Sep 17 00:00:00 2001 From: kyri-petrou <67301607+kyri-petrou@users.noreply.github.com> Date: Tue, 14 May 2024 15:55:20 +1000 Subject: [PATCH] Ignore - Testing CI (#2844) * Update ZIO to 2.1.1 * Update Java to 17/21 * Fix zio cli version * Remove deprecated call to java URL constructor * Test with ZIO 2.0.x * Bump ZIO back to 2.1.1 * Run Body.fromFile in blocking threadpool * Run `FileBody#asArray` in blocking threadpool * Close file in blocking threadpool * Wrap file.length() in ZIO.blocking * Run entire `fromFileZIO` in blocking threadpool * Use blocking aspect on MultipartSpec * Use blocking aspect on other suites * fmt * FormSpec blocking --------- Co-authored-by: Nabil Abdel-Hafeez <7283535+987Nabil@users.noreply.github.com> --- .github/workflows/ci.yml | 54 ++++++++++++++++--- build.sbt | 10 ++-- project/BuildHelper.scala | 2 +- project/Dependencies.scala | 2 +- .../zio/http/gen/scala/CodeGenSpec.scala | 4 +- .../zio/http/netty/NettyBodyWriter.scala | 2 +- .../src/test/scala/zio/http/FormSpec.scala | 2 +- .../src/test/scala/zio/http/HandlerSpec.scala | 4 +- .../scala/zio/http/StaticFileServerSpec.scala | 18 ++++--- .../zio/http/endpoint/MultipartSpec.scala | 2 +- .../shared/src/main/scala/zio/http/Body.scala | 19 +++---- .../src/main/scala/zio/http/Handler.scala | 4 +- 12 files changed, 84 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c44e023649..f20de4089e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,11 @@ jobs: matrix: os: [ubuntu-latest] scala: [2.12.18, 2.13.12, 3.3.1] - java: [graal_graalvm@17, temurin@8] + java: + - graal_graalvm@17 + - graal_graalvm@21 + - temurin@17 + - temurin@21 runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -45,12 +49,30 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} cache: sbt - - name: Setup Java (temurin@8) - if: matrix.java == 'temurin@8' + - name: Setup GraalVM (graal_graalvm@21) + if: matrix.java == 'graal_graalvm@21' + uses: graalvm/setup-graalvm@v1 + with: + java-version: 21 + distribution: graalvm + components: native-image + github-token: ${{ secrets.GITHUB_TOKEN }} + cache: sbt + + - name: Setup Java (temurin@17) + if: matrix.java == 'temurin@17' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + + - name: Setup Java (temurin@21) + if: matrix.java == 'temurin@21' uses: actions/setup-java@v4 with: distribution: temurin - java-version: 8 + java-version: 21 cache: sbt - name: Check formatting @@ -108,12 +130,30 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} cache: sbt - - name: Setup Java (temurin@8) - if: matrix.java == 'temurin@8' + - name: Setup GraalVM (graal_graalvm@21) + if: matrix.java == 'graal_graalvm@21' + uses: graalvm/setup-graalvm@v1 + with: + java-version: 21 + distribution: graalvm + components: native-image + github-token: ${{ secrets.GITHUB_TOKEN }} + cache: sbt + + - name: Setup Java (temurin@17) + if: matrix.java == 'temurin@17' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + + - name: Setup Java (temurin@21) + if: matrix.java == 'temurin@21' uses: actions/setup-java@v4 with: distribution: temurin - java-version: 8 + java-version: 21 cache: sbt - name: Download target directories (2.12.18) diff --git a/build.sbt b/build.sbt index 3f669e921c..335d1b7fff 100644 --- a/build.sbt +++ b/build.sbt @@ -11,7 +11,9 @@ val _ = sys.props += ("ZIOHttpLogLevel" -> Debug.ZIOHttpLogLevel) // CI Configuration ThisBuild / githubWorkflowJavaVersions := Seq( JavaSpec.graalvm(Graalvm.Distribution("graalvm"), "17"), - JavaSpec.temurin("8"), + JavaSpec.graalvm(Graalvm.Distribution("graalvm"), "21"), + JavaSpec.temurin("17"), + JavaSpec.temurin("21"), ) ThisBuild / githubWorkflowPREventTypes := Seq( PREventType.Opened, @@ -130,11 +132,11 @@ lazy val aggregatedProjects: Seq[ProjectReference] = lazy val root = (project in file(".")) .settings(stdSettings("zio-http-root")) .settings(publishSetting(false)) - .aggregate(aggregatedProjects: _*) + .aggregate(aggregatedProjects *) lazy val zioHttp = crossProject(JSPlatform, JVMPlatform) .in(file("zio-http")) - .enablePlugins(Shading.plugins(): _*) + .enablePlugins(Shading.plugins() *) .settings(stdSettings("zio-http")) .settings(publishSetting(true)) .settings(settingsWithHeaderLicense) @@ -353,7 +355,7 @@ lazy val sbtZioHttpGrpcTests = (project in file("sbt-zio-http-grpc-tests")) .disablePlugins(ScalafixPlugin) lazy val zioHttpTestkit = (project in file("zio-http-testkit")) - .enablePlugins(Shading.plugins(): _*) + .enablePlugins(Shading.plugins() *) .settings(stdSettings("zio-http-testkit")) .settings(publishSetting(true)) .settings(Shading.shadingSettings()) diff --git a/project/BuildHelper.scala b/project/BuildHelper.scala index 60d3dbaec0..80d96d53ce 100644 --- a/project/BuildHelper.scala +++ b/project/BuildHelper.scala @@ -36,7 +36,7 @@ object BuildHelper extends ScalaSettings { case _ => Seq.empty } - def settingsWithHeaderLicense() = + def settingsWithHeaderLicense = headerLicense := Some(HeaderLicense.ALv2("2021 - 2023", "Sporta Technologies PVT LTD & the ZIO HTTP contributors.")) def publishSetting(publishArtifacts: Boolean) = { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 033a8923bb..14177ad14b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -5,7 +5,7 @@ object Dependencies { val NettyVersion = "4.1.101.Final" val NettyIncubatorVersion = "0.0.24.Final" val ScalaCompactCollectionVersion = "2.11.0" - val ZioVersion = "2.0.22" + val ZioVersion = "2.1.1" val ZioCliVersion = "0.5.0" val ZioSchemaVersion = "1.1.1" val SttpVersion = "3.3.18" diff --git a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala index 2d73811c8a..0c372219e7 100644 --- a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala +++ b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala @@ -10,7 +10,7 @@ import scala.meta.prettyprinters.XtensionSyntax import scala.util.{Failure, Success, Try} import zio.Scope -import zio.test.TestAspect.flaky +import zio.test.TestAspect.{blocking, flaky} import zio.test._ import zio.http._ @@ -262,5 +262,5 @@ object CodeGenSpec extends ZIOSpecDefault { "/GeneratedUserNameArray.scala", ) }, - ) @@ java11OrNewer @@ flaky // Downloading scalafmt on CI is flaky + ) @@ java11OrNewer @@ flaky @@ blocking // Downloading scalafmt on CI is flaky } diff --git a/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala b/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala index 36f2dc2468..206f5aeda6 100644 --- a/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala +++ b/zio-http/jvm/src/main/scala/zio/http/netty/NettyBodyWriter.scala @@ -53,7 +53,7 @@ object NettyBodyWriter { case body: FileBody => val file = body.file // Write the content. - ctx.write(new DefaultFileRegion(file, 0, file.length())) + ctx.write(new DefaultFileRegion(file, 0, body.fileSize)) // Write the end marker. ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT) diff --git a/zio-http/jvm/src/test/scala/zio/http/FormSpec.scala b/zio-http/jvm/src/test/scala/zio/http/FormSpec.scala index 9e1b0117fc..4dc5f69992 100644 --- a/zio-http/jvm/src/test/scala/zio/http/FormSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/FormSpec.scala @@ -314,5 +314,5 @@ object FormSpec extends ZIOHttpSpec { ) @@ sequential def spec = - suite("FormSpec")(urlEncodedSuite, multiFormSuite, multiFormStreamingSuite) + suite("FormSpec")(urlEncodedSuite, multiFormSuite, multiFormStreamingSuite) @@ blocking } diff --git a/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala index e5630f7ab7..3180291070 100644 --- a/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/HandlerSpec.scala @@ -395,7 +395,7 @@ object HandlerSpec extends ZIOHttpSpec with ExitAssertion { assert(r.body)(equalTo(tempFile)) } } - }, + } @@ TestAspect.blocking, test("must fail if file does not exist") { val http = Handler.fromFileZIO(ZIO.succeed(new java.io.File("does-not-exist"))) @@ -414,7 +414,7 @@ object HandlerSpec extends ZIOHttpSpec with ExitAssertion { status <- http.sandbox.merge.status.run() } yield assertTrue(status == Status.BadRequest) } - }, + } @@ TestAspect.blocking, test("resource regression") { val handler = Handler.fromResource("TestFile.txt").sandbox diff --git a/zio-http/jvm/src/test/scala/zio/http/StaticFileServerSpec.scala b/zio-http/jvm/src/test/scala/zio/http/StaticFileServerSpec.scala index 3c5cecfcf2..89807edf02 100644 --- a/zio-http/jvm/src/test/scala/zio/http/StaticFileServerSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/StaticFileServerSpec.scala @@ -32,10 +32,14 @@ object StaticFileServerSpec extends HttpRunnableSpec { private val testArchivePath = getClass.getResource("/TestArchive.jar").getPath private val resourceOk = - Handler.fromResourceWithURL(new java.net.URL(s"jar:file:$testArchivePath!/TestFile.txt")).sandbox.toRoutes.deploy + Handler + .fromResourceWithURL(new java.net.URI(s"jar:file:$testArchivePath!/TestFile.txt").toURL) + .sandbox + .toRoutes + .deploy private val resourceNotFound = Handler - .fromResourceWithURL(new java.net.URL(s"jar:file:$testArchivePath!/NonExistent.txt")) + .fromResourceWithURL(new java.net.URI(s"jar:file:$testArchivePath!/NonExistent.txt").toURL) .sandbox .toRoutes .deploy @@ -78,10 +82,12 @@ object StaticFileServerSpec extends HttpRunnableSpec { ), suite("unreadable file")( test("should respond with 500") { - val tmpFile = File.createTempFile("test", "txt") - tmpFile.setReadable(false) - val res = Handler.fromFile(tmpFile).sandbox.toRoutes.deploy.run().map(_.status) - assertZIO(res)(equalTo(Status.Forbidden)) + ZIO.blocking { + val tmpFile = File.createTempFile("test", "txt") + tmpFile.setReadable(false) + val res = Handler.fromFile(tmpFile).sandbox.toRoutes.deploy.run().map(_.status) + assertZIO(res)(equalTo(Status.Forbidden)) + } } @@ unix, ), suite("invalid file")( diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala index e8d390e9b9..27dd66a5ab 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/MultipartSpec.scala @@ -271,6 +271,6 @@ object MultipartSpec extends ZIOHttpSpec { ) } }, - ), + ) @@ TestAspect.blocking, ) } diff --git a/zio-http/shared/src/main/scala/zio/http/Body.scala b/zio-http/shared/src/main/scala/zio/http/Body.scala index 6240dd7b6b..119447f33f 100644 --- a/zio-http/shared/src/main/scala/zio/http/Body.scala +++ b/zio-http/shared/src/main/scala/zio/http/Body.scala @@ -238,10 +238,11 @@ object Body { /** * Constructs a [[zio.http.Body]] from the contents of a file. */ - def fromFile(file: java.io.File, chunkSize: Int = 1024 * 4)(implicit trace: Trace): ZIO[Any, Nothing, Body] = - ZIO.succeed(file.length()).map { fileSize => + def fromFile(file: java.io.File, chunkSize: Int = 1024 * 4)(implicit trace: Trace): ZIO[Any, Nothing, Body] = { + ZIO.attemptBlocking(file.length()).orDie.map { fileSize => FileBody(file, chunkSize, fileSize) } + } /** * Constructs a [[zio.http.Body]] from from form data, using multipart @@ -446,10 +447,9 @@ object Body { override val mediaType: Option[MediaType] = None, override val boundary: Option[Boundary] = None, ) extends Body - with UnsafeWriteable - with UnsafeBytes { + with UnsafeWriteable { - override def asArray(implicit trace: Trace): Task[Array[Byte]] = ZIO.attempt { + override def asArray(implicit trace: Trace): Task[Array[Byte]] = ZIO.attemptBlocking { Files.readAllBytes(file.toPath) } @@ -464,8 +464,8 @@ object Body { ZStream.unwrap { for { file <- ZIO.attempt(file) - fs <- ZIO.attempt(new FileInputStream(file)) - size = Math.min(chunkSize.toLong, file.length()).toInt + fs <- ZIO.attemptBlocking(new FileInputStream(file)) + size <- ZIO.attemptBlocking(Math.min(chunkSize.toLong, file.length()).toInt) } yield ZStream .repeatZIOOption[Any, Throwable, Chunk[Byte]] { for { @@ -476,12 +476,9 @@ object Body { else ZIO.fail(None) } yield bytes } - .ensuring(ZIO.succeed(fs.close())) + .ensuring(ZIO.attemptBlocking(fs.close()).ignoreLogged) }.flattenChunks - override private[zio] def unsafeAsArray(implicit unsafe: Unsafe): Array[Byte] = - Files.readAllBytes(file.toPath) - override def contentType(newMediaType: MediaType): Body = copy(mediaType = Some(newMediaType)) override def contentType(newMediaType: MediaType, newBoundary: Boundary): Body = diff --git a/zio-http/shared/src/main/scala/zio/http/Handler.scala b/zio-http/shared/src/main/scala/zio/http/Handler.scala index bf65d57b51..8dbde524c8 100644 --- a/zio-http/shared/src/main/scala/zio/http/Handler.scala +++ b/zio-http/shared/src/main/scala/zio/http/Handler.scala @@ -853,8 +853,8 @@ object Handler extends HandlerPlatformSpecific with HandlerVersionSpecific { def fromFileZIO[R](getFile: ZIO[R, Throwable, File])(implicit trace: Trace): Handler[R, Throwable, Any, Response] = { Handler.fromZIO[R, Throwable, Response]( - getFile.flatMap { file => - ZIO.suspend { + ZIO.blocking { + getFile.flatMap { file => if (!file.exists()) { ZIO.fail(new FileNotFoundException()) } else if (file.isFile && !file.canRead) {