为什么要使用CodeArtifact?
很多公司都跟我司一样,每天都会生成数十个工件(Artifact)供内部使用,因此必须配备一个企业内部使用的Maven库。我们考虑了几个备选解决方案,最后选择了CodeArtifact,主要是因为我们几乎所有的平台都已经托管在AWS上,不需要额外的维护。
日常使用中有什么问题?
CodeArtifact 要求用户使用 AWS 凭证创建授权令牌(Token)来进行身份验证,由于令牌的有效期只有12个小时,手动频繁的在本地和 CI 环境中获取Token是一件让程序员抓狂的事。我们大多数项目都使用 Gradle,因此我们寻找了一个插件,该插件可以自动向 CodeArtifact 进行身份验证并使用所需的令牌配置Repository用户。
如何使用插件?
- 在使用插件之前,先确保本地已经安装了AWS CLI。并且使用如下命令将AWS凭证配置到了本地Profile。
aws config --profile your-profile-name
-
然后,将上面的
your-profile-name
设置到环境变量CODEARTIFACT_PROFILE
中。 -
接下来只需在
build.gradle
中添加以下内容:
plugins {
//Latest version on https://plugins.gradle.org/plugin/ai.clarity.codeartifact
id 'ai.clarity.codeartifact' version '0.0.12'
}
repositories {
maven {
//Your CodeArtifact repository's endpoint
url 'https://domain-id.d.codeartifact.eu-central-1.amazonaws.com/maven/repository/'
}
}
publishing {
repositories {
maven {
//Your CodeArtifact repository's endpoint
url 'https://domain-id.d.codeartifact.eu-central-1.amazonaws.com/maven/repository/'
}
}
}
插件源代码可以参考: github.com/ningmengwan…
如何获取CodeArtifact上的Gradle自定义插件?
如果要使用托管在 AWS CodeArtifact 库中的 Gradle 自定义插件,会出现一种特殊情况。自定义插件的Maven库通常在 setting.gradle
中的 pluginManagement 中配置。 Gradle 对插件的解析发生的时间比其他依赖项要早得多,因此即使将上面介绍的插件应用于build.gradle
,也不能在pluginManagement中配置并使用存放了自定义插件Maven库(CodeArtifact)。
所以需要在 setting.gradle 的解析之前,获取并设置Token。可以在init.gradle
中添加如下代码,获取CodeArtifact的Token并设置到插件所在的Maven库。
~/.gradle/init.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.amazonaws:aws-java-sdk-codeartifact:1.12.108'
}
}
import com.amazonaws.services.codeartifact.AWSCodeArtifactClient;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.codeartifact.model.GetAuthorizationTokenRequest;
def setAuthorizationToken = {mavenArtifactRepository ->
def profile = System.getenv("CODEARTIFACT_PROFILE")
println "aws profile for codeartifact: [$profile]"
def domainLevels = mavenArtifactRepository.url.getHost().split('\\.')
def artifactDomain = domainLevels[0].substring(0,domainLevels[0].lastIndexOf("-"))
def artifactOwner = domainLevels[0].substring(domainLevels[0].lastIndexOf("-")+1)
def region = domainLevels[domainLevels.length -3]
def client = AWSCodeArtifactClient.builder()
.withCredentials(new ProfileCredentialsProvider(profile))
.withRegion(region)
.build();
def result = client.getAuthorizationToken(new GetAuthorizationTokenRequest()
.withDomain(artifactDomain)
.withDomainOwner(artifactOwner)
);
mavenArtifactRepository.credentials {
username "aws"
password result.authorizationToken
}
}
settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
maven {
url = "https://domain-id.d.codeartifact.eu-central-1.amazonaws.com/maven/repository/"
setAuthorizationToken(owner)
}
}
}
}
不使用插件行不行?
完全不使用Gradle插件也是可以的,只需要在定义Repository的地方,加上AWS CLI
的调用即可。代码如下,AWS的Profile需要事先设置到环境变量中。
repositories {
maven {
//Your CodeArtifact repository's endpoint
url 'https://domain-id.d.codeartifact.eu-central-1.amazonaws.com/maven/repository/'
credentials {
def AWSCLI = "aws codeartifact get-authorization-token --domain domain-id --domain-owner owner-account-id --query authorizationToken --output text"
def CODEARTIFACT_PROFILE = System.env.CODEARTIFACT_PROFILE
username "aws"
password CODEARTIFACT_PROFILE == null ?
AWSCLI.execute().text :
"$AWSCLI --profile $CODEARTIFACT_PROFILE".execute().text
}
}
}