diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b002eb02..44439c05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: run: | docker-compose -f "docker-compose.yml" up -d --build - name: Test - run: ./sbt ++${{ matrix.scala }}! test + run: ./sbt ++${{ matrix.scala }} test testJvms: runs-on: ubuntu-20.04 diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index 9557a6ac..223121b5 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -9,8 +9,32 @@ name: Website - published push: branches: - - zio2 + - series/2.x + pull_request: {} jobs: + build: + name: Build and Test + runs-on: ubuntu-latest + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Git Checkout + uses: actions/checkout@v3.3.0 + with: + fetch-depth: '0' + - name: Setup Scala + uses: actions/setup-java@v3.9.0 + with: + distribution: temurin + java-version: 17 + check-latest: true + - name: Check if the README file is up to date + run: sbt docs/checkReadme + - name: Check if the site workflow is up to date + run: sbt docs/checkGithubWorkflow + - name: Check artifacts build process + run: sbt +publishLocal + - name: Check website build process + run: sbt docs/clean; sbt docs/buildWebsite publish-docs: name: Publish Docs runs-on: ubuntu-latest @@ -38,6 +62,7 @@ jobs: generate-readme: name: Generate README runs-on: ubuntu-latest + if: ${{ (github.event_name == 'push') || ((github.event_name == 'release') && (github.event_name == 'published')) }} steps: - name: Git Checkout uses: actions/checkout@v3.3.0 @@ -59,9 +84,9 @@ jobs: git add README.md git commit -m "Update README.md" || echo "No changes to commit" - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v4.2.3 with: - body: | + body: |- Autogenerated changes after running the `sbt docs/generateReadme` command of the [zio-sbt-website](https://zio.dev/zio-sbt) plugin. I will automatically update the README.md file whenever there is new change for README.md, e.g. @@ -69,6 +94,5 @@ jobs: - After any changes to the "docs/index.md" file, I will update the README.md file accordingly. branch: zio-sbt-website/update-readme commit-message: Update README.md - branch-suffix: short-commit-hash + delete-branch: true title: Update README.md - diff --git a/README.md b/README.md index 7e9c95de..4f4c8e6b 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,166 @@ -# ZIO-S3 -An S3 client for ZIO +[//]: # (This file was autogenerated using `zio-sbt-website` plugin via `sbt generateReadme` command.) +[//]: # (So please do not edit it manually. Instead, change "docs/index.md" file or sbt setting keys) +[//]: # (e.g. "readmeDocumentation" and "readmeSupport".) -[![Project stage][Stage]][Stage-Page] -[![CircleCI][Badge-Circle]][Link-Circle] -[![Release][Badge-SonatypeReleases]][Link-SonatypeReleases] -[![Snapshots][Badge-SonatypeSnapshots]][Link-SonatypeSnapshots] +# ZIO S3 -Setup ------ +[ZIO S3](https://github.com/zio/zio-s3) is a thin wrapper over S3 async client for ZIO. -The library is a thin wrapper over s3 async client. -Please find more details in the [website](https://zio.dev/zio-s3/) +[![Production Ready](https://img.shields.io/badge/Project%20Stage-Production%20Ready-brightgreen.svg)](https://github.com/zio/zio/wiki/Project-Stages) ![CI Badge](https://github.com/zio/zio-s3/workflows/CI/badge.svg) [![Sonatype Releases](https://img.shields.io/nexus/r/https/oss.sonatype.org/dev.zio/zio-s3_2.13.svg?label=Sonatype%20Release)](https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-s3_2.13/) [![Sonatype Snapshots](https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-s3_2.13.svg?label=Sonatype%20Snapshot)](https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-s3_2.13/) [![javadoc](https://javadoc.io/badge2/dev.zio/zio-s3-docs_2.13/javadoc.svg)](https://javadoc.io/doc/dev.zio/zio-s3-docs_2.13) [![ZIO S3](https://img.shields.io/github/stars/zio/zio-s3?style=social)](https://github.com/zio/zio-s3) -[Badge-Circle]: https://circleci.com/gh/zio/zio-s3.svg?style=svg "circleci" -[Link-Circle]: https://circleci.com/gh/zio/zio-s3 "circleci" +## Introduction -[Link-SonatypeReleases]: https://oss.sonatype.org/content/repositories/releases/dev/zio/zio-s3_2.12/ "Sonatype Releases" -[Badge-SonatypeReleases]: https://img.shields.io/nexus/r/https/oss.sonatype.org/dev.zio/zio-s3_2.12.svg "Sonatype Releases" +ZIO-S3 is a thin wrapper over the s3 async java client. It exposes the main operations of the s3 java client. -[Badge-SonatypeSnapshots]: https://img.shields.io/nexus/s/https/oss.sonatype.org/dev.zio/zio-s3_2.12.svg "Sonatype Snapshots" -[Link-SonatypeSnapshots]: https://oss.sonatype.org/content/repositories/snapshots/dev/zio/zio-s3_2.12/ "Sonatype Snapshots" +```scala +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import zio.Chunk +import zio.s3._ +import zio.stream.{ZSink, ZStream} +import software.amazon.awssdk.services.s3.model.S3Exception -[Stage]: https://img.shields.io/badge/Project%20Stage-Production%20Ready-brightgreen.svg -[Stage-Page]: https://github.com/zio/zio/wiki/Project-Stages + // list all buckets available + listBuckets.provideLayer( + live("us-east-1", AwsBasicCredentials.create("accessKeyId", "secretAccessKey")) + ) + + // list all objects of all buckets + val l2: ZStream[S3, S3Exception, String] = (for { + bucket <- ZStream.fromIterableZIO(listBuckets) + obj <- listAllObjects(bucket.name) + } yield obj.bucketName + "/" + obj.key).provideLayer( + live("us-east-1", AwsBasicCredentials.create("accessKeyId", "secretAccessKey")) + ) +``` + +All available s3 combinators and operations are available in the package object `zio.s3`, you only need to `import zio.s3._` + +## Installation + +In order to use this library, we need to add the following line in our `build.sbt` file: + +```scala +libraryDependencies += "dev.zio" %% "zio-s3" % "0.4.2.1" +``` + +## Example 1 + +Let's try an example of creating a bucket and adding an object into it. To run this example, we need to run an instance of _Minio_ which is object storage compatible with S3: + +```bash +docker run -p 9000:9000 -e MINIO_ACCESS_KEY=MyKey -e MINIO_SECRET_KEY=MySecret minio/minio server --compat /data +``` + +In this example we create a bucket and then add a JSON object to it and then retrieve that: + +```scala +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.regions.Region +import zio._ +import zio.s3._ +import zio.stream.{ZStream, ZPipeline} +import zio.{Chunk, ExitCode, URIO} + +import java.net.URI + +object ZIOS3Example extends ZIOAppDefault { + + val myApp = for { + _ <- createBucket("docs") + json = Chunk.fromArray("""{ "id" : 1 , "name" : "A1" }""".getBytes) + _ <- putObject( + bucketName = "docs", + key = "doc1", + contentLength = json.length, + content = ZStream.fromChunk(json), + options = UploadOptions.fromContentType("application/json") + ) + _ <- getObject("docs", "doc1") + .via(ZPipeline.utf8Decode) + .foreach(Console.printLine(_)) + } yield () + + def run = + myApp + .provide( + live( + Region.CA_CENTRAL_1, + AwsBasicCredentials.create("MyKey", "MySecret"), + Some(URI.create("http://localhost:9000")) + ) + ) +} +``` + +## Example 2 + +```scala +import software.amazon.awssdk.services.s3.model.S3Exception +import zio._ +import zio.stream.{ ZSink, ZStream } +import zio.s3._ + +// upload +val json: Chunk[Byte] = Chunk.fromArray("""{ "id" : 1 , "name" : "A1" }""".getBytes) +val up: ZIO[S3, S3Exception, Unit] = putObject( + "bucket-1", + "user.json", + json.length, + ZStream.fromChunk(json), + UploadOptions.fromContentType("application/json") +) + +// multipartUpload +import java.io.FileInputStream +import java.nio.file.Paths + +val is = ZStream.fromInputStream(new FileInputStream(Paths.get("/my/path/to/myfile.zip").toFile)) +val proc2: ZIO[S3, S3Exception, Unit] = + multipartUpload( + "bucket-1", + "upload/myfile.zip", + is, + MultipartUploadOptions.fromUploadOptions(UploadOptions.fromContentType("application/zip")) + )(4) + +// download +import java.io.OutputStream + +val os: OutputStream = ??? +val proc3: ZIO[S3, Exception, Long] = getObject("bucket-1", "upload/myfile.zip").run(ZSink.fromOutputStream(os)) +``` + +## Support any commands? + +If you need a method which is not wrapped by the library, you can have access to underlying S3 client in a safe manner by using + +```scala +import java.util.concurrent.CompletableFuture +import zio.s3._ +import software.amazon.awssdk.services.s3.S3AsyncClient + +def execute[T](f: S3AsyncClient => CompletableFuture[T]) +``` + +## Documentation + +Learn more on the [ZIO S3 homepage](https://zio.dev/zio-s3/)! + +## Contributing + +For the general guidelines, see ZIO [contributor's guide](https://zio.dev/about/contributing). + +## Code of Conduct + +See the [Code of Conduct](https://zio.dev/about/code-of-conduct) + +## Support + +Come chat with us on [![Badge-Discord]][Link-Discord]. + +[Badge-Discord]: https://img.shields.io/discord/629491597070827530?logo=discord "chat on discord" +[Link-Discord]: https://discord.gg/2ccFBr4 "Discord" + +## License + +[License](LICENSE) diff --git a/build.sbt b/build.sbt index ecf44db7..54a67b98 100644 --- a/build.sbt +++ b/build.sbt @@ -25,8 +25,11 @@ addCommandAlias("check", "all scalafmtSbtCheck scalafmtCheck test:scalafmtCheck" val zioVersion = "2.0.2" val awsVersion = "2.16.61" +lazy val root = + project.in(file(".")).settings(publish / skip := true).aggregate(`zio-s3`, docs) + lazy val `zio-s3` = project - .in(file(".")) + .in(file("zio-s3")) .enablePlugins(BuildInfoPlugin) .settings(buildInfoSettings("zio.s3")) .settings(stdSettings("zio-s3")) @@ -53,22 +56,16 @@ lazy val `zio-s3` = project lazy val docs = project .in(file("zio-s3-docs")) + .settings(stdSettings("zio-s3-docs")) .settings( - skip / publish := true, moduleName := "zio-s3-docs", scalacOptions -= "-Yno-imports", scalacOptions -= "-Xfatal-warnings", - libraryDependencies ++= Seq( - "dev.zio" %% "zio" % zioVersion - ), projectName := "ZIO S3", - badgeInfo := Some( - BadgeInfo( - artifact = "zio-s3_2.12", - projectStage = ProjectStage.ProductionReady - ) - ), - docsPublishBranch := "zio2" + mainModuleName := (`zio-s3` / moduleName).value, + projectStage := ProjectStage.ProductionReady, + docsPublishBranch := "series/2.x", + ScalaUnidoc / unidoc / unidocProjectFilter := inProjects(`zio-s3`) ) .dependsOn(`zio-s3`) .enablePlugins(WebsitePlugin) diff --git a/project/plugins.sbt b/project/plugins.sbt index a4167c74..f08ad2d4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -8,6 +8,4 @@ addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.2.16") addSbtPlugin("org.portable-scala" % "sbt-crossproject" % "1.2.0") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.5") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") -addSbtPlugin("dev.zio" % "zio-sbt-website" % "0.1.5+27-a79a4f13-SNAPSHOT") - -resolvers += Resolver.sonatypeRepo("public") +addSbtPlugin("dev.zio" % "zio-sbt-website" % "0.3.4") diff --git a/website/core/Footer.js b/website/core/Footer.js deleted file mode 100755 index 07a4910e..00000000 --- a/website/core/Footer.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -class Footer extends React.Component { - docUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - const docsUrl = this.props.config.docsUrl; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - return `${baseUrl}${docsPart}${langPart}${doc}`; - } - - pageUrl(doc, language) { - const baseUrl = this.props.config.baseUrl; - return baseUrl + (language ? `${language}/` : '') + doc; - } - - render() { - return ( - - ); - } -} - -module.exports = Footer; diff --git a/website/package.json b/website/package.json deleted file mode 100644 index 29180a4c..00000000 --- a/website/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "scripts": { - "examples": "docusaurus-examples", - "start": "docusaurus-start", - "build": "docusaurus-build", - "publish-gh-pages": "docusaurus-publish", - "write-translations": "docusaurus-write-translations", - "version": "docusaurus-version", - "rename-version": "docusaurus-rename-version" - }, - "devDependencies": { - "docusaurus": "^1.12.0", - "react-sidecar": "^0.1.1" - } -} diff --git a/website/pages/en/index.js b/website/pages/en/index.js deleted file mode 100755 index 230845f5..00000000 --- a/website/pages/en/index.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const React = require('react'); - -const CompLibrary = require('../../core/CompLibrary.js'); - -const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ -const Container = CompLibrary.Container; -const GridBlock = CompLibrary.GridBlock; - -class HomeSplash extends React.Component { - render() { - const {siteConfig, language = ''} = this.props; - const {baseUrl, docsUrl} = siteConfig; - const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`; - const langPart = `${language ? `${language}/` : ''}`; - const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`; - - const SplashContainer = props => ( -