= Gradle Plugin for AWS CodeArtifact :pluginId: org.unbroken-dome.aws.codeartifact :versionPrefix: 0.5 :versionSuffix: .0 :version: {versionPrefix}{versionSuffix}
This plugin improves support for using AWS CodeArtifact Maven repositories from a Gradle build.
The "standard" way of working with AWS CodeArtifact in Gradle, as recommended by the link:https://docs.aws.amazon.com/codeartifact/latest/ug/maven-gradle.html[AWS Documentation], requires users to fetch an authorization token before the build and pass it to Gradle as an environment variable.This has several drawbacks:
Using this plugin lets you declare your CodeArtifact repositories in a Gradle repositories
block in a more
convenient way, and removes the need to fetch authentication tokens before the build.
== Quickstart
+
codeArtifact
extension when declaring a Maven repository, instead of the url
.
Leave out the credentials
.
+
[source,kotlin]+
You can use this extension almost anywhere where you can declare a repository, including the publishing
block,
a buildscript
block, and the and dependencyManagement
in your settings script.
(For pluginManagement
things are a bit more complicated; see <<_using_gradle_plugins_from_an_aws_codeartifact_repository>> below.)
+ See <<_aws_credentials>> for details.
== How It Works
Unfortunately, Gradle offers very limited possibilities to hook into the artifact resolution process or rewrite the requests to a Maven repository when the dependencies are resolved.In addition, resolution of artifacts (including Gradle plugins) can happen very early in the configuration phase of a Gradle build.
The plugin's solution to this is launching a local proxy server as a build-scoped service, which acts as a temporary Maven repository.The proxy forwards all calls to the correct AWS CodeArtifact endpoint, takes care of endpoint resolution and automatically fetches authorization tokens when required.In addition to taking advantage of Gradle's lazy evaluation features, the proxy server itself acts lazily: it will only make calls to AWS APIs (or even initialize the AWS API clients) once a dependency is actually requested.This way, there is only minimal overhead for the majority of builds that do not require fetching dependencies from a remote repository.
[#_aws_credentials] == AWS Credentials
The proxy server that is launched by the plugin needs AWS credentials to fetch endpoint URLs and tokens for AWS CodeArtifact repositories.
As the proxy server is built using the AWS SDK for Java, it supports passing the credentials via Java system properties
(e.g. aws.profile
) and environment variables (e.g. AWS_PROFILE
) as described in the
link:https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html[SDK documentation].
In addition, the plugin supports passing some AWS settings as Gradle properties for convenience. These can be declared
in a gradle.properties
file, or on the command line with the -P
switch. The following settings are supported as
Gradle properties:
aws.accessKeyId
aws.secretAccessKey
aws.sessionToken
aws.configFile
aws.sharedCredentialsFile
aws.profile
aws.region
TIP: Relative paths in aws.configFile
and aws.sharedCredentialsFile
are resolved from the Gradle project's
root directory.
If these properties are present, they will have higher precedence than system properties or environment variables,
but the default order of the credential providers is still preserved. For example, if you pass environment variables
AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
to the build, as well as a Gradle property aws.profile
, then the
access-key based authorization will be used because that credential provider is higher in the chain than the
profile-based credential provider.
This allows to have a setup that works both in local and CI builds:
aws.profile
property in the gradle.properties file, which is
committed to your version control system. Every developer should have this AWS profile configured in their local
~/.aws/config
and ~/.aws/credentials
file.AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
environment variables
into each build. Since these "direct" credentials have higher precedence than the profile, the aws.profile
property
is ignored, and the given access key is used.== Where to Apply the Plugin
In contrast to most Gradle plugins, which typically work only on a Project
, this plugin supports being applied to
different targets:
the settings script (Settings
object, file name settings.gradle.kts
or settings.gradle
).
This is the recommended usage.
a project build script (Project
object, file name build.gradle.kts
or build.gradle
).
Use this only when building very simple projects without multi-modules and without a settings script. Applying the plugin to your settings script will automatically apply it to every project in the build.
an init script (Gradle
object, file name ~/.gradle/init.gradle
or specified with --init-script
).
This has some limitations, but may be necessary when using other Gradle plugins that are hosted in an AWS CodeArtifact repository (see below).
== Caching AWS CodeArtifact Tokens
Authorization tokens for AWS CodeArtifact are cached in memory, for the duration of a single build (i.e., an invocation of Gradle).
[#_using_gradle_plugins_from_an_aws_codeartifact_repository] == Using Gradle Plugins from an AWS CodeArtifact Repository
A special case arises when using Gradle plugins hosted in an AWS CodeArtifact repository.Resolution of Gradle plugin artifacts happens much earlier than other dependencies, so even applying this plugin to the settings script will not allow you to configure repositories in the following places:
Repositories in a pluginManagement
block of a settings script:
The pluginManagement
is used for both settings plugins and project plugins; unfortunately Gradle does not offer a
separate block for settings plugin management.Therefore, the pluginManagement
block in a settings script will be
evaluated before any settings plugins are applied.
repositories in a buildscript
block of a settings script
There are two possible solutions to this:
buildscript
blocks instead of pluginManagement
(project plugins only).
+
You can use a beforeProject
block in your settings script to apply a buildscript to all projects:
+
.settings.gradle.kts
[source,kotlin]~/.gradle/init.gradle
, but you can also specify it on the Gradle
command line using the --init-script
or -I
option.That way you can keep the init script under version
control as well.
+
[NOTE]AWS_PROFILE
etc.) but will not consider project-level Gradle properties.