Publish Packages
This project has two publishable packages with separate GitHub Actions workflows:
| Package | Registry | Directory | Workflow | Tag pattern |
|---|---|---|---|---|
@wechatbot/wechatbot |
npm | nodejs/ |
.github/workflows/publish-npm.yml |
node-v* |
@wechatbot/pi-agent |
npm | pi-agent/ |
.github/workflows/publish-pi-agent.yml |
pi-agent-v* |
wechatbot-sdk |
PyPI | python/ |
.github/workflows/publish-pypi.yml |
py-v* |
Pre-publish Checklist
Before publishing, verify the following:
- Version is bumped — ensure the version in the package manifest is updated:
- npm:
nodejs/package.json→"version"field - PyPI:
python/pyproject.toml→[project] versionfield
- npm:
- Tests pass — run tests locally before tagging:
- npm:
cd nodejs && npm test - PyPI:
cd python && pytest
- npm:
- Build succeeds — verify the package builds cleanly:
- npm:
cd nodejs && npm run build - PyPI:
cd python && python -m build
- npm:
- Changes are committed and pushed to the main branch
Publishing via Git Tag
Create and push a tag to trigger the GitHub Actions workflow:
Publish Node.js to npm
# 1. Bump version in nodejs/package.json
# 2. Commit the change
git add nodejs/package.json
git commit -m "chore: bump node package to vX.Y.Z"
git push
# 3. Tag and push
git tag node-vX.Y.Z
git push origin node-vX.Y.Z
Publish Python to PyPI
# 1. Bump version in python/pyproject.toml
# 2. Commit the change
git add python/pyproject.toml
git commit -m "chore: bump python package to vX.Y.Z"
git push
# 3. Tag and push
git tag py-vX.Y.Z
git push origin py-vX.Y.Z
Publishing via Manual Dispatch
Both workflows support manual triggering from GitHub Actions UI with a dry run option:
- Go to the repo → Actions tab
- Select Publish to npm or Publish to PyPI
- Click Run workflow
- Optionally enable Dry run to test without actually publishing
- npm dry run: runs
npm publish --dry-run - PyPI dry run: publishes to TestPyPI instead of PyPI
- npm dry run: runs
First-Time Publishing (New Package)
OIDC Trusted Publishing cannot be used for the very first publish of a package — the package must already exist on the registry. Follow these steps for initial setup:
npm — First Publish
- Create an npm account at npmjs.com if you don't have one
- Login locally:
npm login - Publish manually from the package directory:
cd nodejs npm publish --access public - After the first version is live, configure Trusted Publishing (see below) for all subsequent releases
PyPI — First Publish
Option A — Pending trusted publisher (recommended, no token needed):
- Go to pypi.org → log in → Publishing → Add a pending publisher
- Fill in: package name (
wechatbot-sdk), owner (corespeed-io), repo (wechatbot), workflow (publish-pypi.yml), environment (pypi) - Trigger the GitHub Actions workflow — PyPI will accept the first publish via OIDC
Option B — Manual publish:
- Create a PyPI account and generate an API token at pypi.org → Account settings → API tokens
- Publish locally:
cd python python -m build twine upload dist/* - After the first version is live, configure Trusted Publishing (see below)
Configuring Trusted Publishing (OIDC)
Both npm and PyPI use OIDC Trusted Publishing — GitHub Actions exchanges a short-lived OIDC token with the registry, so no long-lived secrets are needed.
npm — Configure Trusted Publisher
- Go to npmjs.com → log in → click your package (
@wechatbot/wechatbot) - Settings → Trusted Publishers → Add a trusted publisher
- Fill in:
- Repository owner:
corespeed-io - Repository name:
wechatbot - Workflow filename:
publish-npm.yml
- Repository owner:
- Click Add
- Workflow requirements:
permissions: id-token: writemust be set in the workflow- npm >= 11.5.1 (the workflow upgrades automatically since Node 22 ships with ~10.x)
- Do NOT set
NODE_AUTH_TOKENenv var — it overrides OIDC package.jsonmust have arepositoryfield matching the GitHub repo
PyPI — Configure Trusted Publisher
- Go to pypi.org → log in → your project (
wechatbot-sdk) → Publishing - Add a new publisher:
- Owner:
corespeed-io - Repository:
wechatbot - Workflow:
publish-pypi.yml - Environment:
pypi
- Owner:
- Click Add
- In GitHub repo → Settings → Environments, create environments
pypi(and optionallytestpypi)
Publishing Both at Once
To release both packages simultaneously:
# Bump both versions, commit, then tag both
git tag node-vX.Y.Z
git tag py-vX.Y.Z
git push origin node-vX.Y.Z py-vX.Y.Z
Go Module Publishing (Future Reference)
Go modules don't use a central registry with upload — they are published by pushing a git tag. The Go module proxy (proxy.golang.org) automatically fetches from GitHub.
- Ensure
go.modexists in the module directory with the correctmodulepath (e.g.module github.com/corespeed-io/wechatbot/go) - Bump version by tagging:
# If the module is in repo root: git tag vX.Y.Z # If the module is in a subdirectory (e.g. go/): git tag go/vX.Y.Z - Push the tag:
git push origin go/vX.Y.Z - The Go proxy picks it up automatically — no CI workflow, no tokens, no Trusted Publishing needed
- Verify:
go list -m github.com/corespeed-io/wechatbot/go@vX.Y.Z
For major versions v2+, the module path must include the major version suffix (e.g.
module github.com/corespeed-io/wechatbot/go/v2).
Rust Crate Publishing (Future Reference)
Rust crates are published to crates.io. Unlike npm/PyPI, crates.io does not support OIDC Trusted Publishing — a token is required.
First Publish
- Create an account at crates.io (login via GitHub)
- Generate an API token: crates.io → Account Settings → API Tokens
- Login locally:
cargo login <token> - Publish:
cd rust cargo publish
CI Publishing
- Add the crates.io API token as
CARGO_REGISTRY_TOKENin GitHub repo → Settings → Secrets - Example workflow step:
- name: Publish to crates.io run: cargo publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
Note:
cargo publishdoes a full build and runs tests before uploading. EnsureCargo.tomlhasversion,license,description, andrepositoryfields — crates.io requires them.
Troubleshooting
| Issue | Solution |
|---|---|
| npm 403 Forbidden | Verify trusted publisher is configured on npmjs.com with correct repo/workflow |
| npm ENEEDAUTH / 404 | Ensure NODE_AUTH_TOKEN is NOT set (it overrides OIDC); ensure npm >= 11.5.1 |
| npm provenance error | Ensure id-token: write permission is set and repository field exists in package.json |
| PyPI auth failure | Verify trusted publisher is configured with correct workflow name and environment |
| TestPyPI upload fails | Create testpypi environment in GitHub; configure trusted publisher on test.pypi.org |
| Version conflict | The version already exists on the registry; bump the version number |