Proof of concept repository for creating and managing independent releases in a polyglot monorepo containing both Python and Node.js packages. This setup integrates Changesets, pnpm, and GitHub Actions to support semantic versioning, tagging, changelog generation, and optional release publishing.
This repository demonstrates how to:
- Use Changesets to track and apply semantic version bumps
- Manage versioning independently for Python and Node packages in a single monorepo
- Tag and optionally release each package with GitHub Actions
- Support publishing and package validation via CI/CD workflows
sgp-changeset-poc/
├── .changeset/ # Markdown files describing version changes
├── .github/workflows/ # GitHub Actions workflows for CI/CD
├── packages/ # Node.js packages
│ └── core/
├── packages-python/ # Python packages
│ └── common_grants_sdk/
├── scripts/ # Helper scripts (e.g. Python version bump)
│ └── bump_python_version.py
├── package.json # pnpm root config with dev dependencies
├── pnpm-workspace.yaml # Workspace config for pnpm (includes Python)
└── README.md # This documentation file
- Tracks version bumps via Changesets (
.changeset/*.md) - Node packages: managed via
pnpm changeset version - Python packages: handled via a custom script
- Git tags are automatically created and pushed
- Format:
common_grants_sdk@0.5.0
- Format:
- Optional workflow (
create-release-from-tag.yml) can be manually triggered
| Workflow File | Description |
|---|---|
build-check-python.yml |
Lint/build/validate Python packages |
create-release-from-tag.yml |
Creates GitHub Releases from pushed tags |
publish-node.yml |
Dry-run publish to npm |
publish-python.yml |
Dry-run publish to TestPyPI |
version.yml |
Unified versioning and tagging |
Because Changesets is designed for Node.js and expects each package to contain a package.json, we include a minimal “fake” Node package under packages-python/ to satisfy this requirement. Without it, Changesets would not recognize Python-only changes in the monorepo.
This adaptation enables the versioning workflow to trigger correctly even when only the Python package has been modified.
Edit a Python or Node package file.
Run:
pnpm changesetThen follow the CLI prompts:
- Select affected package(s)
- Choose version bump type (
patch,minor, ormajor) - Add a short summary
This generates a .md file in .changeset/.
Example output:
---
"common_grants_sdk": patch
---
Fix grant lookup edge case.Include the .changeset/*.md file in your PR.
Upon merging to main, the following actions are triggered automatically via the version.yml workflow:
- The Python package version is bumped using a custom script (
scripts/bump_python_version.py) - The Node packages are versioned using
pnpm changeset version - Corresponding
CHANGELOG.mdfiles are updated for each affected package (Python and/or Node) - All changes (version bumps and changelogs) are committed and pushed back to
main - Git tags are created for each versioned package and pushed to the repository
Once tags have been automatically created and pushed by the version.yml workflow, you can manually trigger the create-release-from-tag.yml workflow to generate GitHub Releases based on those tags.
To do this:
- Navigate to the Actions tab on GitHub.
- Select the Create GitHub Release from Tag workflow from the left-hand menu.
- Click Run workflow.
- Enter the tag you want to release (e.g.
common_grants_sdk@0.2.0). - Click the Run workflow button to initiate the release.
This workflow uses the pushed tags to create GitHub Releases with autogenerated release notes.
After a PR is merged:
-
Verify version bump
- Check version in
common_grants_sdk/setup.py - Check version in
common_grants_sdk/package.json
- Check version in
-
Verify changelog
- Check top entry in
common_grants_sdk/CHANGELOG.md
- Check top entry in
-
Check tags
- Navigate to the GitHub repo > Tags tab
- Ensure tags like
common_grants_sdk@0.5.0appear
-
Check commits
- Look for a
chore: version packages [skip ci]commit fromgithub-actions[bot]
- Look for a