Maintainer guide¶
How to use these docs
These docs are meant to be linked to. Include a link in your project’s readme or CONTRIBUTING.md
file. E.g.,
See https://dmyersturnbull.github.io/ref/maintainer-guide/
but disregard the `security:` commit type.
Or just link to individual sections; e.g.,
Source headers: Refer to https://dmyersturnbull.github.io/ref/maintainer-guide/#source-headers
This guide is collection of best-practices that are easy to learn, use, and automate. It specifies:
- One-commit-to-one-PR and one-issue-to-one-PR policies
- A commit message specification compatible with Conventional Commits
type:
issue labels that map 1-1 with commit types and map to changelog sections
Development process overview¶
There should be a 1-1-1-1-1 correspondence between issues, feature branches, pull requests, commits to the main branch, and changelog items. This simplifies project management, makes development more transparent, and facilitates automation that reduces manual effort and potential human error.
flowchart LR
A[feature branch] --- B[issue] --- C[PR] --- D[commit to <i>main</i>] --- E[changelog item]
Changelog generation¶
This enables generation of changelogs that are actually useful. It allows GitHub’s automatically generated release notes feature and other tools to produce well-organized changelogs that cover every significant change but exclude unimportant ones (e.g. style
). Changelog entries can be linked, too. In fact, every entry can be linked to the corresponding issue, PR, and commit.
Example
Bug fixes¶
Branches¶
Use trunk-based development. In that terminology, a feature branch is a branch to be merged into main. All development should happen in feature branches, and short-lived feature branches are preferred. Name feature branches <type>/<issue>-<description>--<author-initials>
, where <type>
is the issue type (see the section on commit types), <issue>
is the issue number, <description>
is a short description of the issue, Example: doc/14-japanese-translation--sw
.
Each feature branch must be tied to exactly 1 issue and result in 1 commit to main. That means that branches must be squash-merged.
Example
gitGraph
commit id: "initial" tag: "v0.1.0"
commit id: "update docs"
branch feat/12-async-api--dmt
checkout feat/12-async-api--dmt
commit id: "start feature"
checkout main
commit id: "fix bug" tag: "v0.1.1"
checkout feat/12-async-api--dmt
commit id: "complete feature"
checkout main
merge feat/12-async-api--dmt id: "squash and rebase" tag: "v0.2.0"
In some situations, earlier versions need to be maintained, such as for security fixes. Name these branches by releases/<version>
(e.g., releases/v1
).
Issues¶
Issues must have exactly 1 type:
label. Use effort:
and priority:
labels if they are helpful. Split large issues into bit-sized pieces and list those in the larger issue’s description.
Example
Requires several steps:
- [x] [write schema](#21)
- [x] [build schema linter](#22)
- [ ] [create infrastructure to deploy schema](#23)
Handling pull requests¶
Before required status checks have completed successfully, avoid submitting reviews. Instead, just comment.
Squash the commits into one, and ensure the resulting commit message follows the commit message format specification.
!!! tip “GitHub squash and merge
GitHub has a "Squash and merge" button, but there is nowhere to add a commit body or footer.
However, you can work around this in the repository settings:
Under "General" → "Pull Requests" → "Allow squash merging" (which should be checked),
set "default commit message" to "Pull request title and description".
Before clicking "Squash and merge", edit the PR title and description.
The title will be the commit message, and the description will be the commit body and footer.
(Separate the body and footer with a blank line.)
To help a contributor with their PR directly, see “Committing changes to a pull request branch created from a fork”. If the contributor abandoned the PR, instead use gh pr checkout <number>
.
Versioning¶
Versioning is a subset of Semantic Versioning. Pre-releases are permitted only in the forms alpha<int>
, beta<int>
, preview<int>
, and rc<int>
, where <int>
starts at 0. Alpha/beta/preview/RC MUST NOT be used out of order (e.g., not alpha1
, beta1
, alpha2
).
Tags and deployment¶
Tags of the form v<semver>
should result in full deployments. Tags of the form v<major>
should automatically track their most recent semver tags. The latest
tag should always match the main branch.
Repository contents¶
File types¶
- Prefer open standards like AVIF, WEBP, OGGm FLAC, and AV1. (Choose webm over the more general MKV.)
- Use simpler formats, like Markdown instead of ReST.
- Prefer modern compression algorithms like LZ4 (
.lz4
) and ZSTD (.zst
).
Source headers¶
Ensure that nontrivial files contain a header such as
SPDX-FileCopyrightText: Copyright <years>, Contributors to <project>
SPDX-PackageHomePage: <url>
SPDX-License-Identifier: <spdx-id>
Example
For Tyrannosaurus, this is:
SPDX-FileCopyrightText: Copyright 2020-2024, Contributors to Tyrannosaurus
SPDX-PackageHomePage: https://github.com/dmyersturnbull/tyrannosaurus
SPDX-License-Identifier: Apache-2.0
3rd-party code¶
Use SPDX headers in the aforementioned form.
Include a section in NOTICE.txt
mentioning the source file(s), license, and external source. Include the license file in the form LICENSE-<spdx-id>.txt
.
If you are modifying the file, you need 2 sets of SPDX headers, which should be visually separated. Follow those headers with a plain-language statement that you have modified the file.
!!! “example”
Example from
[rcsb/rcsb-chem-search pyproject.toml](https://github.com/rcsb/rcsb-chem-search/blob/master/pyproject.toml):
```python
# SPDX-FileCopyrightText: Copyright 2020-2024, Contributors to Tyrannosaurus
# SPDX-PackageHomePage: https://github.com/dmyersturnbull/tyrannosaurus
# SPDX-License-Identifier: Apache-2.0
#
# SPDX-FileCopyrightText: Copyright 2024, Contributors to rcsb-chem-search
# SPDX-PackageHomePage: https://github.com/rcsb/rcsb-chem-search
# SPDX-License-Identifier: BSD-3-Clause
#
# Adapted from Tyrannosaurus <https://github.com/dmyersturnbull/tyrannosaurus>.
```
Commit messages¶
Conventional commit messages¶
Commit messages must follow a subset of Conventional Commits.
- Breaking changes MUST use
!
. - The body SHOULD be written as CommonMark. In that case, headings more significant than level 4 (
####
) MUST NOT be used. (Treat the subject as a level 3 (###
) heading.) Imperative phrasing SHOULD be used. - Footers MUST be listed one per line in a single paragraph.
- For a breaking change, if a body is included, the
BREAKING CHANGE:
footer MUST be present. - If a body is included, deprecations SHOULD be indicated by a
Deprecates:
footer of the formDeprecates: first, second
. - Closed issues SHOULD be listed in a footer of the form
Closes: #10, #22, #33
. (Note: This guideline requires exactly 1 issue.) - Commits MUST NOT use footers that have not defined. The footers that are defined in this document are
BREAKING CHANGE
,Deprecates
,Closes
, and the attribution trailers listed below. - Projects MAY define their own additional footers; any such footer MUST be designed to facilitate automation or computational analysis.
- Trailers MUST be ordered as:
BREAKING CHANGE:
,Deprecates:
,Closes:
, attribution(s). - Each commit type MUST be
drop
,depr
,feat
,security
,fix
,perf
,build
,docs
,test
,ci
,refactor
, orstyle
.
Allowed attribution trailers
- Acked-by
- Reviewed-by
- Helped-by
- Reported-by
- Mentored-by
- Suggested-by
- CC
- Noticed-by
- Tested-by
- Improved-by
- Thanks-to
- Based-on-patch-by
- Contributions-by
- Co-authored-by
- Requested-by
- Original-patch-by
- Inspired-by
- Signed-off-by
Examples – only message
Example 1:
feat!: add schema
Example 2:
doc(i18n): add JP translation
Example – body and footers
feat!: add major new feature
Introduce option to set custom template **for paid users only**.
Define template parameters:
- name
- status
BREAKING CHANGE: /api/v1/generate-report endpoint
Closes: #14
Co-authored-by: Amelia Johnson <amelia@dev.com>
Co-authored-by: Cecilia Johnson <cecilia@dev.com>
Reviewed-by: Kerri Hendrix <kerri@dev.com>
Acked-by: Tom Monson <joe@dev.com>
Signed-off-by: Sadie Wu <sadie@dev.com>
Refer to the supplemental labels document for details.
Invalid and reverted changes¶
Note that there is no invalid
or state: invalid
: Duplicate issues, issues created by mistake, uninterpretable issues, etc., should be deleted.
Also, there is no revert
type. Instead, use the type that reflects the reversion commit. This might be drop:
or the type of the reverted commit. Label both commits with changelog: exclude
.
Forcibly omitting or including release notes entries¶
Use changelog: exclude
and changelog: exclude
to override which changes are included in the release notes.
changelog: exclude
excludes changes that would normally be included (e.g. feat:
). Use it for
- reversions and reverted commits,
- trivial changes, and
docs:
,tests:
,style:
, etc. commits that support afeat:
commit added in the same release.
changelog: include
adds changes that would normally be ommitted (e.g. style
). Use it only to acknowledge unusually important style
contributions.
Including dependent changes in one commit¶
It is completely acceptable – and encouraged – to add tests and documentation for a new feature inside a feat:
commit, to remove them inside a drop:
commit, and to update them inside a fix:
or security:
commit.
If separate commits were made, consider applying changelog: exclude
to some, as described in the section above.
Details
Effectively, some types can be subsumed into others. This diagram details the allowed ways:
graph TD
fix --> feat
security --> feat
perf --> feat
test --> fix
test --> feat
test --> perf
test --> security
docs --> feat
docs --> fix
ci --> build
build --> fix
refactor --> feat
refactor --> fix
refactor --> build
refactor --> ci
refactor --> test
refactor --> security
s["style"] --> any["*"]
Scopes¶
Scopes should be defined per project. If a scope is defined, it should be applied to all relevant commits, at least to those made after the scope’s introduction.
Suggestions:
i18n
plugins
Reference¶
Pattern
<type>[(<scope>)][!]: <subject>
<body>
[BREAKING CHANGE: <feature, etc.>]
[Deprecates: <feature, etc.>]
[Closes: #<issue>]
[*: <author>]*
"""