

# Working with package groups in CodeArtifact
<a name="package-groups"></a>

*Package groups* can be used to apply configuration to multiple packages that match a defined pattern using package format, package namespace, and package name. You can use package groups to more conveniently configure package origin controls for multiple packages. Package origin controls are used to block or allow ingestion or publishing of new package versions, which protects users from malicious actions known as dependency substitution attacks.

Every domain in CodeArtifact automatically contains a root package group. This root package group, `/*`, contains all packages, and allows package versions to enter repositories in the domain from all origin types by default. The root package group can be modified, but cannot be deleted.

The Package Group Configuration feature operates in an eventually consistent manner when creating a new package group or deleting an existing package group. This means that upon creating or deleting a package group, the origin controls will be applied to the expected associated packages, but with some delay due to the eventual consistent behavior. The time to reach eventual consistency depends on the number of package groups in the domain as well as the number of packages in the domain. There may be a brief period where the origin controls are not immediately reflected on the associated packages after a package group creation or deletion.

Additionally, updates to package group origin controls are effective almost immediately. Unlike the creation or deletion of package groups, changes to the origin controls of an existing package group are reflected on the associated packages without the same delay.

These topics contain information about package groups in AWS CodeArtifact.

**Topics**
+ [Create a package group](create-package-group.md)
+ [View or edit a package group](view-edit-package-group.md)
+ [Delete a package group](delete-package-group.md)
+ [Package group origin controls](package-group-origin-controls.md)
+ [Package group definition syntax and matching behavior](package-group-definition-syntax-matching-behavior.md)
+ [Tag a package group](package-group-tags.md)

# Create a package group
<a name="create-package-group"></a>

You can create a package group using the CodeArtifact console, the AWS Command Line Interface (AWS CLI), or CloudFormation. For more information about managing CodeArtifact package groups with CloudFormation, see [Creating CodeArtifact resources with AWS CloudFormation](cloudformation-codeartifact.md). 

## Create a package group (console)
<a name="create-package-group-console"></a>

