Skip to main content

oras-pants-plugin

A Pantsbuild plugin that publishes the output of pex_binary targets to OCI registries as OCI artifacts with oras. Any registry that stores OCI artifacts works: GitHub Container Registry, Docker Hub, Artifact Registry, ECR, ACR, Harbor, a local registry:2, and so on.

Installation

Add the plugin to pants.toml and enable its backend next to the Python backend:

[GLOBAL]
plugins = ["oras-pants-plugin==<version>"]
backend_packages.add = ["pants.backend.python", "oras_pants_plugin"]

Tell a pex_binary target where to push:

# src/app/BUILD
pex_binary(
    name="app",
    entry_point="main.py",
    oci_repositories=["ghcr.io/my-org/app"],
    oci_tags=["1.2.0", "latest"],
)

Then build and push it through the publish goal:

pants publish src/app:app

Pull it back anywhere with oras pull ghcr.io/my-org/app:1.2.0, which restores app.pex.

How it works

oras is downloaded as a static binary; nothing is installed into a Pants resolve. For every pex_binary target that lists oci_repositories, pants publish:

  1. Packages the target as pants package would. A target without oci_repositories, with skip_oras=True, or run with [oras].skip = true is skipped before it is packaged.
  2. Runs one oras push per oci_repositories entry, in the foreground so oras can show progress. Every artifact pants package produced for the target (the PEX, plus any scie executables) becomes a layer of one OCI artifact, which is tagged with every oci_tags entry at once. The manifest's artifactType is the target's oci_media_type.
  3. Reports each push as published, failed or skipped, like every other publisher. --publish-output writes the same as JSON, with the repository and tags of each push.

A packed or loose layout PEX is a directory, which oras pushes as a gzipped tar layer and oras pull unpacks again. The layer media types are left to oras.

Target fields

Field Target Purpose
oci_repositories pex_binary, pex_binaries <registry>/<repository> references to push to, such as ghcr.io/my-org/app or localhost:5000/app. One push per entry. A reference MUST NOT carry a tag or digest.
oci_tags pex_binary, pex_binaries Tags applied to the artifact in every repository. Default: ["latest"]. [] pushes the artifact untagged, addressable by digest only.
oci_media_type pex_binary, pex_binaries The artifactType of the pushed manifest, passed as --artifact-type. Default: application/vnd.python.pex.v1.
skip_oras pex_binary, pex_binaries If true, the target is skipped by pants publish.
overrides pex_binaries Per-binary values for the fields above, e.g. overrides={"tool.py": {"skip_oras": True}}. On pex_binaries the fields apply to every generated pex_binary.

Configuration

Option Default Purpose
[oras].skip false Skip oras during pants publish.
[oras].args [] Extra arguments for every oras push, e.g. --plain-http or --registry-config /path/to/auth.json. They follow the plugin's own flags, so a repeated flag overrides it.
[oras].extra_env_vars [] Extra environment variables for oras, as NAME=value or NAME to copy from Pants' environment, e.g. HTTPS_PROXY or SSL_CERT_FILE.
[oras].version bundled default oras release to download.
[oras].known_versions bundled default Checksums of downloadable releases; extend to use another version.

Credentials

oras reads the credentials that docker login or oras login store in $DOCKER_CONFIG/config.json or ~/.docker/config.json, and runs the credential helpers configured there. PATH, HOME and DOCKER_CONFIG are always passed to oras, so logging in once is enough:

oras login ghcr.io          # or: docker login ghcr.io
pants publish src/app:app

In CI, pass the token to a login step before pants publish, or point [oras].args at an auth file with --registry-config. Avoid --username/--password in pants.toml: the file is committed.

Pushing to a directory

oras can write to an OCI image layout directory instead of a registry, which is handy for inspecting what would be pushed:

pants --oras-args="['--oci-layout-path', '/tmp/app-layout']" publish src/app:app

The reference in oci_repositories is kept as the tag name inside the layout.

Using a different oras version

Add the release's checksums and sizes to known_versions and set version:

[oras]
version = "1.3.5"
known_versions.add = [
  "1.3.5|linux_arm64 |<sha256>|<size>",
  "1.3.5|linux_x86_64|<sha256>|<size>",
  "1.3.5|macos_arm64 |<sha256>|<size>",
  "1.3.5|macos_x86_64|<sha256>|<size>",
]

Compute each line with curl -L $URL | tee >(wc -c) >(shasum -a 256) >/dev/null, where $URL is the oras_<version>_<os>_<arch>.tar.gz asset of the GitHub release (linux/darwin, amd64/arm64). The release's oras_<version>_checksums.txt lists the same checksums.

Supported versions

Plugin Pants Python oras
0.x 2.33 3.14 >=1.3,<2

Pants loads plugins into its own interpreter, so the plugin requires the Python version Pants runs on. The PEX being published may target any Python version.

Releases

Wheels are published to PyPI. Release notes live in the changelog and on the GitHub releases page.

Contributing, Bug Reports and Feature Requests

This plugin lives in the pants-plugin-depot repo. See its CONTRIBUTING.md, or open an issue.

Metadata

Release files for oras-pants-plugin 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for oras-pants-plugin 0.1.0
File Interpreter ABI Platform
oras_pants_plugin-0.1.0-py3-none-any.whl Python 3 none any Details

Release files / oras_pants_plugin-0.1.0-py3-none-any.whl

Download URL oras_pants_plugin-0.1.0-py3-none-any.whl
Size 16.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
063a92649c1351dd343c5fccd1e76315264e3ff3f9eb5b9060ef460ba19ce2f8
BLAKE2b-256 checksum
How to use checksums
417c4a8b13504bf638753395aad746cf49b83c0e601a96c8666d4214172bafaf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Security for oras-pants-plugin 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for oras_pants_plugin-0.1.0-py3-none-any.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page