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:
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install twine
run: pip install twineWithout 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-prerequisitesPython 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:
- 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 addressnpm: 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:
- 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:
- uses: dtolnay/rust-toolchain@stableDynamic-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@v4withfetch-depth: 0. - [ ]
actions/setup-python@v5+pip install twine(if anykind = "pypi"package). - [ ]
git config user.name/user.emailstep. - [ ]
actions/setup-node@v4(for npm, or if the piot action runtime version matters). - [ ]
actions/download-artifact@v4withpath: artifacts. - [ ]
permissions: contents: write, id-token: write. - [ ] OIDC trusted publisher registered per registry (see Authentication).
Related
- Artifact contract — what the build job must upload and under which names.
- Troubleshooting publish failures — error strings keyed to the prereqs above.