Speakeasy: how do we set up automated publishing to npm and PyPI from CI?
API Development Platforms

Speakeasy: how do we set up automated publishing to npm and PyPI from CI?

7 min read

Most teams hit the same wall: generating SDKs with Speakeasy is easy; reliably publishing them to npm and PyPI from CI without humans clicking buttons is where things slip. The answer is to treat Speakeasy as part of your build pipeline: spec in, artifacts out, and CI takes care of shipping to registries on every release.

Quick Answer: Use Speakeasy in your CI pipeline to regenerate SDKs on each change, then use language‑specific publish steps (npm publish for JavaScript/TypeScript, twine upload for Python) with registry credentials stored as CI secrets. Authenticate Speakeasy via SPEAKEASY_API_KEY, and trigger publishing on tagged releases or main-branch merges.


Frequently Asked Questions

How does Speakeasy fit into automated publishing to npm and PyPI from CI?

Short Answer: Speakeasy generates your SDKs as part of CI, and your CI workflow then runs the standard npm/PyPI publish commands using stored credentials. Speakeasy isn’t the registry; it’s the generator that stays in lockstep with your OpenAPI spec.

Expanded Explanation:
Speakeasy’s job in this flow is to turn your OpenAPI spec into up‑to‑date SDKs on every change. Your CI pipeline pulls the repo, runs the Speakeasy CLI (or uses Speakeasy Studio configuration), commits or packages the generated SDK, and then uses the usual ecosystem tools to publish:

  • For npm: npm publish or pnpm publish
  • For PyPI: twine upload or python -m build && twine upload

You authenticate Speakeasy inside CI by creating an API key in the Speakeasy Platform and exposing it as SPEAKEASY_API_KEY in your CI environment. npm and PyPI credentials live in CI secrets as well. The result is an automated path: update spec → CI runs Speakeasy → packages get built → npm/PyPI get new versions without manual intervention.

Key Takeaways:

  • Speakeasy generates SDKs; your CI and registry tooling handle publishing.
  • Use SPEAKEASY_API_KEY plus npm and PyPI secrets to authenticate everything in CI.

What’s the step‑by‑step process to set up CI publishing to npm and PyPI with Speakeasy?

Short Answer: Wire Speakeasy into your CI workflow, configure registry credentials as secrets, and add publish steps that run on tags or main-branch releases. The pipeline becomes: generate → build → publish.

Expanded Explanation:
The practical setup is mostly CI wiring. You’ll:

  1. Install the Speakeasy CLI in your CI environment.
  2. Set SPEAKEASY_API_KEY as a secret so CI can talk to the Speakeasy Platform.
  3. Run the generation command (often configured via a gen.yaml or project config).
  4. Build the resulting packages (Node package, Python wheel/sdist).
  5. Publish to npm and PyPI using credentials stored as CI secrets.
  6. Trigger all of this only when you actually want a release—e.g., on annotated git tags like v1.2.3.

You keep a single source of truth: your OpenAPI spec. Every time it changes and passes tests, Speakeasy regenerates the SDKs and CI pushes an updated version to both registries so agents and humans always use the latest interface.

Steps:

  1. Create a Speakeasy API key in the Speakeasy Platform and store it as SPEAKEASY_API_KEY in your CI provider.
  2. Add Speakeasy generation to your CI config (e.g., GitHub Actions, GitLab CI, CircleCI).
  3. Add npm and PyPI publish steps that run after a successful build, gated on a release/tag condition.

How does automated publishing to npm differ from publishing to PyPI?

Short Answer: npm uses a Node toolchain and npm publish (auth via token), while PyPI uses Python packaging (build/setuptools) and twine upload (auth via username/token). The Speakeasy part—SDK generation—is effectively the same.

Expanded Explanation:
From Speakeasy’s perspective, both flows start identically: you feed in your OpenAPI spec, Speakeasy generates language‑specific SDKs, and CI takes over. The difference is in how you build and publish:

  • npm expects a package.json, valid semver, and an npm auth token. CI usually sets NODE_AUTH_TOKEN and calls npm publish from the SDK directory.
  • PyPI expects a Python package (with pyproject.toml or setup.cfg/setup.py), and you publish via twine upload. CI sets TWINE_USERNAME/TWINE_PASSWORD (often __token__ plus an API token) or uses a TWINE_API_TOKEN depending on setup.

