Source code for repomatic.github.sponsor
# Copyright Kevin Deldycke <[email protected]> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""Check if a GitHub user is a sponsor of another user or organization.
Uses the GitHub GraphQL API via the `gh` CLI to query sponsorship data.
Supports both user and organization owners, with pagination for accounts
that have more than 100 sponsors.
When run in GitHub Actions, the owner defaults to
{class}`~repomatic.metadata.Metadata`'s view of the repository; the author
and issue/PR number come from the event-payload readers in
{mod}`~repomatic.github.actions`.
"""
from __future__ import annotations
import logging
from functools import lru_cache
from ..metadata import Metadata
from .gh import iter_graphql_nodes
TYPE_CHECKING = False
if TYPE_CHECKING:
from collections.abc import Iterator
[docs]
def get_default_owner() -> str | None:
"""Get the repository owner from CI context.
Delegates to {attr}`Metadata.repo_owner
<repomatic.metadata.Metadata.repo_owner>`.
"""
owner = Metadata().repo_owner
return owner if owner else None
SPONSORS_QUERY_TEMPLATE = """
query($owner: String!, $cursor: String) {
%s(login: $owner) {
sponsorshipsAsMaintainer(first: 100, after: $cursor, includePrivate: true) {
pageInfo { hasNextPage endCursor }
nodes { sponsorEntity { ... on User { login } ... on Organization { login } } }
}
}
}
"""
"""GraphQL query for an account's sponsors, parameterized on the account kind.
The user and organization queries are identical except for the node naming the
account (`user` or `organization`), which doubles as the response's data path:
{func}`_iter_sponsors` interpolates it into both places.
"""
def _iter_sponsors(owner: str, kind: str) -> Iterator[str]:
"""Iterate over all sponsors using pagination.
:param owner: The owner (user or org) to query.
:param kind: The GraphQL node naming the account, `user` or `organization`.
:yields: Login names of sponsors.
"""
for node in iter_graphql_nodes(
SPONSORS_QUERY_TEMPLATE % kind,
(kind, "sponsorshipsAsMaintainer"),
{"owner": owner},
):
login = node.get("sponsorEntity", {}).get("login")
if login:
yield login