Skip to content

Commit af82b2e

Browse files
authored
Clear release notes (#491)
2 parents d1126f4 + 23a8d70 commit af82b2e

2 files changed

Lines changed: 13 additions & 240 deletions

File tree

RELEASE_NOTES.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,36 @@
22

33
## Summary
44

5-
This release adds a new workflow for Dependabot auto-merge and updates mkdocstrings to v2.
5+
<!-- Here goes a general summary of what this release is about -->
66

77
## Upgrading
88

9+
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
10+
911
### Cookiecutter template
1012

1113
All upgrading should be done via the migration script or regenerating the templates.
1214

1315
```bash
14-
curl -sSL https://raw.githubusercontent.com/frequenz-floss/frequenz-repo-config-python/v0.14/cookiecutter/migrate.py | python3
16+
curl -sSL https://raw.githubusercontent.com/frequenz-floss/frequenz-repo-config-python/v0.12/cookiecutter/migrate.py | python3
1517
```
1618

17-
But you might still need to adapt your code, just have a look at the script output for further instructions.
19+
But you might still need to adapt your code:
20+
21+
<!-- Here upgrade steps for cookiecutter specifically -->
1822

1923
## New Features
2024

21-
* `mkdocsstrings-python` v2 is now supported.
25+
<!-- Here goes the main new features and examples or instructions on how to use them -->
2226

2327
### Cookiecutter template
2428

25-
- Dependencies have been updated.
26-
- New warning ignores for protobuf gencode versions in pytest.
27-
- Added Dependabot auto-merge workflow using `frequenz-floss/dependabot-auto-approve` action.
29+
<!-- Here new features for cookiecutter specifically -->
2830

2931
## Bug Fixes
3032

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

33-
- mkdocstrings: Move `paths` key to the right section in `mkdocs.yml`.
34-
- Fix invalid YAML syntax in Dependabot workflow template.
37+
<!-- Here bug fixes for cookiecutter specifically -->

cookiecutter/migrate.py

Lines changed: 1 addition & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -21,251 +21,21 @@
2121
""" # noqa: E501
2222

2323
import hashlib
24-
import json
2524
import os
2625
import subprocess
2726
import tempfile
2827
from pathlib import Path
29-
from typing import Any, SupportsIndex
28+
from typing import SupportsIndex
3029

3130

3231
def main() -> None:
3332
"""Run the migration steps."""
3433
# Add a separation line like this one after each migration step.
3534
print("=" * 72)
36-
print("Creating Dependabot auto-merge workflow...")
37-
create_dependabot_auto_merge_workflow()
38-
print("=" * 72)
39-
print("Disabling CODEOWNERS review requirement in GitHub ruleset...")
40-
disable_codeowners_review_requirement()
41-
print("=" * 72)
42-
print("Updating the mkdocs.yml for mkdocstrings-python v2 compatibility...")
43-
update_mkdocs_yml_mkdocstrings_python_v2()
44-
print("=" * 72)
4535
print("Migration script finished. Remember to follow any manual instructions.")
4636
print("=" * 72)
4737

4838

49-
def update_mkdocs_yml_mkdocstrings_python_v2() -> None:
50-
"""Rename 'inventories' imports to 'inventory'."""
51-
replace_file_contents_atomically(
52-
filepath=Path("mkdocs.yml"),
53-
old=" import:",
54-
new=" inventories:",
55-
)
56-
replace_file_contents_atomically(
57-
filepath=Path("mkdocs.yml"),
58-
old="""\
59-
options:
60-
paths: ["src"]""",
61-
new="""\
62-
paths: ["src"]
63-
options:""",
64-
)
65-
66-
67-
def create_dependabot_auto_merge_workflow() -> None:
68-
"""Create the Dependabot auto-merge workflow file."""
69-
workflow_dir = Path(".github") / "workflows"
70-
workflow_dir.mkdir(parents=True, exist_ok=True)
71-
72-
workflow_content = """\
73-
name: Auto-merge Dependabot PR
74-
75-
on:
76-
pull_request:
77-
78-
permissions:
79-
contents: write
80-
pull-requests: write
81-
82-
jobs:
83-
auto-merge:
84-
if: github.actor == 'dependabot[bot]'
85-
runs-on: ubuntu-latest
86-
steps:
87-
- name: Auto-merge Dependabot PR
88-
uses: frequenz-floss/dependabot-auto-approve@3cad5f42e79296505473325ac6636be897c8b8a1 # v1.3.2
89-
with:
90-
github-token: ${{ secrets.GITHUB_TOKEN }}
91-
dependency-type: 'all'
92-
auto-merge: 'true'
93-
merge-method: 'merge'
94-
add-label: 'tool:auto-merged'
95-
""" # noqa: E501
96-
97-
workflow_file = workflow_dir / "auto-dependabot.yaml"
98-
workflow_file.write_text(workflow_content, encoding="utf-8")
99-
print(f"Created/Updated Dependabot auto-merge workflow at {workflow_file}")
100-
101-
102-
def get_default_branch() -> str | None:
103-
"""Get the default branch name from GitHub.
104-
105-
Returns:
106-
The default branch name, or None if it cannot be determined.
107-
"""
108-
try:
109-
result = subprocess.run(
110-
["gh", "api", "repos/:owner/:repo", "--jq", ".default_branch"],
111-
capture_output=True,
112-
text=True,
113-
check=True,
114-
)
115-
default_branch = result.stdout.strip()
116-
print(f"Default branch: {default_branch}")
117-
return default_branch
118-
except subprocess.CalledProcessError as e:
119-
print(f"Failed to get default branch: {e}")
120-
return None
121-
122-
123-
def find_version_branch_ruleset() -> dict[str, Any] | None:
124-
"""Find the 'Protect version branches' ruleset.
125-
126-
Returns:
127-
The ruleset configuration, or None if not found.
128-
"""
129-
try:
130-
result = subprocess.run(
131-
["gh", "api", "repos/:owner/:repo/rulesets"],
132-
capture_output=True,
133-
text=True,
134-
check=True,
135-
)
136-
rulesets = json.loads(result.stdout)
137-
138-
for ruleset in rulesets:
139-
if ruleset.get("name") == "Protect version branches":
140-
return ruleset # type: ignore[no-any-return]
141-
return None
142-
except subprocess.CalledProcessError as e:
143-
print(f"Failed to fetch rulesets: {e}")
144-
return None
145-
146-
147-
def update_ruleset(ruleset_id: int, ruleset_config: dict[str, Any]) -> bool:
148-
"""Update a GitHub ruleset configuration.
149-
150-
Args:
151-
ruleset_id: The ID of the ruleset to update.
152-
ruleset_config: The updated ruleset configuration.
153-
154-
Returns:
155-
True if the update was successful, False otherwise.
156-
"""
157-
update_payload = {
158-
"name": ruleset_config["name"],
159-
"target": ruleset_config["target"],
160-
"enforcement": ruleset_config["enforcement"],
161-
"conditions": ruleset_config["conditions"],
162-
"rules": ruleset_config["rules"],
163-
}
164-
165-
if "bypass_actors" in ruleset_config:
166-
update_payload["bypass_actors"] = ruleset_config["bypass_actors"]
167-
168-
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
169-
json.dump(update_payload, f, indent=2)
170-
temp_file = f.name
171-
172-
try:
173-
subprocess.run(
174-
[
175-
"gh",
176-
"api",
177-
"-X",
178-
"PUT",
179-
f"repos/:owner/:repo/rulesets/{ruleset_id}",
180-
"--input",
181-
temp_file,
182-
],
183-
capture_output=True,
184-
check=True,
185-
)
186-
return True
187-
except subprocess.CalledProcessError as e:
188-
print(f"Error updating ruleset: {e}")
189-
return False
190-
finally:
191-
os.unlink(temp_file)
192-
193-
194-
def disable_codeowners_review_requirement() -> None:
195-
"""Disable CODEOWNERS review requirement in GitHub repository ruleset."""
196-
# Get repository info
197-
try:
198-
result = subprocess.run(
199-
["gh", "repo", "view", "--json", "owner,name"],
200-
capture_output=True,
201-
text=True,
202-
check=True,
203-
)
204-
repo_info = json.loads(result.stdout)
205-
org = repo_info["owner"]["login"]
206-
repo = repo_info["name"]
207-
ruleset_url = f"https://github.com/{org}/{repo}/settings/rules"
208-
except subprocess.CalledProcessError:
209-
ruleset_url = "GitHub repository settings > Rules"
210-
211-
if get_default_branch() is None:
212-
manual_step(
213-
"Failed to get default branch. "
214-
"Please manually disable the CODEOWNERS review requirement in the "
215-
f"'Protect version branches' ruleset at: {ruleset_url}"
216-
)
217-
return
218-
219-
version_branch_ruleset = find_version_branch_ruleset()
220-
if not version_branch_ruleset:
221-
manual_step(
222-
"'Protect version branches' ruleset not found. "
223-
"Please manually disable the CODEOWNERS review requirement at: "
224-
f"{ruleset_url}"
225-
)
226-
return
227-
228-
ruleset_id = version_branch_ruleset["id"]
229-
print(f"Found ruleset ID: {ruleset_id}")
230-
231-
try:
232-
result = subprocess.run(
233-
["gh", "api", f"repos/:owner/:repo/rulesets/{ruleset_id}"],
234-
capture_output=True,
235-
text=True,
236-
check=True,
237-
)
238-
ruleset_config = json.loads(result.stdout)
239-
except subprocess.CalledProcessError as e:
240-
manual_step(
241-
f"Failed to fetch ruleset configuration: {e}. "
242-
"This action requires admin permissions. "
243-
f"Please manually disable the CODEOWNERS review requirement at: {ruleset_url}"
244-
)
245-
return
246-
247-
updated = False
248-
for rule in ruleset_config.get("rules", []):
249-
if rule.get("type") == "pull_request":
250-
if rule.get("parameters", {}).get("require_code_owner_review"):
251-
rule["parameters"]["require_code_owner_review"] = False
252-
updated = True
253-
break
254-
255-
if not updated:
256-
print("CODEOWNERS review requirement already disabled.")
257-
return
258-
259-
if update_ruleset(ruleset_id, ruleset_config):
260-
print("Successfully disabled CODEOWNERS review requirement in GitHub ruleset.")
261-
else:
262-
manual_step(
263-
"Failed to update GitHub ruleset. This action requires admin permissions. "
264-
"Please manually disable the CODEOWNERS review requirement in the "
265-
f"'Protect version branches' ruleset at: {ruleset_url}"
266-
)
267-
268-
26939
def apply_patch(patch_content: str) -> None:
27040
"""Apply a patch using the patch utility."""
27141
subprocess.run(["patch", "-p1"], input=patch_content.encode(), check=True)

0 commit comments

Comments
 (0)