Skip to main content
You can publish packages to your team’s dedicated private registry on pyx. There are two main ways to publish packages to pyx:
  1. With an authenticated client. This approach is recommended for teams that publish packages from development machines, or that are using CI/CD systems that do not (yet) support Trusted Publishing.
  2. With Trusted Publishing. This approach is recommended for teams that publish packages from GitHub Actions and other supported CI/CD systems.

Publishing with an authenticated client

Once authenticated, you can publish packages to your team’s dedicated private registry. For example, if your team is called acme, you can publish packages to the acme/main index with:
uv publish /path/to/pyarrow-19.0.1.tar.gz --publish-url https://api.pyx.dev/v1/upload/acme/main
Or, configure the index in your pyproject.toml:
[[tool.uv.index]]
name = "main"
url = "https://api.pyx.dev/simple/acme/main"
publish-url = "https://api.pyx.dev/v1/upload/acme/main"
Publishing requires write access; access controls can be configured in the pyx dashboard.
Use uv publish --dry-run to validate your distribution prior to writing to the registry.
Upon completion, you can install the published package with, e.g.:
uv pip install pyarrow --index https://api.pyx.dev/simple/acme/main
Configuring the index in your pyproject.toml lets you omit the URLs from the command line:
[[tool.uv.index]]
name = "main"
url = "https://api.pyx.dev/simple/acme/main"
publish-url = "https://api.pyx.dev/v1/upload/acme/main"
The main index is created by default during onboarding. If you need to create additional indexes, don’t hesitate to get in touch. You can browse uploaded packages in the pyx dashboard, or by querying the Simple API:
export PYX_TOKEN=$(uv auth token pyx.dev)
curl https://api.pyx.dev/simple/acme/main/pyarrow --header "Authorization: Bearer $PYX_TOKEN"
Or visit the Simple API URLs directly in your browser after logging in to the pyx dashboard.

Trusted Publishing

Trusted Publishing is currently in beta. All organizations have access to it, but you may encounter bugs or missing features. If you have feedback, please get in touch.
Trusted Publishing is an authentication method that uses OpenID Connect to allow CI/CD systems to authenticate to package indices (in this case pyx) without needing to manage long-lived API tokens. In other words, with Trusted Publishing, there’s no need to add or persist pyx credentials in GitHub Actions or other supported CI/CD providers. Trusted Publishing comes with usability and security benefits:
  • Usability: with Trusted Publishing, there’s no need to create and provision API tokens on your CI/CD system. The CI/CD system can authenticate directly to pyx.
  • Security: Trusted Publishing uses short-lived credentials that are minimally scoped (down to the exact set of packages configured for publishing). These qualities reduce the blast radius of a compromised credential.
For additional information on Trusted Publishing, see the PyPI documentation and the OpenSSF’s Trusted Publishers for All Package Repositories.

Supported Trusted Publishing providers

At the moment, pyx supports Trusted Publishing with the following CI/CD providers:
At the moment, support for these providers is limited to their hosted offerings (e.g., github.com). Support for self-hosted instances is not yet available.

Enrolling a Trusted Publisher

You can enroll a Trusted Publisher against one or more of your team’s packages in the in the pyx dashboard under Team > Trusted Publishers.
At the moment, only team administrators can enroll Trusted Publishers.
To add a Trusted Publisher, click the “Create Publisher” button and select the projects you want to allow the publisher to upload to. Then, select the provider you want to use and complete the steps for that provider.
  • GitHub Actions
A GitHub Actions Trusted Publisher has three components:
  • The Repository is the owner/repo slug on GitHub from which you’ll be publishing.
  • The Workflow is the filename of the GitHub Actions workflow that will be publishing. This should be the base filename, e.g., publish.yml (not .github/workflows/publish.yml).
  • The Environment is the optional name of the GitHub Actions environment that will be used for publishing. This environment must be configured in the GitHub repository settings and must be used in the workflow via environment: <name>.
    Specifying an environment is optional, but recommended: environments enable you to enforce additional protections, like required reviewers and tag protection rules on your publishing workflow.

Publishing with a Trusted Publisher

Once you’ve enrolled a Trusted Publisher against one or more packages, you can publish to pyx with it.
  • GitHub Actions
On GitHub Actions, we recommend that you use astral-sh/pyx-auth-action. An example job definition is given below.
For isolation reasons, we strongly recommend that you perform your distribution build in a separate job that your publishing job depends on. This ensures that your build environment does not have access to the short-lived credentials used for publishing.
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read # for actions/checkout in private repos

    steps:
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
        with:
          persist-credentials: false

      - name: Set up uv
        uses: astral-sh/setup-uv@eb1897b8dc4b5d5bfe39a428a8f2304605e0983c # v7.0.0

      - name: Build distributions
        run: uv build

      - name: Upload distributions
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: dists
          path: dist/
          if-no-files-found: error

  pyx-publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write # for Trusted Publishing to pyx

    # (Optional) Set the environment to match the environment defined in pyx.
    environment: pyx.dev

    steps:
      - name: Download distributions
        uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
        with:
          name: dists
          path: dist/

      - uses: astral-sh/pyx-auth-action@63955a4c412aae8e6f47603c78e3548a98445a52 # v0.0.5
        id: auth
        with:
          workspace: acme
          registry: main

      - run: uv publish dist/*
        env:
          UV_PUBLISH_URL: ${{ steps.auth.outputs.url }}
          UV_PUBLISH_TOKEN: ${{ steps.auth.outputs.token }}

Private classifiers

pyx supports private classifiers, which you can use to prevent packages from being accidentally published to PyPI (or another index) instead of pyx. Private classifiers come in two forms:
  1. Private :: pyx allows publishing anywhere on pyx (but only to pyx).
  2. Private :: pyx :: <team> restricts publishing to a specific team. For example, Private :: pyx :: acme allows publishing only to the acme team’s registries.
To use private classifiers, add them next to your other classifiers in your pyproject.toml. For example:
[project]
name = "top-secret"
version = "0.1.0"
classifiers = [
  "Programming Language :: Python :: 3",
  "Private :: pyx :: acme",
]
Like PyPI, pyx will reject packages that use the Private :: Do Not Upload classifier. Additionally, like PyPI, pyx will reject any Private :: classifiers not recognized by the rules above.

Twine support

pyx supports publishing from non-uv clients, like twine. To publish with twine, point the twine client to the pyx index, and authenticate via uv auth token pyx.dev:
export TWINE_REPOSITORY_URL=https://api.pyx.dev/v1/upload/acme/main
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=$(uv auth token pyx.dev)
twine upload /path/to/pyarrow-19.0.1.tar.gz
Or, on the command line:
twine upload /path/to/pyarrow-19.0.1.tar.gz \
  --repository-url https://api.pyx.dev/v1/upload/acme/main \
  --username __token__ \
  --password $(uv auth token pyx.dev)
I