/sbt-s3-resolver

AWS S3 based resolver

Primary LanguageScalaGNU Affero General Public License v3.0AGPL-3.0

Sbt S3 resolver

Build Status Codacy Badge Latest release License Gitter

This is an sbt plugin, which helps to resolve dependencies from and publish to Amazon S3 buckets (private or public).

Features

This plugin can publish artifacts in maven or ivy style, but it can resolve only ivy artifacts:

Ivy artifacts publish resolve Maven artifacts publish resolve
public public *
private private

Usage

Plugin sbt dependency

In project/plugins.sbt:

resolvers += "Era7 maven releases" at "https://s3-eu-west-1.amazonaws.com/releases.era7.com"

addSbtPlugin("ohnosequences" % "sbt-s3-resolver" % "<version>")

(see the latest version in the releases list)

Note that since v0.11.0 this plugin is compiled and published only for scala-2.10/sbt-0.13 or higher. If you want it for sbt-0.12, use version v0.10.1.

Setting keys

Key Type Default
awsProfile String "default"
s3credentials AWSCredentialsProvider see below
s3region Region EU_Ireland
s3overwrite Boolean same as isSnapshot key
s3acl S3ACL PublicRead
s3resolver (String, s3) => S3Resolver is set using all above

Where

type Region = com.amazonaws.services.s3.model.Region
type AWSCredentialsProvider = com.amazonaws.auth.AWSCredentialsProvider
type S3ACL = com.amazonaws.services.s3.model.CannedAccessControlList

These defaults are added to your project automatically. So you can just tune the settings keys in build.sbt.

You can use s3resolver setting key that takes a name and an S3 bucket url and returns S3Resolver which is implicitly converted to sbt.Resolver.

Publishing

Normal practice is to use different (snapshots and releases) repositories depending on the version. For example, here is such publishing resolver with ivy-style patterns:

publishMavenStyle := false

publishTo := {
  val prefix = if (isSnapshot.value) "snapshots" else "releases"
  Some(s3resolver.value("My "+prefix+" S3 bucket", s3(prefix+".cool.bucket.com")) withIvyPatterns)
}

You can also switch repository for public and private artifacts — you just set the url of your bucket depending on something. Here s3 constructor takes the name of your S3 bucket (don't worry about s3:// prefix).

Resolving

You can add a sequence of S3 resolvers just like this:

resolvers ++= Seq[Resolver](
  s3resolver.value("Releases resolver", s3("releases.bucket.com")),
  s3resolver.value("Snapshots resolver", s3("snapshots.bucket.com"))
)

Note, that you have to write Seq[Resolver] explicitly, so that S3Resolvers will be converted to sbt.Resolver before appending.

Public Maven artifacts

If your maven artifacts are public, you can resolve them using usual sbt resolvers just transforming your s3://my.bucket.com to

"My S3 bucket" at "https://s3-<region>.amazonaws.com/my.bucket.com"

i.e. without using this plugin. Or if you're using it anyway, you can write:

"My S3 bucket" at s3("my.bucket.com").toHttps(s3region.value)

Credentials

s3credentials key has the AWSCredentialsProvider type from AWS Java SDK. Different kinds of providers look for credentials in different places, plus they can be chained by the | ("or") operator (added in this plugin for convenience).

The default credentials chain in this plugin is

awsProfile := "default"

s3credentials :=
  new ProfileCredentialsProvider(awsProfile.value) |
  new InstanceProfileCredentialsProvider()

You can find other types of credentials providers in the AWS Java SDK docs

If you have different profiles in your ~/.aws/credentials file, you can choose the one you need by setting

awsProfile := "bob"

Or if you would like to use profile credentials and have your env vars override if they exist. This is handy if you have both a local dev environment as well as a CI environment where you need to use env vars.

s3credentials :=
  new ProfileCredentialsProvider(awsProfile.value) |
  new EnvironmentVariableCredentialsProvider()

You can check which credentials are loaded with the showS3Credentials task:

sbt showS3Credentials

Patterns

You can set patterns using .withPatterns(...) method of S3Resolver. Default are maven-style patterns (just as in sbt), but you can change it with the convenience method .withIvyPatterns.

S3 IAM policy

If you want to publish and resolve artifacts in an S3 bucket you should have at least these permissions on your AWS-user/role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::mybucket"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::mybucket/*"
        }
    ]
}

In theory s3:CreateBucket may be also needed in the first statement in case if you publish to a non-existing bucket.