From 1ec55655de127bd7c76bdb6e08229532ec1907f5 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 26 Mar 2025 13:52:20 +0100 Subject: [PATCH 1/4] Use a new grouping strategy for dependabot updates We group patch updates as they should always work. We also group minor updates, as it works too for most libraries, typically except libraries that don't have a stable release yet (v0.x.x branch), so we make some exceptions for them. Major updates and dependencies excluded by the above groups are still managed, but they'll create one PR per dependency, as breakage is expected, so it might need manual intervention. Finally, we group some dependencies that are related to each other, and usually needs to be updated together. Signed-off-by: Leandro Lucarella --- .../.github/dependabot.yml | 47 ++++++++++++++----- .../.github/dependabot.yml | 44 ++++++++++++----- .../frequenz-api-test/.github/dependabot.yml | 45 +++++++++++++----- .../frequenz-app-test/.github/dependabot.yml | 44 ++++++++++++----- .../.github/dependabot.yml | 44 ++++++++++++----- .../.github/dependabot.yml | 44 ++++++++++++----- 6 files changed, 196 insertions(+), 72 deletions(-) diff --git a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/dependabot.yml b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/dependabot.yml index cfeaac00..1341d523 100644 --- a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/dependabot.yml +++ b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/dependabot.yml @@ -13,23 +13,46 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" +{%- if cookiecutter.type == "api" %} + - "frequenz-api-common" +{%- endif %} + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" diff --git a/tests_golden/integration/test_cookiecutter_generation/actor/frequenz-actor-test/.github/dependabot.yml b/tests_golden/integration/test_cookiecutter_generation/actor/frequenz-actor-test/.github/dependabot.yml index 23cd21b1..c5b9db3e 100644 --- a/tests_golden/integration/test_cookiecutter_generation/actor/frequenz-actor-test/.github/dependabot.yml +++ b/tests_golden/integration/test_cookiecutter_generation/actor/frequenz-actor-test/.github/dependabot.yml @@ -13,23 +13,43 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" diff --git a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/dependabot.yml b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/dependabot.yml index d98b4f33..d091a66c 100644 --- a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/dependabot.yml +++ b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/dependabot.yml @@ -13,23 +13,44 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "frequenz-api-common" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" diff --git a/tests_golden/integration/test_cookiecutter_generation/app/frequenz-app-test/.github/dependabot.yml b/tests_golden/integration/test_cookiecutter_generation/app/frequenz-app-test/.github/dependabot.yml index 23cd21b1..c5b9db3e 100644 --- a/tests_golden/integration/test_cookiecutter_generation/app/frequenz-app-test/.github/dependabot.yml +++ b/tests_golden/integration/test_cookiecutter_generation/app/frequenz-app-test/.github/dependabot.yml @@ -13,23 +13,43 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" diff --git a/tests_golden/integration/test_cookiecutter_generation/lib/frequenz-test-python/.github/dependabot.yml b/tests_golden/integration/test_cookiecutter_generation/lib/frequenz-test-python/.github/dependabot.yml index 23cd21b1..c5b9db3e 100644 --- a/tests_golden/integration/test_cookiecutter_generation/lib/frequenz-test-python/.github/dependabot.yml +++ b/tests_golden/integration/test_cookiecutter_generation/lib/frequenz-test-python/.github/dependabot.yml @@ -13,23 +13,43 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" diff --git a/tests_golden/integration/test_cookiecutter_generation/model/frequenz-model-test/.github/dependabot.yml b/tests_golden/integration/test_cookiecutter_generation/model/frequenz-model-test/.github/dependabot.yml index 23cd21b1..c5b9db3e 100644 --- a/tests_golden/integration/test_cookiecutter_generation/model/frequenz-model-test/.github/dependabot.yml +++ b/tests_golden/integration/test_cookiecutter_generation/model/frequenz-model-test/.github/dependabot.yml @@ -13,23 +13,43 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # We group production and development ("optional" in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" From 257698a9a1883c2825b907d361b5b4126405cdd4 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 26 Mar 2025 13:52:49 +0100 Subject: [PATCH 2/4] Add migration step Signed-off-by: Leandro Lucarella --- cookiecutter/migrate.py | 97 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/cookiecutter/migrate.py b/cookiecutter/migrate.py index c0e1dba0..c62bf892 100644 --- a/cookiecutter/migrate.py +++ b/cookiecutter/migrate.py @@ -32,10 +32,107 @@ def main() -> None: """Run the migration steps.""" # Add a separation line like this one after each migration step. print("=" * 72) + regroup_dependabot() + print("=" * 72) print("Migration script finished. Remember to follow any manual instructions.") print("=" * 72) +def regroup_dependabot() -> None: + """Use new dependabot groups to separate dependencies that break often.""" + print("Using new dependabot groups to separate dependencies that break often...") + # Dependabot configuration file + dependabot_file = Path(".github/dependabot.yml") + + # Skip if the file doesn't exist + if not dependabot_file.exists(): + manual_step( + "Dependabot configuration file not found, not excluding " + "frequenz-repo-config from group updates. Please consider adding a " + "dependabot configuration file." + ) + return + + dependabot_content = dependabot_file.read_text(encoding="utf-8") + + new_groups = """\ + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. + groups: + patch: + update-types: + - "patch" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: + update-types: + - "minor" + exclude-patterns: + - "async-solipsism" + - "frequenz-repo-config*" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + # We group repo-config updates as it uses optional dependencies that are + # considered different dependencies otherwise, and will create one PR for + # each if we don't group them. + repo-config: + patterns: + - "frequenz-repo-config*" + mkdocstrings: + patterns: + - "mkdocstrings*" +""" + + marker = " open-pull-requests-limit: 10" + if marker not in dependabot_content: + manual_step( + f"Could not file marker ({marker!r}) in {dependabot_file}, " + "can't update automatically. Please consider using these new groups " + "in the dependabot configuration file:" + ) + return + + text_to_replace = "" + found_marker = False + for line in dependabot_content.splitlines(): + if line == marker: + found_marker = True + continue + if not found_marker: + continue + if line == "" and found_marker: + break + text_to_replace += line + "\n" + + if not text_to_replace: + manual_step( + "Could not find the text to replace with the new depenndabot " + "groups. Please consider using these new groups in the dependabot " + "configuration file:" + ) + return + + replace_file_contents_atomically( + dependabot_file, + text_to_replace, + new_groups, + count=1, + content=dependabot_content, + ) + + def apply_patch(patch_content: str) -> None: """Apply a patch using the patch utility.""" subprocess.run(["patch", "-p1"], input=patch_content.encode(), check=True) From 571587ca414d85e962615d24672253d805ed6a50 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Thu, 27 Mar 2025 14:58:19 +0100 Subject: [PATCH 3/4] Add new grouping to this project's dependabot config Signed-off-by: Leandro Lucarella --- .github/dependabot.yml | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 53bdd6c3..a1c0dac6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,23 +13,36 @@ updates: versioning-strategy: auto # Allow up to 10 open pull requests for updates to dependency versions open-pull-requests-limit: 10 - # Group production and development (required and optional in the context of - # pyproject.toml) dependency updates when they are patch and minor updates, - # so we end up with less PRs being generated. - # Major updates are still managed, but they'll create one PR per - # dependency, as major updates are expected to be breaking, it is better to - # manage them individually. + # We group patch updates as they should always work. + # We also group minor updates, as it works too for most libraries, + # typically except libraries that don't have a stable release yet (v0.x.x + # branch), so we make some exceptions for them. + # Major updates and dependencies excluded by the above groups are still + # managed, but they'll create one PR per dependency, as breakage is + # expected, so it might need manual intervention. + # Finally, we group some dependencies that are related to each other, and + # usually need to be updated together. groups: - required: - dependency-type: "production" + patch: update-types: - - "minor" - "patch" - optional: - dependency-type: "development" + exclude-patterns: + # pydoclint has shipped breaking changes in patch updates often + - "pydoclint" + minor: update-types: - "minor" - - "patch" + exclude-patterns: + - "async-solipsism" + - "markdown-callouts" + - "mkdocs-gen-files" + - "mkdocs-literate-nav" + - "mkdocstrings*" + - "pydoclint" + - "pytest-asyncio" + mkdocstrings: + patterns: + - "mkdocstrings*" - package-ecosystem: "github-actions" directory: "/" From 1f33af3caa67d04d198e68dacf116ba979ffbe15 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 26 Mar 2025 13:52:58 +0100 Subject: [PATCH 4/4] Add release notes Signed-off-by: Leandro Lucarella --- RELEASE_NOTES.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b99e3a30..6fe72e76 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -26,7 +26,12 @@ But you might still need to adapt your code: ### Cookiecutter template - +- Dependabot config now uses a new grouping that should make upgrades more smooth. + + * We group patch updates as they should always work. + * We also group minor updates, as it works too for most libraries, typically except libraries that don't have a stable release yet (v0.x.x branch), so we make some exceptions for them. + * Major updates and dependencies excluded by the above groups are still managed, but they'll create one PR per dependency, as breakage is expected, so it might need manual intervention. + * Finally, we group some dependencies that are related to each other, and usually needs to be updated together. ## Bug Fixes