Introduction
Automating versioning and releases is essential for maintaining a smooth and consistent development workflow. By combining Semantic Versioning (SemVer) with GitHub Actions, you can automatically manage version bumps, changelogs, and releases whenever changes are pushed to your repository. This eliminates manual tasks, improves productivity, and ensures a reliable release process. This process is a part of the broader CI/CD workflow, ensuring consistent and error-free releases.
In this guide, we’ll walk through setting up a GitHub Actions workflow that automates the release process using Semantic Versioning.
Understanding the Setup
Before diving into the implementation, let's look at the key components we'll be using to build our automation workflow:
- Semantic Versioning: This is a versioning system that follows the format
MAJOR.MINOR.PATCH
. - GitHub Actions: A CI/CD tool provided by GitHub that allows you to automate your workflows directly from your GitHub repository.
-
Packages we'll be using:
-
semantic-release
: A fully automatic version management and release publishing tool. -
@semantic-release/changelog
: Automatically generates and updates changelogs based on commit messages. -
@semantic-release/commit-analyzer
: Analyzes commits and determines the next version based on commit messages. -
@semantic-release/git
: Pushes changes made by the semantic-release (like the changelog) back to your Git repository. -
@semantic-release/github
: Creates GitHub releases and adds release notes automatically.
-
What is Semantic Versioning?
Semantic versioning (often abbreviated as SemVer) is a versioning scheme that aims to make it clear whether changes in your project are backward compatible, introduce breaking changes, or simply fix bugs. A typical SemVer version number looks like this: MAJOR.MINOR.PATCH
(e.g. v1.4.8).
- MAJOR version is incremented when you make incompatible API changes that breaks the current feature.
- MINOR version is incremented when you add functionality in a backward-compatible manner.
- PATCH version is incremented when you make backward-compatible bug fixes.
(Note: backward-compatible means the ability to be used with older/previous versions.)
Each update to the project can be classified into one of these categories, and semantic-release automates this process by updating the version automatically based on commit messages.
The Role of GitHub Actions in Continuous Deployment
GitHub Actions allows you to automate workflows directly in your GitHub repository. These workflows can run on various GitHub events like code pushes, pull requests, and more. In this blog, we’ll use GitHub Actions to automate our release process, from building to pushing version updates to the repository.
Why Automate Release?
Automating releases offers several benefits:
- Consistency: No manual steps for incrementing versions or tagging releases.
- Efficiency: Reduced time spent on repetitive tasks like updating changelogs, version numbers, and creating Git tags.
- Error-Free: Eliminates human errors during the release process.
- Reliability: The process is repeatable and can be reused across different repositories.
Automated Versioning with semantic-release
semantic-release
is a powerful tool that automates version management based on your commit messages. It relies on the commit message convention known as Conventional Commits. Here’s how it works:
-
Breaking changes (such as
feat!:
orfix!:
in commit messages) will trigger a major version bump.
fix!: update deprecated API endpoint
[v1.5.2 -> v2.0.0]
-
New features (e.g.,
feat:
in commit messages) will trigger a minor version bump.
feat: add new user login feature
[v2.0.5 -> v2.1.0]
-
Bug fixes (e.g.,
fix:
in commit messages) will trigger a patch version bump.
fix: update documentation
[v4.2.7 -> v4.2.8]
Generating the Changelog
As part of the semantic-release
process, a changelog is automatically generated. Here's an example of what the changelog looks like:
# [4.0.0](<https://github.com/arpanaditya/semantic-versioning-action/compare/v3.1.0...v4.0.0>) (2024-11-26)
* feat!: major update from dev BREAKING CHANGE: major update from dev ([fac5eec](<https://github.com/arpanaditya/semantic-versioning-action/commit/fac5eec5533c1fe3432f96986403efcfadbc79ae>))
### BREAKING CHANGES
* major update from dev
# [3.1.0](<https://github.com/arpanaditya/semantic-versioning-action/compare/v3.0.1...v3.1.0>) (2024-11-26)
### Features
* minor update from dev ([606258b](<https://github.com/arpanaditya/semantic-versioning-action/commit/606258b3318929182319b29a6a81eae0fabb138b>))
Step 1: Install the Required Packages
We need to install the required packages as development dependencies. Run the following command to install them:
npm install --save-dev @semantic-release/changelog@6.0.3 @semantic-release/commit-analyzer@10.0.4 @semantic-release/git@10.0.1 @semantic-release/github@11.0.1 @semantic-release/release-notes-generator@11.0.7 semantic-release@24.2.0
Step 2: Create a GitHbu Actions Workflow
Let’s create a .github/workflows/release.yml
file in your repository. This file will define the GitHub Actions workflow that will be triggered on every push to the repository.
Here’s the basic structure of the release.yml
workflow:
name: Release
on:
push:
branches:
- main # Triggers when code is pushed to the main branch
jobs:
release:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest # Runs on an Ubuntu runner
steps:
# Step 1: Checkout the repository code
- name: Checkout Repository
uses: actions/checkout@v3
# Step 2: Set up Node.js
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "20.x" # Use the Node.js version required for your project
# Step 3: Cache Node.js modules to speed up future builds
- name: Cache Node.js modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-node-modules-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-modules-
# Step 4: Install dependencies
- name: Install Dependencies
run: npm ci
# Step 5: Run semantic-release
- name: Run Semantic Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Provide the GitHub token for authentication
Breakdown of the Workflow Steps
Checkout the Repository: This step checks out the latest code from the repository so that GitHub Actions can work with the latest changes.
Set up Node.js: This action ensures that the correct version of Node.js is set up on the runner. In our case, we’re using Node.js version 20.x .
Cache Node.js Modules: GitHub Action caches the node_modules directory to speed up future builds. This is crucial for larger projects where the installation of dependencies can take time.
Install Dependencies: Using npm ci, this step installs the exact dependencies defined in the package-lock.json file, ensuring that the correct versions of packages are installed.
Run Semantic Release: This step uses the semantic-release package to automatically determine the type of release (major, minor, patch) based on commit messages. It also updates the version in package.json , generates a changelog, and publishes the release.
(Note: The GITHUB_TOKEN is a secure token automatically provided by GitHub for workflows running in your repository. You don’t need to manually create or add this token. It is preconfigured)
Step 3: Configure Semantic Release
Next, we need to configure the semantic-release
package. Create a release.config.js
file in the root directory of your project:
module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
'@semantic-release/git',
'@semantic-release/github',
],
};
Step 4: Commit message Conventions
Semantic release uses Angular Commit Message Conventions messages to determine the type of version bump (major, minor, patch). To follow this, you or your team should follow a Conventional Commit format:
fix: correct a bug
feat: add a new feature
feat!: breaking change BREAKING CHANGE: change that introduces backward incompatibility
We also can use tools like Commitizen Commitizen, and commitlint to enforce valid and consistent commit messages.
By using these commit messages, semantic-release
will automatically determine whether to bump the version and generate the necessary changelogs.
Step 5: Push and Test the Workflow
Once you have set up the workflow and configuration files, push the changes to your GitHub repository. This will trigger the GitHub Actions workflow based on the on_push event.
The action will:
Install the necessary dependencies.
Run Semantic Release to analyze your commits, bump the version, generate release notes, and update the changelog.
Create a new GitHub release and tag.
You can monitor the progress of the workflow in the Actions tab of your GitHub repository.
Conclusion
Automating releases with Semantic Versioning and GitHub Actions streamlines your development workflow, ensuring consistent, error-free versioning, changelogs, and releases. By integrating semantic-release and GitHub Actions, you eliminate manual tasks, reduce human error, and enhance productivity, allowing your team to focus on writing code rather than managing releases. This setup provides a scalable, reliable, and efficient way to handle versioning and publishing, ultimately improving the quality and transparency of your project’s development cycle.
Top comments (0)