Custom Package Metadata#
Enhanced Advanced
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.
# 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.
# 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
}
# 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
orpypi
. 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#
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:
# 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.
# 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
}
# 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.