class

ContributorMural::GitHubApi

Inherits ContributorMural::GitHubSource < Reference < Object

Fetches users from the GitHub REST and GraphQL APIs. Contribution counts and sponsor tier amounts become user weights.

Constants

CONTRIBUTOR_CEILING = 500

GitHub's own ceiling on the contributors endpoint, which it applies by answering with a full list rather than with an error. A repository past it simply stops having contributors as far as this API is concerned, so a list that ends on exactly this number is the only signal there is.

MAX_ATTEMPTS = 3
MAX_RETRY_AFTER = 30.seconds

A secondary rate limit names its own delay; anything longer than this is better spent failing with a message someone can act on.

PAGE_WINDOW = 4

How many pages of one collection may be in flight together. Enough that a thousand stargazers stop being ten round trips in a row, low enough to stay clear of the secondary rate limit that punishes bursts.

PER_PAGE = 100
SECTIONS = ["contributors", "members", "stargazers", "sponsors"] of ::String

Notices are ranked by the section that raised them rather than by which fiber reached the end first, so two runs of one config read alike.

SPONSORS_QUERY = "query($login: String!, $first: Int!, $after: String) {\n repositoryOwner(login: $login) {\n ... on User {\n sponsorshipsAsMaintainer(first: $first, after: $after, activeOnly: true) {\n pageInfo { hasNextPage endCursor }\n nodes {\n tier { monthlyPriceInDollars }\n sponsorEntity {\n ... on User { login name avatarUrl url }\n ... on Organization { login name avatarUrl url }\n }\n }\n }\n }\n ... on Organization {\n sponsorshipsAsMaintainer(first: $first, after: $after, activeOnly: true) {\n pageInfo { hasNextPage endCursor }\n nodes {\n tier { monthlyPriceInDollars }\n sponsorEntity {\n ... on User { login name avatarUrl url }\n ... on Organization { login name avatarUrl url }\n }\n }\n }\n }\n }\n}"

Constructors

new(token : String | Nil = nil, config : Config = Config.empty, api_base : String = "https://api.github.com", backoff_base : Time::Span = 1.second, pool : HTTPPool | Nil = nil)
Source

Instance methods

close

Hands back the connections this client opened. A no-op when the pool was handed in, since closing it would hang up on its other users.

Source
contributors(repo : String) : Array(ResolvedUser)
Source
members(org : String) : Array(ResolvedUser)
Source
notices

Anything the source needs said in the log once the fetching is over.

Collected rather than printed, because the four sources are fetched concurrently: Annotations ends in an IO#puts, which is a write of the message and then a write of the newline, and a flush between the two hands the fiber over — splicing one workflow command into another, which GitHub then parses as neither. Ordering would be a lottery besides.

Source
sponsors(login : String) : Array(ResolvedUser)
Source
stargazers(repo : String) : Array(ResolvedUser)
Source