From 6bbc890462f1f17b09aa02a87d60d9c22de61ce2 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Wed, 29 May 2024 13:29:29 -0700 Subject: [PATCH 1/8] fix: maintain dependabot config filename for existing configs Signed-off-by: Zack Koppert --- evergreen.py | 19 +++++++++++++++---- test_evergreen.py | 14 +++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/evergreen.py b/evergreen.py index 12d6eda..666b113 100644 --- a/evergreen.py +++ b/evergreen.py @@ -80,9 +80,11 @@ def main(): # pragma: no cover continue existing_config = None filename_list = [".github/dependabot.yml", ".github/dependabot.yaml"] + dependabot_filename_to_use = None for filename in filename_list: existing_config = check_existing_config(repo, filename, update_existing) if existing_config: + dependabot_filename_to_use = filename break if created_after_date and is_repo_created_date_before( @@ -130,7 +132,9 @@ def main(): # pragma: no cover body_issue = ( body + "\n\n```yaml\n" - + "# .github/dependabot.yml\n" + + "# " + + dependabot_filename_to_use + + "\n" + dependabot_file + "\n```" ) @@ -151,7 +155,12 @@ def main(): # pragma: no cover count_eligible += 1 try: pull = commit_changes( - title, body, repo, dependabot_file, commit_message + title, + body, + repo, + dependabot_file, + commit_message, + dependabot_filename_to_use, ) print("\tCreated pull request " + pull.html_url) if project_id: @@ -273,7 +282,9 @@ def check_pending_issues_for_duplicates(title, repo) -> bool: return skip -def commit_changes(title, body, repo, dependabot_file, message): +def commit_changes( + title, body, repo, dependabot_file, message, dependabot_filename="dependabot.yml" +): """Commit the changes to the repo and open a pull reques and return the pull request object""" default_branch = repo.default_branch # Get latest commit sha from default branch @@ -282,7 +293,7 @@ def commit_changes(title, body, repo, dependabot_file, message): branch_name = "dependabot-" + str(uuid.uuid4()) repo.create_ref(front_matter + branch_name, default_branch_commit) repo.create_file( - path=".github/dependabot.yaml", + path=".github/" + dependabot_filename, message=message, content=dependabot_file.encode(), # Convert to bytes object branch=branch_name, diff --git a/test_evergreen.py b/test_evergreen.py index b054954..dc085db 100644 --- a/test_evergreen.py +++ b/test_evergreen.py @@ -205,20 +205,28 @@ def test_commit_changes(self, mock_uuid): mock_repo.create_ref.return_value = True mock_repo.create_file.return_value = True mock_repo.create_pull.return_value = "MockPullRequest" + dependabot_file_name = "dependabot.yml" title = "Test Title" body = "Test Body" dependabot_file = 'dependencies:\n - package_manager: "python"\n directory: "/"\n update_schedule: "live"' branch_name = "dependabot-12345678-1234-5678-1234-567812345678" - commit_message = "Create dependabot.yaml" - result = commit_changes(title, body, mock_repo, dependabot_file, commit_message) + commit_message = "Create " + dependabot_file_name + result = commit_changes( + title, + body, + mock_repo, + dependabot_file, + commit_message, + dependabot_file_name, + ) # Assert that the methods were called with the correct arguments mock_repo.create_ref.assert_called_once_with( f"refs/heads/{branch_name}", "abc123" ) mock_repo.create_file.assert_called_once_with( - path=".github/dependabot.yaml", + path=".github/" + dependabot_file_name, message=commit_message, content=dependabot_file.encode(), branch=branch_name, From 6639e038d033ccbafdf9aa878771f56d3a13568c Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 00:04:17 -0700 Subject: [PATCH 2/8] docs: Specify required permissions for editing workflow files --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab15bfd..116289e 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ This action can be configured to authenticate with GitHub App Installation or Pe | field | required | default | description | |-------------------------------|----------|---------|-------------| -| `GH_TOKEN` | True | `""` | The GitHub Token used to scan the repository. Must have read access to all repository you are interested in scanning. | +| `GH_TOKEN` | True | `""` | The GitHub Token used to scan the repository. Must have read access to all repository you are interested in scanning and repo:write and workflow privelages to create a pull request. | #### Other Configuration Options From 0cb0096c83cb879d2cb2ef2d2dc5831d063688a9 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 00:13:30 -0700 Subject: [PATCH 3/8] fix: handle file updates in github API properly and fix filename redundancy --- evergreen.py | 28 +++++++++++++++++++++------- test_evergreen.py | 4 ++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/evergreen.py b/evergreen.py index 666b113..83a6dfb 100644 --- a/evergreen.py +++ b/evergreen.py @@ -161,6 +161,7 @@ def main(): # pragma: no cover dependabot_file, commit_message, dependabot_filename_to_use, + existing_config, ) print("\tCreated pull request " + pull.html_url) if project_id: @@ -283,7 +284,13 @@ def check_pending_issues_for_duplicates(title, repo) -> bool: def commit_changes( - title, body, repo, dependabot_file, message, dependabot_filename="dependabot.yml" + title, + body, + repo, + dependabot_file, + message, + dependabot_filename=".github/dependabot.yml", + existing_config=None, ): """Commit the changes to the repo and open a pull reques and return the pull request object""" default_branch = repo.default_branch @@ -292,12 +299,19 @@ def commit_changes( front_matter = "refs/heads/" branch_name = "dependabot-" + str(uuid.uuid4()) repo.create_ref(front_matter + branch_name, default_branch_commit) - repo.create_file( - path=".github/" + dependabot_filename, - message=message, - content=dependabot_file.encode(), # Convert to bytes object - branch=branch_name, - ) + if existing_config: + repo.file_contents(dependabot_filename).update( + message=message, + content=dependabot_file.encode(), # Convert to bytes object + branch=branch_name, + ) + else: + repo.create_file( + path=dependabot_filename, + message=message, + content=dependabot_file.encode(), # Convert to bytes object + branch=branch_name, + ) pull = repo.create_pull( title=title, body=body, head=branch_name, base=repo.default_branch diff --git a/test_evergreen.py b/test_evergreen.py index dc085db..1db2795 100644 --- a/test_evergreen.py +++ b/test_evergreen.py @@ -205,7 +205,7 @@ def test_commit_changes(self, mock_uuid): mock_repo.create_ref.return_value = True mock_repo.create_file.return_value = True mock_repo.create_pull.return_value = "MockPullRequest" - dependabot_file_name = "dependabot.yml" + dependabot_file_name = ".github/dependabot.yml" title = "Test Title" body = "Test Body" @@ -226,7 +226,7 @@ def test_commit_changes(self, mock_uuid): f"refs/heads/{branch_name}", "abc123" ) mock_repo.create_file.assert_called_once_with( - path=".github/" + dependabot_file_name, + path=dependabot_file_name, message=commit_message, content=dependabot_file.encode(), branch=branch_name, From 9bb6f10634160a4782552b9364fc622f7e550222 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 00:15:42 -0700 Subject: [PATCH 4/8] fix: adopt indentation of existing configs or default to 2 spaces --- dependabot_file.py | 37 ++++++++---- env.py | 2 +- test_dependabot_file.py | 130 ++++++++++++++++++++++++---------------- test_env.py | 22 +++---- 4 files changed, 116 insertions(+), 75 deletions(-) diff --git a/dependabot_file.py b/dependabot_file.py index 9edbc4d..8bdda03 100644 --- a/dependabot_file.py +++ b/dependabot_file.py @@ -4,28 +4,29 @@ import yaml -def make_dependabot_config(ecosystem, group_dependencies) -> str: +def make_dependabot_config(ecosystem, group_dependencies, indent) -> str: """ Make the dependabot configuration for a specific package ecosystem Args: ecosystem: the package ecosystem to make the dependabot configuration for group_dependencies: whether to group dependencies in the dependabot.yml file + indent: the number of spaces to indent the dependabot configuration ex: " " Returns: str: the dependabot configuration for the package ecosystem """ - dependabot_config = f""" - package-ecosystem: '{ecosystem}' - directory: '/' - schedule: - interval: 'weekly' + dependabot_config = f"""{indent[:-2]}- package-ecosystem: '{ecosystem}' +{indent}directory: '/' +{indent}schedule: +{indent}{indent}interval: 'weekly' """ if group_dependencies: - dependabot_config += """ groups: - production-dependencies: - dependency-type: 'production' - development-dependencies: - dependency-type: 'development' + dependabot_config += f"""{indent}groups: +{indent}{indent}production-dependencies: +{indent}{indent}{indent}dependency-type: 'production' +{indent}{indent}development-dependencies: +{indent}{indent}{indent}dependency-type: 'development' """ return dependabot_config @@ -61,7 +62,17 @@ def build_dependabot_file( if existing_config: dependabot_file = existing_config.decoded.decode("utf-8") + directory_line = next( + line for line in dependabot_file.splitlines() if "directory:" in line + ) + indent = " " * (len(directory_line) - len(directory_line.lstrip())) + if len(indent) < 2: + print( + "Invalid dependabot.yml file. No indentation found. Skipping {repo.full_name}" + ) + return None else: + indent = " " * 2 dependabot_file = """--- version: 2 updates: @@ -99,7 +110,7 @@ def build_dependabot_file( if repo.file_contents(file): package_managers_found[manager] = True dependabot_file += make_dependabot_config( - manager, group_dependencies + manager, group_dependencies, indent ) break except github3.exceptions.NotFoundError: @@ -112,7 +123,7 @@ def build_dependabot_file( if file[0].endswith(".tf"): package_managers_found["terraform"] = True dependabot_file += make_dependabot_config( - "terraform", group_dependencies + "terraform", group_dependencies, indent ) break except github3.exceptions.NotFoundError: @@ -123,7 +134,7 @@ def build_dependabot_file( if file[0].endswith(".yml") or file[0].endswith(".yaml"): package_managers_found["github-actions"] = True dependabot_file += make_dependabot_config( - "github-actions", group_dependencies + "github-actions", group_dependencies, indent ) break except github3.exceptions.NotFoundError: diff --git a/env.py b/env.py index 5aee695..e36709c 100644 --- a/env.py +++ b/env.py @@ -187,7 +187,7 @@ def get_env_vars(test: bool = False) -> tuple[ if len(commit_message) > 65536: raise ValueError("COMMIT_MESSAGE environment variable is too long") else: - commit_message = "Create dependabot.yaml" + commit_message = "Create/Update dependabot.yaml" created_after_date = os.getenv("CREATED_AFTER_DATE", "") is_match = re.match(r"\d{4}-\d{2}-\d{2}", created_after_date) diff --git a/test_dependabot_file.py b/test_dependabot_file.py index 42a8d80..ccbd6fb 100644 --- a/test_dependabot_file.py +++ b/test_dependabot_file.py @@ -33,10 +33,10 @@ def test_build_dependabot_file_with_bundler(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'bundler' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'bundler' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -54,7 +54,37 @@ def test_build_dependabot_file_with_existing_config_bundler_no_update(self): result = build_dependabot_file(repo, False, [], existing_config) self.assertEqual(result, expected_result) - def test_build_dependabot_file_with_existing_config_bundler_with_update(self): + def test_build_dependabot_file_with_2_space_indent_existing_config_bundler_with_update( + self, + ): + """Test that the dependabot.yml file is built correctly with bundler""" + repo = MagicMock() + repo.file_contents.side_effect = lambda f, filename="Gemfile": f == filename + + # expected_result maintains existing ecosystem with custom configuration and adds new ecosystem + expected_result = """--- +version: 2 +updates: +- package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore(deps)" +- package-ecosystem: 'bundler' + directory: '/' + schedule: + interval: 'weekly' +""" + existing_config = MagicMock() + existing_config.decoded = b'---\nversion: 2\nupdates:\n- package-ecosystem: "pip"\n directory: "/"\n\ + schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' + result = build_dependabot_file(repo, False, [], existing_config) + self.assertEqual(result, expected_result) + + def test_build_dependabot_file_with_4_space_indent_existing_config_bundler_with_update( + self, + ): """Test that the dependabot.yml file is built correctly with bundler""" repo = MagicMock() repo.file_contents.side_effect = lambda f, filename="Gemfile": f == filename @@ -66,17 +96,17 @@ def test_build_dependabot_file_with_existing_config_bundler_with_update(self): - package-ecosystem: "pip" directory: "/" schedule: - interval: "weekly" + interval: "weekly" commit-message: - prefix: "chore(deps)" + prefix: "chore(deps)" - package-ecosystem: 'bundler' directory: '/' schedule: - interval: 'weekly' + interval: 'weekly' """ existing_config = MagicMock() existing_config.decoded = b'---\nversion: 2\nupdates:\n - package-ecosystem: "pip"\n directory: "/"\n\ - schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' + schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' result = build_dependabot_file(repo, False, [], existing_config) self.assertEqual(result, expected_result) @@ -90,10 +120,10 @@ def test_build_dependabot_file_with_npm(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'npm' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -114,10 +144,10 @@ def test_build_dependabot_file_with_pip(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'pip' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'pip' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -135,10 +165,10 @@ def test_build_dependabot_file_with_cargo(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'cargo' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'cargo' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -151,10 +181,10 @@ def test_build_dependabot_file_with_gomod(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'gomod' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'gomod' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -172,10 +202,10 @@ def test_build_dependabot_file_with_composer(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'composer' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'composer' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -193,10 +223,10 @@ def test_build_dependabot_file_with_hex(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'mix' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'mix' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -209,10 +239,10 @@ def test_build_dependabot_file_with_nuget(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'nuget' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'nuget' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -225,10 +255,10 @@ def test_build_dependabot_file_with_docker(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'docker' - directory: '/' - schedule: - interval: 'weekly' +- package-ecosystem: 'docker' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -241,15 +271,15 @@ def test_build_dependabot_file_with_groups(self): expected_result = """--- version: 2 updates: - - package-ecosystem: 'docker' - directory: '/' - schedule: - interval: 'weekly' - groups: - production-dependencies: - dependency-type: 'production' - development-dependencies: - dependency-type: 'development' +- package-ecosystem: 'docker' + directory: '/' + schedule: + interval: 'weekly' + groups: + production-dependencies: + dependency-type: 'production' + development-dependencies: + dependency-type: 'development' """ result = build_dependabot_file(repo, True, [], None) self.assertEqual(result, expected_result) diff --git a/test_env.py b/test_env.py index 26f1922..facaf1e 100644 --- a/test_env.py +++ b/test_env.py @@ -148,7 +148,7 @@ def test_get_env_vars_optional_values(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private", "public"], @@ -187,7 +187,7 @@ def test_get_env_vars_with_update_existing(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private", "public"], @@ -240,7 +240,7 @@ def test_get_env_vars_auth_with_github_app_installation(self): "secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private", "public"], @@ -301,7 +301,7 @@ def test_get_env_vars_with_repos_no_dry_run(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private", "public"], @@ -340,7 +340,7 @@ def test_get_env_vars_with_repos_disabled_security_updates(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private", "public"], @@ -380,7 +380,7 @@ def test_get_env_vars_with_repos_filter_visibility_multiple_values(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["internal", "private"], @@ -420,7 +420,7 @@ def test_get_env_vars_with_repos_filter_visibility_single_value(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["public"], @@ -490,7 +490,7 @@ def test_get_env_vars_with_repos_filter_visibility_no_duplicates(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["private", "public"], @@ -531,7 +531,7 @@ def test_get_env_vars_with_repos_exempt_ecosystems(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["private", "public"], @@ -571,7 +571,7 @@ def test_get_env_vars_with_no_batch_size(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["private", "public"], @@ -612,7 +612,7 @@ def test_get_env_vars_with_batch_size(self): we can keep our dependencies up to date and secure.", "", False, - "Create dependabot.yaml", + "Create/Update dependabot.yaml", None, False, ["private", "public"], From b6871887d0cd379c4031e80b275cfea4f95d668e Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 13:39:31 -0700 Subject: [PATCH 5/8] fix: magic numbers Co-authored-by: jmeridth Signed-off-by: Zack Koppert --- dependabot_file.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dependabot_file.py b/dependabot_file.py index 8bdda03..3b0a23a 100644 --- a/dependabot_file.py +++ b/dependabot_file.py @@ -59,6 +59,7 @@ def build_dependabot_file( "terraform": False, "github-actions": False, } + DEFAULT_INDENT = 2 if existing_config: dependabot_file = existing_config.decoded.decode("utf-8") @@ -66,13 +67,13 @@ def build_dependabot_file( line for line in dependabot_file.splitlines() if "directory:" in line ) indent = " " * (len(directory_line) - len(directory_line.lstrip())) - if len(indent) < 2: + if len(indent) < DEFAULT_INDENT: print( "Invalid dependabot.yml file. No indentation found. Skipping {repo.full_name}" ) return None else: - indent = " " * 2 + indent = " " * DEFAULT_INDENT dependabot_file = """--- version: 2 updates: From 08c952a139800c993daf851c9a1720176110ce5a Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 14:27:37 -0700 Subject: [PATCH 6/8] fix: No support for indentation other than 2 spaces Signed-off-by: Zack Koppert --- dependabot_file.py | 28 ++++---- test_dependabot_file.py | 142 ++++++++++++++++++---------------------- 2 files changed, 80 insertions(+), 90 deletions(-) diff --git a/dependabot_file.py b/dependabot_file.py index 3b0a23a..86f8341 100644 --- a/dependabot_file.py +++ b/dependabot_file.py @@ -16,17 +16,17 @@ def make_dependabot_config(ecosystem, group_dependencies, indent) -> str: Returns: str: the dependabot configuration for the package ecosystem """ - dependabot_config = f"""{indent[:-2]}- package-ecosystem: '{ecosystem}' -{indent}directory: '/' -{indent}schedule: -{indent}{indent}interval: 'weekly' + dependabot_config = f"""{indent}- package-ecosystem: '{ecosystem}' +{indent}{indent}directory: '/' +{indent}{indent}schedule: +{indent}{indent}{indent}interval: 'weekly' """ if group_dependencies: - dependabot_config += f"""{indent}groups: -{indent}{indent}production-dependencies: -{indent}{indent}{indent}dependency-type: 'production' -{indent}{indent}development-dependencies: -{indent}{indent}{indent}dependency-type: 'development' + dependabot_config += f"""{indent}{indent}groups: +{indent}{indent}{indent}production-dependencies: +{indent}{indent}{indent}{indent}dependency-type: 'production' +{indent}{indent}{indent}development-dependencies: +{indent}{indent}{indent}{indent}dependency-type: 'development' """ return dependabot_config @@ -59,14 +59,16 @@ def build_dependabot_file( "terraform": False, "github-actions": False, } - DEFAULT_INDENT = 2 + DEFAULT_INDENT = 2 # pylint: disable=invalid-name if existing_config: dependabot_file = existing_config.decoded.decode("utf-8") - directory_line = next( - line for line in dependabot_file.splitlines() if "directory:" in line + ecosystem_line = next( + line + for line in dependabot_file.splitlines() + if "- package-ecosystem:" in line ) - indent = " " * (len(directory_line) - len(directory_line.lstrip())) + indent = " " * (len(ecosystem_line) - len(ecosystem_line.lstrip())) if len(indent) < DEFAULT_INDENT: print( "Invalid dependabot.yml file. No indentation found. Skipping {repo.full_name}" diff --git a/test_dependabot_file.py b/test_dependabot_file.py index ccbd6fb..a5ed65a 100644 --- a/test_dependabot_file.py +++ b/test_dependabot_file.py @@ -33,10 +33,10 @@ def test_build_dependabot_file_with_bundler(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'bundler' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'bundler' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -61,54 +61,42 @@ def test_build_dependabot_file_with_2_space_indent_existing_config_bundler_with_ repo = MagicMock() repo.file_contents.side_effect = lambda f, filename="Gemfile": f == filename - # expected_result maintains existing ecosystem with custom configuration and adds new ecosystem + # expected_result maintains existing ecosystem with custom configuration + # and adds new ecosystem expected_result = """--- version: 2 updates: -- package-ecosystem: "pip" - directory: "/" - schedule: - interval: "weekly" - commit-message: - prefix: "chore(deps)" -- package-ecosystem: 'bundler' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore(deps)" + - package-ecosystem: 'bundler' + directory: '/' + schedule: + interval: 'weekly' """ existing_config = MagicMock() - existing_config.decoded = b'---\nversion: 2\nupdates:\n- package-ecosystem: "pip"\n directory: "/"\n\ - schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' + existing_config.decoded = b'---\nversion: 2\nupdates:\n - package-ecosystem: "pip"\n directory: "/"\n\ + schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' result = build_dependabot_file(repo, False, [], existing_config) self.assertEqual(result, expected_result) - def test_build_dependabot_file_with_4_space_indent_existing_config_bundler_with_update( + def test_build_dependabot_file_with_weird_space_indent_existing_config_bundler_with_update( self, ): """Test that the dependabot.yml file is built correctly with bundler""" repo = MagicMock() repo.file_contents.side_effect = lambda f, filename="Gemfile": f == filename - # expected_result maintains existing ecosystem with custom configuration and adds new ecosystem - expected_result = """--- -version: 2 -updates: - - package-ecosystem: "pip" - directory: "/" - schedule: - interval: "weekly" - commit-message: - prefix: "chore(deps)" - - package-ecosystem: 'bundler' - directory: '/' - schedule: - interval: 'weekly' -""" + # expected_result maintains existing ecosystem with custom configuration + # and adds new ecosystem existing_config = MagicMock() - existing_config.decoded = b'---\nversion: 2\nupdates:\n - package-ecosystem: "pip"\n directory: "/"\n\ - schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' + existing_config.decoded = b'---\nversion: 2\nupdates:\n- package-ecosystem: "pip"\n directory: "/"\n\ + schedule:\n interval: "weekly"\n commit-message:\n prefix: "chore(deps)"\n' result = build_dependabot_file(repo, False, [], existing_config) - self.assertEqual(result, expected_result) + self.assertEqual(result, None) def test_build_dependabot_file_with_npm(self): """Test that the dependabot.yml file is built correctly with npm""" @@ -120,10 +108,10 @@ def test_build_dependabot_file_with_npm(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'npm' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -144,10 +132,10 @@ def test_build_dependabot_file_with_pip(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'pip' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'pip' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -165,10 +153,10 @@ def test_build_dependabot_file_with_cargo(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'cargo' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'cargo' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -181,10 +169,10 @@ def test_build_dependabot_file_with_gomod(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'gomod' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'gomod' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -202,10 +190,10 @@ def test_build_dependabot_file_with_composer(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'composer' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'composer' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -223,10 +211,10 @@ def test_build_dependabot_file_with_hex(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'mix' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'mix' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -239,10 +227,10 @@ def test_build_dependabot_file_with_nuget(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'nuget' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'nuget' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -255,10 +243,10 @@ def test_build_dependabot_file_with_docker(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'docker' - directory: '/' - schedule: - interval: 'weekly' + - package-ecosystem: 'docker' + directory: '/' + schedule: + interval: 'weekly' """ result = build_dependabot_file(repo, False, [], None) self.assertEqual(result, expected_result) @@ -271,15 +259,15 @@ def test_build_dependabot_file_with_groups(self): expected_result = """--- version: 2 updates: -- package-ecosystem: 'docker' - directory: '/' - schedule: - interval: 'weekly' - groups: - production-dependencies: - dependency-type: 'production' - development-dependencies: - dependency-type: 'development' + - package-ecosystem: 'docker' + directory: '/' + schedule: + interval: 'weekly' + groups: + production-dependencies: + dependency-type: 'production' + development-dependencies: + dependency-type: 'development' """ result = build_dependabot_file(repo, True, [], None) self.assertEqual(result, expected_result) From 4d28f9f672ac6aba436f50c7532947d653c10716 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 14:43:31 -0700 Subject: [PATCH 7/8] fix: use fstring to get var to print --- dependabot_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependabot_file.py b/dependabot_file.py index 86f8341..92b0939 100644 --- a/dependabot_file.py +++ b/dependabot_file.py @@ -71,7 +71,7 @@ def build_dependabot_file( indent = " " * (len(ecosystem_line) - len(ecosystem_line.lstrip())) if len(indent) < DEFAULT_INDENT: print( - "Invalid dependabot.yml file. No indentation found. Skipping {repo.full_name}" + f"Invalid dependabot.yml file. No indentation found. Skipping {repo.full_name}" ) return None else: From a981676708fa8b113a756c9f425750d7eb83ad3a Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Thu, 30 May 2024 15:14:34 -0700 Subject: [PATCH 8/8] docs: clarify permissions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 116289e..e4852fe 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ This action can be configured to authenticate with GitHub App Installation or Pe | field | required | default | description | |-------------------------------|----------|---------|-------------| -| `GH_TOKEN` | True | `""` | The GitHub Token used to scan the repository. Must have read access to all repository you are interested in scanning and repo:write and workflow privelages to create a pull request. | +| `GH_TOKEN` | True | `""` | The GitHub Token used to scan the repository. Must have read access to all repository you are interested in scanning, `repo:write`, and `workflow` privileges to create a pull request. | #### Other Configuration Options