mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
66056a6eb9
Establish native GitHub synchronization, scoped translation PR checks, locale safeguards, semantic-release handling, and contributor guidance.
287 lines
10 KiB
Markdown
287 lines
10 KiB
Markdown
# Commit Message Guidelines
|
|
|
|
Every commit tells a story. A well-written commit message makes it easy to understand why a change was made, trace regressions, and produce a meaningful changelog. These guidelines define the format for all commits to this repository.
|
|
|
|
## Format
|
|
|
|
```
|
|
<type>(<scope>): <summary>
|
|
|
|
[body]
|
|
|
|
[footer]
|
|
```
|
|
|
|
The **header** is required on every commit and must follow the format described below.
|
|
|
|
The **body** is required on all commits except `docs`. When present, it must be at least 20 characters and written in the imperative mood.
|
|
|
|
The **footer** is optional. Use it to reference issues, close PRs, or document breaking changes.
|
|
|
|
---
|
|
|
|
## Header
|
|
|
|
```
|
|
<type>(<scope>): <summary>
|
|
│ │ │
|
|
│ │ └─ imperative mood, lowercase, no period at the end
|
|
│ │
|
|
│ └─ Scope (optional): auth|books|library|metadata|kobo|opds|reader|
|
|
│ collections|annotations|authors|series|cover|
|
|
│ users|stats|notifications|settings|scanner|
|
|
│ email|audit|smart-scope|types|docker|deps|server|client
|
|
│
|
|
└─ Type: feat|fix|i18n|db|perf|refactor|style|docs|test|build|ci|chore|security|revert
|
|
```
|
|
|
|
The `<type>` and `<summary>` fields are required. The `(<scope>)` field is optional.
|
|
|
|
### Type
|
|
|
|
The type signals the intent of the change at a glance.
|
|
|
|
| Type | When to use |
|
|
| ---------- | -------------------------------------------------------------------------------------------------------- |
|
|
| `feat` | Introduces a new feature or user-visible capability |
|
|
| `fix` | Patches a bug in existing behavior |
|
|
| `i18n` | Adds or updates translations and localization catalogs |
|
|
| `db` | Adds or modifies a Drizzle schema, generates a migration, or changes seed data |
|
|
| `perf` | Improves performance without changing observable behavior |
|
|
| `refactor` | Restructures code without fixing bugs or adding features |
|
|
| `style` | Visual/CSS-only changes: Tailwind tweaks, spacing, color token adjustments |
|
|
| `docs` | Documentation changes only |
|
|
| `test` | Adds or corrects tests without touching production code |
|
|
| `build` | Changes to the build system, tooling config, or external dependencies (Dockerfile, tsconfig, pnpm) |
|
|
| `ci` | CI/CD pipeline changes: GitHub Actions workflows and scripts |
|
|
| `chore` | Routine maintenance that does not fit any other category |
|
|
| `security` | Addresses a security vulnerability; preferred over `fix` so security patches are identifiable in history |
|
|
| `revert` | Reverts a previous commit; the body must reference the reverted SHA and explain why |
|
|
|
|
> If a change genuinely spans multiple types (for example, it adds a feature and fixes a bug), split it into two commits. If that is not practical, use the type that best represents the dominant intent.
|
|
|
|
### Scope
|
|
|
|
Scope is optional but strongly encouraged. It narrows the type to the affected area of the codebase, making the log significantly more readable.
|
|
|
|
Use one scope from the table below. If a change affects multiple areas, use the most dominant one.
|
|
|
|
| Scope | What it covers |
|
|
| --------------- | ------------------------------------------------------------- |
|
|
| `auth` | Authentication, authorization, JWT, OIDC, sessions |
|
|
| `library` | Library management, file system scanning |
|
|
| `books` | Book data, CRUD, book-level state |
|
|
| `authors` | Author data and management |
|
|
| `series` | Book series grouping and management |
|
|
| `cover` | Book cover image storage, retrieval, and optimization |
|
|
| `metadata` | Metadata providers, fetch logic, quality scoring, preferences |
|
|
| `kobo` | Kobo device sync and integration |
|
|
| `opds` | OPDS catalog endpoints |
|
|
| `reader` | In-app reader, reading position, reader preferences |
|
|
| `collections` | Collections and shelf management |
|
|
| `annotations` | Highlights, bookmarks, notes |
|
|
| `users` | User management, profiles, roles |
|
|
| `stats` | Reading sessions, statistics, progress tracking |
|
|
| `notifications` | In-app and email notifications |
|
|
| `settings` | Application settings and configuration |
|
|
| `scanner` | File scanner and upload pipeline |
|
|
| `email` | Email providers, templates, and send preferences |
|
|
| `audit` | Audit logging and event tracking |
|
|
| `smart-scope` | Custom Smart Scopes and collection views |
|
|
| `types` | Shared types in `packages/types/` |
|
|
| `docker` | Dockerfile and Docker Compose files |
|
|
| `deps` | Dependency upgrades (pair with `build` or `chore`) |
|
|
| `server` | Backend-wide changes with no single-module scope |
|
|
| `client` | Frontend-wide changes with no single-module scope |
|
|
|
|
### Summary
|
|
|
|
The summary is a short, imperative description of what the commit does.
|
|
|
|
Rules:
|
|
|
|
- Use the imperative mood: "add", "fix", "remove" (not "added" or "adds")
|
|
- Start with a lowercase letter
|
|
- No period at the end
|
|
- Keep it under 72 characters
|
|
- Describe **what** the commit does, not **why**; that belongs in the body
|
|
|
|
---
|
|
|
|
## Body
|
|
|
|
Write a body when the **why** behind the change is not obvious from the header alone.
|
|
|
|
When to write a body:
|
|
|
|
- The motivation is not clear from the summary
|
|
- The change has side effects, tradeoffs, or gotchas worth calling out
|
|
- You are reverting a commit; reference the SHA and explain the reason
|
|
- The approach taken deserves a brief explanation
|
|
|
|
Format:
|
|
|
|
- Separate from the header with a blank line
|
|
- Use the imperative mood, consistent with the summary
|
|
- Wrap lines at ~100 characters
|
|
- Explain **why** this change exists, not **what** changed; the diff already shows that
|
|
|
|
---
|
|
|
|
## Footer
|
|
|
|
Use the footer to link related issues or PRs, or to announce breaking changes.
|
|
|
|
### Linking issues and PRs
|
|
|
|
```
|
|
Closes #123
|
|
Fixes: #456
|
|
RESOLVED owner/repo#789
|
|
Ref #101
|
|
```
|
|
|
|
GitHub-supported closing keywords are: `close`, `closes`, `closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, `resolved` (case-insensitive; optional colon is allowed, for example `Closes: #123`).
|
|
|
|
Use `Ref #<issue>` for a related issue that should stay open.
|
|
|
|
`Ref` is valid for commit footers, but it does not satisfy the PR-description requirement in CI (PR descriptions must include a GitHub closing keyword).
|
|
|
|
### Breaking changes
|
|
|
|
If the commit introduces a breaking change, open the footer with `BREAKING CHANGE:` followed by a brief summary, a blank line, and clear migration instructions.
|
|
|
|
```
|
|
BREAKING CHANGE: rename BOOKS_PATH env var to LIBRARY_PATH
|
|
|
|
Update your .env or Docker environment to use LIBRARY_PATH instead.
|
|
The old name is no longer recognized and the app will not start without it.
|
|
```
|
|
|
|
Breaking changes must also be explicitly called out in the PR description, including the upgrade steps a user would need to follow.
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
### `feat`
|
|
|
|
```
|
|
feat(kobo): sync reading position on device reconnect
|
|
```
|
|
|
|
```
|
|
feat(opds): add pagination to catalog feed endpoints
|
|
|
|
The OPDS feed now supports ?page= and ?limit= query params.
|
|
Default page size is 20. Clients that do not send pagination params
|
|
get the same behavior as before.
|
|
|
|
Closes #301
|
|
```
|
|
|
|
### `fix`
|
|
|
|
```
|
|
fix(reader): epub chapter navigation skips last page
|
|
```
|
|
|
|
```
|
|
fix(stats): reading session duration wrong after timezone change
|
|
|
|
Duration was computed using local time offsets rather than UTC,
|
|
causing sessions that crossed a DST boundary to report incorrect
|
|
elapsed time.
|
|
|
|
Fixes #412
|
|
```
|
|
|
|
### `i18n`
|
|
|
|
```
|
|
i18n(client): sync German translations from Crowdin
|
|
```
|
|
|
|
### `db`
|
|
|
|
```
|
|
db(books): add language column to books table
|
|
```
|
|
|
|
```
|
|
db(users): add user_preferences table for per-user app settings
|
|
|
|
Generates a migration. Existing users get default values on deploy.
|
|
```
|
|
|
|
### `perf`
|
|
|
|
```
|
|
perf(library): avoid redundant file stat calls during rescan
|
|
```
|
|
|
|
### `refactor`
|
|
|
|
```
|
|
refactor(metadata): extract provider selection into its own service
|
|
```
|
|
|
|
### `style`
|
|
|
|
```
|
|
style(reader): tighten chapter list spacing in sidebar
|
|
```
|
|
|
|
### `docs`
|
|
|
|
```
|
|
docs: add Kobo device setup guide to README
|
|
```
|
|
|
|
### `test`
|
|
|
|
```
|
|
test(collections): cover concurrent shelf update race condition
|
|
```
|
|
|
|
### `build`
|
|
|
|
```
|
|
build(docker): switch to slim node base image in final stage
|
|
```
|
|
|
|
### `ci`
|
|
|
|
```
|
|
ci: add e2e smoke suite to pull request workflow
|
|
```
|
|
|
|
### `chore`
|
|
|
|
```
|
|
chore(deps): upgrade drizzle-orm to 0.38
|
|
```
|
|
|
|
### `security`
|
|
|
|
```
|
|
security(auth): reject tokens signed with legacy algorithm
|
|
|
|
Previous tokens signed with HS256 were still accepted after the
|
|
migration to RS256. This change enforces RS256-only validation.
|
|
|
|
BREAKING CHANGE: all existing sessions will be invalidated on deploy.
|
|
Users will need to log in again.
|
|
```
|
|
|
|
### `revert`
|
|
|
|
```
|
|
revert: revert "feat(kobo): sync reading position on device reconnect"
|
|
|
|
Reverts commit a1b2c3d.
|
|
|
|
Broke sync for devices running firmware < 4.32. Reverting until
|
|
a compatibility shim is in place.
|
|
```
|