Tagged releases with attached builds are great; especially when you don’t need to tag, build, upload, and release it yourself. Enter Semantic Release, an ‘aromantic’ automated release system.
Working in the tech industry, you’ve probably heard of semantic versioning: the practice of marking releases with three numbers, separated by periods, denoting the major, minor, and patch version. The ‘official’ semver website has a detailed explanation, which relies on the technical language of the RFC-2119 versioning specification. Professionally, semantic versioning is used to ensure package managers can calculate an effective map of dependencies, ensuring breaking changes are not accidentally relied upon by any given program.
Why release your own code automatically with semantic versioning? At this point in history, it’s a best practice. At the very least, you’ll have a nice version history and, on platforms like Github, a nice .zip
of your code and a build at that point in time that you can archive. At best, it provides a very well-thought-out, clean mechanism for communicating how much your software has changed to those who rely on it.
On to the meat; how do I use Semantic Release?
If you’re a JavaScript user, you’ll want to take a look at the JavaScript implementation of semantic release. As the projects I maintain are mostly written in Python, I opted for the python implementation instead, as it would be easier to integrate with the Django projects and python libraries I maintain.
Implementation
In the root of your repository, you ought to already have a setup.cfg
file. If not, you can use this Django app
for reference. Typically this python setup file contains config values for all tools used in the repository, like mypy
or flake8
. At the end of the file, add these lines:
# setup.cfg
[semantic_release]
# Replace 'democracy' with your application's package
version_variable = democracy/__init__.py:__version__
commit_author = "actions-user <[email protected]>"
hvcs = github
# The build should not be made or uploaded anywhere:
build_command = echo 'Semantic release build step running.'
upload_to_pypi = False.
upload_to_release = False
# Change f*&%!*& branch to 'main' if needed.
branch = master
Within your package (the main folder of your python project,) in the directory’s __init__.py
file, add this line if it does not already exist:
__version__ = "0.1.0"
Finally, you’ll need to add a step to your CI. I’m using Github Workflows today, but you can use anything that allows job dependencies and secrets storage. Add the following step to your workflow file, ci.yml
:
# ci.yml
name: CI
on: push
jobs:
lint:
# The rest of the linting job appears here.
test:
# The rest of the testing job appears here.
semver:
runs-on: ubuntu-latest
needs: [test, lint]
# Make sure to change this to f*&%*!*^ 'main' if needed.
if: github.ref == 'refs/heads/master'
env:
# Add this to your secrets. Details below.
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- uses: actions/checkout@v2
with:
# Also modify this to f*&%*!*^ 'main' if needed.
ref: 'refs/heads/master'
# A fetch depth of zero grabs all commits,
# rather than just the most recent.
fetch-depth: 0
- name: Set up Python 3.8.*
uses: actions/setup-python@v2
with:
python-version: 3.8.*
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install python_semantic_release
- name: Configure Git
run: |
git config --global user.name "actions-user"
git config --global user.email "[email protected]"
- name: Semantic Release Publish
run: semantic-release publish -v DEBUG
The final configuration step is to add the GH_TOKEN
secret to your repository. You’ll be able to generate this at github.com/settings/tokens
, and add it to your repositories secrets at settings → secrets.
Congratulations! You’ve set up semantic release on your repository. At this point, you’ll be able to push and merge commits and pull requests with the following tags, and the semantic release program will check the commits for the most severe change, make a new release and tag, build a release, and add notes to your changelog. In your repository, the commit will look like this:
Your shiny new release, with changes and assets, will appear like so:
Final Thoughts
Semantic release, when configured correctly, is an invaluable time-saving tool (as long as you name your commits and pull requests correctly!)
Here’s a list of the tools and resources mentioned in this article:
And, as always, thank you for reading!
Comments