Custom Metadata

EnhancedAdvanced

Overview

Posit Package Manager allows administrators to define custom key-value pairs as metadata for packages with flexible matching criteria.

Package metadata can be added globally, affecting multiple packages across a source or repository; or they can be as specific as a single package version in one source or repository.

Custom package metadata support is available at the Enhanced tier for local use and Advanced tier for remote use.

Custom Metadata System

Package metadata utilizes a criteria matching system to apply key-value pairs to packages with increasing specificity the more criteria are matched. As examples of how custom metadata can be applied, you can:

  • Add a risk score to all packages in a repository
  • Add a risk score to a single version of a specific package
  • Add a documentation link to a specific package

The matching criteria for package metadata is displayed when creating metadata. Use the rspm create metadata or rspm create bulk-metadata commands to create new metadata, and rspm list metadata command to list them.

Terminal
# Add a high risk score to all CRAN packages
$ rspm create metadata --source=cran --key=risk --value=10

# Add a high risk score to django 1.0.0
$ rspm create metadata --package-name=django --version='1.0.0' --key=risk --value=10

# Add a low risk score to django 1.0.0 in an exempt source
$ rspm create metadata --package-name=django --version='1.0.0' --source="exempt-source" --key=risk --value=0

# List all metadata
$ rspm list metadata

ID: 1 (global)
-- Data:
    - Key: risk
    - Value: 10
-- Constraints:
    - Source: cran

ID: 2 (Package: django)
-- Data:
    - Key: risk
    - Value: 10
-- Constraints:
    - Version: 1.0.0

ID: 3 (Package: django)
-- Data:
    - Key: risk
    - Value: 0
-- Constraints:
    - Source: exempt-source
    - Version: 1.0.0

Bulk Creation

Bulk creation of metadata can be done both via JSON and CSV input files. See rspm create bulk-metadata for more information.

Terminal
# View the shape of the JSON
$ cat /tmp/metadata.json
[
    {
        "package_name": "ggplot2",
        "key": "risk",
        "value": "10",
        "repo": "cran",
        "source": "cran"
    },
    {
        "package_name": "ggplot2",
        "key": "risk",
        "value": "5",
        "repo": "cran",
        "source": "cran",
        "version": "1.0.0"
    }
]

# Bulk create the metadata
$ bin/rspm create bulk-metadata --path=/tmp/metadata.json
{
  "affected": [
    {
      "id": 1,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "10",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        }
      ]
    },
    {
      "id": 2,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "5",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        },
        {
          "version": "1.0.0"
        }
      ]
    }
  ],
  "rejected": null
}
Terminal
# View the shape of the CSV
$ cat /tmp/metadata.csv
"value","key","source","repo","version","package_name"
"10","risk","cran","cran","","ggplot2"
"5","risk","cran","cran","1.0.0","ggplot2"

# Bulk create the metadata
$ rspm create bulk-metadata --csv-in=/tmp/metadata.csv
{
  "affected": [
    {
      "id": 1,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "10",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        }
      ]
    },
    {
      "id": 2,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "5",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        },
        {
          "version": "1.0.0"
        }
      ]
    }
  ],
  "rejected": null
}

Matching Criteria

Custom metadata supports several matching criteria. These include:

  • Package name: Name of the package. R packages are case-sensitive, while Python packages are case-insensitive.
  • Version: A package version.
  • Source: Name of the source, such as cran or pypi. All source types are supported.
  • Repository: Name of the repository.

For more information on the matching criteria, reference the CLI appendix.

Specificity and Conflicting Key-Value Pairs

When multiple matching keys are matched to a package, the key-value pair with the highest specificity takes precedence.

Examples

Terminal
ID: 1 (global)
-- Data:
    - Key: risk
    - Value: 60
-- Constraints:
    - Source: cran
ID: 2 (Package: plumber)
-- Data:
    - Key: risk
    - Value: 70
ID: 3 (Package: plumber)
-- Data:
    - Key: risk
    - Value: 80
-- Constraints:
    - Version: 1.0.1
ID: 4 (Package: plumber)
-- Data:
    - Key: risk
    - Value: 90
-- Constraints:
    - Source: cran
    - Version: 1.0.1
