Skip to main content

2 posts tagged with "semantic-release"

View All Tags

Release Go modules automatically

· 5 min read

If you happen to have some awesome Golang codes, you probably want to share it with others. Once sharing it, you will need to turn it into a Go module and to version it. Therefore it can be managed easier and to be more friendly to users.

Well, releasing a Go module isn't so difficult but neither is it straightforward. Moreover, you're an engineer so you want to automate everything including this manual work.

Below is my experience when trying to automate the process of releasing Go modules via semantic-release and Github Actions. It wasn't so smooth but life is much easier after that.

Prerequisites

Commit message format

Our commit messages format must follow a convention that is understood by semantic-release. By default, semantic-release uses Angular Commit Message Conventions but it can be changed by the configuration.

Here is an example of the release type that will be done based on commit messages:

Commit messageRelease type
fix(pencil): stop graphite breaking when too much pressure appliedPatch Release
feat(pencil): add 'graphiteWidth' optionMinor (Feature) Release
perf(pencil): remove graphiteWidth option

BREAKING CHANGE: The graphiteWidth option has been removed.
The default graphite width of 10mm is always used for performance reasons.
Major (Breaking) Release

Automated tests

We all want our modules to be released with its best in quality. The only way to achieve that is to take testing seriously. Since releasing is done automatically, so be testing. Therefore, I would assume the CI is already implemented with proper automated testing. And we will only trigger the release step if all test cases are passed.

Setup semantic-release

Configuration

For Node modules, we can straightly use the default configuration. For Go modules, it requires some modifications as Golang doesn't use NPM repository. Thus, we will need to add .releaserc.json, which is semantic-release's configure file, to the root folder in our repository:

{
"branches": [
"main",
{
"name": "beta",
"prerelease": true
}
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github"
]
}

There are a few things I would like to highlight here:

  • @semantic-release/npm is removed from the default plugins config because we don't need to publish our Go module to NPM repo. It's obvious, right?
  • main is used instead of master which is the release branch by default. For those who may not know, Github recently renames the default branch from master to main. Reference.
  • beta is used as a pre-release branch when we're in a heavy development phase with frequent breaking changes. To learn more about release workflow, you can look into semantic-release wiki. I'm really impressed by how well it's documented.

For generating changelog, we will need to include two more plugins:

I don't see CHANGELOG.md scale well and we already have git history so not including these steps makes things easier.

Github Actions

Then, we add a new job in Github Actions workflow for releasing. It should look simple like this:

jobs:
test:
# an amazing test configs
release:
name: Release
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release
  • needs: test means the release job is only executed if the test job is successful.
  • npx semantic-release is the command to execute semantic-release. GITHUB_TOKEN will be needed for tagging.
  • semantic-release is able to detect if the job is triggered by pull_request and ignore it. Therefore, we won't need to worry about skipping the job from pull requests.

Pre-releases

Sometimes, the module is in a heavy development and it's expected to have multiple breaking changes. In this situation, a pre-release version like v1.0.0-beta.12 is needed before a stable one. semantic-release supports this pretty well. All we need to do is:

  • Create a beta branch and commit your changes here. Relevant commits in this branch will trigger semantic-release to create a new pre-release.
  • Once the module becomes stable, we merge it to the main branch. The merge should trigger semantic-release to create a new stable version.

Summary

semantic-release is a handy library. It can free your hands from release modules in a timely manner. One downside is that a buggy module can be released if automated tests are not properly implemented.

semantic-release is not the only package out there to automate the process. Another alternative written in Golang is go-semantic-release. go-semantic-release doesn't have as many plugins as semantic-release but it works better with Go module. Especially, it allows starting versioning with 0.x.x which is a Go's convention for pre-releases.

References

Releases with Semantic-release

· 3 min read

I have been writing a coupe of NPM packages recently and publishing those NPM packages was quite manual and repetitive. Including bumping versions, changelog and Github releases, the amount of manual work will cost plenty of time. It could easily take up to 30 minutes to have a nicely published NPM package. I then googled the problem and found sementic-release. The tool is very handy as it provides a bunch of cool features due to its plugins system.

semantic-release supports CI workflow as well as local workflow; however, I only used it with a local workflow.

Installation

In order to start using semantic-release, you will need to setup both NPM token as well as Github token in environment variables. I store them in one of my dotfiles for convenience. An example of my .localrc:

export GH_TOKEN=someveryrandomgithubtoken
export NPM_TOKEN=anothersuperrandomnpmtoken

If you not sure how to generate those tokens, semantic-release-cli can help to generate them in few minutes and initialize configurations for a project. I used it in my first project to get tokens and to be familiar with the tool. I then no longer use it as it keeps asking passwords and MFA token which is inconvenient:

yarn global add semantic-release-cli
semantic-release-cli setup

semantic-release-cli basically adds semantic-release as a development dependency and a couple of configs to package.json.

If GH_TOKEN and NPM_TOKEN are configured, it might be faster to add semantic-release manually:

npm install --save-dev semantic-release

I updated scripts in package.json for convenience:

{
"scripts": {
"release": "semantic-release"
}
}

So I only need yarn release to access its commands.

Configurations

I use release.config.js for storing configurations. By default, the configuration should be like this:

module.exports = {
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github",
],
};

With the default configurations, semantic-release will analyze commits using Angular conventions to generate release notes. It then publishes to NPM repository and publishes a new release in Github. It also update package.json for the new package version but committing it. Therefore, an additional plugin is required in order to push the change to Github.

As I also want to generate CHANGELOG and commit the change to my repository automatically, I added two more plugins:

yarn add -D @semantic-release/changelog @semantic-release/git

and in release.config.js:

module.exports = {
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git",
],
};

The two new plugins will generate CHANGELOG.md and push it together with package.json to github. You can read more about them in:

Release

After all of those configurations, Release is super simple. After saving your changes to the repository, you can run:

yarn release -d

to review your release notes. After verifying, you can use the following command to publish:

yarn release --no-ci

Then a new version of your package will be published to NPM and Github.

CI

I didn't set up a CI as one-command release is more than enough for me. If you want to get of your hands free, you can try with Github Actions via this document. Another cool thing about semantic-release is that it can analyze the commit history to decide to change the version accordingly. Basically, everything can be automated.