There are a multitude of ways to release software. In this article we will be discussing deployment of software with Semantic Release, Conventional Commits and GitHub actions.
In an Agile world we want to release software often. So the question becomes how do we release software in such a way that we can release often, not break existing deployments and keep track of what was released - without the need for manual reporting on features implemented and bugs fixed.
So how do we go about releasing and deploying this.
Starting with Conventional commits
Conventional commits are git commit messages that have a defined structure to make commits human and machine readable. Here are what a few typical commits may look like.
feat(data): add JSON file with 1 meme entry
fix(data): correct the path of meme
build: add new script command for tests
feat(header): add Header component
Each commit is prefixed with a type - feat
, fix
, docs
, build
etc - see documentation for full list. The type is followed by optional scope surrounded by parenthesis to describe the thing being worked on feat(component-name)
, docs(component-name)
etc.
As a team, all developers must follow this convention in order for Semantic Release to work correctly. This is because these commits will be what get added in the release notes generated by Semantic Release.
[Developers sign up for this convention typically at the start of a project]
Semantic Versioning
Semantic versioning or SemVer for short is a specification that describes how software should be versioned. When you see a software version like 12.6.1
, which is very common these days, the 12
in this case is the MAJOR version, the 6
the MINOR version and the 1
a PATCH version.
A MAJOR version number is incremented by 1 (usually) to describe this new version is incompatible with the previous version, so it is a major change. The MINOR version number is also incremented by 1 which describes new functionality has been added in a backwards compatible manner. The PATCH version describes, what usually are, bug fixes to the existing software version.
Semantic Release
Semantic Release uses the specification designed by Semantic Versioning (SemVer) and couples that with Conventional Commits and a CI (continuous integration) environment to create fully automated releases.
Example of Semantic Release in GitHub
Semantic Release for GitHub
So we know that we need to use Conventional Commits, and that Semantic Releases uses those to generate releases and increment the software version. But how do releases get generated in GitHub? This is where the GitHub Semantic Release package comes in.
GitHub actions
GitHub Actions is a tool used for automating software development workflows, such as building, testing, and deploying code. When a workflow is triggered, GitHub Actions runs a series of steps in a virtual environment, such as running a script, checking out code, or deploying to a server. We will create a GitHub action by adding a release.yml
file in to the .github/workflows
folder in the repo.
Getting Started
Let’s now create a barebones repository structure to demonstrate how Conventional Commits, Semantic Release and GitHub Actions all work together. Be sure to have the latest Node installed on your machine.
- Create new repo and clone it to your machine
-
Change directory to cloned repository and initialise an NPM project
cd dev-project-2023 npm init -y
This create a new Node project which allows us to take advantage of NPM and many packages that facilitate our development
-
Install Jest
yarn add jest
Jest is a testing framework, setup here just as an example for the project.
-
Set up files
- Create an
index.js
file - this is typically where our application might start from
function get2() { return 2; } module.exports = get2;
b. Create a
test.js
file
const get2 = require("./index.js"); test("Runs get2 returns 2", () => { expect(get2()).toBe(2); });
- Create an
-
Install SR and GHSR - Lets install SemanticRelease and GitHub Semantic Release packages
yarn add semantic-release github-semantic-release
-
Create an
.releaser.json
file
{ "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/github" ], "branches": ["main"] }
-
Create a
.release.yml
file inside.github/workflows
folder
name: Release "on": push: branches: - main jobs: release: name: release runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 14.17 - run: yarn install --frozen-lockfile - run: npx semantic-release env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
-
Secrets
Secrets are encrypted variables that we use for authentication needed for the GitHub Semantic Release package to use. The secret (
secrets.GH_TOKEN
) will contain your personal access token that you will need to generate in the settings tab of the repo. Follow the instructions here https://github.com/semantic-release/github#configuration -
Create a new branch called
next
offmain
- Create a feature branch called
feature-branch-x
offnext
- Create a feature branch called
-
Conventional commits
- Make a change any change, lets say to the function and test file. And commit:
feat(index): change function
function get3() { return 3; } module.exports = get3;
test(index): change test file
const get3 = require("./index.js"); test("Runs get3 returns 3", () => { expect(get3()).toBe(3); });
Merge feature branch back into
next
List of tags and releases
Here we can see that after making several changes, how a tag is created and a subsequent release generated.
Conclusion
Together Semantic versioning, conventional commits, Github Semantic Release, and Github Actions form a powerful suite of tools that can help to streamline the software development process and ensure the delivery of high-quality software releases. By utilizing these tools, developers can work more efficiently, reduce the risk of errors, and focus on delivering valuable software to users.
Top comments (0)