

# Use Maven snapshots
<a name="maven-snapshots"></a>

 A Maven *snapshot* is a special version of a Maven package that refers to the latest production branch code. It is a development version that precedes the final release version. You can identify a snapshot version of a Maven package by the suffix `SNAPSHOT` that's appended to the package version. For example, the snapshot of version `1.1` is `1.1-SNAPSHOT`. For more information, see [What is a SNAPSHOT version?](https://maven.apache.org/guides/getting-started/index.html#What_is_a_SNAPSHOT_version) on the Apache Maven Project website. 

 AWS CodeArtifact supports publishing and consuming Maven snapshots. Unique snapshots that use a time-based version number are the only snapshots that are supported. CodeArtifact doesn't support non-unique snapshots that are generated by Maven 2 clients. You can publish a supported Maven snapshot to any CodeArtifact repository.

**Topics**
+ [Snapshot publishing in CodeArtifact](#maven-snapshot-publishing)
+ [Consuming snapshot versions](#maven-consuming-snapshot-versions)
+ [Deleting snapshot versions](#maven-deleting-snapshot-versions)
+ [Snapshot publishing with curl](#maven-snapshot-publishing-curl)
+ [Snapshots and external connections](#maven-snapshot-external-connections)
+ [Snapshots and upstream repositories](#maven-snapshot-upstream-repositories)

## Snapshot publishing in CodeArtifact
<a name="maven-snapshot-publishing"></a>

AWS CodeArtifact supports the request patterns that clients, such as `mvn`, use when publishing snapshots. Because of this, you can follow the documentation for your build tool or package manager without having a detailed understanding of how Maven snapshots are published. If you’re doing something more complex, this section describes in detail how CodeArtifact handles snapshots. 

 When a Maven snapshot is published to a CodeArtifact repository, its previous version is preserved in a new version called a build. Each time a Maven snapshot is published, a new build version is created. All previous versions of a snapshot are maintained in its build versions. When a Maven snapshot is published, its package version status is set to `Published` and the status of the build that contains the previous version is set to `Unlisted`. This behavior applies only to Maven package versions where the package version has `-SNAPSHOT` as a suffix. 

For example, snapshot versions of a maven package called `com.mycompany.myapp:pkg-1` are uploaded to a CodeArtifact repository called `my-maven-repo`. The snapshot version is `1.0-SNAPSHOT`. So far, no versions of `com.mycompany.myapp:pkg-1` have been published. First, the assets of the initial build are published at these paths:

```
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
```

Note that the timestamp `20210728.194552-1` is generated by the client publishing the snapshot builds.

After the .pom and .jar files are uploaded, the only version of `com.mycompany.myapp:pkg-1` that exists in the repository is `1.0-20210728.194552-1`. This happens even though the version specified in the preceding path is `1.0-SNAPSHOT`. The package version status at this point is `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"
}
```

Next, the client uploads the `maven-metadata.xml` file for the package version:

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

When the maven-metadata.xml file is uploaded successfully, CodeArtifact creates the `1.0-SNAPSHOT` package version and sets the `1.0-20210728.194552-1` version to `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"
}
```

At this point, the snapshot version `1.0-SNAPSHOT` can be consumed in a build. While there are two versions of `com.mycompany.myapp:pkg-1` in the repository `my-maven-repo`, they both contain the same assets.

```
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"
]
```

Running the same `list-package-version-assets` command as shown previously with the `--package-version` parameter changed to `1.0-20210728.194552-1` results in an identical output.

As additional builds of `1.0-SNAPSHOT` are added to the repository, a new `Unlisted` package version is created for each new build. The assets of the version `1.0-SNAPSHOT` are updated each time so that the version always refers to the latest build for that version. Updating the `1.0-SNAPSHOT` with the latest assets is initiated by uploading the `maven-metadata.xml` file for the new build. 

## Consuming snapshot versions
<a name="maven-consuming-snapshot-versions"></a>

If you request a snapshot, the version with the status `Published` is returned. This is always the most recent version of the Maven snapshot. You can also request a particular build of a snapshot using the build version number (for example, `1.0-20210728.194552-1`) instead of the snapshot version (for example, `1.0-SNAPSHOT`) in the URL path. To see the build versions of a Maven snapshot, use the [ListPackageVersions ](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_ListPackageVersions.html) API in the *CodeArtifact API Guide* and set the status parameter to `Unlisted`.

## Deleting snapshot versions
<a name="maven-deleting-snapshot-versions"></a>

To delete all build versions of a Maven snapshot, use the [DeletePackageVersions](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_DeletePackageVersions.html) API, specifying the versions that you want to delete.

## Snapshot publishing with curl
<a name="maven-snapshot-publishing-curl"></a>

If you have existing snapshot versions stored in Amazon Simple Storage Service (Amazon S3) or another artifact repository product, you may want to republish them to AWS CodeArtifact. Because of how CodeArtifact supports Maven snapshots (see [Snapshot publishing in CodeArtifact](#maven-snapshot-publishing)), publishing snapshots with a generic HTTP client such as `curl` is more complex than publishing Maven release versions as described in [Publishing with curl](maven-curl.md). Note that this section isn’t relevant if you’re building and deploying snapshot versions with a Maven client such as `mvn` or `gradle`. You need to follow the documentation for that client.

Publishing a snapshot version involves publishing one or more builds of a snapshot version. In CodeArtifact, if there are *n* builds of a snapshot version, there will be *n \$1 1* CodeArtifact versions: *n* build versions all with a status of `Unlisted`, and one snapshot version (the latest published build) with a status of `Published`. The snapshot version (that is, the version with a version string that contains “-SNAPSHOT”) contains an identical set of assets to the latest published build. The simplest way to create this structure using `curl` is as follows:

1. Publish all assets of all builds using `curl`. 

1. Publish the `maven-metadata.xml` file of the last build (that is, the build with the most-recent date-time stamp) with `curl`. This will create a version with “`-SNAPSHOT`” in the version string and with the correct set of assets.

1. Use the [UpdatePackageVersionsStatus](https://docs.aws.amazon.com/codeartifact/latest/APIReference/API_UpdatePackageVersionsStatus.html) API to set the status of all the non-latest build versions to `Unlisted`. 

 Use the following `curl` commands to publish snapshot assets (such as .jar and .pom files) for the snapshot version `1.0-SNAPSHOT` of a package `com.mycompany.app:pkg-1`: 

```
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
```

When using these examples:
+ Replace *my\$1domain* with your CodeArtifact domain name.
+ Replace *111122223333* with the AWS account ID of the owner of your CodeArtifact domain.
+ Replace *us-west-2* with the AWS Region in which your CodeArtifact domain is located.
+ Replace *my\$1maven\$1repo* with your CodeArtifact repository name.

**Important**  
You must prefix the value of the `--data-binary` parameter with the `@` character. When putting the value in quotation marks, the `@` must be included inside the quotation marks.

You may have more than two assets to upload for each build. For example, there might be Javadoc and source JAR files in addition to the main JAR and `pom.xml`. It is not necessary to publish checksum files for the package version assets because CodeArtifact automatically generates checksums for each uploaded asset. To verify the assets were uploaded correctly, fetch the generated checksums using the `list-package-version-assets` command and compare those to the original checksums. For more information about how CodeArtifact handles Maven checksums, see [Use Maven checksums](maven-checksums.md).

Use the following curl command to publish the `maven-metadata.xml` file for the latest build version:

```
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
```

The `maven-metadata.xml` file must reference at least one of the assets in the latest build version in the `<snapshotVersions>` element. In addition, the `<timestamp>` value must be present and must match the timestamp in the asset file names. For example, for the `20210729.171330-2` build published previously, the contents of `maven-metadata.xml` would be: 

```
<?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>
```

After `maven-metadata.xml` has been published, the last step is to set all the other build versions (that is, all the build versions apart from the latest build) to have a package version status of `Unlisted`. For example, if the `1.0-SNAPSHOT` version has two builds, with the first build being `20210728.194552-1`, the command to set that build to `Unlisted` is:

```
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
```

## Snapshots and external connections
<a name="maven-snapshot-external-connections"></a>

Maven snapshots cannot be fetched from a Maven public repository through an external connection. AWS CodeArtifact only supports importing Maven release versions.

## Snapshots and upstream repositories
<a name="maven-snapshot-upstream-repositories"></a>

In general, Maven snapshots work in the same way as Maven release versions when used with upstream repositories, but there is a limitation if you plan on publishing snapshots of the same package version to two repositories which have an upstream relationship. For example, say that there are two repositories in an AWS CodeArtifact domain, `R` and `U`, where `U` is an upstream of `R`. If you publish a new build in `R`, when a Maven client requests the latest build of that snapshot version, CodeArtifact returns the latest version from `U`. This can be unexpected since the latest version is now in `R`, not `U`. There are two ways to avoid this:

1. Don't publish builds of a snapshot version such as `1.0-SNAPSHOT` in `R`, if `1.0-SNAPSHOT` exists in `U`.

1. Use CodeArtifact package origin controls to disable upstreams on that package in `R`. The latter will allow you to publish builds of`1.0-SNAPSHOT` in `R`, but it will also prevent `R` from getting any other versions of that package from `U` that aren't already retained.