An Automated Release Pipeline on GitHub Actions
Large engineering organizations can ship software many times per day — Amazon was already deploying every 11.6 seconds in 2011. Most teams won't need that scale, but the underlying practices are no longer exclusive to companies with dedicated release-engineering staff. With GitHub Actions and a few well-established conventions, a small team can automate versioning, changelog generation, and publishing without much ongoing effort.
This article walks through the essential building blocks: a simple branching model, semantic versioning, conventional commit messages, and a release automation tool. The examples use NPM packages, but the same approach applies to Python packages or Docker containers.
A Lightweight Branching Strategy
GitHub Flow is a minimal branching model that suits most teams working on modular codebases or microservices. The rules are deliberately few:
mainis always in a releasable state.- Create a branch from
mainfor each change. - Open a Pull Request when the work is complete.
- Merge the Pull Request into
mainafter approval. - Create a release by tagging
main.
This model works best with short-lived branches and small changes. If you keep feature branches open for weeks, you'll spend increasing time resolving merge conflicts. Frequent, small releases reduce the risk associated with each deployment, and hotfix branches become less necessary — urgent fixes can simply be treated as regular changes that flow through the same pipeline.
Versioning with SemVer
Semantic versioning communicates the impact of a release in the version number itself, formatted as vX.Y.Z:
X— breaking change.Y— new feature.Z— bug fix or non-visible change.
Users can read the version and know whether an upgrade requires attention or can be done automatically.
Commit Message Conventions
Conventional Commits standardize how commit messages are written, enabling tooling to parse the Git history meaningfully. The core structure follows a type prefix with an optional scope, and importantly, a commit may declare a BREAKING CHANGE.
Three types matter most in practice:
fix— a bug fix.feat— a new feature.BREAKING CHANGE— requires user action.
This convention is the foundation for automatic version bumping and release-note generation.
Release Automation with Standard Version
Standard Version reads your Git log and performs the mechanical parts of a release:
- Generates release notes from conventional commits.
- Determines the next version number from existing Git tags.
- Bumps the version in
package.json. - Creates a commit with the release notes and version change.
- Tags that commit.
Install it with NPM and define a script in package.json, or run it with npx. The tool can be triggered by your CI pipeline after merges, which makes every merge to main a potential release.
One crucial detail is avoiding an infinite build loop. Standard Version commits and pushes changes, which would normally trigger another workflow run. Adding a [skip ci] marker to the commit message tells GitHub Actions to ignore that commit. Configure this in package.json alongside the release script.
The GitHub Actions Workflow
GitHub Actions is configured with YAML files placed in a .github/workflows directory. A minimal example defines triggers, jobs, and steps. To have the workflow commit and push back to the repository, only a standard git config step is required in the job.
The complete setup lives in two places:
package.json— holds release tooling configuration and thereleasescript..github/workflows/<your-workflow.yml>— defines when and how the pipeline runs.
What the Release Step Does
When a push to main triggers the workflow, npm run release executes and produces a complete release:
- Writes a new section in
CHANGELOG.md. - Computes the next version from tags.
- Bumps
package.json. - Creates the commit with those updates.
- Tags the commit.
The subsequent git push --follow-tags origin main pushes both the new tag and the release commit back to the repository. The entire release decision becomes a matter of what commit messages contain.
Adjusting the Cadence
Releasing on every merge is fast and convenient when you have a strong test suite that runs before the workflow executes. If that cadence feels aggressive, the pipeline can be adapted for manual triggering. The core value remains: versioning, changelog, and tagging are automated, reproducible, and documented entirely in Git history.



