Skip to content

Commit cf9992e

Browse files
jmeridthzkoppertclaude
authored
fix: handle invalid YAML in existing dependabot config gracefully (#526)
* fix: return None instead of re-raising on invalid YAML in existing dependabot config Fixes #523 ## What Changed build_dependabot_file() to return None instead of re-raising when an existing dependabot config has invalid YAML (e.g., duplicate keys, indentation errors). Updated existing test expectations and added a new test for the duplicate key scenario reported in the issue. ## Why When a repository had an invalid dependabot.yml (such as a duplicate key), the YAML parse error crashed the entire program, preventing all remaining repositories from being processed. Returning None allows the caller's existing `if dependabot_file is None` check to skip the repo and continue. ## Notes - The error message is still printed via the existing `print(f"YAML indentation error: {e}")` so users can identify which repo has a broken config. - The second test at line 175 (indentation error) also changed from `assertRaises` to `assertIsNone` since it exercises the same code path. Signed-off-by: jmeridth <jmeridth@gmail.com> * fix: move None guard above yaml.dump to avoid writing null to debug file ## What Moved the `if dependabot_file is None` check above the `yaml.dump()` call in `main()` so that None results skip immediately without writing `null` to `dependabot-output.yaml`. ## Why The previous ordering called `yaml.dump(None, yaml_file)` before checking for None, writing a `null` YAML literal to the debug artifact. This was a pre-existing issue for the "no package managers" path, but the YAML error handling change made it newly reachable via the error path. ## Notes - The YAML object and stream setup also moved below the guard since they're only needed when dependabot_file is not None. Signed-off-by: jmeridth <jmeridth@gmail.com> * fix: Update dependabot_file.py Co-authored-by: Zack Koppert <zkoppert@github.com> Signed-off-by: Jason Meridth <jmeridth@gmail.com> * fix: restore return None and remove duplicate print in YAML error handler The UI merge of the error message suggestion accidentally replaced `return None` with the new print line, leaving two print statements and no early return. This caused UnboundLocalError on repos with invalid YAML configs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: jmeridth <jmeridth@gmail.com> * fix: use generic "Skipping repository" message when dependabot_file is None ## What Change the print message from "No (new) compatible package manager found" to "Skipping repository" when `build_dependabot_file()` returns `None`. ## Why `build_dependabot_file()` now returns `None` for two distinct reasons: no compatible package managers found, and a YAML parse error. The old message was only accurate for the first case and misleading for the second. Since the YAML error is already printed just before this point, a generic message avoids false attribution. Signed-off-by: jmeridth <jmeridth@gmail.com> --------- Signed-off-by: jmeridth <jmeridth@gmail.com> Signed-off-by: Jason Meridth <jmeridth@gmail.com> Co-authored-by: Zack Koppert <zkoppert@github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2fe6476 commit cf9992e

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

dependabot_file.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ def build_dependabot_file(
250250
try:
251251
dependabot_file = yaml.load(base64.b64decode(existing_config.content))
252252
except ruamel.yaml.YAMLError as e:
253-
print(f"YAML indentation error: {e}")
254-
raise
253+
print(f"YAML parsing error in existing dependabot config: {e}")
254+
return None
255255
else:
256256
dependabot_file = copy.deepcopy(data)
257257

evergreen.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ def main(): # pragma: no cover
178178
cooldown,
179179
)
180180

181+
if dependabot_file is None:
182+
print("\tSkipping repository")
183+
continue
184+
181185
yaml = ruamel.yaml.YAML()
182186
stream = io.StringIO()
183187
yaml.indent(mapping=2, sequence=4, offset=2)
@@ -186,10 +190,6 @@ def main(): # pragma: no cover
186190
with open("dependabot-output.yaml", "w", encoding="utf-8") as yaml_file:
187191
yaml.dump(dependabot_file, yaml_file)
188192

189-
if dependabot_file is None:
190-
print("\tNo (new) compatible package manager found")
191-
continue
192-
193193
dependabot_file = yaml.dump(dependabot_file, stream)
194194
dependabot_file = stream.getvalue()
195195

test_dependabot_file.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,29 @@ def test_build_dependabot_file_with_2_space_indent_existing_config_bundler_with_
131131
)
132132
self.assertEqual(result, expected_result)
133133

134+
def test_build_dependabot_file_with_duplicate_key_in_existing_config(self):
135+
"""Test that a duplicate key in existing dependabot config returns None instead of crashing"""
136+
repo = MagicMock()
137+
repo.file_contents.side_effect = lambda f, filename="Gemfile": f == filename
138+
139+
existing_config = MagicMock()
140+
existing_config.content = base64.b64encode(b"""
141+
version: 2
142+
updates:
143+
- package-ecosystem: "maven"
144+
directory: "/"
145+
schedule:
146+
interval: "daily"
147+
schedule:
148+
interval: "weekly"
149+
day: "friday"
150+
""")
151+
152+
result = build_dependabot_file(
153+
repo, False, [], {}, existing_config, "weekly", "", [], None
154+
)
155+
self.assertIsNone(result)
156+
134157
def test_build_dependabot_file_with_weird_space_indent_existing_config_bundler_with_update(
135158
self,
136159
):
@@ -152,10 +175,10 @@ def test_build_dependabot_file_with_weird_space_indent_existing_config_bundler_w
152175
prefix: "chore(deps)"
153176
""")
154177

155-
with self.assertRaises(ruamel.yaml.YAMLError):
156-
build_dependabot_file(
157-
repo, False, [], {}, existing_config, "weekly", "", [], None
158-
)
178+
result = build_dependabot_file(
179+
repo, False, [], {}, existing_config, "weekly", "", [], None
180+
)
181+
self.assertIsNone(result)
159182

160183
def test_build_dependabot_file_with_incorrect_indentation_in_extra_dependabot_config_file(
161184
self,

0 commit comments

Comments
 (0)