This document describes how to publish new versions of the Prompty runtimes.
Both runtimes use tag-based releases: push a GPG-signed tag, CI builds/tests/publishes via OIDC (no secrets needed).
| Runtime | Registry | Tag format | CI workflow |
|---|---|---|---|
| Python | PyPI | python/{version} |
prompty-python.yml |
| TypeScript | npm | typescript/{version} |
prompty-ts-release.yml |
Run these exact steps locally before pushing tags. They mirror CI. If these pass locally, CI will pass. Do not skip this.
cd runtime/typescript
# 1. Clean install from lockfile (exactly like CI)
rm -rf node_modules packages/*/node_modules packages/*/dist
# Windows: Remove-Item -Recurse -Force node_modules -EA 0; Get-ChildItem packages -Dir | % { Remove-Item -Recurse -Force "$_\node_modules","$_\dist" -EA 0 }
npm ci
# 2. Build all packages INCLUDING DTS declarations
npm run build
# 3. Run all tests
npm run test
# 4. Type-check
npm run lintWhy clean build matters:
tsupgenerates TypeScript declarations (DTS) using a stricter compiler mode than Vitest. Code can pass tests but fail DTS build. Always build from clean before tagging.
cd runtime/python/prompty
# 1. Lint
uv run ruff check .
# 2. Format check
uv run ruff format --check .
# 3. Run tests with coverage (exact CI command)
python -m pytest tests/ -q --tb=short --cov=prompty --cov-report=term --cov-report=json
# Windows venv: .venv\Scripts\python.exe -m pytest ...Python — edit runtime/python/prompty/prompty/_version.py:
VERSION = "2.0.0a4" # PEP 440: a=alpha, b=beta, rc=release candidateTypeScript — update all 4 packages + cross-references:
cd runtime/typescript
node -e "
const fs = require('fs');
const version = '2.0.0-alpha.4'; // <-- set your version here
for (const p of ['core','openai','foundry','anthropic']) {
const path = 'packages/' + p + '/package.json';
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
const old = pkg.version;
pkg.version = version;
for (const depType of ['dependencies','devDependencies','peerDependencies']) {
if (!pkg[depType]) continue;
for (const [k,v] of Object.entries(pkg[depType])) {
if (k.startsWith('@prompty/') && v.includes(old)) {
pkg[depType][k] = v.replace(old, version);
}
}
}
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
console.log(p + ': ' + pkg.version);
}
"See Pre-flight checklist above.
git add -A
git commit -S -m "chore: bump versions to {version}"
# Verify signature
git log --format="%h %G? %s" -1 # must show 'G'git push origin maingit tag -s "python/2.0.0a4" -m "Prompty Python 2.0.0a4
<release notes>"
git tag -s "typescript/2.0.0-alpha.4" -m "Prompty TypeScript 2.0.0-alpha.4
<release notes>"
git push origin "python/2.0.0a4" "typescript/2.0.0-alpha.4"https://github.com/microsoft/prompty/actions
# Python
pip install prompty==2.0.0a4
python -c "import prompty; print(prompty.__version__)"
# TypeScript
npm info @prompty/core versions --json | tail -5| Workflow | Node | OS | Purpose |
|---|---|---|---|
prompty-ts-check.yml |
22, 24 | ubuntu, windows | Test matrix |
prompty-ts-release.yml |
24 | ubuntu | Publish (npm 11+ for OIDC) |
| Workflow | Python | OS | Purpose |
|---|---|---|---|
prompty-python-check.yml |
3.11, 3.12, 3.13 | ubuntu | Test matrix |
prompty-python-check.yml |
3.11 | windows | Compat check |
prompty-python.yml |
3.11 | ubuntu | Publish to PyPI |
| Install | What you get |
|---|---|
pip install prompty |
Core only |
pip install prompty[openai] |
+ OpenAI provider |
pip install prompty[foundry] |
+ Microsoft Foundry provider |
pip install prompty[anthropic] |
+ Anthropic provider |
pip install prompty[jinja2] |
+ Jinja2 renderer |
pip install prompty[all] |
Everything |
| Package | What it is |
|---|---|
@prompty/core |
Loader, pipeline, types, tracing |
@prompty/openai |
OpenAI provider |
@prompty/foundry |
Microsoft Foundry provider |
@prompty/anthropic |
Anthropic provider |
The trusted publisher config on the registry must match exactly:
- Owner:
microsoft - Repository:
prompty - Workflow filename:
prompty-python.ymlorprompty-ts-release.yml - Environment: (leave blank)
tsup DTS is stricter than Vitest. Common fix: as unknown as Record<string, unknown>.
Always run npm run build from clean before tagging.
Known Node 22 bug (npm/cli#9151).
Publish workflow uses Node 24 which ships npm 11 natively. Do NOT add
npm install -g npm@latest to any workflow.
PowerShell doesn't support \ line continuation. Keep run: commands on a single line.
# Delete old tags
git tag -d "typescript/2.0.0-alpha.4"
git push origin :refs/tags/typescript/2.0.0-alpha.4
# Fix, commit, push
git push origin main
# Re-tag and push
git tag -s "typescript/2.0.0-alpha.4" -m "..."
git push origin "typescript/2.0.0-alpha.4"PyPI does not allow re-uploading the same version. If Python published but TS failed, only re-tag TS. If you must re-publish Python, bump to the next version.