| name | commit-and-release |
| description | Guide for writing Conventional Commit messages, committing changes, and creating releases in this repository. Use when asked to commit, write a commit message, stage files, push, or create/cut a release.
|
Commit message format
All commits follow Conventional Commits:
<type>(<scope>): <description>
Types:
| Type | When to use |
|---|
feat | New service, new feature, new config capability |
fix | Correcting a bug, misconfiguration, or broken behavior |
chore | Tooling, dependencies, version bumps |
ci | Changes to GitHub Actions workflows or lefthook config |
docs | Documentation only |
refactor | Code/config restructure without behavior change |
Scope is the service folder name or tool involved (e.g. immich, traefik, renovate, mise, cog). Multi-service changes may omit the scope.
Breaking changes are indicated in one of two ways (or both):
-
! immediately before the colon: feat(traefik)!: remove legacy middleware
-
A BREAKING CHANGE: footer in the commit body (MUST be uppercase):
feat(traefik): remove legacy middleware
BREAKING CHANGE: chain-auth middleware has been renamed to chain-oauth
| Commit type | Version bump |
|---|
fix | PATCH |
feat | MINOR |
BREAKING CHANGE | MAJOR |
Examples
feat(radarr): add compose stack with Traefik labels
fix(immich): correct OAuth roleClaim field name
ci: add zizmor workflow security scan
chore(mise): bump git-cliff to 2.12.0
docs(architecture): document init container pattern
Verify before committing
Use cog verify to check a message before committing:
mise exec -- cog verify "feat(immich): add hardware transcoding"
Exit code 0 = valid. The commit-msg lefthook runs this automatically on every git commit.
Commit workflow (step-by-step procedure)
Follow these steps in order every time the user asks to commit, push, or "commit & push".
Step 1 — Inspect what changed
git diff --stat HEAD
git status --short
Use this to understand the scope: which services, which file types, how many files.
Step 2 — Stage the files
Prefer explicit paths over git add .:
git add services/immich/compose.yaml docs/ARCHITECTURE.md
If the user has already staged files, skip this step.
Step 3 — Derive and validate the commit message
Draft a message following the Conventional Commits format below.
Then validate it with cog verify before asking the user:
mise exec -- cog verify "feat(immich): add hardware transcoding support"
Exit code 0 = valid. If it fails, fix the message and retry.
Step 4 — Ask the user to confirm the commit message
MANDATORY: Before committing, use the vscode_askQuestions tool to present the proposed commit message and ask for confirmation. Provide the message as an option the user can click — do not just print it in chat.
Example question structure:
- Header: "Commit message"
- Question: "Does this commit message look right?"
- Options: the proposed message as a selectable option, plus "Let me edit it" as a free-form alternative
- Set
allowFreeformInput: true so the user can type a corrected message
If the user selects the proposed message, proceed. If they provide a different message, use that one and re-run cog verify before continuing.
Step 5 — Run the pre-commit hook
Run lefthook explicitly so linting errors are surfaced before the commit:
mise exec -- lefthook run pre-commit
If any check fails, stop and report the errors. Do not commit until all checks pass.
Step 6 — Commit
git commit -m "<confirmed-message>"
The commit-msg hook will re-run cog verify automatically. Both hooks must pass.
Step 7 — Push
git push
Making a commit
-
Stage the relevant files — prefer explicit paths over git add .:
git add services/immich/compose.yaml docs/ARCHITECTURE.md
-
Commit with a Conventional Commit message:
git commit -m "feat(immich): add hardware transcoding support"
The pre-commit hook runs all linters (yamlfmt, shellcheck, checkov, trivy, etc.) automatically. The commit-msg hook validates the message with cog verify. Both must pass.
-
For multi-paragraph commit bodies, write the subject line first, leave a blank line, then add detail:
git commit -m "feat(immich): add hardware transcoding support
- Mount /dev/dri for VAAPI access
- Add cap_add: SYS_RAWIO with justification comment
- Update ARCHITECTURE.md init container table"
Creating a release
Prerequisites: working tree must be clean (all changes committed) and in sync with origin.
Pull latest changes first
Always sync before releasing to avoid push rejections:
git pull origin main
Dry-run first
Always preview before releasing:
mise exec -- cog bump --minor --dry-run
mise exec -- cog bump --patch --dry-run
Cut the release
mise exec -- cog bump --minor
cog bump executes this pipeline automatically:
- Calculates the next semver version from conventional commits since the previous tag
- Runs
git-cliff to regenerate CHANGELOG.md (range configured in cog.toml)
- Runs
dprint fmt CHANGELOG.md to ensure it passes CI
- Stages
CHANGELOG.md and creates a chore(version): <version> commit
- Creates the
v<version> git tag
- Pushes the commit and tag to
origin
The tag push triggers .github/workflows/release.yml, which generates release-scoped notes with git-cliff --latest --strip all and auto-creates the GitHub Release — no manual steps on GitHub.com needed.
Release complete
After every successful release, end with a celebrative message. Be enthusiastic, reference the version number, and congratulate the team on shipping. Make it fun — this is a milestone worth celebrating! Example:
"SHIP IT! v0.12.0 is now LIVE and sailing into production! The stacks are deployed, the changelog is fresh, and the CI is green. Take a beer — you've earned it!"