@@ -32,10 +32,107 @@ def main() -> None:
3232 """Run the migration steps."""
3333 # Add a separation line like this one after each migration step.
3434 print ("=" * 72 )
35+ regroup_dependabot ()
36+ print ("=" * 72 )
3537 print ("Migration script finished. Remember to follow any manual instructions." )
3638 print ("=" * 72 )
3739
3840
41+ def regroup_dependabot () -> None :
42+ """Use new dependabot groups to separate dependencies that break often."""
43+ print ("Using new dependabot groups to separate dependencies that break often..." )
44+ # Dependabot configuration file
45+ dependabot_file = Path (".github/dependabot.yml" )
46+
47+ # Skip if the file doesn't exist
48+ if not dependabot_file .exists ():
49+ manual_step (
50+ "Dependabot configuration file not found, not excluding "
51+ "frequenz-repo-config from group updates. Please consider adding a "
52+ "dependabot configuration file."
53+ )
54+ return
55+
56+ dependabot_content = dependabot_file .read_text (encoding = "utf-8" )
57+
58+ new_groups = """\
59+ # We group patch updates as they should always work.
60+ # We also group minor updates, as it works too for most libraries,
61+ # typically except libraries that don't have a stable release yet (v0.x.x
62+ # branch), so we make some exceptions for them.
63+ # Major updates and dependencies excluded by the above groups are still
64+ # managed, but they'll create one PR per dependency, as breakage is
65+ # expected, so it might need manual intervention.
66+ # Finally, we group some dependencies that are related to each other, and
67+ # usually need to be updated together.
68+ groups:
69+ patch:
70+ update-types:
71+ - "patch"
72+ exclude-patterns:
73+ # pydoclint has shipped breaking changes in patch updates often
74+ - "pydoclint"
75+ minor:
76+ update-types:
77+ - "minor"
78+ exclude-patterns:
79+ - "async-solipsism"
80+ - "frequenz-repo-config*"
81+ - "markdown-callouts"
82+ - "mkdocs-gen-files"
83+ - "mkdocs-literate-nav"
84+ - "mkdocstrings*"
85+ - "pydoclint"
86+ - "pytest-asyncio"
87+ # We group repo-config updates as it uses optional dependencies that are
88+ # considered different dependencies otherwise, and will create one PR for
89+ # each if we don't group them.
90+ repo-config:
91+ patterns:
92+ - "frequenz-repo-config*"
93+ mkdocstrings:
94+ patterns:
95+ - "mkdocstrings*"
96+ """
97+
98+ marker = " open-pull-requests-limit: 10"
99+ if marker not in dependabot_content :
100+ manual_step (
101+ f"Could not file marker ({ marker !r} ) in { dependabot_file } , "
102+ "can't update automatically. Please consider using these new groups "
103+ "in the dependabot configuration file:"
104+ )
105+ return
106+
107+ text_to_replace = ""
108+ found_marker = False
109+ for line in dependabot_content .splitlines ():
110+ if line == marker :
111+ found_marker = True
112+ continue
113+ if not found_marker :
114+ continue
115+ if line == "" and found_marker :
116+ break
117+ text_to_replace += line + "\n "
118+
119+ if not text_to_replace :
120+ manual_step (
121+ "Could not find the text to replace with the new depenndabot "
122+ "groups. Please consider using these new groups in the dependabot "
123+ "configuration file:"
124+ )
125+ return
126+
127+ replace_file_contents_atomically (
128+ dependabot_file ,
129+ text_to_replace ,
130+ new_groups ,
131+ count = 1 ,
132+ content = dependabot_content ,
133+ )
134+
135+
39136def apply_patch (patch_content : str ) -> None :
40137 """Apply a patch using the patch utility."""
41138 subprocess .run (["patch" , "-p1" ], input = patch_content .encode (), check = True )
0 commit comments