5.4 KiB
Release Process
This document covers how releases are created, what triggers Docker image publishing, and how to roll back if needed.
Overview
BookOrbit uses semantic-release for automated versioning and GitHub Release creation. Releases are triggered manually via workflow_dispatch and produce:
- A Git tag (
vX.Y.Z) - A GitHub Release with auto-generated release notes
- A Docker image pushed to GHCR (
X.Y.Z+latest)
PR Requirements
Squash merge required
All PRs to main must use squash merge. The squash commit message becomes the commit that semantic-release analyzes for version bumps.
PR title format
PR titles must follow the commit guidelines:
<type>(<scope>): <summary>
The PR title is validated by commitlint in the release workflow. Invalid titles will fail the Lint PR Title check.
Types that trigger releases
| Type | Release | Notes |
|---|---|---|
feat |
minor | New features |
fix |
patch | Bug fixes |
perf |
patch | Performance improvements |
security |
patch | Security patches |
db |
patch | Database/schema changes |
style |
patch | Visual/CSS changes |
revert |
none | No release |
refactor |
none | No release |
docs |
none | No release |
test |
none | No release |
build |
none | No release |
ci |
none | No release |
chore |
none | No release |
Breaking changes (BREAKING CHANGE: in footer) always trigger a major release regardless of type.
Manual Release Runbook
Releases are triggered manually from the GitHub Actions UI.
Prerequisites
- All changes are merged to
main. - CI has passed for the latest commit on
main.
Steps
- Go to Actions > Release workflow.
- Click Run workflow.
- Select
mainbranch. - Click Run workflow.
The workflow will:
- Verify the dispatch is from
main. - Verify CI has passed for the current commit.
- Run semantic-release to determine the next version.
- Create a Git tag and GitHub Release with release notes.
- Build, scan, and push the Docker image (if a new version was published).
No release produced
If all commits since the last release are non-releasable types (chore, docs, test, build, ci, refactor), semantic-release will skip the release. The Docker publish job will also be skipped.
Docker Image Publishing
Release images
The release.yml workflow publishes Docker images after a successful release:
ghcr.io/bookorbit/bookorbit:<X.Y.Z>- version-specific tagghcr.io/bookorbit/bookorbit:latest- latest stable release
Images are scanned with Trivy before push. If critical or high vulnerabilities are found, the push is blocked.
Continuous validation images
The container-image.yml workflow still runs on CI success (push to main) and publishes validation images with branch and SHA tags. These are not release images.
Rollback
Rolling back to a previous release
To deploy a previous version:
# In your production docker-compose.yml or .env, set:
APP_IMAGE=ghcr.io/bookorbit/bookorbit:X.Y.Z
Replace X.Y.Z with the version you want to roll back to, then redeploy:
pnpm prod:down
pnpm prod:up
Deleting a bad release tag
If a release was created in error and needs to be removed:
# Delete tag locally and remotely
git tag -d vX.Y.Z
git push origin :refs/tags/vX.Y.Z
Then delete the corresponding GitHub Release from the Releases page.
Release Workflow Architecture
The release.yml workflow has four jobs:
┌──────────────┐ ┌──────────────────┐
│ commitlint │ │ release-dry-run │ (PR only)
└──────────────┘ └──────────────────┘
┌──────────────┐ ┌──────────────────┐
│ release │────>│ docker-publish │ (workflow_dispatch only)
└──────────────┘ └──────────────────┘
- commitlint: Validates PR title format (PR only).
- release-dry-run: Runs semantic-release in dry-run mode to validate config (PR only).
- release: Creates the actual release (manual dispatch only). Outputs
published,version, andtag. - docker-publish: Builds and pushes Docker image (only when a release was published).
Concurrency
- PR checks cancel older runs for the same PR.
- Manual release runs are serialized and never canceled mid-flight.
- PR checks and manual releases do not block each other.
Configuration Files
| File | Purpose |
|---|---|
.releaserc.json |
semantic-release config (plugins, release rules) |
commitlint.config.cjs |
commitlint config (type/scope validation) |
.github/workflows/release.yml |
Release and Docker publish workflow |