1. Open the AWS CodeArtifact console at [https://console.aws.amazon.com/codesuite/codeartifact/home](https://console.aws.amazon.com/codesuite/codeartifact/home).

1. In the navigation pane, choose **Domains**, and then choose the domain in which you want to create a package group.

1. Choose **Package groups**, and choose **Create package group**.

1. In **Package group definition**, enter the package group definition for your package group. The package group definition determines which packages are associated with the group. You can enter the package group definition manually with text, or you can use the visual mode to make selections and the package group definition will be created automatically.

1. To use the visual mode to create the package group definition:

   1. Choose **Visual** to switch to the visual mode..

   1. In **Package format**, choose the format of the packages to be associated with this group.

   1. In **Namespace (Scope)**, choose the namespace criteria to match on.
      + **Equals**: Match the specified namespace exactly. If chosen, enter the namespace to match on.
      + **Blank**: Match packages with no namespace.
      + **Starts with word**: Match namespaces that begin with a specified word. If chosen, enter the prefix word to match on. For more information about words and word boundaries, see [Words, word boundaries, and prefix matching](package-group-definition-syntax-matching-behavior.md#package-group-word-boundary-prefix).
      + **All**: Match packages in all namespaces.

   1. If **Equals**, **Blank**, or **Starts with word** is selected, in **Package name**, choose the package name criteria to match on.
      + **Exactly equals**: Match the specified package name exactly. If chosen, enter the package name to match on.
      + **Starts with prefix**: Match packages that start with the specified prefix.
      + **Starts with word**: Match packages that begin with a specified word. If chosen, enter the prefix word to match on. For more information about words and word boundaries, see [Words, word boundaries, and prefix matching](package-group-definition-syntax-matching-behavior.md#package-group-word-boundary-prefix).
      + **All**: Match all packages.

   1. Choose **Next** to review the definition.

1. To enter the package group definition with text:

   1. Choose **Text** to switch to the text mode.

   1. In **Package group definition**, enter the package group definition. For more information about package group definition syntax, see [Package group definition syntax and matching behavior](package-group-definition-syntax-matching-behavior.md).

   1. Choose **Next** to review the definition.

1. In **Review definition**, review the packages that will be included in the new package group based on the definition provided previously. After reviewing, choose **Next**.

1. In **Package group information**, optionally add a description and contact email for the package group. Choose **Next**.

1. In **Package origin controls**, configure the origin controls to be applied to the packages in the group. For more information about package group origin controls, see [Package group origin controls](package-group-origin-controls.md).

1. Choose **Create package group**.

## Create a package group (AWS CLI)
<a name="create-package-group-cli"></a>

Use the `create-package-group` command to create a package group in your domain. For the `--package-group` option, enter the package group definition that determines which packages are associated with the group. For more information about package group definition syntax, see [Package group definition syntax and matching behavior](package-group-definition-syntax-matching-behavior.md).

If you haven't, configure the AWS CLI by following the steps in [Setting up with AWS CodeArtifact](get-set-up-for-codeartifact.md).

```
aws codeartifact create-package-group \
         --domain my_domain \
         --package-group '/nuget/*' \
         --domain-owner 111122223333 \
         --contact-info contact@email.com \
         --description "a new package group" \
         --tags key=key1,value=value1
```

# View or edit a package group
<a name="view-edit-package-group"></a>

You can view a list of all package groups, view details of a specific package group, or edit a package group's details or configuration using the CodeArtifact console or the AWS Command Line Interface (AWS CLI). 

## View or edit a package group (console)
<a name="view-edit-package-group-console"></a>

1. Open the AWS CodeArtifact console at [https://console.aws.amazon.com/codesuite/codeartifact/home](https://console.aws.amazon.com/codesuite/codeartifact/home).

1. In the navigation pane, choose **Domains**, and then choose the domain that contains the package group you want to view or edit.

1. Choose **Package groups**, and choose the package group you want to view or edit.

1. In **Details**, view information about the package group including its parent group, description, ARN, contact email, and package origin controls.

1. In **Subgroups**, view a list of package groups that have this group as a parent group. The package groups in this list can inherit settings from this package group. For more information, see [Package group hierarchy and pattern specificity](package-group-definition-syntax-matching-behavior.md#package-group-hierarchy-pattern-specificity).

1. In **Packages**, view the packages that belong to this package group based on the package group definition. In the **Strength** column, you can see the strength of the package association. For more information, see [Package group hierarchy and pattern specificity](package-group-definition-syntax-matching-behavior.md#package-group-hierarchy-pattern-specificity).

1. To edit package group information, choose **Edit package group**.

   1. In **Information**, update the package group's description or contact information. You cannot edit a package group's definition.

   1. In **Package group origin controls**, update the package group's origin control settings, which determine how associated packages can enter repositories in the domain. For more information, see [Package group origin controls](package-group-origin-controls.md).

## View or edit a package group (AWS CLI)
<a name="view-edit-package-group-cli"></a>

Use the following commands to view or edit package groups with the AWS CLI. If you haven't, configure the AWS CLI by following the steps in [Setting up with AWS CodeArtifact](get-set-up-for-codeartifact.md).

To view all package groups in a domain, use the `list-package-groups` command.

```
aws codeartifact list-package-groups \
         --domain my_domain \
         --domain-owner 111122223333
```

To view details about a package group, use the `describe-package-group` command. For more information about package group definitions, see [Package group definition syntax and examples](package-group-definition-syntax-matching-behavior.md#package-group-definition-syntax-examples).

```
aws codeartifact describe-package-group \
         --domain my_domain \
         --domain-owner 111122223333 \
         --package-group '/nuget/*'
```

To view the child package groups of a package group, use the `list-sub-package-groups` command.

```
aws codeartifact list-sub-package-groups \
         --domain my_domain \
         --domain-owner 111122223333 \
         --package-group '/nuget/*' \
```

To view the package group that is associated to a package, use the `get-associated-package-group` command. You must use the normalized package name and namespace for the NuGet, Python, and Swift package formats. For more information about how the package names and namespaces are normalized, see the [NuGet](nuget-name-normalization.md), [Python](python-name-normalization.md), and [Swift](swift-name-normalization.md) name normalization documentation. 

```
aws codeartifact get-associated-package-group \
         --domain my_domain \
         --domain-owner 111122223333 \
         --format npm \
         --package packageName \
         --namespace scope
```

To edit a package group, use the `update-package-group` command. This command is used to update a package group's contact information or description. For information about package group origin control settings, and adding or editing them, see [Package group origin controls](package-group-origin-controls.md). For more information about package group definitions, see [Package group definition syntax and examples](package-group-definition-syntax-matching-behavior.md#package-group-definition-syntax-examples)

```
aws codeartifact update-package-group \
         --domain my_domain \
         --package-group '/nuget/*' \
         --domain-owner 111122223333 \
         --contact-info contact@email.com \
         --description "updated package group description"
```

# Delete a package group
<a name="delete-package-group"></a>

You can delete a package group using the CodeArtifact console or the AWS Command Line Interface (AWS CLI).

Note the following behavior when deleting package groups:
+ The root package group, `/*`, cannot be deleted.
+ The packages and package versions that are associated with that package group are not deleted.
+ When a package group is deleted, the direct child package groups will become children of the package group's direct parent package group. Therefore, if any of the child groups are inheriting any settings from the parent, those settings could change.

## Delete a package group (console)
<a name="delete-package-group-console"></a>

1. Open the AWS CodeArtifact console at [https://console.aws.amazon.com/codesuite/codeartifact/home](https://console.aws.amazon.com/codesuite/codeartifact/home).

1. In the navigation pane, choose **Domains**, and then choose the domain that contains the package group you want to view or edit.

1. Choose **Package groups**.

1. Choose the package group you want to delete and choose **Delete**.

1. Enter delete in the field and choose **Delete**.

## Delete a package group (AWS CLI)
<a name="delete-package-group-cli"></a>

To delete a package group, use the `delete-package-group` command.

```
aws codeartifact delete-package-group \
         --domain my_domain \
         --domain-owner 111122223333 \
         --package-group '/nuget/*'
```

# Package group origin controls
<a name="package-group-origin-controls"></a>

Package origin controls are used to configure how package versions can enter a domain. You can set up origin controls on a package group to configure how versions of every package associated with the package group can enter specified repositories in the domain.

Package group origin control settings consist of the following:
+ [Restriction settings](#package-group-origin-control-settings-restrictions): These settings define if packages can enter a repository in CodeArtifact from publishing, internal upstreams, or external, public repositories.
+ [Allowed repository lists](#package-group-origin-control-settings-repositories): Each restriction setting can be set to allow specific repositories. If a restriction setting is set to allow specific repositories, that restriction will have a corresponding allowed repository list.

**Note**  
Origin control settings for package groups are slightly different than the origin control settings for individual packages. For more information about origin control settings for packages, see [Package origin control settings](package-origin-controls.md#package-origin-control-settings).

## Restriction settings
<a name="package-group-origin-control-settings-restrictions"></a>

The restriction settings of a package group's origin control settings determine how the packages associated with that group can enter repositories in the domain.

### PUBLISH
<a name="package-group-origin-control-settings-restrictions-publish"></a>

The `PUBLISH` setting configures whether package versions can be published directly to any repository in the domain using package managers or similar tools.
+ **ALLOW**: Package versions can be published directly to all repositories.
+ **BLOCK**: Package versions cannot be published directly to any repository.
+ **ALLOW\$1SPECIFIC\$1REPOSITORIES**: Package versions can only be published directly to repositories specified in the allowed repository list for publishing.
+ **INHERIT**: The `PUBLISH` setting is inherited from the first parent package group with a setting that is not `INHERIT`.

### EXTERNAL\$1UPSTREAM
<a name="package-group-origin-control-settings-restrictions-ext-upstream"></a>

The `EXTERNAL_UPSTREAM` setting configures whether package versions can be ingested from external, public repositories when requested by a package manager. For a list of supported external repositories, see [Supported external connection repositories](external-connection.md#supported-public-repositories).
+ **ALLOW**: Any package version can be ingested into all repositories from a public source with an external connection.
+ **BLOCK**: Package versions cannot be ingested into any repository from a public source with an external connection.
+ **ALLOW\$1SPECIFIC\$1REPOSITORIES**: Package versions can only be ingested from a public source into repositories specified in the allowed repository list for external upstreams.
+ **INHERIT**: The `EXTERNAL_UPSTREAM` setting is inherited from the first parent package group with a setting that is not `INHERIT`.

### INTERNAL\$1UPSTREAM
<a name="package-group-origin-control-settings-restrictions-int-upstream"></a>

The `INTERNAL_UPSTREAM` setting configures whether package versions can be retained from internal upstream repositories in the same CodeArtifact domain when requested by a package manager.
+ **ALLOW**: Any package version can be retained from other CodeArtifact repositories configured as upstream repositories.
+ **BLOCK**: Package versions cannot be retained from other CodeArtifact repositories configured as upstream repositories.
+ **ALLOW\$1SPECIFIC\$1REPOSITORIES**: Package versions can only be retained from other CodeArtifact respositories configured as upstream repositories into repositories specified in the allowed repository list for internal upstreams.
+ **INHERIT**: The `INTERNAL_UPSTREAM` setting is inherited from the first parent package group with a setting that is not `INHERIT`.

## Allowed repository lists
<a name="package-group-origin-control-settings-repositories"></a>

When a restriction setting is configured as `ALLOW_SPECIFIC_REPOSITORIES`, the package group contains an accompanying allowed repositories list which contains a list of repositories allowed for that restriction setting. Therefore, a package group contains anywhere from 0 to 3 allowed repository lists, one for each setting configured as `ALLOW_SPECIFIC_REPOSITORIES`.

When you add a repository to a package group's allowed repository list, you must specify which allowed repository list to add it to.

The possible allowed repository lists are as follows:
+ `EXTERNAL_UPSTREAM`: Allow or block ingestion of package versions from external repositories in the added repository.
+ `INTERNAL_UPSTREAM`: Allow or block pulling package versions from another CodeArtifact repository in the added repository.
+ `PUBLISH`: Allow or block direct publishing of package versions from package managers to the added repository.

## Editing package group origin control settings
<a name="package-group-edit-origin-controls"></a>

To add or edit origin controls for a package group, perform the steps in the following procedure. For information about the package group origin control settings, see [Restriction settings](#package-group-origin-control-settings-restrictions) and [Allowed repository lists](#package-group-origin-control-settings-repositories).

**To add or edit package group origin controls (CLI)**

1. If you haven't, configure the AWS CLI by following the steps in [Setting up with AWS CodeArtifact](get-set-up-for-codeartifact.md).

1. Use the `update-package-group-origin-configuration` command to add or edit package origin controls.
   + For `--domain`, enter the CodeArtifact domain that contains the package group you want to update.
   + For `--domain-owner`, enter the account number of the owner of the domain.
   + For `--package-group`, enter the package group you want to update.
   + For `--restrictions`, enter key-value pairs that represent the origin control restrictions.
   + For `--add-allowed-repositories`, enter a JSON object containing the restriction type and repository name to add to the corresponding allowed repositories list for the restriction.
   + For `--remove-allowed-repositories`, enter a JSON object containing the restriction type and repository name to remove from the corresponding allowed repositories list for the restriction.

   ```
   aws codeartifact update-package-group-origin-configuration \
      --domain my_domain \
      --domain-owner 111122223333 \
      --package-group '/nuget/*' \
      --restrictions INTERNAL_UPSTREAM=ALLOW_SPECIFIC_REPOSITORIES \
      --add-allowed-repositories originRestrictionType=INTERNAL_UPSTREAM,repositoryName=my_repo \
      --remove-allowed-repositories originRestrictionType=INTERNAL_UPSTREAM,repositoryName=my_repo2
   ```

   The following example adds multiple restrictions, and multiple repositories in one command.

   ```
   aws codeartifact update-package-group-origin-configuration \
      --domain my_domain \
      --domain-owner 111122223333 \
      --package-group '/nuget/*' \
      --restrictions PUBLISH=BLOCK,EXTERNAL_UPSTREAM=ALLOW_SPECIFIC_REPOSITORIES,INTERNAL_UPSTREAM=ALLOW_SPECIFIC_REPOSITORIES \
      --add-allowed-repositories originRestrictionType=INTERNAL_UPSTREAM,repositoryName=my_repo originRestrictionType=INTERNAL_UPSTREAM,repositoryName=my_repo2 \
      --remove-allowed-repositories originRestrictionType=INTERNAL_UPSTREAM,repositoryName=my_repo2
   ```

## Package group origin control configuration examples
<a name="package-group-origin-control-examples"></a>

The following examples show package origin control configurations for common package management scenarios.

### Allowing packages with private names to be published, but not ingested
<a name="package-group-origin-control-examples-one"></a>

This scenario is likely a common scenario in package management:
+ Allow packages with private names to be published to repositories in your domain from package managers, and block them from being ingested to repositories in your domain from external, public repositories.
+ Allow all other packages to be ingested to repositories in your domain from external, public repositories, and block them from being published to repositories in your domain from package managers.

To achieve this, you should configure a package group with a pattern that includes the private name(s), and origin settings of **PUBLISH: ALLOW**, **EXTERNAL\$1UPSTREAM: BLOCK**, and **INTERNAL\$1UPSTREAM: ALLOW**. This will ensure packages with private names can be published directly, but cannot be ingested from external repositories.

The following AWS CLI commands create and configure a package group with origin restriction settings that match the desired behavior:

To create the package group:

```
aws codeartifact create-package-group \
   --domain my_domain \
   --package-group /npm/space/anycompany~ \
   --domain-owner 111122223333 \
   --contact-info contact@email.com | URL \
   --description "my package group"
```

To update the package group's origin configuration:

```
aws codeartifact update-package-group-origin-configuration \
   --domain my_domain \
   --domain-owner 111122223333 \
   --package-group '/npm/space/anycompany~' \
   --restrictions PUBLISH=ALLOW,EXTERNAL_UPSTREAM=BLOCK,INTERNAL_UPSTREAM=ALLOW
```

### Allowing ingestion from external repositories through one repository
<a name="package-group-origin-control-examples-ingestion-one-repo"></a>

In this scenario, your domain has multiple repositories. Of those repositories, `repoA` has an upstream connection to `repoB`, which has an external connection to the public repository, `npmjs.com`, as shown:

`repoA --> repoB --> npmjs.com`

You want to allow ingestion of packages from a specific package group, `/npm/space/anycompany~` from `npmjs.com` into `repoA`, but only through `repoB`. You also want to block ingestion of packages associated with the package group into any other repositories in your domain, and block direct publishing of packages with package managers. To achieve this, you create and configure the package group as follows:

Origin restriction settings of **PUBLISH: BLOCK**, and **EXTERNAL\$1UPSTREAM: ALLOW\$1SPECIFIC\$1REPOSITORIES**, and **INTERNAL\$1UPSTREAM: ALLOW\$1SPECIFIC\$1REPOSITORIES**.

`repoA` and `repoB` added to the appropriate allowed repository list:
+ `repoA` should be added to the `INTERNAL_UPSTREAM` list, as it will get packages from its internal upstream, `repoB`.
+ `repoB` should be added to the `EXTERNAL_UPSTREAM` list, as it will get packages from the external repository, `npmjs.com`.

The following AWS CLI commands create and configure a package group with origin restriction settings that match the desired behavior:

To create the package group:

```
aws codeartifact create-package-group \
   --domain my_domain \
   --package-group /npm/space/anycompany~ \
   --domain-owner 111122223333 \
   --contact-info contact@email.com | URL \
   --description "my package group"
```

To update the package group's origin configuration:

```
aws codeartifact update-package-group-origin-configuration \
   --domain my_domain \
   --domain-owner 111122223333 \
   --package-group /npm/space/anycompany~ \
   --restrictions PUBLISH=BLOCK,EXTERNAL_UPSTREAM=ALLOW_SPECIFIC_REPOSITORIES,INTERNAL_UPSTREAM=ALLOW_SPECIFIC_REPOSITORIES \
   --add-allowed-repositories originRestrictionType=INTERNAL_UPSTREAM,repositoryName=repoA originRestrictionType=EXTERNAL_UPSTREAM,repositoryName=repoB
```

## How package group origin control settings interact with package origin control settings
<a name="package-group-origin-control-settings-interaction"></a>

Because packages have origin control settings, and their associated package groups have origin control settings, it's important to understand how those two different settings interact with one another. For information about the interaction between the settings, see [How package origin controls interact with package group origin controls](package-origin-controls.md#package-origin-controls-interaction-package-groups).

# Package group definition syntax and matching behavior
<a name="package-group-definition-syntax-matching-behavior"></a>

This topic contains information about defining package groups, pattern matching behavior, package association strength, and package group hierarchy.

**Contents**
+ [Package group definition syntax and examples](#package-group-definition-syntax-examples)
  + [Package group definition and normalization](#package-group-definition-syntax-examples-normalization)
  + [Namespaces in package group definitions](#package-group-definition-syntax-examples-namespaces)
+ [Package group hierarchy and pattern specificity](#package-group-hierarchy-pattern-specificity)
+ [Words, word boundaries, and prefix matching](#package-group-word-boundary-prefix)
+ [Case sensitivity](#package-group-case-sensitivity)
+ [Strong and weak match](#package-group-strong-and-weak-match)
+ [Additional variations](#package-group-additional-variations)

## Package group definition syntax and examples
<a name="package-group-definition-syntax-examples"></a>

 The pattern syntax for defining package groups closely follows the formatting of package paths. A package path is created from a package's coordinate components (format, namespace, and name) by adding a forward slash to the start and separating each of the components with a forward slash. For example, the package path for the npm package named *anycompany-ui-components* in the namespace *space* is */npm/space/anycompany-ui-components*.

A package group pattern follows the same structure as a package path, except components that are not specified as part of the group definition are omitted, and the pattern is terminated with a suffix. The suffix that is included determines the matching behavior of the pattern, as follows:
+ A `$` suffix will match the full package coordinate.
+ A `~` suffix will match a prefix.
+ A `*` suffix will match all values of the previously defined component.

Here are example patterns for each of the allowed combinations:

1. All package formats: `/*`

1. A specific package format: `/npm/*`

1. Package format and namespace prefix: `/maven/com.anycompany~`

1. Package format and namespace: `/npm/space/*`

1. Package format, namespace, and name prefix: `/npm/space/anycompany-ui~`

1. Package format, namespace, and name: `/maven/org.apache.logging.log4j/log4j-core$`

As shown in the examples above, the `~` suffix is added to the end of a namespace or name to represent a prefix match and `*` comes after a forward slash when used to match all values for the next component in the path (either all formats, all namespaces, or all names).

### Package group definition and normalization
<a name="package-group-definition-syntax-examples-normalization"></a>

CodeArtifact normalizes NuGet, Python, and Swift package names, and normalizes Swift package namespaces before storing them. CodeArtifact uses these normalized names when matching packages with package group definitions. Therefore, package groups that contain a namespace or name in these formats must use the normalized namespace and name. For more information about how the package names and namespaces are normalized, see the [NuGet](nuget-name-normalization.md), [Python](python-name-normalization.md), and [Swift](swift-name-normalization.md) name normalization documentation.

### Namespaces in package group definitions
<a name="package-group-definition-syntax-examples-namespaces"></a>

For packages or package formats without a namespace (Python and NuGet), package groups must not contain a namespace. The package group definition for these package groups contain a blank namespace section. For example, the path for the Python package named *requests* is */python//requests*.

For packages or package formats with a namespace (Maven, generic, and Swift), the namespace must be included if the package name is included. For the Swift package format, the normalized package namespace will be used. For more information about how Swift package namespaces are normalized, see [Swift package name and namespace normalization](swift-name-normalization.md).

## Package group hierarchy and pattern specificity
<a name="package-group-hierarchy-pattern-specificity"></a>

The packages that are “in” or “associated with” a package group are packages with a package path that matches the group’s pattern but do not match a more specific group’s pattern. For example, given the package groups `/npm/*` and `/npm/space/*`, the package path */npm//react* is associated with the first group (`/npm/*`) while */npm/space/aui.components* and */npm/space/amplify-ui-core* are associated with the second group (`/npm/space/*`). Even though a package may match multiple groups, each package is only associated with a single group, the most specific match, and only that one group’s configuration applies to the package.

When a package path matches multiple patterns, the “more specific” pattern can be thought of as the longest matching pattern. Alternatively, the more specific pattern is the one that matches a proper subset of the packages that match the less specific pattern. From our earlier example, every package that matches `/npm/space/*` also matches `/npm/*`, but the reverse is not true, which makes `/npm/space/*` the more specific pattern because it is a proper subset of `/npm/*`. Because one group is a subset of another group, it creates a hierarchy, in which `/npm/space/*` is a subgroup of the parent group, `/npm/*`.

Though only the most specific package group’s configuration applies to a package, that group may be configured to inherit from its parent group’s configuration.

## Words, word boundaries, and prefix matching
<a name="package-group-word-boundary-prefix"></a>

Before discussing prefix matching, let's define some key terms:
+ A *word* a letter or number followed by zero or more letters, numbers, or mark characters (such as accents, umlauts, etc.).
+ A *word boundary* is at the end of a word, when a non-word character is reached. Non-word characters are punctuation characters such as `.`, `-`, and `_`.

Specifically, the regex pattern for a word is `[\p{L}\p{N}][\p{L}\p{N}\p{M}]*`, which can be broken down as follows:
+ `\p{L}` represents any letter.
+ `\p{N}` represents any number.
+ `\p{M}` represents any mark character, such as accents, umlauts, etc.

Therefore, `[\p{L}\p{N}]` represents a number or letter, and `[\p{L}\p{N}\p{M}]*` represents zero or more letters, numbers, or mark characters and a word boundary is at the end of each match of this regex pattern.

**Note**  
Word boundary matching is based on this definition of a “word”. It is not based on words defined in a dictionary, or CameCase. For example, there is no word boundary in `oneword` or `OneWord`.

Now that word and word boundary are defined, we can use them to describe prefix matching in CodeArtifact. To indicate a prefix match on a word boundary, a match character (`~`) is used after a word character. For example, the pattern `/npm/space/foo~` matches the package paths `/npm/space/foo` and `/npm/space/foo-bar`, but not `/npm/space/food` or `/npm/space/foot`.

A wildcard (`*`) is required to be used instead of `~` when following a non-word character, such as in the pattern `/npm/*`.

## Case sensitivity
<a name="package-group-case-sensitivity"></a>

Package group definitions are case sensitive, which means that patterns that differ only by case can exist as separate package groups. For example, a user can create separate package groups with the patterns `/npm//AsyncStorage$`, `/npm//asyncStorage$`, and `/npm//asyncstorage$` for the three separate packages that exist on the npm Public Registry: *AsyncStorage*, *asyncStorage*, *asyncstorage* that differ only by case. 

While case matters, CodeArtifact still associates packages to a package group if the package has a variation of the pattern that differs by case. If a user creates the `/npm//AsyncStorage$` package group without creating the other two groups shown above, then all case variations of the name *AsyncStorage*, including *asyncStorage* and *asyncstorage*, will be associated with the package group. But, as described in the next section, [Strong and weak match](#package-group-strong-and-weak-match), these variations will be handled differently than *AsyncStorage*, which exactly matches the pattern. 

## Strong and weak match
<a name="package-group-strong-and-weak-match"></a>

The information in the previous section, [Case sensitivity](#package-group-case-sensitivity), states that package groups are case sensitive, and then goes on to explain they are case insensitive. This is because package group definitions in CodeArtifact have a concept of strong match (or exact match) and a weak match (or variation match). A strong match is when the package matches the pattern exactly, without any variation. A weak match is when the package matches a variation of the pattern, such as different letter case. Weak match behavior prevents packages that are variations of a package group’s pattern from rolling up to a more general package group. When a package is a variation (weak match) of the most specific matching group’s pattern, then the package is associated with the group but the package is blocked instead of applying the group’s origin control configuration, preventing any new versions of the package from being pulled from upstreams or published. This behavior reduces the risk of supply chain attacks resulting from dependency confusion of packages with nearly identical names.

To illustrate weak match behavior, suppose package group `/npm/*` allows ingestion and blocks publishing. A more specific package group, `/npm//anycompany-spicy-client$`, is configured to block ingestion and allow publish. The package named *anycompany-spicy-client* is a strong match of the package group, which allows package versions to be published and blocks ingestion of package versions. The only casing of the package name that is allowed to be published is *anycompany-spicy-client*, since it is a strong match for the package definition pattern. A different case variation, such as *AnyCompany-spicy-client* is blocked from publishing because it is a weak match. More importantly, the package group blocks ingestion of all case variations, not just the lowercase name used in the pattern, reducing the risk of a dependency confusion attack.

## Additional variations
<a name="package-group-additional-variations"></a>

In addition to case differences, weak matching also ignores differences in sequences of dash `-`, dot `.`, underscore `_`, and confusable characters (such as similar looking characters from separate alphabets). During normalization used for weak matching, CodeArtifact performs casefolding (similar to converting to lowercase), replaces sequences of dash, dot, and underscore characters with a single dot, and normalizes confusable characters.

Weak matching treats dashes, dots, and underscores as equivalent but does not completely ignore them. This means that *foo-bar*, *foo.bar*, *foo..bar*, and *foo\$1bar* are all weak match equivalents, but *foobar* is not. Although several public repositories implement steps to prevent these types of varations, the protection provided by public repositories does not make this feature of package groups unnecessary. For example, public repositories such as the npm Public Registry registry will only prevent new variations of the package named *my-package* if *my-package* is already published to it. If *my-package* is an internal package and package group `/npm//my-package$` is created that allows publish and blocks ingestion, you likely don't want to publish *my-package* to the npm Public Registry in order to prevent a variant such as *my.package* from being allowed.

While some package formats such as Maven treat these characters differently (Maven treats `.` as a namespace hierarchy separator but not `-` or `_`), something like *com.act-on* could still be confused with *com.act.on*.

**Note**  
Note that whenever multiple variations are associated with a package group, an administrator may create a new package group for a specific variation to configure different behavior for that variation. 

# Tag a package group in CodeArtifact
<a name="package-group-tags"></a>

Tags are key-value pairs associated with AWS resources. You can apply tags to your package groups in CodeArtifact. For information about CodeArtifact resource tagging, use cases, tag key and value constraints, and supported resource types, see [Tagging resources](tag-resources.md).

You can use the CLI to specify tags when you create a package group or add, remove, or update the value of tags of an existing package group.

## Tag package groups (CLI)
<a name="package-group-tags-cli"></a>

You can use the CLI to manage package group tags.

If you haven't, configure the AWS CLI by following the steps in [Setting up with AWS CodeArtifact](get-set-up-for-codeartifact.md).

**Tip**  
To add tags, you must provide the Amazon Resource Name (ARN) of the package group. To get the ARN of the package group, run the `describe-package-group` command:  

```
aws codeartifact describe-package-group \
   --domain my_domain \
   --package-group /npm/scope/anycompany~ \
   --query packageGroup.arn
```

**Topics**
+ [Add tags to a package group (CLI)](#package-group-tags-add-cli)
+ [View tags for a package group (CLI)](#package-group-tags-list-cli)
+ [Edit tags for a package group (CLI)](#package-group-tags-edit-cli)
+ [Remove tags from a package group (CLI)](#package-group-tags-delete-cli)

### Add tags to a package group (CLI)
<a name="package-group-tags-add-cli"></a>

You can add tags to package groups when they are created, or to an existing package group. For information about adding tags to a package group when you create it, see [Create a package group](create-package-group.md).

To add a tag to an existing package group with the AWS CLI, at the terminal or command line, run the **tag-resource** command, specifying the Amazon Resource Name (ARN) of the package group where you want to add tags and the key and value of the tag you want to add. For information about package group ARNs, see [Package group ARNs](auth-and-access-control-permissions-reference.md#package-group-arns).

You can add more than one tag to a package group. For example, to tag a package group, */npm/scope/anycompany\$1* with two tags, a tag key named *key1* with the tag value of *value1*, and a tag key named *key2* with the tag value of *value2*:

```
aws codeartifact tag-resource \
   --resource-arn arn:aws:codeartifact:us-west-2:123456789012:package-group/my_domain/npm/scope/anycompany~ \
   --tags key=key1,value=value1 key=key2,value=value2
```

If successful, this command has no output.

### View tags for a package group (CLI)
<a name="package-group-tags-list-cli"></a>

Follow these steps to use the AWS CLI to view the AWS tags for a package group. If no tags have been added, the returned list is empty.

At the terminal or command line, run the **list-tags-for-resource** command with the Amazon Resource Name (ARN) of the package group. For information about package group ARNs, see [Package group ARNs](auth-and-access-control-permissions-reference.md#package-group-arns).

For example, to view a list of tag keys and tag values for a package group, */npm/scope/anycompany\$1* named with an ARN value of `arn:aws:codeartifact:us-west-2:123456789012:package-group/my_domain/npm/scope/anycompany~`

```
aws codeartifact list-tags-for-resource \
   --resource-arn arn:aws:codeartifact:us-west-2:123456789012:package-group/my_domain/npm/scope/anycompany~
```

If successful, this command returns information similar to the following:

```
{
    "tags": {
        "key1": "value1",
        "key2": "value2"
    }
}
```

### Edit tags for a package group (CLI)
<a name="package-group-tags-edit-cli"></a>

Follow these steps to use the AWS CLI to edit a tag for a package group. You can change the value for an existing key or add another key. You can also remove tags from a package group, as shown in the next section.

At the terminal or command line, run the **tag-resource** command, specifying the ARN of the package group where you want to update a tag and specify the tag key and tag value. For information about package group ARNs, see [Package group ARNs](auth-and-access-control-permissions-reference.md#package-group-arns).

```
aws codeartifact tag-resource \
   --resource-arn arn:aws:codeartifact:us-west-2:123456789012:package-group/my_domain/npm/scope/anycompany~ \
   --tags key=key1,value=newvalue1
```

If successful, this command has no output.

### Remove tags from a package group (CLI)
<a name="package-group-tags-delete-cli"></a>

Follow these steps to use the AWS CLI to remove a tag from a package group.

**Note**  
If you delete a package group, all tag associations are removed from the deleted package group. You do not have to remove tags before you delete a package group.

At the terminal or command line, run the **untag-resource** command, specifying the ARN of the package group where you want to remove tags and the tag key of the tag you want to remove. For information about package group ARNs, see [Package group ARNs](auth-and-access-control-permissions-reference.md#package-group-arns).

For example, to remove multiple tags on a package group, */npm/scope/anycompany\$1*, with the tag keys *key1* and *key2*:

```
aws codeartifact untag-resource \
   --resource-arn arn:aws:codeartifact:us-west-2:123456789012:package-group/my_domain/npm/scope/anycompany~ \
   --tag-keys key1 key2
```

If successful, this command has no output. After removing tags, you can view the remaining tags on the package group using the `list-tags-for-resource` command.