In both worlds, you must ensure the version in your package metadata matches your release strategy (e.g., derived from the git tag). Speakeasy often writes or updates those version fields as part of the generation pipeline so npm and PyPI releases stay in lockstep with your API versioning.

Comparison Snapshot:

  • Option A: npm (JavaScript/TypeScript)
    Uses Node, npm publish, NODE_AUTH_TOKEN, semver in package.json.
  • Option B: PyPI (Python)
    Uses Python build tooling, twine upload, TWINE_* credentials, versions in pyproject.toml or setup.cfg.
  • Best for:
    Dual-publishing when you’ve generated both TS and Python SDKs and want clients and agents in both ecosystems to stay up to date automatically.

What do I actually need in place to implement Speakeasy‑driven npm and PyPI publishing from CI?

Short Answer: You need a stable OpenAPI spec, the Speakeasy CLI or Studio configuration, CI access to your SDK repos, and registry credentials stored as secrets. From there, it’s just a matter of scripting the workflow.

Expanded Explanation:
Implementation is mostly about wiring together existing building blocks. Speakeasy provides the generation engine; your CI provider provides the scheduling and secrets; npm/PyPI provide the distribution. The heavy lift is ensuring your repos are structured for packaging and that your CI config is explicit about when to publish (to avoid accidental releases on every commit).

A clean setup usually looks like:

  • OpenAPI spec in your API repo (or a dedicated spec repo).
  • One repo per SDK (e.g., my-api-ts-sdk, my-api-python-sdk), or a mono‑repo with clear package boundaries.
  • Speakeasy generation invoked in CI, either in the SDK repo directly or via a pipeline triggered from the spec repo that pushes changes as PRs.
  • CI jobs that only publish when a specific condition is met (tags, manual approvals, or a “release” branch).

What You Need:

  • Speakeasy access and config:
    • A valid OpenAPI spec.
    • Speakeasy CLI installed in CI (brew install speakeasy-api/tap/speakeasy locally; CI equivalents per OS).
    • SPEAKEASY_API_KEY set from the Speakeasy Platform.
  • Registry‑ready SDK repos:
    • npm: package.json, built artifacts if needed, and a versioning scheme.
    • PyPI: pyproject.toml or setup.cfg/setup.py, plus build config.
  • CI & secrets:
    • CI workflows capable of running Node and Python.
    • npm token (usually NODE_AUTH_TOKEN or NPM_TOKEN) and PyPI token (TWINE_USERNAME/TWINE_PASSWORD or token‑based env).

How should we structure this for long‑term reliability and release discipline?

Short Answer: Treat npm and PyPI publishing as release artifacts driven by your OpenAPI spec and git tags, with Speakeasy wired into CI. That keeps all SDK interfaces, agents, and infrastructure clients in sync with your API changes without drift.

Expanded Explanation:
The strategic value isn’t just “we automated npm/PyPI.” It’s that your SDKs and agent interfaces become another output of your API release process, not an afterthought. When your OpenAPI spec changes, you can:

  • Validate the spec and run tests.
  • Regenerate SDKs in TS, Python, and any other targets.
  • Bump versions based on tags (e.g., v1.4.01.4.0).
  • Publish to npm and PyPI as part of a single CI pipeline.
  • Optionally, update Terraform providers, CLIs, or MCP servers using the same pattern.

This is where Speakeasy earns its keep: instead of manually touching each SDK whenever the API moves, your CI “ships with every commit” through generated pull requests or release pipelines. That consistency matters especially when agents are in the loop—Cursor, Claude Code, or GitHub Copilot can rely on up‑to‑date, type‑safe SDKs, and you don’t have to wonder which version they’re calling.

Why It Matters:

  • No drift between API and clients:
    Every change in your OpenAPI spec flows through to npm and PyPI, so humans and agents both see the same behavior.
  • Faster, safer releases:
    Publishing becomes a deterministic pipeline—tags in, SDKs out—so teams can accelerate releases without sacrificing code quality or DX.

Quick Recap

To automate publishing to npm and PyPI from CI with Speakeasy, you wire Speakeasy into your pipeline as the generator, authenticate it via SPEAKEASY_API_KEY, and then use standard npm and PyPI publish steps with registry credentials stored as CI secrets. Trigger these jobs on releases (typically git tags), and your JavaScript/TypeScript and Python SDKs will update automatically whenever your OpenAPI spec changes—no manual releases, no drift, just reproducible artifacts that ship with every commit.

Next Step

Get Started