使用Gradle插件简化AWS CodeArtifact的运用

1,699 阅读2分钟

为什么要使用CodeArtifact?

很多公司都跟我司一样,每天都会生成数十个工件(Artifact)供内部使用,因此必须配备一个企业内部使用的Maven库。我们考虑了几个备选解决方案,最后选择了CodeArtifact,主要是因为我们几乎所有的平台都已经托管在AWS上,不需要额外的维护。

日常使用中有什么问题?

CodeArtifact 要求用户使用 AWS 凭证创建授权令牌(Token)来进行身份验证,由于令牌的有效期只有12个小时,手动频繁的在本地和 CI 环境中获取Token是一件让程序员抓狂的事。我们大多数项目都使用 Gradle,因此我们寻找了一个插件,该插件可以自动向 CodeArtifact 进行身份验证并使用所需的令牌配置Repository用户。

如何使用插件?

  1. 在使用插件之前,先确保本地已经安装了AWS CLI。并且使用如下命令将AWS凭证配置到了本地Profile。
aws config --profile your-profile-name
  1. 然后,将上面的 your-profile-name 设置到环境变量 CODEARTIFACT_PROFILE 中。

  2. 接下来只需在 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
    }
  }
}

参考链接