ID: 5 (Package: plumber)
-- Data:
    - Key: risk
    - Value: 95
-- Constraints:
    - Source: cran
    - Repo: cran
    - Version: 1.0.1

Given the above set of 5 metadata records, the plumber package with version 1.0.1 in the cran repository will have a risk score of 95.

Editing Metadata

Custom metadata can be edited using the same rspm create metadata command, by passing the --update-existing flag.

Following the example above for creating new metadata, we can update it like this:

Terminal
# Lower the risk score of all CRAN packages
$ rspm create metadata --source=cran --key=risk --value=5 --update-existing

# List all metadata
$ rspm list metadata
ID: 1 (global)
-- Data:
    - Key: risk
    - Value: 5
-- Constraints:
    - Source: cran

Bulk Edit

Bulk edits of metadata is done via the rspm create bulk-metadata command. There are no additional flags necessary, the command automatically updates existing records if the value has changed.

Terminal
# View existing metadata
$ rspm list metadata --output-format=json
[
  {
    "id": 1,
    "package_name": "ggplot2",
    "key": "risk",
    "value": "10",
    "constraints": [
      {
        "repo_id": 2,
        "repo": "cran",
      },
      {
        "source_id": 1
        "source_name": "cran"
      }
    ]
  },
  {
    "id": 2,
    "package_name": "ggplot2",
    "key": "risk",
    "value": "5",
    "constraints": [
      {
        "repo_id": 2,
        "repo": "cran",
      },
      {
        "source_id": 1
        "source_name": "cran"
      },
      {
        "version": "1.0.0"
      }
    ]
  }
]

# View the shape of the JSON
$ cat /tmp/metadata.json
[
    {
        "package_name": "ggplot2",
        "key": "risk",
        "value": "20",
        "repo": "cran",
        "source": "cran"
    },
    {
        "package_name": "ggplot2",
        "key": "risk",
        "value": "10",
        "repo": "cran",
        "source": "cran",
        "version": "1.0.0"
    }
]

# Bulk edit the metadata
$ rspm create bulk-metadata --path=/tmp/metadata.json
{
  "affected": [
    {
      "id": 1,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "20",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        }
      ]
    },
    {
      "id": 2,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "10",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        },
        {
          "version": "1.0.0"
        }
      ]
    }
  ],
  "rejected": null
}
Terminal
# View existing metadata
$ rspm list metadata --output-format=json
[
  {
    "id": 1,
    "package_name": "ggplot2",
    "key": "risk",
    "value": "10",
    "constraints": [
      {
        "repo_id": 2,
        "repo": "cran",
      },
      {
        "source_id": 1
        "source_name": "cran"
      }
    ]
  },
  {
    "id": 2,
    "package_name": "ggplot2",
    "key": "risk",
    "value": "5",
    "constraints": [
      {
        "repo_id": 2,
        "repo": "cran",
      },
      {
        "source_id": 1
        "source_name": "cran"
      },
      {
        "version": "1.0.0"
      }
    ]
  }
]

# View the shape of the CSV
$ cat /tmp/metadata.csv
"value","key","source","repo","version","package_name"
"20","risk","cran","cran","","ggplot2"
"10","risk","cran","cran","1.0.0","ggplot2"

# Bulk edit the metadata
$ rspm create bulk-metadata --csv-in=/tmp/metadata.csv
{
  "affected": [
    {
      "id": 1,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "20",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        }
      ]
    },
    {
      "id": 2,
      "package_name": "ggplot2",
      "key": "risk",
      "value": "10",
      "constraints": [
        {
          "repo_id": 2,
          "repo": "cran",
        },
        {
          "source_id": 1
          "source_name": "cran"
        },
        {
          "version": "1.0.0"
        }
      ]
    }
  ],
  "rejected": null
}

Remote Usage

The metadata commands can also be used remotely, e.g. rspm create metadata. This allows automating metadata management.

When generating a token to set metadata remotely, the rspm create token command must include either --scope=metadata:admin or --scope=global:admin. The metadata:admin scope gives full access to create, update, delete, and list metadata.

For more information on remotely adding or editing metadata, refer to the Admin CLI - Remote Use section.

Remote usage of custom metadata commands is available at the Advanced tier.

Back to top