Fix Version Bumps With Changesets Workflow
Hey there, code enthusiasts! Let's dive into a crucial update for our repository: replacing the manual version bumping process with a slick, automated Changesets workflow. This upgrade isn't just about streamlining our release process; it's about solving real-world problems and aligning with industry best practices. Let's explore why this change is essential, how it works, and the benefits we'll gain. Get ready to say goodbye to conflicts and hello to a smoother, more efficient workflow!
The Problem: Manual Version Bumping Woes
Currently, our repository uses a manual approach to version bumping within the on-merge-main.yml file. While it might seem straightforward, this method has a few significant drawbacks that impact our development workflow. Understanding these issues is key to appreciating the benefits of the Changesets workflow. The current system introduces several pain points for our developers and release managers. Let's break down the core problems:
Conflict Central: PR Conflicts on Every Merge
One of the biggest headaches is the constant conflicts we face on every pull request (PR). Because the manual version bumping process changes the main branch directly after a merge, any open PRs quickly become outdated. This leads to a cycle of resolving conflicts, pushing updates, and waiting for the build to pass. It slows down our developers and increases the time it takes to get features and fixes into production. Nobody likes merging conflicts, right? It's time-consuming and can introduce errors if not handled carefully. This constant need to resolve conflicts disrupts the flow of development and can lead to frustration among contributors.
Lost in Translation: No Automatic CHANGELOG Updates
Manual version bumping also means we're missing out on automatic CHANGELOG updates. The current setup doesn't generate or update the CHANGELOG.md files. Maintaining a changelog manually is time-consuming and error-prone. It means we have to remember every change and create the entry in the changelog, which can easily be forgotten or done inconsistently. A good changelog is essential for keeping track of changes, communicating with our users, and ensuring transparency. A properly maintained changelog keeps our users informed about the changes, bug fixes, and new features.
Loose Cannons: Uncontrolled and Immediate Releases
The current system releases packages immediately after every merge. This lack of control prevents us from batching releases and can lead to a less predictable release schedule. With the current setup, every merge triggers an immediate package publish. This can be problematic if multiple features or bug fixes are merged in rapid succession. It limits our ability to coordinate releases, which can cause confusion or even instability. We need to be able to control when and what we release.
Redundant Code and Technical Debt
Lastly, we're maintaining custom version bump logic, which is unnecessary since Changesets provides a complete solution. This adds to our technical debt and increases the risk of errors. Manual version bumping involves writing and maintaining custom scripts to determine the new version, update package.json files, and commit the changes. This is code we don't need to write or maintain, and that's always a good thing.
Current State: A Snapshot of Our Versioning
Let's take a look at the current setup and how it compares to what we want to achieve with Changesets. Here's a quick overview of what we have and where the manual version bumping process currently sits:
What We Have Now
- .changeset/config.json: Configured and ready to go. We've set up the configuration file. This is a critical first step, as it tells Changesets how to behave. It defines how we want our versions to be managed and how the changesets should be structured.
- package.json Scripts: Scripts are in place for Changesets. This includes commands like
changeset versionandchangeset publish. These scripts are the building blocks of our automated process, and they enable us to execute various Changesets actions easily. - Manual Version Bumping in on-merge-main.yml: This is where the problem lies. The current
on-merge-main.ymlfile contains the manual version bumping logic that we want to replace. This involves calculating version bumps from commit messages, updating package.json files, committing changes, and publishing packages.
Current Workflow: A Step-by-Step Breakdown
The current workflow is outlined in the on-merge-main.yml file. Here's what the process looks like:
- Manual Calculation: The workflow manually calculates version bumps based on commit messages. This is the first step, where we try to determine the type of change (patch, minor, major) based on the commit messages.
- Looping Through package.json: The system loops through all
package.jsonfiles in the repository. This allows the script to update the version numbers correctly. - Updating Versions: The script updates the versions using a combination of bash and Node.js commands. This process changes the version numbers in each
package.jsonfile. It's a critical part of the process. - Direct Commit to Main: The updated
package.jsonfiles are committed directly to themainbranch. This is the root cause of the conflict issues we've been experiencing. - Package Publication: Finally, the packages are published to the registry. This makes the new versions available to anyone who depends on our packages.
Desired State: Embracing the Changesets Workflow
So, what does the future look like? We're embracing the Changesets workflow to solve all these problems. Changesets provides an elegant and automated solution for version management, making our development process smoother and more efficient. The key is to leverage the power of the Changesets tool.
Step 1: Changeset Creation in Every PR
The first step involves the contributors. They will create a Changeset file describing their changes before merging their PR. This is a crucial step that ensures we have detailed information about each change. It's simple, and it keeps everyone informed.
npx changeset
This command creates a new changeset file in the .changeset directory. The file name is unique and reflects the changes being made. The Changeset file is a markdown file with two parts: a header that describes the changes to packages and a descriptive section. The contributor will select the packages affected by the changes and the type of change (patch, minor, or major). The contributor then provides a brief description of the change.
---
"@happyvertical/ai": minor
"@happyvertical/sql": patch
---
Add new AI provider support and fix SQL connection pooling
Step 2: Automated Version PR
After a PR merges, a special GitHub Action will kick in. This action is designed to handle all of our versioning and publishing needs. Once pull requests are merged, the Changesets GitHub Action takes over:
- Changeset Detection: First, it detects all the new changeset files that were created in the merged pull requests.
- Version PR Creation: Then, it creates a pull request, dubbed the "Version Packages" PR.
- Aggregation of Changesets: The pull request aggregates all the individual changesets, combining them into a single, cohesive unit. This means all the changes are combined in one place.
- Version Bumping: This step involves bumping the versions in the
package.jsonfiles of all the affected packages. The version numbers are automatically updated based on the type of change specified in the changeset. - CHANGELOG Updates: This crucial step updates the
CHANGELOG.mdfiles for each affected package. This step keeps our users informed about the changes, bug fixes, and new features. - Changeset Deletion: Finally, it deletes all the individual changeset files. This cleanup ensures that we don't have unused files cluttering up the repository.
Step 3: Release with a Merge
When we're ready to release, we simply merge the Version Packages PR. This simple step triggers the publication of our packages to the registry. This gives us complete control over our release process and eliminates any surprises.
- Version Packages PR Review: Before merging, we review the "Version Packages" pull request to ensure everything is correct.
- Version Packages PR Merge: After reviewing, we merge the Version Packages PR. This is the trigger that starts the release process.
- Packages Publication: Once the Version Packages PR merges, the packages are published to the registry. This makes the latest versions of our packages available.
Benefits: Why Changesets is a Game Changer
The Changesets workflow offers a multitude of benefits, making it an excellent choice for our project. It addresses the problems of the current setup and provides several improvements that enhance our development experience and streamline our release process. Let's explore the key benefits:
Goodbye Conflicts: Zero Version Collisions
We bid farewell to the dreaded merge conflicts. By separating version bumping into a dedicated pull request, we eliminate the need to update main directly after every merge. This means fewer interruptions for developers and faster time to merge. Main only changes when the Version PR merges (controlled).
Changelog Magic: Automated CHANGELOG Generation
Changesets automates the generation of CHANGELOG.md files. This saves time and ensures consistent and accurate documentation of all changes. Better changelogs! Automatic CHANGELOG.md generation ensures that we're always up-to-date and providing clear information about each release.
Release Control: Batching for Success
We gain control over our releases, allowing us to batch multiple PRs into a single release. This increases predictability and allows us to coordinate releases. Merge multiple PRs, and release once. It gives us better control over when we release new versions.
No Collisions: Unique Change Files
Each PR adds a unique changeset file, preventing version collisions. This ensures that changesets do not interfere with each other and are applied correctly. Each PR adds a unique changeset file.
Workflow Standard: Industry-Standard Practices
Changesets follows industry standards for monorepos, aligning with tools like Turborepo and pnpm. This alignment simplifies integration with other tools and improves the overall development experience. Conventional workflow. Industry standard for monorepos.
Code Reduction: Less Code to Maintain
We'll have less code to maintain, as we remove the manual version bump logic. This reduces our technical debt and reduces the risk of errors. No version collisions. Each PR adds a unique changeset file.
Implementation Plan: Making the Switch
To make the transition to Changesets successful, we need a clear and concise implementation plan. This plan includes the necessary steps to set up the Changesets workflow and ensure a smooth transition. The implementation plan includes creating workflows, updating our code, and educating contributors.
1. Changesets Workflow Creation: The .github/workflows/changeset-version.yml
First, we'll create the changeset-version.yml workflow file. This file automates the creation of the "Version Packages" PR after PR merges.
name: Changesets Version
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
packages: write
jobs:
version:
name: Create Version PR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Environment
uses: ./.github/actions/setup-environment
with:
node-version: '24'
registry-url: 'https://npm.pkg.github.com'
- name: Create Version PR or Publish
uses: changesets/action@v1
with:
version: pnpm run version-packages
publish: pnpm run release
commit: 'chore: version packages'
title: 'chore: version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2. The Great Cleanup: Updating on-merge-main.yml
Next, we'll update the on-merge-main.yml file to remove the manual version-bumping logic. This includes removing the steps that calculate version bumps, bump versions, and create git tags.
3. The Checks: Adding Changeset Requirement
We will also add a Changeset check to ensure that all PRs include a changeset. This check will prevent us from merging PRs that are missing a changeset.
name: Changeset Check
on:
pull_request:
types: [opened, synchronize, labeled, unlabeled]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for changeset
run: |
# Skip if PR has 'skip-changeset' label
if gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name' | grep -q 'skip-changeset'; then
echo "Skipping changeset check (skip-changeset label)"
exit 0
fi
# Check if changeset exists
if ls .changeset/*.md 2>/dev/null | grep -v README.md; then
echo "âś… Changeset found"
else
echo "❌ No changeset found"
echo "Please run: npx changeset"
exit 1
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4. Documentation: Updating CONTRIBUTING.md
We'll update our CONTRIBUTING.md file to include instructions on how to add a changeset. This will help contributors to understand the new workflow and how to create a changeset.
## Adding a Changeset
Before merging your PR, add a changeset describing your changes:
```bash
npx changeset
Select the packages affected and the type of change:
patch- Bug fixes, small changesminor- New features, non-breaking changesmajor- Breaking changes (treated as minor until 1.0.0)
Write a clear description of the change for the CHANGELOG.
To skip the changeset requirement, add the skip-changeset label to your PR.
### 5. Migration Steps: The Checklist
1. âś… Create `changeset-version.yml` workflow
2. âś… Update `on-merge-main.yml` (remove manual bumping)
3. âś… Add `changeset-check.yml` workflow
4. âś… Update `CONTRIBUTING.md`
5. âś… Test with a small PR
6. âś… Monitor first few releases
7. âś… Document in `CASCADE.md`
## Testing Plan: Ensuring a Smooth Transition
To ensure everything works as expected, we'll perform the following tests:
1. **Test PR Creation**: Create a test PR that adds a changeset. This will ensure that our contributors understand how to create changesets.
2. **Merge Verification**: Merge the PR and verify that the "Version Packages" PR is created. This ensures the workflow is correctly triggered.
3. **Review the Version PR**: Review the version PR to check the versions and `CHANGELOG` entries. This is to verify that all the changes are present.
4. **Merge and Publish**: Merge the Version PR and verify that the packages are published. This is the final step to ensure the packages are available.
5. **Cascade Triggers**: Test cascade triggers to ensure everything works well.
## Cascade Compatibility: Seamless Integration
The Changesets workflow will work seamlessly with our existing cascade system. The cascade system will trigger when the Version Packages PR merges. No changes are required to the cascade system.
## Breaking Changes: What You Need to Know
This change introduces a few breaking changes, but they're necessary for a smoother development process. We've made it simple for contributors to work with Changesets.
### **For Contributors**
* **Mandatory Changesets**: Contributors must run `npx changeset` before merging their PR.
* **Skipping Changesets**: For non-publishable changes (documentation, tests, etc.), add the `skip-changeset` label.
### **For Release Process**
* **No Auto-Publish**: No longer auto-publishes on every merge.
* **Merge Requirement**: You must merge the "Version Packages" PR to publish.
* **Batch Releases**: We can batch multiple changes into one release.
## Related Issues: Addressing Conflicts and Improving Workflow
This change addresses the conflicts issue mentioned in #366 and improves the release workflow. The workflow aligns with industry standards.
## References: For Further Reading
* [Changesets Documentation](https://github.com/changesets/changesets)
* [Changesets GitHub Action](https://github.com/changesets/action)
* [Turborepo + Changesets Guide](https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing)
With these changes, we will improve our release workflow, reduce conflicts, and automate the creation of change logs. We'll be using a proven industry standard for managing versions and publishing packages. It's a win-win for everyone involved!