Skip to content

Commit cdda78e

Browse files
authored
docs(ci): documenting the new developer workflow (#523)
1 parent 3e8c54e commit cdda78e

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

docs/conventional_workflow.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Conventional Commit Workflow
2+
3+
This document describes the development and release workflow for the Universal Numbers Library using conventional commits, git-cliff, and tag-based releases.
4+
5+
## Overview
6+
7+
The workflow separates **development** (branches + conventional commits) from **releasing** (git tags). No files on main are modified during a release, so in-flight branches never need to rebase due to version bumps.
8+
9+
## Conventional Commit Format
10+
11+
Every commit message (and PR title) follows this format:
12+
13+
```
14+
<type>(<optional scope>): <description>
15+
```
16+
17+
### Types
18+
19+
| Type | Meaning | Example |
20+
|------------|----------------------------------|----------------------------------------------------|
21+
| `feat` | New feature | `feat(dfloat): add decimal256 support` |
22+
| `fix` | Bug fix | `fix(posit): correct subnormal rounding` |
23+
| `docs` | Documentation only | `docs: update build instructions` |
24+
| `style` | Formatting, no logic change | `style(cfloat): fix indentation` |
25+
| `refactor` | Code change, no new feature/fix | `refactor(lns): simplify encoding logic` |
26+
| `perf` | Performance improvement | `perf(blas): vectorize dot product` |
27+
| `test` | Adding or fixing tests | `test(fixpnt): add overflow edge cases` |
28+
| `build` | Build system changes | `build(cmake): add AVX-512 detection` |
29+
| `ci` | CI/CD changes | `ci: add clang-18 to test matrix` |
30+
| `chore` | Maintenance, deps, etc. | `chore: update docker base image` |
31+
32+
### Scopes
33+
34+
Scopes are optional but recommended. Use the number system name or infrastructure area:
35+
36+
`posit`, `cfloat`, `fixpnt`, `lns`, `integer`, `dfloat`, `hfloat`, `dd`, `qd`,
37+
`bfloat16`, `areal`, `valid`, `einteger`, `edecimal`, `erational`, `efloat`, `ereal`,
38+
`blockbinary`, `microfloat`, `e8m0`, `mxblock`, `nvblock`,
39+
`blas`, `math`, `numeric`, `cmake`, `ci`, `docker`, `deps`
40+
41+
### Breaking Changes
42+
43+
Append `!` after the type to signal a breaking change:
44+
45+
```
46+
feat!: redesign number system API
47+
feat(posit)!: change template parameter order
48+
```
49+
50+
This indicates a major version bump when releasing.
51+
52+
## Day-to-Day Development
53+
54+
### 1. Create a feature branch
55+
56+
```bash
57+
git checkout main && git pull
58+
git checkout -b feat/decimal256
59+
```
60+
61+
Branch naming convention: `feat/`, `fix/`, `refactor/`, `docs/`, etc.
62+
63+
### 2. Work and commit
64+
65+
Use conventional commit messages for your commits:
66+
67+
```bash
68+
git commit -m 'feat(dfloat): add decimal256 significand handling'
69+
git commit -m 'test(dfloat): add decimal256 regression tests'
70+
git commit -m 'fix(dfloat): correct overflow in wide multiply'
71+
```
72+
73+
### 3. Push and create a PR
74+
75+
```bash
76+
git push -u origin feat/decimal256
77+
gh pr create --title 'feat(dfloat): add decimal256 support'
78+
```
79+
80+
The PR title must follow conventional commit format. The `conventional-commits.yml` workflow validates this automatically.
81+
82+
### 4. Merge
83+
84+
Use **squash merge** on GitHub. The PR title becomes the commit message on main. This keeps main's history clean with one conventional commit per PR.
85+
86+
### 5. Clean up
87+
88+
```bash
89+
git checkout main && git pull
90+
git branch -d feat/decimal256
91+
git push origin --delete feat/decimal256
92+
```
93+
94+
## Releasing
95+
96+
Releases are **decoupled** from development. You decide when to release. Commits accumulate on main and are grouped into a release when you push a tag.
97+
98+
### 1. Ensure main is ready
99+
100+
```bash
101+
git checkout main && git pull
102+
```
103+
104+
Verify CI is green on the latest main commit.
105+
106+
### 2. Preview the changelog (optional)
107+
108+
```bash
109+
# See what will be in the release notes
110+
git cliff --unreleased
111+
```
112+
113+
### 3. Tag the release
114+
115+
Use **single quotes** (bash interprets `!` in double quotes as history expansion):
116+
117+
```bash
118+
# Patch release (bug fixes only)
119+
git tag -a v4.0.1 -m 'fix: patch release description'
120+
121+
# Minor release (new features, backward compatible)
122+
git tag -a v4.1.0 -m 'feat: minor release description'
123+
124+
# Major release (breaking changes)
125+
git tag -a v5.0.0 -m 'feat!: major release description'
126+
```
127+
128+
### 4. Push the tag
129+
130+
```bash
131+
git push origin v4.1.0
132+
```
133+
134+
### 5. CI does the rest
135+
136+
The `release.yml` workflow triggers on the tag push and:
137+
138+
1. Generates release notes with git-cliff from all conventional commits since the previous tag
139+
2. Creates a GitHub Release with the structured changelog
140+
3. Builds and pushes the Docker image to Docker Hub
141+
142+
No files on main are modified. No rebase cascade for in-flight branches.
143+
144+
## Version Resolution
145+
146+
CMakeLists.txt derives the version from the most recent git tag using `git describe --tags`. This means:
147+
148+
- **In a git checkout**: version comes from the tag automatically
149+
- **From a source tarball** (no `.git`): falls back to the hardcoded `UNIVERSAL_FALLBACK_VERSION_*` variables in CMakeLists.txt
150+
- **Override**: pass `-DUNIVERSAL_VERSION_MAJOR=X -DUNIVERSAL_VERSION_MINOR=Y -DUNIVERSAL_VERSION_PATCH=Z` to cmake
151+
152+
The fallback version should be updated periodically in a normal commit (e.g., after a major release).
153+
154+
## Versioning Policy
155+
156+
The project follows [Semantic Versioning](https://semver.org/):
157+
158+
- **MAJOR** (`feat!:` or `BREAKING CHANGE:` footer): incompatible API changes
159+
- **MINOR** (`feat:`): new functionality, backward compatible
160+
- **PATCH** (`fix:`): bug fixes, backward compatible
161+
162+
You decide the version number when you create the tag. The conventional commit types are a guide, not an automated enforcement.
163+
164+
## Tools
165+
166+
| Tool | Purpose | Config File |
167+
|------|---------|-------------|
168+
| [git-cliff](https://git-cliff.org/) | Changelog generation from conventional commits | `cliff.toml` |
169+
| [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) | PR title linting | `.github/workflows/conventional-commits.yml` |
170+
171+
### Installing git-cliff locally
172+
173+
```bash
174+
# Via cargo
175+
cargo install git-cliff
176+
177+
# Via brew (macOS/Linux)
178+
brew install git-cliff
179+
```
180+
181+
### Useful git-cliff commands
182+
183+
```bash
184+
# Preview unreleased changes (since last tag)
185+
git cliff --unreleased
186+
187+
# Generate full changelog
188+
git cliff -o CHANGELOG.md
189+
190+
# Show changes between two tags
191+
git cliff v3.105.2..v4.0.0
192+
193+
# Show latest release only
194+
git cliff --latest
195+
```
196+
197+
## Quick Reference
198+
199+
```
200+
Development:
201+
git checkout -b feat/thing # branch
202+
git commit -m 'feat(x): ...' # conventional commits
203+
gh pr create --title 'feat(x): ..' # PR with conventional title
204+
squash merge # clean commit on main
205+
206+
Releasing:
207+
git cliff --unreleased # preview changelog
208+
git tag -a v4.1.0 -m 'description' # tag (use single quotes!)
209+
git push origin v4.1.0 # push tag -> CI creates release
210+
211+
Branch cleanup:
212+
git branch -d feat/thing # delete local
213+
git push origin --delete feat/thing # delete remote
214+
```

0 commit comments

Comments
 (0)