Skip to content

Commit

Permalink
Merge pull request #60 from gbrindisi/visibility
Browse files Browse the repository at this point in the history
Filter repositories in scope by their visibility
  • Loading branch information
zkoppert authored Mar 4, 2024
2 parents 42556ba + 45cd16c commit c405c0a
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Below are the allowed configuration options:
| `GH_ENTERPRISE_URL` | False | "" | The `GH_ENTERPRISE_URL` is used to connect to an enterprise server instance of GitHub. github.com users should not enter anything here. |
| `ORGANIZATION` | Required to have `ORGANIZATION` or `REPOSITORY` | | The name of the GitHub organization which you want this action to work from. ie. github.com/github would be `github` |
| `REPOSITORY` | Required to have `ORGANIZATION` or `REPOSITORY` | | The name of the repository and organization which you want this action to work from. ie. `github/evergreen` or a comma separated list of multiple repositories `github/evergreen,super-linter/super-linter` |
| `EXEMPT_REPOS` | False | "" | These repositories will be exempt from this action considering them for dependabot enablement. ex: If my org is set to `github` then I might want to exempt a few of the repos but get the rest by setting `EXEMPT_REPOS` to ``github/evergreen,github/contributors` |
| `EXEMPT_REPOS` | False | "" | These repositories will be exempt from this action considering them for dependabot enablement. ex: If my org is set to `github` then I might want to exempt a few of the repos but get the rest by setting `EXEMPT_REPOS` to `github/evergreen,github/contributors` |
| `TYPE` | False | pull | Type refers to the type of action you want taken if this workflow determines that dependabot could be enabled. Valid values are `pull` or `issue`.|
| `TITLE` | False | "Enable Dependabot" | The title of the issue or pull request that will be created if dependabot could be enabled. |
| `BODY` | False | **Pull Request:** "Dependabot could be enabled for this repository. Please enable it by merging this pull request so that we can keep our dependencies up to date and secure." **Issue:** "Please update the repository to include a Dependabot configuration file. This will ensure our dependencies remain updated and secure.Follow the guidelines in [creating Dependabot configuration files](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file) to set it up properly.Here's an example of the code:" | The body of the issue or pull request that will be created if dependabot could be enabled. |
Expand All @@ -47,6 +47,7 @@ Below are the allowed configuration options:
| `PROJECT_ID` | False | "" | If set, this will assign the issue or pull request to the project with the given ID. ( The project ID on GitHub can be located by navigating to the respective project and observing the URL's end.) **The `ORGANIZATION` variable is required** |
| `DRY_RUN` | False | false | If set to true, this action will not create any issues or pull requests. It will only log the repositories that could have dependabot enabled. This is useful for testing. |
| `GROUP_DEPENDENCIES` | False | false | If set to true, dependabot configuration will group dependencies updates based on [dependency type](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups) (production or development, where supported) |
| `FILTER_VISIBILITY` | False | "public,private,internal" | Use this flag to filter repositories in scope by their visibility (`public`, `private`, `internal`). By default all repository are targeted. ex: to ignore public repositories set this value to `private,internal`. |
| `ENABLE_SECURITY_UPDATES` | False | true | If set to true, Evergreen will enable [Dependabot security updates](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates) on target repositories. Note that the GitHub token needs to have the `administration:write` permission on every repository in scope to successfully enable security updates. |

### Example workflows
Expand Down
17 changes: 17 additions & 0 deletions env.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def get_env_vars() -> (
str,
str | None,
bool | None,
list[str] | None,
bool | None,
]
):
Expand All @@ -45,6 +46,7 @@ def get_env_vars() -> (
dry_run (bool): Whether or not to actually open issues/pull requests
commit_message (str): The commit message of the follow up
group_dependencies (bool): Whether to group dependencies in the dependabot.yml file
filter_visibility (list[str]): Run the action only on repositories with the specified listed visibility
enable_security_updates (bool): Whether to enable security updates in target repositories
"""
# Load from .env file if it exists
Expand Down Expand Up @@ -166,6 +168,20 @@ def get_env_vars() -> (
else:
dry_run_bool = False

filter_visibility = os.getenv("FILTER_VISIBILITY")
filter_visibility_list = []
if filter_visibility:
filter_visibility_set = set()
for visibility in filter_visibility.split(","):
if visibility.strip().lower() not in ["public", "private", "internal"]:
raise ValueError(
"FILTER_VISIBILITY environment variable not 'public', 'private', or 'internal'"
)
filter_visibility_set.add(visibility.strip().lower())
filter_visibility_list = sorted(list(filter_visibility_set))
else:
filter_visibility_list = sorted(["public", "private", "internal"]) # all

project_id = os.getenv("PROJECT_ID")
if project_id and not project_id.isnumeric():
raise ValueError("PROJECT_ID environment variable is not numeric")
Expand All @@ -183,5 +199,6 @@ def get_env_vars() -> (
commit_message,
project_id,
group_dependencies_bool,
filter_visibility_list,
enable_security_updates_bool,
)
3 changes: 3 additions & 0 deletions evergreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def main(): # pragma: no cover
commit_message,
project_id,
group_dependencies,
filter_visibility,
enable_security_updates,
) = env.get_env_vars()

Expand All @@ -54,6 +55,8 @@ def main(): # pragma: no cover
continue
if repo.archived:
continue
if repo.visibility.lower() not in filter_visibility:
continue
try:
if repo.file_contents(".github/dependabot.yml").size > 0:
continue
Expand Down
137 changes: 137 additions & 0 deletions test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def test_get_env_vars_with_org(self):
"Create dependabot configuration",
"123",
False,
["internal", "private", "public"],
True, # enable_security_updates
)
result = get_env_vars()
Expand Down Expand Up @@ -78,6 +79,7 @@ def test_get_env_vars_with_repos(self):
"Create dependabot configuration",
"123",
False,
["internal", "private", "public"],
True, # enable_security_updates
)
result = get_env_vars()
Expand Down Expand Up @@ -108,6 +110,7 @@ def test_get_env_vars_optional_values(self):
"Create dependabot.yaml",
None,
False,
["internal", "private", "public"],
True, # enable_security_updates
)
result = get_env_vars()
Expand Down Expand Up @@ -158,6 +161,7 @@ def test_get_env_vars_with_repos_no_dry_run(self):
"Create dependabot.yaml",
None,
False,
["internal", "private", "public"],
True, # enable_security_updates
)
result = get_env_vars()
Expand Down Expand Up @@ -190,6 +194,139 @@ def test_get_env_vars_with_repos_disabled_security_updates(self):
"Create dependabot.yaml",
None,
False,
["internal", "private", "public"],
False, # enable_security_updates
)
result = get_env_vars()
self.assertEqual(result, expected_result)

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"ENABLE_SECURITY_UPDATES": "false",
"FILTER_VISIBILITY": "private,internal",
},
clear=True,
)
def test_get_env_vars_with_repos_filter_visibility_multiple_values(self):
"""Test that filter_visibility is set correctly when multiple values are provided"""
expected_result = (
"my_organization",
[],
"my_token",
"",
[],
"pull",
"Enable Dependabot",
"Dependabot could be enabled for this repository. \
Please enable it by merging this pull request so that \
we can keep our dependencies up to date and secure.",
None,
False,
"Create dependabot.yaml",
None,
False,
["internal", "private"],
False, # enable_security_updates
)
result = get_env_vars()
self.assertEqual(result, expected_result)

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"ENABLE_SECURITY_UPDATES": "false",
"FILTER_VISIBILITY": "public",
},
clear=True,
)
def test_get_env_vars_with_repos_filter_visibility_single_value(self):
"""Test that filter_visibility is set correctly when a single value is provided"""
expected_result = (
"my_organization",
[],
"my_token",
"",
[],
"pull",
"Enable Dependabot",
"Dependabot could be enabled for this repository. \
Please enable it by merging this pull request so that \
we can keep our dependencies up to date and secure.",
None,
False,
"Create dependabot.yaml",
None,
False,
["public"],
False, # enable_security_updates
)
result = get_env_vars()
self.assertEqual(result, expected_result)

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"ENABLE_SECURITY_UPDATES": "false",
"FILTER_VISIBILITY": "foobar",
},
clear=True,
)
def test_get_env_vars_with_repos_filter_visibility_invalid_single_value(self):
"""Test that filter_visibility throws an error when an invalid value is provided"""
with self.assertRaises(ValueError):
get_env_vars()

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"ENABLE_SECURITY_UPDATES": "false",
"FILTER_VISIBILITY": "public, foobar, private",
},
clear=True,
)
def test_get_env_vars_with_repos_filter_visibility_invalid_multiple_value(self):
"""Test that filter_visibility throws an error when an invalid value is provided"""
with self.assertRaises(ValueError):
get_env_vars()

@patch.dict(
os.environ,
{
"ORGANIZATION": "my_organization",
"GH_TOKEN": "my_token",
"ENABLE_SECURITY_UPDATES": "false",
"FILTER_VISIBILITY": "private,private,public",
},
clear=True,
)
def test_get_env_vars_with_repos_filter_visibility_no_duplicates(self):
"""Test that filter_visibility is set correctly when there are duplicate values"""
expected_result = (
"my_organization",
[],
"my_token",
"",
[],
"pull",
"Enable Dependabot",
"Dependabot could be enabled for this repository. \
Please enable it by merging this pull request so that \
we can keep our dependencies up to date and secure.",
None,
False,
"Create dependabot.yaml",
None,
False,
["private", "public"],
False, # enable_security_updates
)
result = get_env_vars()
Expand Down

0 comments on commit c405c0a

Please sign in to comment.