Skip to content

Commit

Permalink
fix: skip repo if no package manager found (#270)
Browse files Browse the repository at this point in the history
* fix: skip repo if no package manager found

* feat: add gradle and devcontainers support + tests

* feat: add test for dependabot extra configuration at env level

* fix: add registries key if existing configuration dependabot configuration exists
  • Loading branch information
ricardojdsilva87 authored Dec 3, 2024
1 parent b467ec6 commit b599bcb
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ maven:
password: "${{secrets.password}}"
```
The principal key of each configuration need to match the package managers that the [script is looking for](https://github.com/github/evergreen/blob/main/dependabot_file.py#L78).
The principal key of each configuration need to match the package managers that the [script is looking for](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem).
The `dependabot.yaml` created file will look like the following with the `registries:` key added:

Expand Down
20 changes: 20 additions & 0 deletions dependabot_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def make_dependabot_config(
if extra_dependabot_config:
ecosystem_config = extra_dependabot_config.get(ecosystem)
if ecosystem_config:
if "registries" not in dependabot_config:
dependabot_config.update({"registries": {}})
dependabot_config["registries"][ecosystem] = ecosystem_config
dependabot_config["updates"][-1].update(
{"registries": [SingleQuotedScalarString(ecosystem)]}
Expand Down Expand Up @@ -184,6 +186,7 @@ def build_dependabot_file(
],
"docker": ["Dockerfile"],
"maven": ["pom.xml"],
"gradle": ["build.gradle", "build.gradle.kts"],
}

# Detect package managers where manifest files have known names
Expand Down Expand Up @@ -242,6 +245,23 @@ def build_dependabot_file(
break
except github3.exceptions.NotFoundError:
pass
if "devcontainers" not in exempt_ecosystems_list:
try:
for file in repo.directory_contents(".devcontainer"):
if file[0] == "devcontainer.json":
package_managers_found["devcontainers"] = True
make_dependabot_config(
"devcontainers",
group_dependencies,
schedule,
schedule_day,
labels,
dependabot_file,
extra_dependabot_config,
)
break
except github3.exceptions.NotFoundError:
pass

if any(package_managers_found.values()):
return dependabot_file
Expand Down
4 changes: 4 additions & 0 deletions env.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ def get_env_vars(
labels_list = [label.lower().strip() for label in labels_str.split(",")]

dependabot_config_file = os.getenv("DEPENDABOT_CONFIG_FILE")
if dependabot_config_file and not os.path.exists(dependabot_config_file):
raise ValueError(
f"No dependabot extra configuration found. Please create one in {dependabot_config_file}"
)

return (
organization,
Expand Down
33 changes: 10 additions & 23 deletions evergreen.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""This file contains the main() and other functions needed to open an issue/PR dependabot is not enabled but could be"""

import base64
import io
import os
import sys
import uuid
from datetime import datetime
Expand Down Expand Up @@ -123,26 +121,15 @@ def main(): # pragma: no cover
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
# If running locally on a computer the local file takes precedence over the one existent on the repository
if os.path.exists(dependabot_config_file):
try:
with open(
dependabot_config_file, "r", encoding="utf-8"
) as extra_dependabot_config:
extra_dependabot_config = yaml.load(extra_dependabot_config)
except ruamel.yaml.YAMLError as e:
print(f"YAML indentation error: {e}")
continue
else:
try:
extra_dependabot_config = check_existing_config(
repo, dependabot_config_file
).content
extra_dependabot_config = yaml.load(
base64.b64decode(extra_dependabot_config)
)
except ruamel.yaml.YAMLError as e:
print(f"YAML indentation error: {e}")
continue
try:
with open(
dependabot_config_file, "r", encoding="utf-8"
) as extra_dependabot_config:
extra_dependabot_config = yaml.load(extra_dependabot_config)
except ruamel.yaml.YAMLError as e:
print(f"YAML indentation error: {e}")
continue

else:
# If no dependabot configuration file is present set the variable empty
extra_dependabot_config = None
Expand Down Expand Up @@ -173,7 +160,7 @@ def main(): # pragma: no cover
print("\tNo (new) compatible package manager found")
continue

yaml.dump(dependabot_file, stream)
dependabot_file = yaml.dump(dependabot_file, stream)
dependabot_file = stream.getvalue()

# If dry_run is set, just print the dependabot file
Expand Down
51 changes: 46 additions & 5 deletions test_dependabot_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ def test_build_dependabot_file_with_extra_dependabot_config_file(self):

# expected_result maintains existing ecosystem with custom configuration
# and adds new ecosystem
extra_dependabot_config = MagicMock()
extra_dependabot_config.content = base64.b64encode(
extra_dependabot_config = yaml.load(
b"""
npm:
type: 'npm'
Expand All @@ -215,9 +214,6 @@ def test_build_dependabot_file_with_extra_dependabot_config_file(self):
password: '${{secrets.password}}'
"""
)
extra_dependabot_config = yaml.load(
base64.b64decode(extra_dependabot_config.content)
)

expected_result = yaml.load(
b"""
Expand Down Expand Up @@ -448,6 +444,26 @@ def test_build_dependabot_file_with_maven(self):
)
self.assertEqual(result, expected_result)

def test_build_dependabot_file_with_gradle(self):
"""Test that the dependabot.yml file is built correctly with gradle"""
repo = MagicMock()
repo.file_contents.side_effect = lambda filename: filename == "build.gradle"

expected_result = yaml.load(
b"""
version: 2
updates:
- package-ecosystem: 'gradle'
directory: '/'
schedule:
interval: 'weekly'
"""
)
result = build_dependabot_file(
repo, False, [], {}, None, "weekly", "", [], None
)
self.assertEqual(result, expected_result)

def test_build_dependabot_file_with_terraform_with_files(self):
"""Test that the dependabot.yml file is built correctly with Terraform"""
repo = MagicMock()
Expand Down Expand Up @@ -498,6 +514,31 @@ def test_build_dependabot_file_with_terraform_without_files(self):
)
self.assertIsNone(result)

def test_build_dependabot_file_with_devcontainers(self):
"""Test that the dependabot.yml file is built correctly with devcontainers"""
repo = MagicMock()
response = MagicMock()
response.status_code = 404
repo.file_contents.side_effect = github3.exceptions.NotFoundError(resp=response)
repo.directory_contents.side_effect = lambda path: (
[("devcontainer.json", None)] if path == ".devcontainer" else []
)

expected_result = yaml.load(
b"""
version: 2
updates:
- package-ecosystem: 'devcontainers'
directory: '/'
schedule:
interval: 'weekly'
"""
)
result = build_dependabot_file(
repo, False, [], None, None, "weekly", "", [], None
)
self.assertEqual(result, expected_result)

def test_build_dependabot_file_with_github_actions(self):
"""Test that the dependabot.yml file is built correctly with GitHub Actions"""
repo = MagicMock()
Expand Down
20 changes: 20 additions & 0 deletions test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,26 @@ def test_get_env_vars_project_id_not_a_number(self):
"PROJECT_ID environment variable is not numeric",
)

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"SCHEDULE": "weekly",
"DEPENDABOT_CONFIG_FILE": "config.yaml",
},
clear=True,
)
def test_get_env_vars_with_dependabot_config_file_set_but_not_found(self):
"""Test that no dependabot file configuration is present and the DEPENDABOT_CONFIG_FILE is set"""
with self.assertRaises(ValueError) as context_manager:
get_env_vars(True)
the_exception = context_manager.exception
self.assertEqual(
str(the_exception),
"No dependabot extra configuration found. Please create one in config.yaml",
)


if __name__ == "__main__":
unittest.main()

0 comments on commit b599bcb

Please sign in to comment.