diff --git a/.github/workflows/consumer_contract_tests.yml b/.github/workflows/consumer_contract_tests.yml deleted file mode 100644 index 27889230d1b..00000000000 --- a/.github/workflows/consumer_contract_tests.yml +++ /dev/null @@ -1,145 +0,0 @@ -name: Consumer contract tests -# The purpose of this workflow is to run a suite of Cromwell contract tests against mock service provider(s) using Pact framework. -# -# More details about Contract Testing can be found in our handbook -# -# https://broadworkbench.atlassian.net/wiki/spaces/IRT/pages/2660368406/Getting+Started+with+Pact+Contract+Testing -# -# This workflow involves Cromwell as a consumer, and ANY provider (e.g. Sam) Cromwell consumes. -# Each party owns a set of tests (aka contract tests). -# -# Consumer contract tests (aka consumer tests) runs on a mock provider service and does not require a real provider service. -# Provider contract tests (aka provider verification tests) runs independently of any consumer. -# -# Specifically: -# Cromwell runs consumer tests against mock service. Upon success, publish consumer pacts to -# Pact Broker https://pact-broker.dsp-eng-tools.broadinstitute.org/. -# -# Pact Broker is the source of truth to forge contractual obligations between consumer and provider. -# -# This workflow meets the criteria of Pact Broker *Platinum* as described in https://docs.pact.io/pact_nirvana/step_6. -# The can-i-deploy job has been added to this workflow to support *Platinum* and gate the code for promotion to default branch. -# -# This is how it works. -# -# Consumer makes a change that results in a new pact published to Pact Broker. -# Pact Broker notifies provider(s) of the changed pact and trigger corresponding verification workflows. -# Provider downloads relevant versions of consumer pacts from Pact Broker and kicks off verification tests against the consumer pacts. -# Provider updates Pact Broker with verification status. -# Consumer kicks off can-i-deploy on process to determine if changes can be promoted and used for deployment. -# -# NOTE: The publish-contracts workflow will use the latest commit of the branch that triggers this workflow to publish the unique consumer contract version to Pact Broker. - -on: - pull_request: - branches: - - develop - paths-ignore: - - 'README.md' - push: - branches: - - develop - paths-ignore: - - 'README.md' - merge_group: - branches: - - develop - -jobs: - init-github-context: - runs-on: ubuntu-latest - outputs: - repo-branch: ${{ steps.extract-branch.outputs.repo-branch }} - repo-version: ${{ steps.extract-branch.outputs.repo-version }} - fork: ${{ steps.extract-branch.outputs.fork }} - - steps: - - uses: actions/checkout@v3 - - - name: Obtain branch properties - id: extract-branch - run: | - FORK=false - GITHUB_EVENT_NAME=${{ github.event_name }} - if [[ "$GITHUB_EVENT_NAME" == "push" ]]; then - GITHUB_REF=${{ github.ref }} - GITHUB_SHA=${{ github.sha }} - elif [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then - FORK=${{ github.event.pull_request.head.repo.fork }} - GITHUB_REF=refs/heads/${{ github.head_ref }} - GITHUB_SHA=${{ github.event.pull_request.head.sha }} - elif [[ "$GITHUB_EVENT_NAME" == "merge_group" ]]; then - GITHUB_REF=refs/heads/${{ github.head_ref }} - else - echo "Failed to extract branch information" - exit 1 - fi - echo "repo-branch=${GITHUB_REF/refs\/heads\//""}" >> $GITHUB_OUTPUT - echo "repo-version=${GITHUB_SHA}" >> $GITHUB_OUTPUT - echo "fork=${FORK}" >> $GITHUB_OUTPUT - - - name: Is PR triggered by forked repo? - if: ${{ steps.extract-branch.outputs.fork == 'true' }} - run: | - echo "PR was triggered by forked repo" - - - name: Echo repo and branch information - run: | - echo "repo-owner=${{ github.repository_owner }}" - echo "repo-name=${{ github.event.repository.name }}" - echo "repo-branch=${{ steps.extract-branch.outputs.repo-branch }}" - echo "repo-version=${{ steps.extract-branch.outputs.repo-version }}" - - cromwell-consumer-contract-tests: - runs-on: ubuntu-latest - needs: [init-github-context] - outputs: - pact-b64: ${{ steps.encode-pact.outputs.pact-b64 }} - - steps: - - uses: actions/checkout@v3 - - name: Run consumer tests - run: | - docker run --rm -v $PWD:/working \ - -v jar-cache:/root/.ivy \ - -v jar-cache:/root/.ivy2 \ - -w /working \ - sbtscala/scala-sbt:openjdk-17.0.2_1.7.2_2.13.10 \ - sbt "project pact4s" clean test - - - name: Output consumer contract as non-breaking base64 string - id: encode-pact - run: | - cd pact4s - NON_BREAKING_B64=$(cat target/pacts/cromwell-consumer-drshub-provider.json | base64 -w 0) - echo "pact-b64=${NON_BREAKING_B64}" >> $GITHUB_OUTPUT - - # Prevent untrusted sources from using PRs to publish contracts - # since access to secrets is not allowed. - publish-contracts: - runs-on: ubuntu-latest - if: ${{ needs.init-github-context.outputs.fork == 'false' }} - needs: [init-github-context, cromwell-consumer-contract-tests] - steps: - - name: Dispatch to terra-github-workflows - uses: broadinstitute/workflow-dispatch@v3 - with: - workflow: .github/workflows/publish-contracts.yaml - repo: broadinstitute/terra-github-workflows - ref: refs/heads/main - token: ${{ secrets.BROADBOT_GITHUB_TOKEN }} # github token for access to kick off a job in the private repo - inputs: '{ "pact-b64": "${{ needs.cromwell-consumer-contract-tests.outputs.pact-b64 }}", "repo-owner": "${{ github.repository_owner }}", "repo-name": "${{ github.event.repository.name }}", "repo-branch": "${{ needs.init-github-context.outputs.repo-branch }}" }' - - can-i-deploy: - runs-on: ubuntu-latest - if: ${{ needs.init-github-context.outputs.fork == 'false' && false}} # Disabling this step for now until there is a webhook setup - needs: [ init-github-context, publish-contracts ] - steps: - - name: Dispatch to terra-github-workflows - uses: broadinstitute/workflow-dispatch@v3 - with: - workflow: .github/workflows/can-i-deploy.yaml - repo: broadinstitute/terra-github-workflows - ref: refs/heads/main - token: ${{ secrets.BROADBOT_GITHUB_TOKEN }} # github token for access to kick off a job in the private repo - inputs: '{ "pacticipant": "cromwell-consumer", "version": "${{ needs.init-github-context.outputs.repo-version }}" }' diff --git a/build.sbt b/build.sbt index 3754a92305d..44a67721e42 100644 --- a/build.sbt +++ b/build.sbt @@ -355,11 +355,6 @@ lazy val `cromwell-drs-localizer` = project .dependsOn(common) .dependsOn(`cloud-nio-impl-drs` % "test->test") -lazy val pact4s = project.in(file("pact4s")) - .settings(pact4sSettings) - .dependsOn(services) - .disablePlugins(sbtassembly.AssemblyPlugin) - lazy val server = project .withExecutableSettings("cromwell", serverDependencies) .dependsOn(engine) @@ -425,5 +420,4 @@ lazy val root = (project in file(".")) .aggregate(wes2cromwell) .aggregate(wom) .aggregate(womtool) - .aggregate(pact4s) .withAggregateSettings() diff --git a/pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/BlobFileSystemContractSpec.scala b/filesystems/blob/src/test/scala/cromwell/filesystems/blob/BlobFileSystemContractSpec.scala similarity index 97% rename from pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/BlobFileSystemContractSpec.scala rename to filesystems/blob/src/test/scala/cromwell/filesystems/blob/BlobFileSystemContractSpec.scala index f023257fef9..611a50f5603 100644 --- a/pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/BlobFileSystemContractSpec.scala +++ b/filesystems/blob/src/test/scala/cromwell/filesystems/blob/BlobFileSystemContractSpec.scala @@ -1,4 +1,4 @@ -package org.broadinstitute.dsde.workbench.cromwell.consumer +package cromwell.filesystems.blob import au.com.dius.pact.consumer.{ConsumerPactBuilder, PactTestExecutionContext} import au.com.dius.pact.core.model.RequestResponsePact diff --git a/pact4s/README.md b/pact4s/README.md deleted file mode 100644 index d33447f7356..00000000000 --- a/pact4s/README.md +++ /dev/null @@ -1,51 +0,0 @@ -c# pact4s [Under construction] - -pact4s is used for contract testing. - -# Dependencies - -```scala - val pact4sDependencies = Seq( - pact4sScalaTest, - pact4sCirce, - http4sEmberClient, - http4sDsl, - http4sEmberServer, - http4sCirce, - circeCore, - typelevelCat, - scalaTest - ) - -lazy val pact4s = project.in(file("pact4s")) - .settings(pact4sSettings) - .dependsOn(http % "test->test;compile->compile") -``` - -## Building and running contract tests -Clone the repo. -``` -$ git clone https://github.com/broadinstitute/cromwell.git -$ cd cromwell -``` - -If you are already using OpenJDK 11, run the following command. -``` -$ sbt "project pact4s" clean test -``` - -Otherwise, you can run the command inside a docker container with OpenJDK 11 installed. -This is especially useful when automating contract tests in a GitHub Action runner which does not guarantee the correct OpenJDK version. -``` -docker run --rm -v $PWD:/working \ - -v jar-cache:/root/.ivy \ - -v jar-cache:/root/.ivy2 \ - -w /working \ - sbtscala/scala-sbt:openjdk-11.0.16_1.8.1_2.13.10 \ - sbt "project pact4s" clean test -``` - -The generated contracts can be found in the `./target/pacts` folder -- `cromwell-consumer-drshub-provider.json` -- `cromwell-consumer-fake-provider.json` - diff --git a/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClient.scala b/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClient.scala deleted file mode 100644 index 3fa11515118..00000000000 --- a/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClient.scala +++ /dev/null @@ -1,93 +0,0 @@ -package org.broadinstitute.dsde.workbench.cromwell.consumer - -import cats.effect.Concurrent -import cats.syntax.all._ -import com.typesafe.scalalogging.LazyLogging -import io.circe.{Decoder, Encoder} -import org.http4s._ -import org.http4s.circe.CirceEntityCodec.{circeEntityDecoder, circeEntityEncoder} -import org.http4s.client.Client - -case class AccessUrl(url: String, headers: List[String]) - -case class ResourceMetadataRequest(url: String, fields: List[String]) - -case class ResourceMetadata(contentType: String, - size: Long, - timeCreated: String, - timeUpdated: String, - bucket: Option[String], - name: Option[String], - gsUri: Option[String], - googleServiceAccount: Option[Map[String, Map[String, String]]], - fileName: Option[String], - accessUrl: Option[AccessUrl], - hashes: Map[String, String], - localizationPath: Option[String], - bondProvider: Option[String] -) -trait DrsHubClient[F[_]] extends LazyLogging { - def fetchSystemStatus(): F[Boolean] - - def resolveDrsObject(drsPath: String, fields: List[String]): F[ResourceMetadata] - -} - -/* - This class represents the consumer (Cromwell) view of the DrsHub provider that implements the following endpoints: - - GET /status - - GET /api/v4/drs/resolve - */ -class DrsHubClientImpl[F[_]: Concurrent](client: Client[F], baseUrl: Uri) extends DrsHubClient[F] { - val apiVersion = "v4" - - implicit val accessUrlDecoder: Decoder[AccessUrl] = Decoder.forProduct2("url", "headers")(AccessUrl.apply) - implicit val resourceMetadataDecoder: Decoder[ResourceMetadata] = Decoder.forProduct13( - "contentType", - "size", - "timeCreated", - "timeUpdated", - "bucket", - "name", - "gsUri", - "googleServiceAccount", - "fileName", - "accessUrl", - "hashes", - "localizationPath", - "bondProvider" - )(ResourceMetadata.apply) - implicit val resourceMetadataRequestEncoder: Encoder[ResourceMetadataRequest] = Encoder.forProduct2("url", "fields")(x => - (x.url, x.fields) - ) - implicit val resourceMetadataRequestEntityEncoder: EntityEncoder[F, ResourceMetadataRequest] = circeEntityEncoder[F, ResourceMetadataRequest] - override def fetchSystemStatus(): F[Boolean] = { - val request = Request[F](uri = baseUrl / "status").withHeaders( - org.http4s.headers.Accept(MediaType.application.json) - ) - client.run(request).use { resp => - resp.status match { - case Status.Ok => true.pure[F] - case Status.InternalServerError => false.pure[F] - case _ => UnknownError.raiseError - } - } - } - - override def resolveDrsObject(drsPath: String, fields: List[String]): F[ResourceMetadata] = { - val body = ResourceMetadataRequest(url = drsPath, fields = fields) - val entityBody: EntityBody[F] = EntityEncoder[F, ResourceMetadataRequest].toEntity(body).body - val request = Request[F](uri = baseUrl / "api" / apiVersion / "drs" / "resolve", method=Method.POST, body=entityBody).withHeaders( - org.http4s.headers.`Content-Type`(MediaType.application.json) - ) - client.run(request).use { resp => - resp.status match { - case Status.Ok => resp.as[ResourceMetadata] - case _ => UnknownError.raiseError - } - } - } - -} - - diff --git a/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/Helper.scala b/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/Helper.scala deleted file mode 100644 index ceeefc7479f..00000000000 --- a/pact4s/src/main/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/Helper.scala +++ /dev/null @@ -1,207 +0,0 @@ -package org.broadinstitute.dsde.workbench.cromwell.consumer - -import au.com.dius.pact.consumer.dsl.{DslPart, PactDslResponse, PactDslWithProvider} -import pact4s.algebras.PactBodyJsonEncoder -case object UnknownError extends Exception - -object PactHelper { - def buildInteraction(builder: PactDslResponse, - state: String, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int, - responseHeaders: Seq[(String, String)], - body: DslPart - ): PactDslResponse = - builder - .`given`(state) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - .body(body) - - def buildInteraction(builder: PactDslResponse, - state: String, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int, - responseHeaders: Seq[(String, String)], - ): PactDslResponse = - builder - .`given`(state) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - - def buildInteraction(builder: PactDslResponse, - state: String, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int - ): PactDslResponse = - builder - .`given`(state) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - - def buildInteraction(builder: PactDslResponse, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int - ): PactDslResponse = - builder - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - - def buildInteraction(builder: PactDslWithProvider, - state: String, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int, - responseHeaders: Seq[(String, String)], - body: DslPart - ): PactDslResponse = - builder - .`given`(state) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - .body(body) - - def buildInteraction(builder: PactDslWithProvider, - state: String, - stateParams: Map[String, Any], - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - requestBody: DslPart, - status: Int, - responseHeaders: Seq[(String, String)], - responsBody: DslPart - ): PactDslResponse = - builder - .`given`(state, scala.jdk.CollectionConverters.MapHasAsJava(stateParams).asJava) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .body(requestBody) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - .body(responsBody) - - def buildInteraction(builder: PactDslResponse, - state: String, - stateParams: Map[String, Any], - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int, - responseHeaders: Seq[(String, String)], - body: DslPart - ): PactDslResponse = - builder - .`given`(state, scala.jdk.CollectionConverters.MapHasAsJava(stateParams).asJava) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - .body(body) - - def buildInteraction[A](builder: PactDslWithProvider, - state: String, - stateParams: Map[String, Any], - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - status: Int, - responseHeaders: Seq[(String, String)], - body: A - )(implicit ev: PactBodyJsonEncoder[A]): PactDslResponse = - builder - .`given`(state, scala.jdk.CollectionConverters.MapHasAsJava(stateParams).asJava) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .willRespondWith() - .status(status) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(responseHeaders.toMap).asJava) - .body(ev.toJsonString(body)) - - def buildInteraction[A](builder: PactDslResponse, - state: String, - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - requestBody: A, - status: Int - )(implicit ev: PactBodyJsonEncoder[A]): PactDslResponse = - builder - .`given`(state) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .body(ev.toJsonString(requestBody)) - .willRespondWith() - .status(status) - - def buildInteraction[A](builder: PactDslResponse, - state: String, - stateParams: Map[String, Any], - uponReceiving: String, - method: String, - path: String, - requestHeaders: Seq[(String, String)], - requestBody: A, - status: Int - )(implicit ev: PactBodyJsonEncoder[A]): PactDslResponse = - builder - .`given`(state, scala.jdk.CollectionConverters.MapHasAsJava(stateParams).asJava) - .uponReceiving(uponReceiving) - .method(method) - .path(path) - .headers(scala.jdk.CollectionConverters.MapHasAsJava(requestHeaders.toMap).asJava) - .body(ev.toJsonString(requestBody)) - .willRespondWith() - .status(status) -} diff --git a/pact4s/src/test/resources/logback.xml b/pact4s/src/test/resources/logback.xml deleted file mode 100644 index 24316805e7e..00000000000 --- a/pact4s/src/test/resources/logback.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - %d [%thread] %-5level %logger{35} - %msg%n - - - - - - - - - - diff --git a/pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClientSpec.scala b/pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClientSpec.scala deleted file mode 100644 index a4ebe56d76a..00000000000 --- a/pact4s/src/test/scala/org/broadinstitute/dsde/workbench/cromwell/consumer/DrsHubClientSpec.scala +++ /dev/null @@ -1,170 +0,0 @@ -package org.broadinstitute.dsde.workbench.cromwell.consumer - -import au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody -import au.com.dius.pact.consumer.dsl._ -import au.com.dius.pact.consumer.{ConsumerPactBuilder, PactTestExecutionContext} -import au.com.dius.pact.core.model.RequestResponsePact -import cats.effect.IO -import org.broadinstitute.dsde.workbench.cromwell.consumer.PactHelper._ -import org.http4s.Uri -import org.http4s.blaze.client.BlazeClientBuilder -import org.http4s.client.Client -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import pact4s.scalatest.RequestResponsePactForger - -import java.util.concurrent.Executors -import scala.concurrent.ExecutionContext - -class DrsHubClientSpec extends AnyFlatSpec with Matchers with RequestResponsePactForger { - val ec = ExecutionContext.fromExecutorService(Executors.newCachedThreadPool()) - implicit val cs = IO.contextShift(ec) - /* - Define the folder that the pact contracts get written to upon completion of this test suite. - */ - override val pactTestExecutionContext: PactTestExecutionContext = - new PactTestExecutionContext( - "./target/pacts" - ) - - private val requestFields = List( - "bucket", - "accessUrl", - "googleServiceAccount", - "fileName", - "hashes", - "localizationPath", - "bondProvider", - "name", - "size", - "timeCreated", - "timeUpdated", - "gsUri", - "contentType", - ) - - val filesize = 123L - val timeCreated = "2021-03-04T20:00:00.000Z" - val bucket = "fc-secure-1234567890" - val filename = "my-file.bam" - val bondProvider = "anvil" - val fileHash = "a2317edbd2eb6cf6b0ee49cb81e3a556" - val accessUrl = f"gs://${bucket}/${filename}" - - - val drsResourceResponsePlaceholder: ResourceMetadata = ResourceMetadata( - "application/octet-stream", - filesize, - timeCreated, - timeCreated, - None, - None, - None, - None, - None, - Option(AccessUrl(accessUrl, List("Header", "Example"))), - Map("md5" -> fileHash), - None, - Option(bondProvider) - ) - - val resourceMetadataResponseDsl: DslPart = newJsonBody { o => - o.stringType("contentType", "application/octet-stream") - o.numberType("size", filesize) - o.stringType("timeCreated", timeCreated) - o.stringType("timeUpdated", timeCreated) - o.nullValue("gsUri") - o.nullValue("googleServiceAccount") - o.nullValue("fileName") - o.`object`("accessUrl" , { a => - a.stringType("url", accessUrl) - a.`array`("headers", { h => - h.stringType("Header") - h.stringType("Example") - () - }) - () - }) - o.`object`("hashes", { o => - o.stringType("md5", fileHash) - () - }) - o.nullValue("localizationPath") - o.stringType("bondProvider", bondProvider) - () - }.build - - val fileId = "1234567890" - - val resourceRequestDsl = newJsonBody { o => - o.stringType("url", f"drs://test.theanvil.io/${fileId}") - o.array("fields", { a => - requestFields.map(a.stringType) - () - }) - () - }.build - - val consumerPactBuilder: ConsumerPactBuilder = ConsumerPactBuilder - .consumer("cromwell-consumer") - - val pactProvider: PactDslWithProvider = consumerPactBuilder - .hasPactWith("drshub-provider") - - var pactDslResponse: PactDslResponse = buildInteraction( - pactProvider, - state = "resolve Drs url", - stateParams = Map[String, String]( - "fileId" -> fileId, - "bucket" -> bucket, - "filename" -> filename, - "bondProvider" -> bondProvider, - "fileHash" -> fileHash, - "accessUrl" -> accessUrl, - "fileSize" -> filesize.toString, - "timeCreated" -> timeCreated - ), - uponReceiving = "Request to resolve drs url", - method = "POST", - path = "/api/v4/drs/resolve", - requestHeaders = Seq("Content-type" -> "application/json"), - requestBody = resourceRequestDsl, - status = 200, - responseHeaders = Seq(), - responsBody = resourceMetadataResponseDsl - ) - - pactDslResponse = buildInteraction( - pactDslResponse, - state = "Drshub is ok", - uponReceiving = "Request for drshub api status", - method = "GET", - path = "/status", - requestHeaders = Seq(), - status = 200, - responseHeaders = Seq() - ) - - override val pact: RequestResponsePact = pactDslResponse.toPact - - val client: Client[IO] = { - BlazeClientBuilder[IO](ExecutionContext.global).resource.allocated.unsafeRunSync()._1 - } - - /* - we should use these tests to ensure that our client class correctly handles responses from the provider - i.e. decoding, error mapping, validation - */ - it should "get DrsHub ok status" in { - new DrsHubClientImpl[IO](client, Uri.unsafeFromString(mockServer.getUrl)) - .fetchSystemStatus() - .attempt - .unsafeRunSync() shouldBe Right(true) - } - - it should "resolve drs object" in { - new DrsHubClientImpl[IO](client, Uri.unsafeFromString(mockServer.getUrl)) - .resolveDrsObject("drs://drs.example.com/1234567890", requestFields) - .attempt - .unsafeRunSync() shouldBe Right(drsResourceResponsePlaceholder) - } -} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ef829d6f780..405ecd2d3c4 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -91,7 +91,6 @@ object Dependencies { private val mysqlV = "8.0.28" private val nettyV = "4.1.72.Final" private val owlApiV = "5.1.19" - private val pact4sV = "0.9.0" private val postgresV = "42.4.1" private val pprintV = "0.7.3" private val rdf4jV = "3.7.1" @@ -104,7 +103,7 @@ object Dependencies { private val scalaPoolV = "0.4.3" private val scalacticV = "3.2.13" private val scalameterV = "0.21" - private val scalatestV = "3.2.15" + private val scalatestV = "3.2.10" private val scalatestScalacheckV = scalatestV + ".0" private val scoptV = "4.1.0" private val sentryLogbackV = "5.7.4" @@ -443,7 +442,7 @@ object Dependencies { - https://www.scalatest.org/user_guide/generator_driven_property_checks - https://www.scalatest.org/user_guide/writing_scalacheck_style_properties */ - private val scalacheckBaseV = "1.17" + private val scalacheckBaseV = "1.15" private val scalacheckDependencies = List( "org.scalatestplus" %% s"scalacheck-${scalacheckBaseV.replace(".", "-")}" % scalatestScalacheckV % Test, ) @@ -595,12 +594,14 @@ object Dependencies { val sfsBackendDependencies = List ( "org.lz4" % "lz4-java" % lz4JavaV ) - val scalaTest = "org.scalatest" %% "scalatest" % scalatestV + val testDependencies: List[ModuleID] = List( - scalaTest, + "org.scalatest" %% "scalatest" % scalatestV, // Use mockito Java DSL directly instead of the numerous and often hard to keep updated Scala DSLs. // See also scaladoc in common.mock.MockSugar and that trait's various usages. "org.mockito" % "mockito-core" % mockitoV, + "io.github.jbwheatley" %% "pact4s-scalatest" % "0.7.0", + "io.github.jbwheatley" %% "pact4s-circe" % "0.7.0" ) ++ slf4jBindingDependencies // During testing, add an slf4j binding for _all_ libraries. val kindProjectorPlugin = "org.typelevel" % "kind-projector" % kindProjectorV cross CrossVersion.full @@ -796,23 +797,5 @@ object Dependencies { The jakarta.annotation inclusion is above in googleApiClientDependencies. */ ExclusionRule("javax.annotation", "javax.annotation-api"), - ExclusionRule("javax.activation"), - ) - - val http4sDsl = "org.http4s" %% "http4s-dsl" % http4sV - val http4sEmberClient = "org.http4s" %% "http4s-ember-client" % http4sV - val http4sEmberServer = "org.http4s" %% "http4s-ember-server" % http4sV - val http4sCirce = "org.http4s" %% "http4s-circe" % http4sV - val pact4sScalaTest = "io.github.jbwheatley" %% "pact4s-scalatest" % pact4sV % Test - val pact4sCirce = "io.github.jbwheatley" %% "pact4s-circe" % pact4sV - - val pact4sDependencies = Seq( - pact4sScalaTest, - pact4sCirce, - http4sEmberClient, - http4sDsl, - http4sEmberServer, - http4sCirce, - scalaTest, ) } diff --git a/project/Settings.scala b/project/Settings.scala index 32559422066..797d7917dd9 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -98,22 +98,6 @@ object Settings { ) ) - val pact4sSettings = sharedSettings ++ List( - libraryDependencies ++= pact4sDependencies, - - /** - * Invoking pact tests from root project (sbt "project pact" test) - * will launch tests in a separate JVM context that ensures contracts - * are written to the pact/target/pacts folder. Otherwise, contracts - * will be written to the root folder. - */ - Test / fork := true - - ) ++ assemblySettings - - lazy val pact4s = project.in(file("pact4s")) - .settings(pact4sSettings) - /* Docker instructions to install Google Cloud SDK image in docker image. It also installs `crcmod` which is needed while downloading large files using `gsutil`. diff --git a/project/build.properties b/project/build.properties index 54f486b9dc3..2b4cbe4d584 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1,2 +1,2 @@ # scala-steward:off -sbt.version=1.8.1 +sbt.version=1.5.5 diff --git a/project/plugins.sbt b/project/plugins.sbt index 151ba4b87e3..bdb54f675bf 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.9.0") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.1") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.1") addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.0") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.4") addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.2.16")