Skip to content

Commit 29352bb

Browse files
authored
Clear release notes and migration script (#351)
We also add some convenience function to the migration template so it is available for future use.
2 parents 7d21f0b + 361db61 commit 29352bb

File tree

3 files changed

+35
-136
lines changed

3 files changed

+35
-136
lines changed

.github/cookiecutter-migrate.template.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
And remember to follow any manual instructions for each run.
2121
""" # noqa: E501
2222

23+
import hashlib
2324
import os
2425
import subprocess
2526
import tempfile
@@ -98,6 +99,26 @@ def replace_file_contents_atomically( # noqa; DOC501
9899
raise
99100

100101

102+
def calculate_file_sha256_skip_lines(filepath: Path, skip_lines: int) -> str | None:
103+
"""Calculate SHA256 of file contents excluding the first N lines.
104+
105+
Args:
106+
filepath: Path to the file to hash
107+
skip_lines: Number of lines to skip at the beginning
108+
109+
Returns:
110+
The SHA256 hex digest, or None if the file doesn't exist
111+
"""
112+
if not filepath.exists():
113+
return None
114+
115+
# Read file and normalize line endings to LF
116+
content = filepath.read_text(encoding="utf-8").replace("\r\n", "\n")
117+
# Skip first N lines and ensure there's a trailing newline
118+
remaining_content = "\n".join(content.splitlines()[skip_lines:]) + "\n"
119+
return hashlib.sha256(remaining_content.encode()).hexdigest()
120+
121+
101122
def manual_step(message: str) -> None:
102123
"""Print a manual step message in yellow."""
103124
print(f"\033[0;33m>>> {message}\033[0m")

RELEASE_NOTES.md

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@
22

33
## Summary
44

5-
This release introduces a new MkDocs macros *pluglet* system that simplifies documentation setup and provides enhanced functionality for version information and code annotations. It also includes changes to how pytest warnings are handled in templates.
5+
<!-- Here goes a general summary of what this release is about -->
66

77
## Upgrading
88

9-
- The `nox` default `pytest` session doesn't pass `-W=all -vv` to `pytest` anymore. You can use the `pyproject.toml` file to configure default options for `pytest`, for example:
10-
11-
```toml
12-
[tool.pytest.ini_options]
13-
addopts = "-W=all -Werror -Wdefault::DeprecationWarning -Wdefault::PendingDeprecationWarning -vv"
14-
```
9+
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
1510

1611
### Cookiecutter template
1712

@@ -23,20 +18,20 @@ curl -sSL https://raw.githubusercontent.com/frequenz-floss/frequenz-repo-config-
2318

2419
But you might still need to adapt your code:
2520

26-
- `pytest` now uses `-Werror` by default (but still treat deprecations as normal warnings), so if your tests run with warnings, they will now be turned to errors, and you'll need to fix them.
27-
28-
- Projects using `docs/_scripts/macros.py` with customized scripts can use the new provided utility functions. See the [`mkdocstrings_macros` documentation](https://frequenz-floss.github.io/frequenz-repo-config-python/v0.12/reference/frequenz/repo/config/mkdocs/mkdocstrings_macros/) for the new features and setup.
21+
<!-- Here upgrade steps for cookiecutter specifically -->
2922

3023
## New Features
3124

32-
- Two new modules were introduced to facilitate the configuration of `macros` for use within docstrings via `mkdocstrings`: [`mkdocstrings_macros`](https://frequenz-floss.github.io/frequenz-repo-config-python/v0.12/reference/frequenz/repo/config/mkdocs/mkdocstrings_macros/) and [`annotations`](https://frequenz-floss.github.io/frequenz-repo-config-python/v0.12/reference/frequenz/repo/config/mkdocs/annotations/).
25+
<!-- Here goes the main new features and examples or instructions on how to use them -->
3326

3427
### Cookiecutter template
3528

36-
- `pytest` now uses `-Werror -Wdefault::DeprecationWarning -Wdefault::PendingDeprecationWarning` by default. Deprecations are still treated as warnings, as when testing with the `pytest_min` session is normal to get deprecation warnings as we are using old versions of dependencies.
29+
<!-- Here new features for cookiecutter specifically -->
3730

3831
## Bug Fixes
3932

33+
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
34+
4035
### Cookiecutter template
4136

42-
- Fixed a compatibility issue in the macros doc script with `mkdocsstrings` 0.28.
37+
<!-- Here bug fixes for cookiecutter specifically -->

cookiecutter/migrate.py

Lines changed: 6 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -30,125 +30,8 @@
3030

3131
def main() -> None:
3232
"""Run the migration steps."""
33-
add_default_pytest_options()
33+
# Add a separation line like this one after each migration step.
3434
print("=" * 72)
35-
migrate_mkdocs_macros()
36-
print("=" * 72)
37-
38-
39-
def add_default_pytest_options() -> None:
40-
"""Add default pytest options to pyproject.toml."""
41-
pyproject_toml = Path("pyproject.toml")
42-
pyproject_toml_content = pyproject_toml.read_text(encoding="utf-8")
43-
marker = "[tool.pytest.ini_options]\n"
44-
new_options = (
45-
"-W=all -Werror -Wdefault::DeprecationWarning "
46-
"-Wdefault::PendingDeprecationWarning -vv"
47-
)
48-
49-
print(f"Adding default pytest options to {pyproject_toml}...")
50-
if pyproject_toml_content.find(marker) == -1:
51-
print(
52-
"Couldn't find the the {marker.strip()} marker in pyproject.toml, skipping update."
53-
)
54-
return
55-
56-
if pyproject_toml_content.find("\naddopts") >= 0:
57-
print("It looks like some options are already configured, skipping update.")
58-
manual_step(f"Please consider `{new_options}` if they are not there yet.")
59-
return
60-
61-
replace_file_contents_atomically(
62-
pyproject_toml,
63-
marker,
64-
marker + f'addopts = "{new_options}"\n',
65-
)
66-
67-
68-
def migrate_mkdocs_macros() -> None:
69-
"""Migrate from custom macros.py to standard module."""
70-
macros_file = Path("docs/_scripts/macros.py")
71-
mkdocs_yaml = Path("mkdocs.yaml")
72-
if not mkdocs_yaml.exists():
73-
mkdocs_yaml = Path("mkdocs.yml")
74-
75-
known_hashes = {
76-
"47a991286132471b6cb666577beb89e78c0f5d4975c53f0dcb319c4338a2c3cb",
77-
"6bb960c72b370ac77918f49d7a35f39c0ddb58fe52cf2d12caa2577098fd8469",
78-
"7351276ac314955a343bab09d1602e50300887291f841643e9fb79c94acc923c",
79-
"8fa5f9f3fd928e17f590e3ab056434474633259d615971404db0d2f3034adb62",
80-
"ba3ff5f1612b3dd22372a8ca95394b8ea468f18dcefc494c73811c8433fcb880",
81-
"dd32e8759abc43232bb3db5b33c0a7cf8d8442db6135c594968c499d8bae0ce5",
82-
}
83-
84-
print("Checking if docs/_scripts/macros.py can be migrated...")
85-
86-
file_hash = calculate_file_sha256_skip_lines(macros_file, 2)
87-
if not file_hash:
88-
return
89-
90-
if file_hash not in known_hashes:
91-
manual_step("The macros.py file seems to be customized. You have two options:")
92-
manual_step("")
93-
manual_step(
94-
"1. Switch to the standard module (if you don't have custom macros):"
95-
)
96-
manual_step(" a. Update mkdocs.yaml to use the standard module:")
97-
manual_step(
98-
' module_name: docs/_scripts/macros -> modules: ["frequenz.repo.config.mkdocs.mkdocstrings_macros"]' # noqa: E501
99-
)
100-
manual_step(" b. Remove docs/_scripts/macros.py")
101-
manual_step("")
102-
manual_step("2. Keep your custom macros but use the standard functionality:")
103-
manual_step(" a. Update mkdocs.yaml:")
104-
manual_step(" - Keep using module_name: docs/_scripts/macros")
105-
manual_step(" b. Update your macros.py to be minimal:")
106-
manual_step(" ```python")
107-
manual_step(
108-
" from frequenz.repo.config.mkdocs.mkdocstrings_macros import hook_env_with_everything" # noqa: E501
109-
)
110-
manual_step("")
111-
manual_step(" def define_env(env):")
112-
manual_step(" # Add your custom variables, filters, and macros here")
113-
manual_step(" env.variables.my_var = 'Example'")
114-
manual_step(" env.filters.my_filter = lambda x: x.upper()")
115-
manual_step("")
116-
manual_step(
117-
" # This must be at the end to enable all standard features"
118-
)
119-
manual_step(" hook_env_with_everything(env)")
120-
manual_step(" ```")
121-
manual_step("")
122-
manual_step("See the docs for more details:")
123-
manual_step(
124-
"https://frequenz-floss.github.io/frequenz-repo-config-python/v0.12/reference/frequenz/repo/config/mkdocs/mkdocstrings_macros/" # noqa: E501
125-
)
126-
return
127-
128-
if not mkdocs_yaml.exists():
129-
print("mkdocs.yaml/yml not found, skipping macros migration")
130-
return
131-
132-
content = mkdocs_yaml.read_text(encoding="utf-8")
133-
if "module_name: docs/_scripts/macros" not in content:
134-
print("Custom macros configuration not found in mkdocs.yaml")
135-
return
136-
137-
print("Updating mkdocs.yaml to use standard module...")
138-
new_content = content.replace(
139-
"module_name: docs/_scripts/macros",
140-
'modules: ["frequenz.repo.config.mkdocs.mkdocstrings_macros"]',
141-
)
142-
new_content = new_content.replace(
143-
"# inside docstrings. See the comment in `docs/_scripts/macros.py` for more\n"
144-
" # details\n",
145-
"# inside docstrings.\n",
146-
)
147-
148-
replace_file_contents_atomically(mkdocs_yaml, content, new_content)
149-
150-
print("Removing docs/_scripts/macros.py...")
151-
macros_file.unlink()
15235

15336

15437
def apply_patch(patch_content: str) -> None:
@@ -216,11 +99,6 @@ def replace_file_contents_atomically( # noqa; DOC501
21699
raise
217100

218101

219-
def manual_step(message: str) -> None:
220-
"""Print a manual step message in yellow."""
221-
print(f"\033[0;33m>>> {message}\033[0m")
222-
223-
224102
def calculate_file_sha256_skip_lines(filepath: Path, skip_lines: int) -> str | None:
225103
"""Calculate SHA256 of file contents excluding the first N lines.
226104
@@ -241,5 +119,10 @@ def calculate_file_sha256_skip_lines(filepath: Path, skip_lines: int) -> str | N
241119
return hashlib.sha256(remaining_content.encode()).hexdigest()
242120

243121

122+
def manual_step(message: str) -> None:
123+
"""Print a manual step message in yellow."""
124+
print(f"\033[0;33m>>> {message}\033[0m")
125+
126+
244127
if __name__ == "__main__":
245128
main()

0 commit comments

Comments
 (0)