Skip to content

Commit 99d050e

Browse files
authored
Add CONTRIBUTING guide (frequenz-floss#61)
- Add a new title template variable - Use the new title variable in the README template - Add basic CONTRIBUTING.md template - Add API-specific sections to the CONTRIBUTING template Fixes frequenz-floss#10.
2 parents f01fe67 + 4b768a8 commit 99d050e

File tree

4 files changed

+185
-2
lines changed

4 files changed

+185
-2
lines changed

cookiecutter/cookiecutter.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
],
99
"name": null,
1010
"description": null,
11+
"title": "{{cookiecutter | title}}",
1112
"keywords": "(comma separated: 'frequenz', <type> and <name> are included automatically)",
1213
"github_org": "frequenz-floss",
1314
"license": [
@@ -26,6 +27,7 @@
2627
"local_extensions.github_repo_name",
2728
"local_extensions.keywords",
2829
"local_extensions.pypi_package_name",
29-
"local_extensions.python_package"
30+
"local_extensions.python_package",
31+
"local_extensions.title"
3032
]
3133
}

cookiecutter/local_extensions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ def github_repo_name(cookiecutter: dict[str, str]) -> str:
8282
return f"{pypi}{end}"
8383

8484

85+
@_simple_filter # type: ignore[misc]
86+
def title(cookiecutter: dict[str, str]) -> str:
87+
"""Build a default mkdocs site name for the project.
88+
89+
Args:
90+
cookiecutter: The cookiecutter context.
91+
92+
Returns:
93+
The default site name.
94+
"""
95+
match cookiecutter["type"]:
96+
case "actor":
97+
return f"Frequenz {cookiecutter['name']} actor"
98+
case "api":
99+
return f"Frequenz {cookiecutter['name']} API"
100+
case "lib":
101+
return f"Freqenz {cookiecutter['name']} library"
102+
case "app":
103+
return f"Frequenz {cookiecutter['name']} app"
104+
case "model":
105+
return f"Frequenz {cookiecutter['name']} AI model"
106+
case _ as repo_type:
107+
assert False, f"Unhandled repository type {repo_type!r}"
108+
109+
85110
@_simple_filter # type: ignore[misc]
86111
def keywords(cookiecutter: dict[str, str]) -> str:
87112
"""Extend cookiecutter["keywords"] with predefined ones by repository type.
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Contributing to {{cookiecutter.title}}
2+
3+
## Build
4+
5+
You can use `build` to simply build the source and binary distribution:
6+
7+
```sh
8+
python -m pip install build
9+
python -m build
10+
```
11+
12+
## Local development
13+
{%- if cookiecutter.type == "api" %}
14+
15+
You need to make sure you have the `git submodules` updated:
16+
17+
```sh
18+
git submodule update --init
19+
```
20+
21+
### Running protolint
22+
23+
To make sure some common mistakes are avoided and to ensure a consistent style
24+
it is recommended to run `protolint`. After you [installed
25+
`protolint`](https://github.com/yoheimuta/protolint#installation), just run:
26+
27+
```sh
28+
protolint lint proto
29+
```
30+
31+
### Python setup
32+
{%- endif %}
33+
34+
You can use editable installs to develop the project locally (it will install
35+
all the dependencies too):
36+
37+
```sh
38+
python -m pip install -e .
39+
```
40+
{%- if cookiecutter.type == "api" %}
41+
42+
This will also generate the Python files from the `proto/` files and leave them
43+
in `py/`, so you can inspect them.
44+
{%- endif %}
45+
46+
Or you can install all development dependencies (`mypy`, `pylint`, `pytest`,
47+
etc.) in one go too:
48+
```sh
49+
python -m pip install -e .[dev]
50+
```
51+
52+
If you don't want to install all the dependencies, you can also use `nox` to
53+
run the tests and other checks creating its own virtual environments:
54+
55+
```sh
56+
python -m pip install .[dev-noxfile]
57+
nox
58+
```
59+
60+
You can also use `nox -R` to reuse the current testing environment to speed up
61+
test at the expense of a higher chance to end up with a dirty test environment.
62+
{%- if cookiecutter.type == "api" %}
63+
64+
### Upgrading dependencies
65+
66+
If you want to update the dependency `frequenz-api-common`, then you need to:
67+
68+
1. Update the submodule `frequenz-api-common`
69+
2. Update the version of the `frequenz-api-common` package in `pyproject.toml`
70+
71+
The version of `frequenz-api-common` used in both places mentioned above should
72+
be the same.
73+
74+
Here is an example of upgrading the `frequenz-api-common` dependency to version
75+
`v0.2.0`:
76+
```sh
77+
ver="0.2.0"
78+
79+
cd submodules/frequenz-api-common
80+
git remote update
81+
git checkout v${ver}
82+
cd -
83+
84+
sed s/"frequenz-api-common == [0-9]\.[0-9]\.[0-9]"/"frequenz-api-common == ${ver}"/g -i pyproject.toml
85+
```
86+
{%- endif %}
87+
88+
### Running tests / checks individually
89+
90+
For a better development test cycle you can install the runtime and test
91+
dependencies and run `pytest` manually.
92+
93+
```sh
94+
python -m pip install .[dev-pytest] # included in .[dev] too
95+
96+
# And for example
97+
pytest tests/test_*.py
98+
```
99+
100+
Or you can use `nox`:
101+
102+
```sh
103+
nox -R -s pytest -- test/test_*.py
104+
```
105+
106+
The same appliest to `pylint` or `mypy` for example:
107+
108+
```sh
109+
nox -R -s pylint -- test/test_*.py
110+
nox -R -s mypy -- test/test_*.py
111+
```
112+
113+
## Releasing
114+
115+
These are the steps to create a new release:
116+
117+
1. Get the latest head you want to create a release from.
118+
119+
2. Update the `RELEASE_NOTES.md` file if it is not complete, up to date, and
120+
remove template comments (`<!-- ... ->`) and empty sections. Submit a pull
121+
request if an update is needed, wait until it is merged, and update the
122+
latest head you want to create a release from to get the new merged pull
123+
request.
124+
125+
3. Create a new signed tag using the release notes and
126+
a [semver](https://semver.org/) compatible version number with a `v` prefix,
127+
for example:
128+
129+
```sh
130+
git tag -s --cleanup=whitespace -F RELEASE_NOTES.md v0.0.1
131+
```
132+
133+
4. Push the new tag.
134+
135+
5. A GitHub action will test the tag and if all goes well it will create
136+
a [GitHub
137+
Release](https://github.com/{{cookiecutter.github_org}}/{{cookiecutter.github_repo_name}}/releases),
138+
and upload a new package to
139+
[PyPI](https://pypi.org/project/{{cookiecutter.pypi_package_name}}/)
140+
automatically.
141+
142+
6. Once this is done, reset the `RELEASE_NOTES.md` with the template:
143+
144+
```sh
145+
cp .github/RELEASE_NOTES.template.md RELEASE_NOTES.md
146+
```
147+
148+
Commit the new release notes and create a PR (this step should be automated
149+
eventually too).
150+
151+
7. Celebrate!
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
# Frequenz {{cookiecutter.name}} {{cookiecutter.type}}
1+
# {{cookiecutter.title}}
22

33
{{cookiecutter.description}}
44

55
TODO(cookiecutter): Improve the README file
6+
7+
## Contributing
8+
9+
If you want to know how to build this project and contribute to it, please
10+
check out the [Contributing Guide](CONTRIBUTING.md).

0 commit comments

Comments
 (0)