Skip to content

Commit 3e09c1c

Browse files
authored
Merge branch 'main' into copilot/fix-377
2 parents 8c74c03 + 4229a2d commit 3e09c1c

File tree

8 files changed

+192
-15
lines changed

8 files changed

+192
-15
lines changed

.github/copilot-instructions.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copilot Instructions
2+
3+
This is a GitHub Action that given an organization, team, or specified repositories, opens an issue/PR if dependabot is not enabled, or there are more package ecosystems that could be added. It also enables [automated security updates](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates#managing-dependabot-security-updates-for-your-repositories) for the repository. Please follow these guidelines when contributing:
4+
5+
## Code Standards
6+
7+
### Required Before Each Commit
8+
9+
- Run `make lint` before committing any changes to ensure proper code linting and formatting.
10+
11+
### Development Flow
12+
13+
- Lint: `make lint`
14+
- Test: `make test`
15+
16+
## Repository Structure
17+
18+
- `Makefile`: Contains commands for linting, testing, and other tasks
19+
- `requirements.txt`: Python dependencies for the project
20+
- `requirements-test.txt`: Python dependencies for testing
21+
- `README.md`: Project documentation and setup instructions
22+
- `setup.py`: Python package setup configuration
23+
- `test_*.py`: Python test files matching the naming convention for test discovery
24+
25+
## Key Guidelines
26+
27+
1. Follow Python best practices and idiomatic patterns
28+
2. Maintain existing code structure and organization
29+
3. Write unit tests for new functionality.
30+
4. Document changes to environment variables in the `README.md` file.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: "Copilot Setup Steps"
2+
3+
# Automatically run the setup steps when they are changed to allow for easy validation, and
4+
# allow manual testing through the repository's "Actions" tab
5+
on:
6+
workflow_dispatch:
7+
push:
8+
paths:
9+
- .github/workflows/copilot-setup-steps.yml
10+
pull_request:
11+
paths:
12+
- .github/workflows/copilot-setup-steps.yml
13+
14+
# Set the permissions to the lowest permissions possible needed for your steps.
15+
# Copilot will be given its own token for its operations.
16+
permissions:
17+
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
18+
contents: read
19+
20+
jobs:
21+
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
22+
copilot-setup-steps:
23+
runs-on: ubuntu-latest
24+
25+
# You can define any steps you want, and they will run before the agent starts.
26+
# If you do not check out your code, Copilot will do this for you.
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4.2.2
30+
31+
- name: Set up Python
32+
uses: actions/setup-python@v5.6.0
33+
with:
34+
python-version: 3.12
35+
36+
- name: Install dependencies
37+
run: |
38+
pip install -r requirements.txt -r requirements-test.txt

.github/workflows/super-linter.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ jobs:
3535
DEFAULT_BRANCH: main
3636
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3737
GITHUB_ACTIONS_COMMAND_ARGS: -shellcheck=
38+
FIX_MARKDOWN_PRETTIER: true

README.md

Lines changed: 48 additions & 5 deletions
Large diffs are not rendered by default.

env.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def get_env_vars(
9999
) -> tuple[
100100
str | None,
101101
list[str],
102+
str | None,
102103
int | None,
103104
int | None,
104105
bytes,
@@ -135,6 +136,7 @@ def get_env_vars(
135136
Returns:
136137
organization (str): The organization to search for repositories in
137138
repository_list (list[str]): A list of repositories to search for
139+
search_query (str): A search query string to filter repositories by
138140
gh_app_id (int | None): The GitHub App ID to use for authentication
139141
gh_app_installation_id (int | None): The GitHub App Installation ID to use for authentication
140142
gh_app_private_key_bytes (bytes): The GitHub App Private Key as bytes to use for authentication
@@ -162,18 +164,19 @@ def get_env_vars(
162164
dependabot_config_file (str): Dependabot extra configuration file location path
163165
"""
164166

165-
if not test:
167+
if not test: # pragma: no cover
166168
# Load from .env file if it exists and not testing
167169
dotenv_path = join(dirname(__file__), ".env")
168170
load_dotenv(dotenv_path)
169171

170172
organization = os.getenv("ORGANIZATION")
171173
repositories_str = os.getenv("REPOSITORY")
174+
search_query = os.getenv("REPOSITORY_SEARCH_QUERY", "").strip()
172175
team_name = os.getenv("TEAM_NAME")
173-
# Either organization or repository must be set
174-
if not organization and not repositories_str:
176+
# Either organization, repository, or search_query must be set
177+
if not organization and not repositories_str and not search_query:
175178
raise ValueError(
176-
"ORGANIZATION and REPOSITORY environment variables were not set. Please set one"
179+
"ORGANIZATION, REPOSITORY, and REPOSITORY_SEARCH_QUERY environment variables were not set. Please set one"
177180
)
178181
# Team name and repository are mutually exclusive
179182
if repositories_str and team_name:
@@ -352,6 +355,7 @@ def get_env_vars(
352355
return (
353356
organization,
354357
repositories_list,
358+
search_query,
355359
gh_app_id,
356360
gh_app_installation_id,
357361
gh_app_private_key_bytes,

evergreen.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def main(): # pragma: no cover
2020
(
2121
organization,
2222
repository_list,
23+
search_query,
2324
gh_app_id,
2425
gh_app_installation_id,
2526
gh_app_private_key,
@@ -77,7 +78,7 @@ def main(): # pragma: no cover
7778

7879
# Get the repositories from the organization, team name, or list of repositories
7980
repos = get_repos_iterator(
80-
organization, team_name, repository_list, github_connection
81+
organization, team_name, repository_list, search_query, github_connection
8182
)
8283

8384
# Setting up the action summary content
@@ -341,9 +342,21 @@ def enable_dependabot_security_updates(ghe, owner, repo, access_token):
341342
print("\tFailed to enable Dependabot security updates.")
342343

343344

344-
def get_repos_iterator(organization, team_name, repository_list, github_connection):
345-
"""Get the repositories from the organization, team_name, or list of repositories"""
345+
def get_repos_iterator(
346+
organization, team_name, repository_list, search_query, github_connection
347+
):
348+
"""Get the repositories from the organization, team_name, repository_list, or via search query"""
349+
# Use GitHub search API if REPOSITORY_SEARCH_QUERY is set
350+
if search_query:
351+
# Return repositories matching the search query
352+
repos = []
353+
# Search results need to be converted to a list of repositories since they are returned as a search iterator
354+
for repo in github_connection.search_repositories(search_query):
355+
repos.append(repo.repository)
356+
return repos
357+
346358
repos = []
359+
# Default behavior: list all organization/team repositories or specific repository list
347360
if organization and not repository_list and not team_name:
348361
repos = github_connection.organization(organization).repositories()
349362
elif team_name and organization:

test_env.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def setUp(self):
3939
"TYPE",
4040
"UPDATE_EXISTING",
4141
"REPO_SPECIFIC_EXEMPTIONS",
42+
"REPOSITORY_SEARCH_QUERY",
4243
"SCHEDULE",
4344
"SCHEDULE_DAY",
4445
"LABELS",
@@ -68,6 +69,7 @@ def test_get_env_vars_with_org(self):
6869
expected_result = (
6970
"my_organization",
7071
[],
72+
"", # search_query
7173
None,
7274
None,
7375
b"",
@@ -120,6 +122,7 @@ def test_get_env_vars_with_org_and_repo_specific_exemptions(self):
120122
expected_result = (
121123
"my_organization",
122124
[],
125+
"", # search_query
123126
None,
124127
None,
125128
b"",
@@ -232,6 +235,7 @@ def test_get_env_vars_with_repos(self):
232235
expected_result = (
233236
None,
234237
["org/repo1", "org2/repo2"],
238+
"", # search_query
235239
None,
236240
None,
237241
b"",
@@ -289,6 +293,7 @@ def test_get_env_vars_with_team(self):
289293
expected_result = (
290294
"my_organization",
291295
[],
296+
"", # search_query
292297
None,
293298
None,
294299
b"",
@@ -364,6 +369,7 @@ def test_get_env_vars_optional_values(self):
364369
expected_result = (
365370
"my_organization",
366371
[],
372+
"", # search_query
367373
None,
368374
None,
369375
b"",
@@ -410,6 +416,7 @@ def test_get_env_vars_with_update_existing(self):
410416
expected_result = (
411417
"my_organization",
412418
[],
419+
"", # search_query
413420
None,
414421
None,
415422
b"",
@@ -450,7 +457,7 @@ def test_get_env_vars_missing_org_or_repo(self):
450457
the_exception = cm.exception
451458
self.assertEqual(
452459
str(the_exception),
453-
"ORGANIZATION and REPOSITORY environment variables were not set. Please set one",
460+
"ORGANIZATION, REPOSITORY, and REPOSITORY_SEARCH_QUERY environment variables were not set. Please set one",
454461
)
455462

456463
@patch.dict(
@@ -470,6 +477,7 @@ def test_get_env_vars_auth_with_github_app_installation(self):
470477
expected_result = (
471478
"my_organization",
472479
[],
480+
"", # search_query
473481
12345,
474482
678910,
475483
b"hello",
@@ -559,6 +567,7 @@ def test_get_env_vars_with_repos_no_dry_run(self):
559567
expected_result = (
560568
"my_organization",
561569
[],
570+
"", # search_query
562571
None,
563572
None,
564573
b"",
@@ -605,6 +614,7 @@ def test_get_env_vars_with_repos_disabled_security_updates(self):
605614
expected_result = (
606615
"my_organization",
607616
[],
617+
"", # search_query
608618
None,
609619
None,
610620
b"",
@@ -652,6 +662,7 @@ def test_get_env_vars_with_repos_filter_visibility_multiple_values(self):
652662
expected_result = (
653663
"my_organization",
654664
[],
665+
"", # search_query
655666
None,
656667
None,
657668
b"",
@@ -699,6 +710,7 @@ def test_get_env_vars_with_repos_filter_visibility_single_value(self):
699710
expected_result = (
700711
"my_organization",
701712
[],
713+
"", # search_query
702714
None,
703715
None,
704716
b"",
@@ -776,6 +788,7 @@ def test_get_env_vars_with_repos_filter_visibility_no_duplicates(self):
776788
expected_result = (
777789
"my_organization",
778790
[],
791+
"", # search_query
779792
None,
780793
None,
781794
b"",
@@ -824,6 +837,7 @@ def test_get_env_vars_with_repos_exempt_ecosystems(self):
824837
expected_result = (
825838
"my_organization",
826839
[],
840+
"", # search_query
827841
None,
828842
None,
829843
b"",
@@ -871,6 +885,7 @@ def test_get_env_vars_with_no_batch_size(self):
871885
expected_result = (
872886
"my_organization",
873887
[],
888+
"", # search_query
874889
None,
875890
None,
876891
b"",
@@ -919,6 +934,7 @@ def test_get_env_vars_with_batch_size(self):
919934
expected_result = (
920935
"my_organization",
921936
[],
937+
"", # search_query
922938
None,
923939
None,
924940
b"",
@@ -1056,6 +1072,7 @@ def test_get_env_vars_with_valid_schedule_and_schedule_day(self):
10561072
expected_result = (
10571073
"my_organization",
10581074
[],
1075+
"", # search_query
10591076
None,
10601077
None,
10611078
b"",
@@ -1141,6 +1158,7 @@ def test_get_env_vars_with_a_valid_label(self):
11411158
expected_result = (
11421159
"my_organization",
11431160
[],
1161+
"", # search_query
11441162
None,
11451163
None,
11461164
b"",
@@ -1187,6 +1205,7 @@ def test_get_env_vars_with_valid_labels_containing_spaces(self):
11871205
expected_result = (
11881206
"my_organization",
11891207
[],
1208+
"", # search_query
11901209
None,
11911210
None,
11921211
b"",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy