Skip to content

Runner prerequisites ​

putitoutthere shells out to per-language tools (twine, cargo, npm) and to git. The scaffolded release.yml covers the common needs, but depending on your shape, a few runner-level prerequisites need wiring before putitoutthere publish runs.

This page is the single reference for those prerequisites. Every shape guide links here rather than repeating the list.

PyPI: twine + Python ​

The PyPI handler calls twine upload as a subprocess. Hosted GitHub runners don't ship twine on PATH, so the publish job must install it before the piot step:

yaml
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
- name: Install twine
  run: pip install twine

Without these steps, the publish job fails with:

pypi: twine not found on PATH (ENOENT).
Did the publish job run `pip install twine` before the piot step?
See https://thekevinscott.github.io/putitoutthere/guide/runner-prerequisites

Python minor version is flexible — 3.10+ all work. We pick 3.12 in the scaffolded workflow; pin yours to whatever you test against.

Why doesn't piot bundle twine? ​

piot is a Node CLI. Bundling twine would mean either shipping a Python runtime with the Action (enormous) or pulling it at runtime (slow + brittle). Every Actions workflow already has a mechanism for installing Python packages — setup-python + pip install. We use that mechanism instead of reinventing it.

The scaffolded release.yml emitted by putitoutthere initincludes these steps when your config has a kind = "pypi" package; this page is for readers adapting an existing workflow or debugging a failed run.

Git committer identity ​

piot cuts an annotated tag per successful publish (git tag -a -m …). Annotated tags require a committer identity — user.name + user.email — and hosted GitHub runners don't set one by default. Configure it before the piot step:

yaml
- name: Configure git identity
  run: |
    git config --global user.name "github-actions[bot]"
    git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"

The 41898282+github-actions[bot]@users.noreply.github.com email is GitHub's canonical no-reply address for the github-actions[bot] identity. Using it means the tag attribution shows up correctly in the GitHub UI.

If you want tags attributed to a specific user instead, substitute any valid name + email. Committer identity does not affect OIDC trusted publishing — it's purely for the git side.

Without this step, publish fails at tag creation with:

*** Please tell me who you are.
fatal: unable to auto-detect email address

npm: NODE_AUTH_TOKEN (fallback only) ​

OIDC is the default path for npm too, but if you fall back to a long-lived token, actions/setup-node wires the token under the env name NODE_AUTH_TOKEN when registry-url is set:

yaml
- uses: actions/setup-node@v4
  with:
    node-version: '24'
    registry-url: 'https://registry.npmjs.org'
env:
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

piot also accepts NPM_TOKEN as a fallback name — wire the secret under whichever name you prefer, they're equivalent.

crates.io: cargo + CARGO_REGISTRY_TOKEN ​

Hosted runners ship cargo preinstalled, so no setup step is required. For the token, the workflow scaffolds CARGO_REGISTRY_TOKEN pulled from rust-lang/crates-io-auth-action@v1 when using OIDC.

If you're on a self-hosted runner without cargo:

yaml
- uses: dtolnay/rust-toolchain@stable

Dynamic-version Python projects ​

One more runner-level prereq, specific to PyPI packages using [project].dynamic = ["version"]: set SETUPTOOLS_SCM_PRETEND_VERSION_FOR_<PKG> (or the maturin equivalent) on the build job so the backend uses piot's planned version instead of deriving one from git. See dynamic versions.

Summary checklist ​

Before cutting your first release, confirm the publish job has:

  • [ ] actions/checkout@v4 with fetch-depth: 0.
  • [ ] actions/setup-python@v5 + pip install twine (if any kind = "pypi" package).
  • [ ] git config user.name / user.email step.
  • [ ] actions/setup-node@v4 (for npm, or if the piot action runtime version matters).
  • [ ] actions/download-artifact@v4 with path: artifacts.
  • [ ] permissions: contents: write, id-token: write.
  • [ ] OIDC trusted publisher registered per registry (see Authentication).

Released under the MIT License.