Skip to content

05 Publishing

Asterios Raptis edited this page Mar 9, 2026 · 4 revisions

Publishing auf PyPI

Dieser Guide beschreibt den vollständigen Ablauf vom lokalen Projekt bis zum öffentlichen Paket auf pypi.org.

Voraussetzungen

  • Account auf pypi.org
  • Optional: Account auf test.pypi.org (empfohlen für den ersten Durchlauf)
  • Poetry installiert und Projekt läuft lokal (make ci bestanden)
  • 2FA auf PyPI aktiviert (Pflicht seit 2024)

Schritt 1: API-Token generieren

Auf pypi.org einloggen, dann: Account Settings, API Tokens, "Add API token".

  • Name: z.B. manuscript-tools-publish
  • Scope: Beim ersten Mal "Entire account", danach auf das Projekt einschränken

Token kopieren (beginnt mit pypi-). Wird nur einmal angezeigt.

Schritt 2: Token bei Poetry hinterlegen

poetry config pypi-token.pypi pypi-DEIN_TOKEN_HIER

Der Token wird in der Poetry-Konfiguration gespeichert, nicht im Projekt. Er landet also nicht im Git-Repository.

Für TestPyPI zusätzlich:

poetry config repositories.testpypi https://test.pypi.org/legacy/
poetry config pypi-token.testpypi pypi-DEIN_TEST_TOKEN

Schritt 3: 2FA mit pass-otp (optional)

PyPI erfordert 2FA. Statt einer mobilen App lässt sich TOTP über pass-otp lokal und GPG-verschlüsselt verwalten.

Voraussetzungen

  • GPG mit gültigem privaten Schlüssel
  • pass mit initialisiertem Store (~/.password-store)
  • pass-otp Plugin (via brew install pass-otp oder apt install pass-extension-otp)

Einrichtung

pass otp insert -s --issuer PyPI --account dein-username pypi/dein-username

Den 32-stelligen Secret Key eingeben (aus den PyPI 2FA-Einstellungen). Das Secret wird verschlüsselt unter ~/.password-store/pypi/dein-username.gpg abgelegt.

Code abrufen

# Im Terminal anzeigen
pass otp pypi/dein-username

# Direkt in die Zwischenablage (löscht sich nach 45s)
pass otp -c pypi/dein-username

Backup

  • GPG-Key extern sichern (ohne ihn ist der Zugriff auf die TOTP-Seeds unmöglich)
  • Store via pass git push auf ein privates Repository sichern
  • Recovery Codes separat speichern: pass insert pypi/recovery_codes

Schritt 4: Version erhöhen

Das Bump-Skript hält pyproject.toml und __init__.py synchron:

make bump-patch   # 0.4.0 -> 0.4.1
make bump-minor   # 0.4.0 -> 0.5.0
make bump-major   # 0.4.0 -> 1.0.0

Alternativ mit expliziter Version:

python scripts/bump_version.py 1.0.0

Schritt 5: Publizieren

Auf TestPyPI (Probelauf)

make publish-test

Läuft automatisch ci (Lint + Format + Tests), dann build, dann publish auf TestPyPI.

Testen ob die Installation funktioniert:

pip install --index-url https://test.pypi.org/simple/ manuscript-tools

Auf PyPI (produktiv)

make publish

Gleicher Ablauf: ci, build, publish. Das Paket ist danach unter pypi.org/project/manuscript-tools verfügbar.

Vollständiger Release-Workflow

# 1. Version erhöhen
make bump-minor

# 2. Commit und Tag
git add -A
git commit -m "chore: bump version to $(poetry version -s)"
git tag -a "v$(poetry version -s)" -m "v$(poetry version -s)"

# 3. Push
git push origin main --tags

# 4. CI + Build + Publish (ein Kommando)
make publish

Oder über GitHub Actions (siehe Entwicklung und CI): Ein git push origin v0.5.0 löst automatisch den Publish-Workflow aus.

Häufige Probleme

"File already exists": PyPI akzeptiert keine Version, die bereits existiert. Lösung: Version erhöhen, auch für Korrekturen.

"Invalid API token": Token abgelaufen oder falsch kopiert. Neues Token generieren und mit poetry config pypi-token.pypi erneut setzen.

"403 Forbidden": 2FA-Code fehlt oder abgelaufen. Mit pass otp pypi/dein-username neuen Code abrufen.

CI schlägt vor Publish fehl: make publish führt make ci als Vorbedingung aus. Lint- oder Testfehler verhindern den Publish. Das ist Absicht.


Zurück: Integration | Weiter: Entwicklung und CI

Clone this wiki locally