abdolence / sbt-gcs-resolver

SBT plugin for Google Cloud Storage (GCS) and Google Artifact Registry with Coursier support
Apache License 2.0
28 stars 7 forks source link

`getOutputStream` support for `GcsArtifactRegistryUrlConnection` to able to use it in other plugins and extensions #6

Closed 987Nabil closed 2 years ago

987Nabil commented 2 years ago

This makes it possible to upload data to artifactregistry:// URLs

987Nabil commented 2 years ago

I would like to use the plugin to upload a maven-metadata.xml file. So I impl. this method.

abdolence commented 2 years ago

Hey, thanks for the contribution and it is probably needed for some use cases. Can you share how did you test this? (Asking since my setup is probably different I assume and I'm curious).

987Nabil commented 2 years ago

Sure. I want scala-steward to update our artifact registry hosted libs. Since GAR only supports maven, a maven-metadata.xml is needed to store a list of all available versions. Scala Steward uses this to figure out the newest version/update. So what I do, is downloading the latest maven-metadata.xml, which already works well by creating the url, opening a connection and downloading the file. This uses GcsArtifactRegistryUrlConnection since your plugin is enabled in sbt. Then I update (or create if not yet existing) the maven-metadata.xml and upload it to GAR. This does not work yet, since the missing code that I'd like to add. I tried this by creating a connection explicitly like this

  private def getUploadConnection(log: Logger): URL => GcsArtifactRegistryUrlConnection =
    (metaDataUrl: URL) => {
      new GcsArtifactRegistryUrlConnection(
        createHttpRequestFactory(GoogleCredentials.getApplicationDefault),
        metaDataUrl,
      )(
        log
      ) {
        final val googleHttpRequestFactory = createHttpRequestFactory(GoogleCredentials.getApplicationDefault)
        final val genericUrl               = GcsArtifactRegistryGenericUrlFactory.createFromUrl(metaDataUrl)
        override def getOutputStream: OutputStream = {
          if (!connected) {
            connect()
          }
          new ByteArrayOutputStream() {
            override def close(): Unit = {
              super.close()
              Try {
                googleHttpRequestFactory
                  .buildPutRequest(genericUrl, new ByteArrayContent(getRequestProperty("Content-Type"), toByteArray))
                  .execute()
              }.recover { case e: Exception =>
                log.error(s"Failed to upload $metaDataUrl\n${e.getMessage}")
                throw e
              }
            }
          }
        }
      }
    }

File got updated and uploaded just like I expected.

987Nabil commented 2 years ago

I tried using https://github.com/sbt/sbt-maven-resolver first, but that did not work.

abdolence commented 2 years ago

Alright, thanks for the detailed answer. First of all, I wanted to mention there is GcsArtifactRegistryIvyUrlHandler that is able to upload files to AR (which is used for that purpose right now for other artefacts). Secondly, I don't see any harm in adding that ability to GcsArtifactRegistryUrlConnection as well, so thanks for your contribution and I'll merge it, but unfortunately, this is not covered by any kind of test from myself yet.

abdolence commented 2 years ago

Released in v1.7.0 https://github.com/abdolence/sbt-gcs-resolver/releases/tag/v1.7.0

987Nabil commented 2 years ago

Tanks! 😃