Skip to content

Commit

Permalink
fix: try two public urls for maintainer exists lint (#2171)
Browse files Browse the repository at this point in the history
* fix: try two public urls for maintainer exists lint

* test: add test for org

* fix: need to use the teams endpoint

* fix: ignore redirects and use more specific urls

* doc: add news item
  • Loading branch information
beckermr authored Nov 27, 2024
1 parent 0e1d50f commit 79183e2
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
42 changes: 35 additions & 7 deletions conda_smithy/lint_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,16 +413,44 @@ def _maintainer_exists(maintainer: str) -> bool:
gh = _cached_gh()
try:
gh.get_user(maintainer)
is_user = True
except github.UnknownObjectException:
return False
return True
is_user = False

# for w/e reason, the user endpoint returns an entry for orgs
# however the org endpoint does not return an entry for users
# so we have to check both
try:
gh.get_organization(maintainer)
is_org = True
except github.UnknownObjectException:
is_org = False
else:
return (
requests.get(
f"https://api.github.com/users/{maintainer}"
).status_code
== 200
# this API request has no token and so has a restrictive rate limit
# return (
# requests.get(
# f"https://api.github.com/users/{maintainer}"
# ).status_code
# == 200
# )
# so we check two public URLs instead.
# 1. github.com/<maintainer>?tab=repositories - this URL works for all users and all orgs
# 2. https://github.com/orgs/<maintainer>/teams - this URL only works for
# orgs so we make sure it fails
# we do not allow redirects to ensure we get the correct status code
# for the specific URL we requested
req_profile = requests.get(
f"https://github.com/{maintainer}?tab=repositories",
allow_redirects=False,
)
is_user = req_profile.status_code == 200
req_org = requests.get(
f"https://github.com/orgs/{maintainer}/teams",
allow_redirects=False,
)
is_org = req_org.status_code == 200

return is_user and not is_org


@lru_cache(maxsize=1)
Expand Down
24 changes: 24 additions & 0 deletions news/2171-fix-maintainer_exists.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
**Added:**

* <news item>

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* Fixed a bug in checking in recipe maintainers exist without a GitHub token
where the anonymous API would run out of requests. (#2171)

**Security:**

* <news item>
36 changes: 36 additions & 0 deletions tests/test_lint_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,42 @@ def test_maintainer_exists(self):
expected_message = 'Recipe maintainer "isuruf" does not exist'
self.assertNotIn(expected_message, lints)

lints, _ = linter.lintify_meta_yaml(
{"extra": {"recipe-maintainers": ["conda-forge"]}},
conda_forge=True,
)
expected_message = 'Recipe maintainer "conda-forge" does not exist'
self.assertIn(expected_message, lints)

def test_maintainer_exists_no_token(self):
gh_token = os.environ.get("GH_TOKEN", None)
try:
if "GH_TOKEN" in os.environ:
del os.environ["GH_TOKEN"]

lints, _ = linter.lintify_meta_yaml(
{"extra": {"recipe-maintainers": ["support"]}},
conda_forge=True,
)
expected_message = 'Recipe maintainer "support" does not exist'
self.assertIn(expected_message, lints)

lints, _ = linter.lintify_meta_yaml(
{"extra": {"recipe-maintainers": ["isuruf"]}}, conda_forge=True
)
expected_message = 'Recipe maintainer "isuruf" does not exist'
self.assertNotIn(expected_message, lints)

lints, _ = linter.lintify_meta_yaml(
{"extra": {"recipe-maintainers": ["conda-forge"]}},
conda_forge=True,
)
expected_message = 'Recipe maintainer "conda-forge" does not exist'
self.assertIn(expected_message, lints)
finally:
if gh_token is not None:
os.environ["GH_TOKEN"] = gh_token

def test_maintainer_team_exists(self):
lints, _ = linter.lintify_meta_yaml(
{
Expand Down

0 comments on commit 79183e2

Please sign in to comment.