

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 CodeArtifact 与 Maven 结合使用
<a name="using-maven"></a>

许多不同的语言（包括 Java、Kotlin、Scala 和 Clojure）都使用 Maven 存储库格式。许多不同的构建工具（包括 Maven、Gradle、Scala SBT、Apache Ivy 和 Leiningen）都支持 CodeArtifact。

我们已经测试并确认了以下版本与 CodeArtifact 兼容：
+ 最新的 **Maven** 版本：3.6.3。
+ 最新的 **Gradle** 版本：6.4.1。我们还测试了 5.5.1。
+ 最新的 **Clojure** 版本：1.11.1。我们还测试了其他版本。

**Topics**
+ [在 Gradle 中使用 CodeArtifact](maven-gradle.md)
+ [CodeArtifact 与 mvn 一起使用](maven-mvn.md)
+ [通过 deps.edn 来使用 CodeArtifact](maven-deps.md)
+ [使用 curl 进行发布](maven-curl.md)
+ [使用 Maven 校验和](maven-checksums.md)
+ [使用 Maven 快照](maven-snapshots.md)
+ [从上游和外部连接请求 Maven 程序包](maven-upstream-external-connections-request.md)
+ [Maven 故障排除](maven-troubleshooting.md)

# 在 Gradle 中使用 CodeArtifact
<a name="maven-gradle"></a>

按照[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)中所述，将 CodeArtifact 身份验证令牌存入环境变量后，请按照以下说明使用来自 CodeArtifact 存储库的 Maven 程序包，以及将新程序包发布到 CodeArtifact 存储库。

**Topics**
+ [提取依赖项](#fetching-dependencies)
+ [提取插件](#fetching-plugins)
+ [发布构件](#publishing-artifacts)
+ [在 IntelliJ IDEA 中运行 Gradle 构建](#gradle-intellij)

## 提取依赖项
<a name="fetching-dependencies"></a>

要在 Gradle 构建中提取来自 CodeArtifact 的依赖项，请遵循以下程序。

**在 Gradle 构建中提取来自 CodeArtifact 的依赖项**

1. 如果还没有身份验证令牌，请按照[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)中的步骤创建 CodeArtifact 身份验证令牌并将其存储在环境变量中。

1. 在项目 `build.gradle` 文件中的 `repositories` 部分添加一个 `maven` 部分。

   ```
   maven {
            url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
            credentials {
                username "aws"
                password System.env.CODEARTIFACT_AUTH_TOKEN
            }
   }
   ```

   前面示例中的 `url` 是 CodeArtifact 存储库的端点。Gradle 使用端点来连接到您的存储库。在示例中，`my_domain` 是域的名称，`111122223333` 是域所有者的 ID，`my_repo` 是存储库的名称。您可以使用 `get-repository-endpoint` AWS CLI 命令检索存储库的端点。

   例如，如果在名为 *my\$1domain* 的域中有一个名为 *my\$1repo* 的存储库，则命令如下所示：

   ```
   aws codeartifact get-repository-endpoint --domain my_domain --domain-owner 111122223333 --repository my_repo --format maven
   ```

   `get-repository-endpoint` 命令会返回存储库端点：

   ```
   url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
   ```

   前面示例中的 `credentials` 对象包括您在步骤 1 中创建的 CodeArtifact 身份验证令牌，Gradle 使用该令牌对 CodeArtifact 进行身份验证。
**注意**  
要使用双堆栈端点，请使用 `codeartifact.region.on.aws` 端点。

1. （可选）- 要使用 CodeArtifact 存储库作为项目依赖项的唯一来源，请从 `build.gradle` 的 `repositories` 中移除任何其他部分。如果您有多个存储库，Gradle 会按照列出的顺序在每个存储库中搜索依赖项。

1. 配置存储库后，您可以使用标准 Gradle 语法在 `dependencies` 部分添加项目依赖项。

   ```
   dependencies {
       implementation 'com.google.guava:guava:27.1-jre'
       implementation 'commons-cli:commons-cli:1.4'
       testImplementation 'org.testng:testng:6.14.3'
   }
   ```

## 提取插件
<a name="fetching-plugins"></a>

默认情况下，Gradle 会解析来自公有 [Gradle 插件门户](https://plugins.gradle.org/)的插件。要从 CodeArtifact 存储库提取插件，请按以下步骤操作。

**从 CodeArtifact 存储库提取插件**

1. 如果还没有身份验证令牌，请按照[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)中的步骤创建 CodeArtifact 身份验证令牌并将其存储在环境变量中。

1. 在 `settings.gradle` 文件中添加一个 `pluginManagement` 块。`pluginManagement` 块必须出现在 `settings.gradle` 中的任何其他语句之前，请参阅以下代码段：

   ```
   pluginManagement {
       repositories {
           maven {
               name 'my_repo'
               url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
               credentials {
                   username 'aws'
                   password System.env.CODEARTIFACT_AUTH_TOKEN
               }
           }
       }
   }
   ```

这将确保 Gradle 会解析来自指定存储库的插件。存储库必须有一个与 Gradle 插件门户网站（例如 `gradle-plugins-store`）有外部连接的上游存储库，以便构建版本可以使用常用的 Gradle 插件。有关更多信息，请参阅 [Gradle 文档](https://docs.gradle.org/current/userguide/plugins.html#sec:custom_plugin_repositories)。

## 发布构件
<a name="publishing-artifacts"></a>

本节介绍如何将使用 Gradle 构建的 Java 库发布到 CodeArtifact 存储库。

首先，将 `maven-publish` 插件添加到项目 `build.gradle` 文件的 `plugins` 部分。

```
plugins {
    id 'java-library'
    id 'maven-publish'
}
```

接下来，在项目 `build.gradle` 文件中添加一个 `publishing` 部分。

```
publishing {
    publications {
        mavenJava(MavenPublication) {
            groupId = 'group-id'
            artifactId = 'artifact-id'
            version = 'version'
            from components.java
        }
    }
    repositories {
        maven {
            url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
            credentials {
                username "aws"
                password System.env.CODEARTIFACT_AUTH_TOKEN
            }
        }
    }
}
```

`maven-publish` 插件根据 `publishing` 部分中指定的 `groupId`、`artifactId` 和 `version` 生成 POM 文件。

对 `build.gradle` 作出的这些更改完成后，运行以下命令来构建项目并将其上传到存储库。

```
./gradlew publish
```

使用 `list-package-versions` 来确认程序包已成功发布。

```
aws codeartifact list-package-versions --domain my_domain --domain-owner 111122223333 --repository my_repo --format maven\
  --namespace com.company.framework --package my-package-name
```

示例输出：

```
{
    "format": "maven",
    "namespace": "com.company.framework",
    "package": "example",
    "versions": [
        {
            "version": "1.0", 
            "revision": "REVISION-SAMPLE-1-C7F4S5E9B772FC",
            "status": "Published"
        }
    ]
}
```

有关更多信息，请参阅 Gradle 网站上的以下主题：
+  [构建 Java 库](https://guides.gradle.org/building-java-libraries/) 
+  [将项目作为模块发布](https://docs.gradle.org/current/userguide/publishing_setup.html) 

## 在 IntelliJ IDEA 中运行 Gradle 构建
<a name="gradle-intellij"></a>

您可以在 IntelliJ IDEA 中运行 Gradle 构建，从 CodeArtifact 提取依赖项。要使用 CodeArtifact 进行身份验证，您必须向 Gradle 提供 CodeArtifact 授权令牌。提供身份验证令牌的方法有三种。
+ 方法 1：将身份验证令牌存储在 `gradle.properties` 中。如果您能够覆盖 `gradle.properties` 文件或添加内容，请使用此方法。
+ 方法 2：将身份验证令牌存储在单独的文件中。如果您不想修改 `gradle.properties` 文件，请使用此方法。
+ 方法 3：通过在 `build.gradle` 中以内联脚本形式运行 `aws`，为每次运行生成新的身份验证令牌。如果您希望 Gradle 脚本在每次运行时都提取一个新令牌，请使用此方法。令牌不会存储在文件系统中。

------
#### [ Token stored in gradle.properties ]

**方法 1：将身份验证令牌存储在 `gradle.properties` 中**
**注意**  
该示例显示了位于 `GRADLE_USER_HOME` 中的 `gradle.properties` 文件。

1. 使用以下代码段来更新 `build.gradle` 文件：

   ```
   repositories {
       maven {
                url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
                credentials {
                    username "aws"
                    password "$codeartifactToken"
                }   
       }   
   }
   ```

1. 要从 CodeArtifact 提取插件，请在 `settings.gradle` 文件中添加一个 `pluginManagement` 块。`pluginManagement` 块必须出现在 `settings.gradle` 中的任何其他语句之前。

   ```
   pluginManagement {
       repositories {
           maven {
               name 'my_repo'
               url 'https://my_domain-111122223333.codeartifact.region.amazonaws.com/maven/my_repo/'
               credentials {
                   username 'aws'
                   password "$codeartifactToken"
               }
           }
       }
   }
   ```

1. 提取 CodeArtifact 身份验证令牌：

   ```
   export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain my_domain --domain-owner 111122223333 --query authorizationToken --output text --profile profile-name`
   ```

1. 将身份验证令牌写入 `gradle.properties` 文件中：

   ```
   echo "codeartifactToken=$CODEARTIFACT_AUTH_TOKEN" > ~/.gradle/gradle.properties
   ```

------
#### [ Token stored in separate file ]

**方法 2：将身份验证令牌存储在单独的文件中**

1. 使用以下代码段来更新 `build.gradle` 文件：

   ```
   def props = new Properties()
   file("file").withInputStream { props.load(it) }
   
   repositories {
   
       maven {
                url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
                credentials {
                    username "aws"
                    password props.getProperty("codeartifactToken")
                }
       }
   }
   ```

1. 要从 CodeArtifact 提取插件，请在 `settings.gradle` 文件中添加一个 `pluginManagement` 块。`pluginManagement` 块必须出现在 `settings.gradle` 中的任何其他语句之前。

   ```
   pluginManagement {
       def props = new Properties()
       file("file").withInputStream { props.load(it) }
       repositories {
           maven {
               name 'my_repo'
               url 'https://my_domain-111122223333.codeartifact.region.amazonaws.com/maven/my_repo/'
               credentials {
                   username 'aws'
                   password props.getProperty("codeartifactToken")
               }
           }
       }
   }
   ```

1. 提取 CodeArtifact 身份验证令牌：

   ```
   export CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain my_domain --domain-owner 111122223333 --query authorizationToken --output text --profile profile-name`
   ```

1. 将身份验证令牌写入在 `build.gradle` 文件中指定的文件：

   ```
   echo "codeartifactToken=$CODEARTIFACT_AUTH_TOKEN" > file
   ```

------
#### [ Token generated for each run in build.gradle ]

**方法 3：通过在 `build.gradle` 中以内联脚本形式运行 `aws`，为每次运行生成新的身份验证令牌**

1. 使用以下代码段来更新 `build.gradle` 文件：

   ```
   def codeartifactToken = "aws codeartifact get-authorization-token --domain my_domain --domain-owner 111122223333 --query authorizationToken --output text --profile profile-name".execute().text
       repositories {
           maven {
               url 'https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/'
               credentials {
                   username "aws"
                   password codeartifactToken
               }
           }
       }
   ```

1. 要从 CodeArtifact 提取插件，请在 `settings.gradle` 文件中添加一个 `pluginManagement` 块。`pluginManagement` 块必须出现在 `settings.gradle` 中的任何其他语句之前。

   ```
   pluginManagement {
       def codeartifactToken = "aws codeartifact get-authorization-token --domain my_domain --domain-owner 111122223333 --query authorizationToken --output text --profile profile-name".execute().text
       repositories {
           maven {
               name 'my_repo'
               url 'https://my_domain-111122223333.codeartifact.region.amazonaws.com/maven/my_repo/'
               credentials {
                   username 'aws'
                   password codeartifactToken
               }
           }
       }
   }
   ```

------

# CodeArtifact 与 mvn 一起使用
<a name="maven-mvn"></a>

您可以使用 `mvn` 命令来执行 Maven 构建。本节介绍如何配置`mvn`以使用 CodeArtifact 存储库。

**Topics**
+ [提取依赖项](#fetching-dependencies)
+ [发布构件](#publishing-artifacts)
+ [发布第三方构件](#publishing-third-party-artifacts)
+ [将 Maven 依赖项下载限制到存储库 CodeArtifact](#restrict-maven-downloads)
+ [Apache Maven 项目信息](#apache-maven-project-info)

## 提取依赖项
<a name="fetching-dependencies"></a>

`mvn`要配置为从 CodeArtifact 存储库获取依赖项，必须编辑 Maven 配置文件`settings.xml`，也可以编辑项目的 POM。

1. 如果还没有，请按照中所述在环境变量中创建 CodeArtifact 身份验证令牌并将其存储在环境变量中[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)，以设置对存储 CodeArtifact 库的身份验证。

1. 在 `settings.xml` 中（该文件通常位于 `~/.m2/settings.xml`），添加一个引用 `CODEARTIFACT_AUTH_TOKEN` 环境变量的 `<servers>` 部分，以便 Maven 可在 HTTP 请求中传递令牌。

   ```
   <settings>
   ...
       <servers>
           <server>
               <id>codeartifact</id>
               <username>aws</username>
               <password>${env.CODEARTIFACT_AUTH_TOKEN}</password>
           </server>
       </servers>
   ...
   </settings>
   ```

1. 在`<repository>`元素中添加 CodeArtifact 仓库的 URL 端点。您可以在 `settings.xml` 或项目的 POM 文件中执行此操作。

   您可以使用`get-repository-endpoint` AWS CLI 命令检索仓库的终端节点。

   例如，在名为的域*my\$1repo*中有一个名为的存储库*my\$1domain*，命令如下所示：

   ```
   aws codeartifact get-repository-endpoint --domain my_domain --repository my_repo --format maven
   ```

   `get-repository-endpoint` 命令会返回存储库端点：

   ```
   url 'https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/'
   ```
**注意**  
要使用双堆栈端点，请使用 `codeartifact.region.on.aws` 端点。

   按如下方式将存储库端点添加到 `settings.xml`。

   ```
   <settings>
   ...
       <profiles>
           <profile>
               <id>default</id>
               <repositories>
                   <repository>
                       <id>codeartifact</id>
                       <url>https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/</url>
                   </repository>
               </repositories>
           </profile>
       </profiles>
       <activeProfiles>
           <activeProfile>default</activeProfile>
       </activeProfiles>
       ...
   </settings>
   ```

   或者，您可以将该`<repositories>`部分添加到项目 POM 文件中，仅 CodeArtifact 用于该项目。

   ```
   <project>
   ...
       <repositories>
           <repository>
               <id>codeartifact</id>
               <name>codeartifact</name>
               <url>https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/</url>
           </repository>
       </repositories>
   ...
   </project>
   ```

**重要**  
可以在 `<id>` 元素中使用任何值，但必须与 `<server>` 和 `<repository>` 元素中的值相同。这样，就可以将指定的凭据包含在对的请求中 CodeArtifact。

更改这些配置后，就可以构建项目了。

```
mvn compile
```

Maven 会记录下载到控制台的所有依赖项的完整 URL。

```
[INFO] ------------------< com.example.example:myapp >-------------------
[INFO] Building myapp 1.0
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/commons-cli/commons-cli/1.4/commons-cli-1.4.pom
Downloaded from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/commons-cli/commons-cli/1.4/commons-cli-1.4.pom (11 kB at 3.9 kB/s)
Downloading from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/org/apache/commons/commons-parent/42/commons-parent-42.pom
Downloading from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/org/apache/commons/commons-parent/42/commons-parent-42.pom
Downloaded from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/org/apache/commons/commons-parent/42/commons-parent-42.pom (68 kB at 123 kB/s)
Downloading from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/commons-cli/commons-cli/1.4/commons-cli-1.4.jar
Downloaded from codeartifact: https://<domain>.d.codeartifact.us-west-2.amazonaws.com/maven/myrepo/commons-cli/commons-cli/1.4/commons-cli-1.4.jar (54 kB at 134 kB/s)
```

## 发布构件
<a name="publishing-artifacts"></a>

要将 Maven 工件发布`mvn`到 CodeArtifact 存储库，还必须编辑`~/.m2/settings.xml`和项目 POM。

1. 如果还没有，请按照中所述在环境变量中创建 CodeArtifact 身份验证令牌并将其存储在环境变量中[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)，以设置对存储 CodeArtifact 库的身份验证。

1. 在 `settings.xml` 中添加一个引用 `CODEARTIFACT_AUTH_TOKEN` 环境变量的 `<servers>` 部分，以便 Maven 可在 HTTP 请求中传递令牌。

   ```
   <settings>
   ...
       <servers>
           <server>
               <id>codeartifact</id>
               <username>aws</username>
               <password>${env.CODEARTIFACT_AUTH_TOKEN}</password>
           </server>
       </servers>
   ...
   </settings>
   ```

1. 将 `<distributionManagement>` 部分添加到项目的 `pom.xml`。

   ```
   <project>
   ...
        <distributionManagement>
            <repository>
                <id>codeartifact</id>
                <name>codeartifact</name>
                <url>https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/</url>
            </repository>
        </distributionManagement>
   ...
   </project>
   ```

更改这些配置后，就可以开始构建项目并将项目发布到指定的存储库。

```
mvn deploy
```

使用 `list-package-versions` 来确认程序包已成功发布。

```
aws codeartifact list-package-versions --domain my_domain --domain-owner 111122223333 --repository my_repo --format maven \
  --namespace com.company.framework --package my-package-name
```

示例输出：

```
{
    "defaultDisplayVersion": null,
    "format": "maven",
    "namespace": "com.company.framework",
    "package": "my-package-name",
    "versions": [
        {
            "version": "1.0", 
            "revision": "REVISION-SAMPLE-1-C7F4S5E9B772FC",
            "status": "Published"
        }
    ]
}
```

## 发布第三方构件
<a name="publishing-third-party-artifacts"></a>

您可以使用将第三方 Maven 工件发布到 CodeArtifact 存储库。`mvn deploy:deploy-file`这对于想要发布构件且只有 JAR 文件且无权访问程序包源代码或 POM 文件的用户很有用。

`mvn deploy:deploy-file` 命令会根据命令行中传递的信息生成 POM 文件。

**发布第三方 Maven 构件**

1. 如果还没有，请按照中所述在环境变量中创建 CodeArtifact 身份验证令牌并将其存储在环境变量中[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)，以设置对存储 CodeArtifact 库的身份验证。

1. 创建 `~/.m2/settings.xml` 文件并输入以下内容：

   ```
   <settings>
       <servers>
           <server>
               <id>codeartifact</id>
               <username>aws</username>
               <password>${env.CODEARTIFACT_AUTH_TOKEN}</password>
           </server>
       </servers>
   </settings>
   ```

1. 运行 `mvn deploy:deploy-file` 命令：

   ```
   mvn deploy:deploy-file -DgroupId=commons-cli          \
   -DartifactId=commons-cli       \
   -Dversion=1.4                  \
   -Dfile=./commons-cli-1.4.jar   \
   -Dpackaging=jar                \
   -DrepositoryId=codeartifact    \
   -Durl=https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/repo-name/
   ```
**注意**  
上面的示例会发布 `commons-cli 1.4`。修改 groupID、artifactID、version 和 file 参数来发布另一个 JAR。

这些说明基于 *Apache Maven* 文档中关于[ JARs 将第三方部署到远程存储库的指南](https://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html)中的示例。

## 将 Maven 依赖项下载限制到存储库 CodeArtifact
<a name="restrict-maven-downloads"></a>

 如果无法从已配置的存储库提取程序包，则默认情况下，`mvn` 命令会从 Maven Central 提取程序包。将`mirrors`元素添加到`settings.xml`，以便`mvn`始终使用您的 CodeArtifact 存储库。

```
<settings>
  ...
    <mirrors>
      <mirror>
        <id>central-mirror</id>
        <name>CodeArtifact Maven Central mirror</name>
        <url>https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/</url>
        <mirrorOf>central</mirrorOf>
      </mirror>
    </mirrors>
  ...
</settings>
```

如果添加 `mirrors` 元素，则在 `settings.xml` 或 `pom.xml` 中还必须有一个 `pluginRepository` 元素。以下示例从存储库中获取应用程序依赖关系和 Maven 插件。 CodeArtifact 

```
<settings>
...
  <profiles>
    <profile>
      <pluginRepositories>
        <pluginRepository>
          <id>codeartifact</id>
          <name>CodeArtifact Plugins</name>
          <url>https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/</url>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>
...
</settings>
```

以下示例从 CodeArtifact 存储库中获取应用程序依赖关系，并从 Maven Central 获取 Maven 插件。

```
<profiles>
   <profile>
     <id>default</id>
     ...
     <pluginRepositories>
       <pluginRepository>
         <id>central-plugins</id>
         <name>Central Plugins</name>
         <url>https://repo.maven.apache.org/maven2/</url>
         <releases>
             <enabled>true</enabled>
         </releases>
         <snapshots>
             <enabled>true</enabled>
         </snapshots>
       </pluginRepository>
     </pluginRepositories>
   ....
   </profile>
 </profiles>
```

## Apache Maven 项目信息
<a name="apache-maven-project-info"></a>

有关 Maven 的更多信息，请参阅 Apache Maven Project 网站上的以下主题：
+  [设置多个存储库](https://maven.apache.org/guides/mini/guide-multiple-repositories.html) 
+  [设置参考](https://maven.apache.org/settings.html) 
+  [分配管理](https://maven.apache.org/pom.html#Distribution_Management) 
+  [配置文件](https://maven.apache.org/pom.html#Profiles) 

# 通过 deps.edn 来使用 CodeArtifact
<a name="maven-deps"></a>

您可以使用包含 `clj` 命令的 `deps.edn` 来管理 Clojure 项目的依赖项。本节说明如何配置 `deps.edn` 来使用 CodeArtifact 存储库。

**Topics**
+ [提取依赖项](#fetching-dependencies-deps)
+ [发布构件](#publishing-artifacts-deps)

## 提取依赖项
<a name="fetching-dependencies-deps"></a>

要将 `Clojure` 配置为从 CodeArtifact 存储库提取依赖项，必须编辑 Maven 配置文件 `settings.xml`。

1. 在 `settings.xml` 中，添加一个引用 `CODEARTIFACT_AUTH_TOKEN` 环境变量的 `<servers>` 部分，以便 Clojure 可在 HTTP 请求中传递令牌。
**注意**  
Clojure 预计 settings.xml 文件位于 `~/.m2/settings.xml`。如果该文件在其他地方，则在此位置创建该文件。

   ```
   <settings>
   ...
       <servers>
           <server>
               <id>codeartifact</id>
               <username>aws</username>
               <password>${env.CODEARTIFACT_AUTH_TOKEN}</password>
           </server>
       </servers>
   ...
   </settings>
   ```

1. 如果您的项目还没有 POM xml 文件，请使用 `clj -Spom` 生成该文件。

1. 在您的 `deps.edn` 配置文件中，添加与 Maven `settings.xml` 中的服务器 ID 相匹配的存储库。

   ```
   :mvn/repos {
     "clojars" nil
     "central" nil
     "codeartifact" {:url "https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/"}
   }
   ```
**注意**  
`tools.deps` 保证首先检查 `central` 和 `clojars` 存储库中是否有 Maven 库。之后，系统会检查 `deps.edn` 中列出的其他存储库。
为了防止直接从 Clojars 和 Maven Central 下载，`central` 和 `clojars` 需要设置为 `nil`。

   确保环境变量中有 CodeArtifact 身份验证令牌（请参见[使用环境变量传递身份验证令牌](tokens-authentication.md#env-var)）。在发生这些更改之后构建程序包时，`deps.edn` 将从 CodeArtifact 中提取依赖项。
**注意**  
要使用双堆栈端点，请使用 `codeartifact.region.on.aws` 端点。

## 发布构件
<a name="publishing-artifacts-deps"></a>

1. 更新 Maven 设置和 `deps.edn`，将 CodeArtifact 添加为 Maven 认可的服务器（请参见[提取依赖项](#fetching-dependencies-deps)）。您可以使用诸如 [deps-deploy](https://github.com/slipset/deps-deploy) 之类的工具将构件上传到 CodeArtifact。

1. 在 `build.clj` 中，添加一个 `deploy` 任务，将所需的构件上传到先前设置的 `codeartifact` 存储库。

   ```
   (ns build
   (:require [deps-deploy.deps-deploy :as dd]))
   
   (defn deploy [_]
     (dd/deploy {:installer :remote
             :artifact "PATH_TO_JAR_FILE.jar"
             :pom-file "pom.xml" ;; pom containing artifact coordinates
             :repository "codeartifact"}))
   ```

1. 通过运行以下命令来发布构件：`clj -T:build deploy`

有关修改默认存储库的更多信息，请参阅**《Clojure Deps 和 CLI 参考依据》中的[修改默认存储库](https://clojure.org/reference/deps_and_cli#_modifying_the_default_repositories)。

# 使用 curl 进行发布
<a name="maven-curl"></a>

本节介绍如何使用 HTTP 客户端 `curl` 将 Maven 构件发布到 CodeArtifact 存储库。如果您的环境中没有 Maven 客户端或想要安装 Maven 客户端，则使用 `curl` 发布构件会很有用。

**使用 `curl` 发布 Maven 构件**

1. 按照 [使用环境变量传递身份验证令牌](tokens-authentication.md#env-var) 中的步骤提取 CodeArtifact 授权令牌，然后返回到这些步骤。

1. 使用以下 `curl` 命令将 JAR 发布到 CodeArtifact 存储库：

   在此程序中的每个 `curl` 命令中，替换以下占位符：
   + 将 *my\$1domain* 替换为您的 CodeArtifact 域名。
   + 将 *111122223333* 替换为您的 CodeArtifact 域所有者的 ID。
   + 将 *us-west-2* 替换为您的 CodeArtifact 域所在的区域。
   + 将 *my\$1repo* 替换为您的 CodeArtifact 存储库名称。

   ```
   curl --request PUT https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/com/mycompany/app/my-app/1.0/my-app-1.0.jar \
        --user "aws:$CODEARTIFACT_AUTH_TOKEN" --header "Content-Type: application/octet-stream" \
        --data-binary @my-app-1.0.jar
   ```
**重要**  
必须在 `--data-binary` 参数的值前面加上一个 `@` 字符。将值放在引号中时，`@` 必须包含在引号内。

1. 使用以下 `curl` 命令将 POM 发布到 CodeArtifact 存储库：

   ```
   curl --request PUT https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_repo/com/mycompany/app/my-app/1.0/my-app-1.0.pom \
        --user "aws:$CODEARTIFACT_AUTH_TOKEN" --header "Content-Type: application/octet-stream" \
        --data-binary @my-app-1.0.pom
   ```

1. 此时，Maven 构件将位于您的 CodeArtifact 存储库中，状态为 `Unfinished`。为了能够使用程序包，程序包必须处于 `Published` 状态。您可以通过向程序包上传 `maven-metadata.xml` 文件来将程序包从 `Unfinished` 切换为 `Published`，或者调用 [UpdatePackageVersionsStatus API](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_UpdatePackageVersionsStatus.html) 来更改状态。

   1.  选项 1：使用以下 `curl` 命令将 `maven-metadata.xml` 文件添加到您的程序包中：

      ```
      curl --request PUT https://my_domain-111122223333.d.codeartifact.region.amazonaws.com/maven/my_repo/com/mycompany/app/my-app/maven-metadata.xml \
           --user "aws:$CODEARTIFACT_AUTH_TOKEN" --header "Content-Type: application/octet-stream" \
           --data-binary @maven-metadata.xml
      ```

      以下是 `maven-metadata.xml` 文件的内容示例：

      ```
      <metadata modelVersion="1.1.0">
          <groupId>com.mycompany.app</groupId>
          <artifactId>my-app</artifactId>
          <versioning>
              <latest>1.0</latest>
              <release>1.0</release>
              <versions>
                  <version>1.0</version>
              </versions>
              <lastUpdated>20200731090423</lastUpdated>
          </versioning>
      </metadata>
      ```

   1.  选项 2：使用 `UpdatePackageVersionsStatus` API 将程序包状态更新为 `Published`。

      ```
      aws codeartifact update-package-versions-status \
          --domain my_domain \
          --domain-owner 111122223333 \
          --repository my_repo \
          --format maven \
          --namespace com.mycompany.app \
          --package my-app \
          --versions 1.0 \
          --target-status Published
      ```

如果您只有构件的 JAR 文件，则可以使用 `mvn` 将可使用的程序包版本发布到 CodeArtifact 存储库。如果您无法访问构件的源代码或 POM，此方法会很有用。有关详细信息，请参阅[发布第三方构件](maven-mvn.md#publishing-third-party-artifacts)。

# 使用 Maven 校验和
<a name="maven-checksums"></a>

 将 Maven 工件发布到 AWS CodeArtifact 存储库时，将使用与包中每个*资产*或文件关联的校验和来验证上传。资产的例子包括 *jar*、*pom* 和 *war* 文件。对于每个资产，Maven 构件都包含多个校验和文件，这些文件使用带有附加扩展名（例如 `md5` 或 `sha1`）的资产名称。例如，名为 `my-maven-package.jar` 的文件的校验和文件可能是 `my-maven-package.jar.md5` 和 `my-maven-package.jar.sha1`。

**注意**  
 Maven 使用术语“`artifact`”。在本指南中，Maven 程序包与 Maven 构件相同。有关更多信息，请参阅[AWS CodeArtifact软件包](https://docs.aws.amazon.com/codeartifact/latest/ug/welcome.html#welcome-concepts-package)。

## 校验和存储
<a name="maven-checksum-storage"></a>

CodeArtifact 不将 Maven 校验和存储为资产。这意味着校验和不会作为单个资产出现在 [ListPackageVersionAssets API](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_ListPackageVersionAssets.html) 的输出中。取而代之的是，计算的 CodeArtifact校验和适用于所有支持的校验和类型的每种资产。例如，调用 ListPackageVersionAssets Maven 软件包版本的部分响应`commons-lang:commons-lang 2.1`是：

```
{
    "name": "commons-lang-2.1.jar",
    "size": 207723,
    "hashes": {
        "MD5": "51591549f1662a64543f08a1d4a0cf87",
        "SHA-1": "4763ecc9d78781c915c07eb03e90572c7ff04205",
        "SHA-256": "2ded7343dc8e57decd5e6302337139be020fdd885a2935925e8d575975e480b9",
        "SHA-512": "a312a5e33b17835f2e82e74ab52ab81f0dec01a7e72a2ba58bb76b6a197ffcd2bb410e341ef7b3720f3b595ce49fdd9994ea887ba08ff6fe21b2c714f8c405af"
    }
},
{
    "name": "commons-lang-2.1.pom",
    "size": 9928,
    "hashes": {
        "MD5": "8e41bacdd69de9373c20326d231c8a5d",
        "SHA-1": "a34d992202615804c534953aba402de55d8ee47c",
        "SHA-256": "f1a709cd489f23498a0b6b3dfbfc0d21d4f15904791446dec7f8a58a7da5bd6a",
        "SHA-512": "1631ce8fe4101b6cde857f5b1db9b29b937f98ba445a60e76cc2b8f2a732ff24d19b91821a052c1b56b73325104e9280382b2520edda4e7696698165c7e09161"
    }
},
        {
    "name": "maven-metadata.xml",
    "size": 121,
    "hashes": {
        "MD5": "11bb3d48d984f2f49cea1e150b6fa371",
        "SHA-1": "7ef872be17357751ce65cb907834b6c5769998db",
        "SHA-256": "d04d140362ea8989a824a518439246e7194e719557e8d701831b7f5a8228411c",
        "SHA-512": "001813a0333ce4b2a47cf44900470bc2265ae65123a8c6b5ac5f2859184608596baa4d8ee0696d0a497755dade0f6bf5e54667215a06ceae1effdfb7a8d30f88"
    }
}
```

 尽管校验和未存储为资产，但 Maven 客户端仍然可以在预期的位置发布和下载校验和。例如，如果 `commons-lang:commons-lang 2.1` 位于名为 `maven-repo` 的存储库中，则 JAR 文件的 SHA-256 校验和的 URL 路径将为：

```
/maven/maven-repo/commons-lang/commons-lang/2.1/commons-lang-2.1.jar.sha256
```

如果您要 CodeArtifact 使用通用 HTTP 客户端（例如，将现有 Maven 软件包（例如，之前存储在 Amazon S3 中的包）上传到通用 HTTP 客户端`curl`，则无需上传校验和。 CodeArtifact 将自动生成它们。如果您想验证资产是否已正确上传，可以使用 ListPackageVersionAssets API 操作将响应中的校验和与每项资产的原始校验和值进行比较。

## 发布期间校验和不匹配
<a name="maven-checksum-mismatch"></a>

除了资产和校验和，Maven 构件还包含一个 `maven-metadata.xml` 文件。Maven 程序包的正常发布顺序是先上传所有资产和校验和，然后再上传 `maven-metadata.xml`。例如，假设客户端配置为发布 SHA-256 校验和文件，则前面所述的 Maven 程序包版本 `commons-lang 2.1` 的发布顺序为：

```
PUT commons-lang-2.1.jar
PUT commons-lang-2.1.jar.sha256
PUT commons-lang-2.1.pom
PUT commons-lang-2.1.pom.sha256
PUT maven-metadata.xml
PUT maven-metadata.xml.sha256
```

上传资产（例如 JAR 文件）的校验和文件时，如果上传的校验和值与由计算的校验和值**不匹配，则校验和上传请求将失败，并显示 400（错误请求）**响应。 CodeArtifact如果相应的资产不存在，则请求将失败，并显示 **404（未找到）**响应。为避免出现此错误，您必须先上传资产，然后再上传校验和。

上传后`maven-metadata.xml`， CodeArtifact 通常会将 Maven 包版本的状态从更改`Unfinished`为。`Published`如果检测到任何资产的校验和不匹配，则 CodeArtifact 会根据`maven-metadata.xml`发布**请求返回 400（错误请求）**。此错误可能会导致客户端停止上传该程序包版本的文件。如果出现这种情况，并且 `maven-metadata.xml` 文件未上传，则无法下载已上传的程序包版本的任何资产。这是因为程序包版本的状态未设置为 `Published`，而是保持为 `Unfinished`。

CodeArtifact 即使`maven-metadata.xml`已上传且软件包版本状态已设置为，也允许向 Maven 软件包版本添加更多资产。`Published`在此状态下，上传不匹配的校验和文件的请求也会失败，并显示 **400（错误请求）**响应。但是，由于程序包版本状态已设置为 `Published`，因此您可以从程序包中下载任何资产，包括校验和文件上传失败的资产。在为上传校验和文件失败的资产下载校验和时，客户端收到的校验和值将是 CodeArtifact 根据上传的资产数据计算得出的校验和值。

CodeArtifact 校验和比较区分大小写，计算的校验和采用 CodeArtifact 小写格式。因此，如果上传了校验和`909FA780F76DA393E992A3D2D495F468`，它将因校验和不匹配而失败，因为它 CodeArtifact 不将其视为等于。`909fa780f76da393e992a3d2d495f468`

## 在校验和不匹配情况下恢复
<a name="maven-checksum-mismatch-recovery"></a>

如果由于校验和不匹配导致校验和上传失败，请尝试以下方法之一进行恢复：
+ 再次运行发布 Maven 构件的命令。如果因网络问题导致校验和文件损坏，此方法可能会起作用。如果这样可以解决网络问题，则校验和匹配且下载成功。
+ 删除程序包版本，然后重新发布。有关更多信息，请参阅 *AWS CodeArtifact API 参考[DeletePackageVersions](https://docs.aws.amazon.com/dms/latest/APIReference/API_DeletePackageVersions.html)*中的。

# 使用 Maven 快照
<a name="maven-snapshots"></a>

 Maven *快照*是 Maven 程序包的特殊版本，该版本引用了最新的生产分支代码。它是先于最终发布版本的开发版本。您可以通过附加到程序包版本的后缀 `SNAPSHOT` 来识别 Maven 程序包的快照版本。例如，版本 `1.1` 的快照是 `1.1-SNAPSHOT`。有关更多信息，请参阅 Apache Maven Project 网站上的 [What is a SNAPSHOT version?](https://maven.apache.org/guides/getting-started/index.html#What_is_a_SNAPSHOT_version)。

 AWS CodeArtifact 支持发布和使用 Maven 快照。仅支持使用基于时间的版本号的唯一快照。 CodeArtifact 不支持 Maven 2 客户端生成的非唯一快照。您可以将支持的 Maven 快照发布到任何 CodeArtifact 存储库。

**Topics**
+ [快照发布在 CodeArtifact](#maven-snapshot-publishing)
+ [使用快照版本](#maven-consuming-snapshot-versions)
+ [删除快照版本](#maven-deleting-snapshot-versions)
+ [使用 curl 进行快照发布](#maven-snapshot-publishing-curl)
+ [快照和外部连接](#maven-snapshot-external-connections)
+ [快照和上游存储库](#maven-snapshot-upstream-repositories)

## 快照发布在 CodeArtifact
<a name="maven-snapshot-publishing"></a>

AWS CodeArtifact 支持客户端（例如`mvn`）在发布快照时使用的请求模式。因此，您无需详细了解 Maven 快照的发布方式，即可按照构建工具或程序包管理器的文档进行操作。如果你正在做更复杂的事情，本节将详细介绍如何 CodeArtifact 处理快照。

 将 Maven 快照发布到 CodeArtifact 存储库时，其先前版本将保留在名为 build 的新版本中。每次发布 Maven 快照时，都会创建一个新的构建版本。快照的所有先前版本都保留在其构建版本中。发布 Maven 快照时，其程序包版本状态将设置为 `Published`，包含先前版本的版本的构建的状态设置为 `Unlisted`。此行为仅适用于程序包版本使用 `-SNAPSHOT` 作为后缀的 Maven 程序包版本。

例如，名为的 maven 包的快照版本`com.mycompany.myapp:pkg-1`会上传到名为的 CodeArtifact 存储库。`my-maven-repo`快照版本是 `1.0-SNAPSHOT`。到目前为止，尚未发布 `com.mycompany.myapp:pkg-1` 的任何版本。首先，在以下路径发布初始构建的资产：

```
PUT maven/my-maven-repo/com/mycompany/myapp/pkg-1/1.0-SNAPSHOT/pkg-1-1.0-20210728.194552-1.jar
PUT maven/my-maven-repo/com/mycompany/myapp/pkg-1/1.0-SNAPSHOT/pkg-1-1.0-20210728.194552-1.pom
```

请注意，由发布快照版本的客户端生成时间戳 `20210728.194552-1`。

上传 .pom 和 .jar 文件后，存储库中唯一存在的 `com.mycompany.myapp:pkg-1` 版本是 `1.0-20210728.194552-1`。即使在前面的路径中指定的版本是 `1.0-SNAPSHOT`，也会发生这种情况。此时的程序包版本状态为 `Unfinished`。

```
aws codeartifact list-package-versions --domain my-domain --repository \
  my-maven-repo --package pkg-1 --namespace com.mycompany.myapp --format maven
{
    "versions": [
        {
            "version": "1.0-20210728.194552-1",
            "revision": "GipMW+599JmwTcTLaXo9YvDsVQ2bcrrk/02rWJhoKUU=",
            "status": "Unfinished"
        }
    ],
    "defaultDisplayVersion": null,
    "format": "maven",
    "package": "pkg-1",
    "namespace": "com.mycompany.myapp"
}
```

接下来，客户端上传程序包版本的 `maven-metadata.xml` 文件：

```
PUT my-maven-repo/com/mycompany/myapp/pkg-1/1.0-SNAPSHOT/maven-metadata.xml
```

成功上传 maven-metadata.xml 文件后， CodeArtifact 会创建`1.0-SNAPSHOT`包版本并将`1.0-20210728.194552-1`版本设置为`Unlisted`。

```
aws codeartifact list-package-versions --domain my-domain --repository \
  my-maven-repo --package pkg-1 --namespace com.mycompany.myapp --format maven
{
    "versions": [
        {
            "version": "1.0-20210728.194552-1",
            "revision": "GipMW+599JmwTcTLaXo9YvDsVQ2bcrrk/02rWJhoKUU=",
            "status": "Unlisted"
        },
        {
            "version": "1.0-SNAPSHOT",
            "revision": "tWu8n3IX5HR82vzVZQAxlwcvvA4U/+S80edWNAkil24=",
            "status": "Published"
        }
    ],
    "defaultDisplayVersion": "1.0-SNAPSHOT",
    "format": "maven",
    "package": "pkg-1",
    "namespace": "com.mycompany.myapp"
}
```

此时，可以在构建中使用快照版本 `1.0-SNAPSHOT`。虽然存储库 `my-maven-repo` 中有 `com.mycompany.myapp:pkg-1` 的两个版本，但它们都包含相同的资产。

```
aws codeartifact list-package-version-assets --domain my-domain --repository \
  my-maven-repo --format maven --namespace com.mycompany.myapp \
 --package pkg-1 --package-version 1.0-SNAPSHOT--query 'assets[*].name'
[ 
     "pkg-1-1.0-20210728.194552-1.jar",
     "pkg-1-1.0-20210728.194552-1.pom"
]
```

将 `--package-version` 参数更改为 `1.0-20210728.194552-1`，运行如前所示的相同 `list-package-version-assets` 命令会得到相同的输出。

在向存储库中添加 `1.0-SNAPSHOT` 的额外构建时，会为每个新构建创建一个新的 `Unlisted` 程序包版本。每次都会更新版本 `1.0-SNAPSHOT` 的资产，因此版本始终引用该版本的最新构建。通过上传新构建的 `maven-metadata.xml` 文件，开始将 `1.0-SNAPSHOT` 更新为包含最新资产。

## 使用快照版本
<a name="maven-consuming-snapshot-versions"></a>

如果您请求快照，则会返回状态为 `Published` 的版本。这始终是 Maven 快照的最新版本。您也可以在 URL 路径中使用构建版本号（例如 `1.0-20210728.194552-1`）而不是快照版本（例如 `1.0-SNAPSHOT`）来请求快照的特定构建。要查看 Maven 快照的编译版本，请使用 [ListPackageVersions ](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_ListPackageVersions.html)API *指南中的 CodeArtifact API* 并将状态参数设置为`Unlisted`。

## 删除快照版本
<a name="maven-deleting-snapshot-versions"></a>

要删除 Maven 快照的所有构建版本，请使用 [DeletePackageVersions](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_DeletePackageVersions.html)API，指定要删除的版本。

## 使用 curl 进行快照发布
<a name="maven-snapshot-publishing-curl"></a>

如果您在亚马逊简单存储服务 (Amazon S3) Simple Storage Service 或其他项目存储库产品中存储了现有快照版本，则可能需要将其重新发布到。 AWS CodeArtifact由于 CodeArtifact支持 Maven 快照的方式（请参阅[快照发布在 CodeArtifact](#maven-snapshot-publishing)），因此使用通用 HTTP 客户端（例如）发布快照比发布 Maven 发行版本要复杂得多，如中所述。`curl` [使用 curl 进行发布](maven-curl.md)请注意，如果您使用 `mvn` 或 `gradle` 等 Maven 客户端来构建和部署快照版本，则本节不相关。您需要遵循该客户端的文档进行操作。

发布快照版本涉及发布快照版本的一个或多个构建。在中 CodeArtifact，如果快照版本有 *n* 个内部版本，则将有 *n \$1 1 个* CodeArtifact 版本：*n* 个版本的状态均为`Unlisted`，一个快照版本（最新发布的版本）的状态为`Published`。快照版本（即版本字符串包含“-SNAPSHOT”的版本）包含一组与最新发布的构建相同的资产。使用 `curl` 创建此结构的最简单方法如下：

1. 使用 `curl` 发布所有构建的所有资产。

1. 使用 `curl` 发布最后一个构建（即带有最新日期时间戳的构建）的 `maven-metadata.xml` 文件。这将创建一个版本字符串中带有“`-SNAPSHOT`”且具有正确资产集的版本。

1. 使用 [UpdatePackageVersionsStatus](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_UpdatePackageVersionsStatus.html)API 将所有非最新版本的状态设置为。`Unlisted`

 使用以下 `curl` 命令来发布程序包 `com.mycompany.app:pkg-1` 的快照版本 `1.0-SNAPSHOT` 的快照资产（例如 .jar 和 .pom 文件）：

```
curl --user "aws:$CODEARTIFACT_AUTH_TOKEN" -H "Content-Type: application/octet-stream" \
     -X PUT https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_maven_repo/com/mycompany/app/pkg-1/1.0-SNAPSHOT/pkg-1-1.0-20210729.171330-2.jar \
     --data-binary @pkg-1-1.0-20210728.194552-1.jar
```

```
curl --user "aws:$CODEARTIFACT_AUTH_TOKEN" -H "Content-Type: application/octet-stream" \
     -X PUT https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_maven_repo/com/mycompany/app/pkg-1/1.0-SNAPSHOT/pkg-1-1.0-20210729.171330-2.pom \
     --data-binary @pkg-1-1.0-20210728.194552-1.pom
```

使用这些示例时：
+ *my\$1domain*用您的 CodeArtifact 域名替换。
+ *111122223333*替换为您的 CodeArtifact 域名所有者的 AWS 账户 ID。
+ *us-west-2*替换 AWS 区域 为您的 CodeArtifact 域名所在的。
+ *my\$1maven\$1repo*替换为您的 CodeArtifact 存储库名称。

**重要**  
必须在 `--data-binary` 参数的值前面加上 `@` 字符。将值放在引号中时，`@` 必须包含在引号内。

每个构建可能有两个以上的资产需要上传。例如，除了主 JAR 和 `pom.xml` 之外，可能还有 Javadoc 和源 JAR 文件。没有必要发布包版本资产的校验和文件，因为会 CodeArtifact自动为每个上传的资源生成校验和。要验证资产是否已正确上传，请使用 `list-package-version-assets` 命令提取生成的校验和，并将其与原始校验和进行比较。有关如何 CodeArtifact 处理 Maven 校验和的更多信息，请参阅。[使用 Maven 校验和](maven-checksums.md)

使用以下 curl 命令来发布最新构建版本的 `maven-metadata.xml` 文件：

```
curl --user "aws:$CODEARTIFACT_AUTH_TOKEN" -H "Content-Type: application/octet-stream" \
     -X PUT https://my_domain-111122223333.d.codeartifact.us-west-2.amazonaws.com/maven/my_maven_repo/com/mycompany/app/pkg-1/1.0-SNAPSHOT/maven-metadata.xml \
     --data-binary @maven-metadata.xml
```

`maven-metadata.xml` 文件必须引用 `<snapshotVersions>` 元素中最新构建版本的至少一个资产。此外，必须存在 `<timestamp>` 值，且该值必须与资产文件名中的时间戳相匹配。例如，对于之前发布的 `20210729.171330-2` 构建，`maven-metadata.xml` 的内容将为：

```
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>com.mycompany.app</groupId>
  <artifactId>pkg-1</artifactId>
  <version>1.0-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20210729.171330</timestamp>
      <buildNumber>2</buildNumber>
    </snapshot>
    <lastUpdated>20210729171330</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>1.0-20210729.171330-2</value>
        <updated>20210729171330</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>1.0-20210729.171330-2</value>
        <updated>20210729171330</updated>
      </snapshotVersion>
    </snapshotVersions>
  </versioning>
</metadata>
```

发布 `maven-metadata.xml` 后，最后一步是将所有其他构建版本（即除最新构建之外的所有构建版本）的程序包版本状态设置为 `Unlisted`。例如，如果 `1.0-SNAPSHOT` 版本有两个构建，第一个构建是 `20210728.194552-1`，则将该构建设置为 `Unlisted` 的命令是：

```
aws codeartifact update-package-versions-status --domain my-domain --domain-owner 111122223333 \
   --repository my-maven-repo --format maven --namespace com.mycompany.app --package pkg-1 \
   --versions 1.0-20210728.194552-1 --target-status Unlisted
```

## 快照和外部连接
<a name="maven-snapshot-external-connections"></a>

无法通过外部连接从 Maven 公共存储库获取 Maven 快照。 AWS CodeArtifact 仅支持导入 Maven 发行版本。

## 快照和上游存储库
<a name="maven-snapshot-upstream-repositories"></a>

通常，与上游存储库一起使用时，Maven 快照的工作方式与 Maven 发布版本相同，但如果您计划将同一程序包版本的快照发布到两个具有上游关系的存储库，则存在一定的限制。例如，假设一个 AWS CodeArtifact 域中有两个存储库，`R`以及`U`，其中`U`是的上游`R`。如果您在中发布新版本`R`，则当 Maven 客户端请求该快照版本的最新版本时，会 CodeArtifact 返回来自`U`的最新版本。这可能出乎意料，因为最新版本现在位于 `R` 中，而不是 `U` 中。有两种方法可以避免这种情况：

1. 如果 `U` 中存在 `1.0-SNAPSHOT`，则不要发布快照版本的内部版本（例如 `R` 中的 `1.0-SNAPSHOT`）。

1. 使用 CodeArtifact 包源控件在中`R`禁用该软件包的上游。后者将允许您在 `R` 中发布 `1.0-SNAPSHOT` 的内部版本，但它也将防止 `R` 从 `U` 中获取该程序包的其他任何尚未保留的版本。

# 从上游和外部连接请求 Maven 程序包
<a name="maven-upstream-external-connections-request"></a>



## 导入标准资产名称
<a name="maven-import-standard-asset-names"></a>

从公共存储库（例如 Maven Central）导入 Maven 包版本时，AWS CodeArtifact 会尝试导入该软件包版本中的所有资产。如 [请求包含上游存储库的程序包版本](repo-upstream-behavior.md) 中所述，在以下时候会发生导入：
+ 客户端向 CodeArtifact 存储库请求 Maven 资产。
+ 程序包版本尚未出现在存储库或其上游中。
+ 存在与公有 Maven 存储库的可访问外部连接。

尽管客户端可能只请求了一个资产，但仍会 CodeArtifact 尝试导入它能找到的适用于该软件包版本的所有资产。如何 CodeArtifact 发现哪些资产可用于 Maven 软件包版本取决于特定的公共存储库。一些公有 Maven 存储库支持请求资产列表，但其他存储库则不支持。对于不提供列出资产的方式的存储库， CodeArtifact 会生成一组可能存在的资产名称。例如，当请求任何 Maven 包版本的资源`junit 4.13.2`时， CodeArtifact 将尝试导入以下资产：
+ `junit-4.13.2.pom`
+ `junit-4.13.2.jar`
+ `junit-4.13.2-javadoc.jar`
+ `junit-4.13.2-sources.jar`

## 导入非标准资产名称
<a name="maven-import-nonstandard-asset-names"></a>

当 Maven 客户端请求的资产与上述模式不匹配时， CodeArtifact 会检查该资产是否存在于公共存储库中。如果存在资产，则会将其导入并添加到现有的程序包版本记录（如果存在）中。例如，Maven 程序包版本 `com.android.tools.build:aapt2 7.3.1-8691043` 包含以下资产：
+ `aapt2-7.3.1-8691043.pom`
+ `aapt2-7.3.1-8691043-windows.jar`
+ `aapt2-7.3.1-8691043-osx.jar`
+ `aapt2-7.3.1-8691043-linux.jar`

当客户请求 POM 文件时，如果无法列出软件包版本的资产，则 POM 将 CodeArtifact 是唯一导入的资产。这是因为其他资产都不符合标准资产名称模式。但是，当客户端请求其中一个 JAR 资产时，该资产将被导入并添加到存储在中的现有软件包版本中 CodeArtifact。最下游存储库（客户端向其发出请求的存储库）和具有外部连接的存储库中的程序包版本都将更新为包含新资产，如[上游存储库的程序包保留](repo-upstream-behavior.md#package-retention-upstream-repos)中所述。

通常，软件包版本一旦保留在 CodeArtifact 存储库中，就不会受到上游存储库中更改的影响。有关更多信息，请参阅 [上游存储库的程序包保留](repo-upstream-behavior.md#package-retention-upstream-repos)。但是，对于具有前面所述的非标准名称的 Maven 资产，其行为与此规则不同。虽然如果客户端没有请求额外的资产，下游程序包版本就不会更改，但在这种情况下，保留的程序包版本在最初保留后经过修改，因此不是一成不变的。这种行为是必要的，因为否则将无法通过 CodeArtifact访问具有非标准名称的 Maven 资产。如果将软件包版本保留在存储库中之后，将其添加到公共存储库上的 Maven 软件包版本中，则该行为也会启用。 CodeArtifact 

## 检查资产来源
<a name="origin-checks-for-assets"></a>

将新资源添加到先前保留的 Maven 软件包版本时， CodeArtifact 确认保留的软件包版本的来源与新资产的来源相同。这可以防止创建“混合”程序包版本，其中不同的资产来自不同的公有存储库。如果不进行此检查，则如果将 Maven 包版本发布到多个公共存储库，并且这些存储库是存储库上游图的一部分，则可能会发生资产混合。 CodeArtifact 

## 在上游存储库中导入新资产和程序包版本状态
<a name="new-asset-importing-pv-status-upstream-repos"></a>

上游存储库中软件包版本的软件包版本[状态](packages-overview.md#package-version-status)可能会 CodeArtifact 阻止在下游存储库中保留这些版本。

例如，假设一个域有三个存储库：`repo-A`、`repo-B` 和 `repo-C`，其中 `repo-B` 是 `repo-A` 的上游存储库，`repo-C` 是 `repo-B` 的下游存储库。

![\[上游存储库中新资产和程序包版本的工作原理示意图。\]](http://docs.aws.amazon.com/zh_cn/codeartifact/latest/ug/images/Maven-new-asset-pv-upstream.png)


`repo-B` 中存在 Maven 程序包 `com.android.tools.build:aapt2` 的程序包版本 `7.3.1`，其状态为 `Published`。它不存在于 `repo-A` 中。如果客户端从 `repo-A` 请求此程序包版本的资产，则响应将为 200（正常），且 Maven 程序包版本 `7.3.1` 将保留在 `repo-A` 中。但是，如果 `repo-B` 中的程序包版本 `7.3.1` 的状态为 `Archived` 或 `Disposed`，则响应将为 404（未找到），因为处于这两种状态的程序包版本的资产不可下载。

请注意，为 `repo-A`、`repo-B` 和 `repo-C` 中的 `com.android.tools.build:aapt2` 将[程序包来源控制](package-origin-controls.md)设置为 `upstream=BLOCK`，则无论程序包的版本状态是什么，都可防止从 `repo-A` 为该程序包的所有版本提取新资产。

# Maven 故障排除
<a name="maven-troubleshooting"></a>

以下信息可协助您处理 Maven 和 CodeArtifact 中的常见问题。

## 禁用并行写入来修复错误 429：请求过多
<a name="disable-parallel-puts"></a>

从版本 3.9.0 开始，Maven 会并行上传程序包构件（一次最多 5 个文件）。这会导致 CodeArtifact 偶尔使用错误响应代码 429（请求过多）进行响应。如果遇到此错误，可以禁用并行写入来修复错误。

要禁用并行写入，请在 `settings.xml` 文件的配置文件中将 `aether.connector.basic.parallelPut` 属性设置为 `false`，如以下示例所示：

```
<settings>
    <profiles>
        <profile>
            <id>default</id>
            <properties>
                <aether.connector.basic.parallelPut>false</aether.connector.basic.parallelPut>
            </properties>
        </profile>
    </profiles>
<settings>
```

有关更多信息，请参阅 Maven 文档中的[构件解析程序配置选项](https://maven.apache.org/resolver/configuration.html)。