From 0288da3406cfb61368cc19d4f8f02e139301a79a Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Wed, 17 Feb 2021 12:54:53 +0100 Subject: [PATCH] Fix scalapb-validate setup instructions by bumping sbt-protoc (#1264) * move scalapb-validation sbt instructions to scripted * bump sbt-protoc for better integration with common-protos Fixes scripted 10-scalapb-validate, see * https://github.com/scalapb/ScalaPB/pull/873#issuecomment-769968656 * https://github.com/scalapb/scalapb-validate/issues/70 Other changes * cacheClassLoaders is now deprecated, see https://github.com/thesamet/sbt-protoc/commit/2a730a4 * Forcing recompilation is no longer necessary as the cache gets invalidated if a sandbox genererator classpath is updated, see https://github.com/thesamet/sbt-protoc/commit/80824b0 * The new classloader caching implementation resolves sandboxed generators artifacts earlier, even if they are no sources. That is the case for Test / protocGenerate, which was starting before codeGenProject / Compile / publishLocal, causing: > Error downloading com.lightbend.akka.grpc:akka-grpc-codegen_2.12: > 1.1.0-5-c5975cd5 * demonstrate usage of validate_at_construction Requires https://github.com/scalapb/scalapb-validate/commit/8529a55 --- benchmark-java/build.sbt | 2 +- docs/src/main/paradox/apidesign.md | 10 +---- project/ReflectiveCodeGen.scala | 3 -- project/plugins.sbt | 2 +- .../10-scalapb-validate/build.sbt | 13 +++++++ .../10-scalapb-validate/project/plugins.sbt | 3 ++ .../src/main/protobuf/helloworld.proto | 39 +++++++++++++++++++ .../src/main/scala/example/myapp/Main.scala | 20 ++++++++++ .../myapp/helloworld/GreeterServiceImpl.scala | 19 +++++++++ .../gen-scala-server/10-scalapb-validate/test | 1 + 10 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/build.sbt create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/project/plugins.sbt create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/protobuf/helloworld.proto create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/Main.scala create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/helloworld/GreeterServiceImpl.scala create mode 100644 sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/test diff --git a/benchmark-java/build.sbt b/benchmark-java/build.sbt index ec3d1f8fd..3613d71cc 100644 --- a/benchmark-java/build.sbt +++ b/benchmark-java/build.sbt @@ -29,7 +29,7 @@ val root = project.in(file(".")) "org.scalatest" %% "scalatest" % "3.1.2" % "test", "org.scalatestplus" %% "junit-4-12" % "3.1.2.0" % "test" ), - Compile / PB.generate := ((Compile / PB.generate) dependsOn ( + PB.artifactResolver := (PB.artifactResolver dependsOn ( codeGenProject / Compile / publishLocal)).value ) diff --git a/docs/src/main/paradox/apidesign.md b/docs/src/main/paradox/apidesign.md index 4285082d2..4e326bfea 100644 --- a/docs/src/main/paradox/apidesign.md +++ b/docs/src/main/paradox/apidesign.md @@ -51,15 +51,7 @@ Follow the [documentation](https://scalapb.github.io/docs/validation) to update in order to generate the validators using `sbt-protoc` (@ref[used by Akka gRPC](buildtools/sbt.md#sbt-protoc-settings)). With the default parameters and target set by Akka gRPC, additions to your `build.sbt` should be: -```scala -import scalapb.GeneratorOption._ - -libraryDependencies += - "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf" - -Compile / PB.targets += - scalapb.validate.gen(FlatPackage) -> (Compile / akkaGrpcCodeGeneratorSettings / target).value -``` +@@snip[build.sbt](/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/build.sbt) { #setup } The `validate_at_construction` option can be particularly interesting in a server-side context since method implementations will automatically receive pre-validated requests and will not diff --git a/project/ReflectiveCodeGen.scala b/project/ReflectiveCodeGen.scala index 8ce40c1da..435634f45 100644 --- a/project/ReflectiveCodeGen.scala +++ b/project/ReflectiveCodeGen.scala @@ -64,8 +64,6 @@ object ReflectiveCodeGen extends AutoPlugin { } } }.value, - // Reload generators on each invocation - PB.cacheClassLoaders := false, setCodeGenerator := loadAndSetGenerator( // the magic sauce: use the output classpath from the the sbt-plugin project and instantiate generators from there (fullClasspath in Compile in ProjectRef(file("."), "sbt-akka-grpc")).value, @@ -76,7 +74,6 @@ object ReflectiveCodeGen extends AutoPlugin { codeGeneratorSettings.value, PB.targets.value.asInstanceOf[ListBuffer[Target]], scalaBinaryVersion.value), - PB.recompile ~= (_ => true), PB.protoSources in Compile := PB.protoSources.value ++ Seq( PB.externalIncludePath.value, sourceDirectory.value / "proto"))) ++ Seq( diff --git a/project/plugins.sbt b/project/plugins.sbt index ceef5c8e4..dea714677 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,6 +1,6 @@ enablePlugins(BuildInfoPlugin) -val sbtProtocV = "1.0.0" +val sbtProtocV = "1.0.1" buildInfoKeys := Seq[BuildInfoKey]("sbtProtocVersion" -> sbtProtocV) diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/build.sbt b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/build.sbt new file mode 100644 index 000000000..d828c098d --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/build.sbt @@ -0,0 +1,13 @@ +resolvers += Resolver.sonatypeRepo("staging") +resolvers += Resolver.bintrayRepo("akka", "snapshots") + +//#setup +import scalapb.GeneratorOption._ + +enablePlugins(AkkaGrpcPlugin) + +libraryDependencies += + "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf" +Compile / PB.targets += + scalapb.validate.gen(FlatPackage) -> (Compile / akkaGrpcCodeGeneratorSettings / target).value +//#setup diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/project/plugins.sbt b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/project/plugins.sbt new file mode 100644 index 000000000..647fd7538 --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/project/plugins.sbt @@ -0,0 +1,3 @@ +addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % sys.props("project.version")) + +libraryDependencies ++= Seq("com.thesamet.scalapb" %% "scalapb-validate-codegen" % "0.2.2") diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/protobuf/helloworld.proto b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/protobuf/helloworld.proto new file mode 100644 index 000000000..2a880fa09 --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/protobuf/helloworld.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; + +option java_package = "example.myapp.helloworld.grpc"; + +package helloworld; + +import "validate/validate.proto"; +import "scalapb/scalapb.proto"; +import "scalapb/validate.proto"; + +option (scalapb.options) = { + scope: FILE + [scalapb.validate.file] { + validate_at_construction: true + insert_validator_instance: false + } +}; + +// The greeting service definition. +service GreeterService { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} + + rpc ItKeepsTalking (stream HelloRequest) returns (HelloReply) {} + + rpc ItKeepsReplying (HelloRequest) returns (stream HelloReply) {} + + rpc StreamHellos (stream HelloRequest) returns (stream HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1 [(validate.rules).string.min_len = 3];; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/Main.scala b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/Main.scala new file mode 100644 index 000000000..b940c6d46 --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/Main.scala @@ -0,0 +1,20 @@ +package example.myapp + +import scala.util.{Failure, Success, Try} +import scalapb.validate._ + +import example.myapp.helloworld.grpc.HelloRequest + +object Main extends App { + + Try(HelloRequest("valid")) match { + case Success(_) => // expected + case Failure(e) => throw new RuntimeException("unexpected violations for \"valid\"", e) + } + + Try(HelloRequest("ko")) match { + case Success(_) => throw new RuntimeException("unexpected success for \"ko\"") + case Failure(e) => // expected + } + +} diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/helloworld/GreeterServiceImpl.scala b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/helloworld/GreeterServiceImpl.scala new file mode 100644 index 000000000..4efdcb425 --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/src/main/scala/example/myapp/helloworld/GreeterServiceImpl.scala @@ -0,0 +1,19 @@ +package example.myapp.helloworld + +import scala.concurrent.Future + +import akka.NotUsed +import akka.stream.scaladsl.Source + +import example.myapp.helloworld.grpc._ + +class GreeterServiceImpl extends GreeterService { + override def sayHello(in: HelloRequest): Future[HelloReply] = ??? + + override def streamHellos(in: Source[HelloRequest, NotUsed]): Source[HelloReply, NotUsed] = ??? + + override def itKeepsTalking(in: Source[HelloRequest, NotUsed]): Future[HelloReply] = ??? + + override def itKeepsReplying(in: HelloRequest): Source[HelloReply, NotUsed] = ??? + +} diff --git a/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/test b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/test new file mode 100644 index 000000000..9e4c2371c --- /dev/null +++ b/sbt-plugin/src/sbt-test/gen-scala-server/10-scalapb-validate/test @@ -0,0 +1 @@ +> run \ No newline at end of file