Search

Using C# Code to Access the GitHub API

Overview

If you code, you’re probably already familiar with GitHub. It is one of the most popular solutions available for source code management. It provides extensive features that meet almost all common needs.

What many don’t know is that it also provides a fairly robust API for accessing those features programmatically. This article will provide C# coding examples to introduce some of the more common features of that API.

Thankfully, the folks at GitHub have already created a NuGet package, named Octokit, to do most of the heavy lifting for GitHub API V3. While it is not quite perfect yet, it does get the job done.

Additionally, GitHub is currently (2/6/2019) beta testing a new framework, named Octokit.GraphQL.net, for GitHub API V4. However, this is beyond the scope of this article. For those who want to follow its progress, a link to its GitHub repository is provided in the Further Reading section of this article.

Sample Applications

The source code for two sample applications is included with this article:

  • GitHubApiSnippets.sln – This Windows Console application contains all of the sample code included with this article. The source code for this application can be downloaded from the following location: GitHubApiSnippets.zip.
  • GitHubApiDemo.sln – This Windows form application allows the user to experiment with GitHub API searches without writing code. The source code for this application can be downloaded from the following location: GitHubApiDemo.zip.

Both of these applications are licensed under CPOL.

Both of these applications were developed and built using Visual Studio 2017 Professional. However, they should also be compatible with Visual Studio 2017 Community and any later versions of Visual Studio.

A more detailed description of both applications is provided at the end of this article.

Getting Started

To use the GitHub API, an application must first connect to it. There are three common ways to connect: unauthenticated access, basic authentication, and OAuth token authentication. With all of these connection types, the GitHub API will limit the frequency of requests and separately limit the frequency and size of searches.

Client Identity

In all cases, the client needs to identify itself. This is done by providing a simple textual identity. The text should be one of the following (in order of preference): the name of the product, the GitHub organization, or the GitHub username. The following code provides an example.

				
					var productInformation = new ProductHeaderValue(GitHubIdentity);
				
			

Rate Limits

The GitHub API does impose some strict limits on the frequency of requests. Authenticated users are limited to 5,000 requests per hour. Unauthenticated users are limited to 60 requests per hour. Administrators of GitHub Enterprise servers can adjust these rate limits on a per-user and per-application basis. For more information, see GitHub Enterprise – Configuring Rate Limits in the Further Reading section of this article.

Search Limits

The GitHub API also imposes separate limits on search requests. Authenticated users are limited to 30 search requests per minute. Unauthenticated users are limited to 10 search requests per minute. Individual searches are also limited by the number of items they will return. A search, which may be broken into multiple requests/pages, is limited to a maximum of 1,000 items.

Unauthenticated Access

The simplest means of access is via an unauthenticated client. However, this type of client has the least access and the most restrictive rate limits. It is not recommended, except to create an OAuth token. The following code provides an example.

				
					var productInformation = new ProductHeaderValue(GitHubIdentity);
var client = new GitHubClient(productInformation);
				
			

Basic Authentication

To create a client using basic authentication, the application shares a username and a password with GitHub. This is a simple means of authentication. It is the one most likely used by desktop applications. Its sole disadvantage is that the application is at least temporarily aware of the user’s GitHub credentials. For web applications, OAuth token authentication is recommended. The following code provides an example of basic authentication.

				
					var productInformation = new ProductHeaderValue(GitHubIdentity);
var credentials = new Credentials(username, password, AuthenticationType.Basic);
var client = new GitHubClient(productInformation) { Credentials = credentials };
				
			

OAuth Token Authentication

With OAuth, a user authenticates using a token that was issued by the GitHub web site. It has the advantage that the application is never aware of the user’s GitHub credentials. Once the token is available, the connection process is very simple and similar to basic authentication. The following code provides an example.

				
					var productInformation = new ProductHeaderValue(GitHubIdentity);
var credentials = new Credentials(token);
var client = new GitHubClient(productInformation) { Credentials = credentials };
				
			

The complexity of this approach arises from the necessity to create an OAuth token. For the purposes of command-line applications, it is possible for a user to directly create an access token. To do this, follow the instructions here: https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/.

However, this is not recommended for web applications. Instead, web applications should use the OAuth web application flow described below.

OAuth Web Application Flow

The place where OAuth is strongest is with web applications. In this instance, you don’t start with an OAuth token. Instead, the application allows the GitHub web site to authenticate the user. The application then requests a token for that user. After the token is available, the connection process is exactly as was previously described.

The process is a little bit complicated and beyond the scope of this article, but we’ll at least provide a quick overview and a link to a very detailed description. Basically, the flow is as follows:

  1. You register your application with GitHub and receive a client identity and a client secret. This is a one-time thing. Once the application has been registered you “bake” the identity and secret into your application’s code.
  2. Your application re-directs to a GitHub URL, specifying a randomly generated key and the requested permissions. The randomly generated key helps to prevent cross-site request forgeries.
  3. GitHub authenticates the user.
  4. The GitHub URL re-directs back to your web site providing the same randomly generated key and an authentication code.
  5. Your application confirms the randomly generated key. It then creates an authentication code by specifying the client’s identity, the client’s secret, and the authentication code.
  6. In return, your application receives an OAuth token used to authenticate, as previously described.

The code to request a token is as follows:

				
					var client = new GitHubClient(new ProductHeaderValue(GitHubIdentity));

OauthToken tokenInfo = await client.Oauth.CreateAccessToken(
  new OauthTokenRequest(clientId, clientSecret, authenticationCode));

string token = tokenInfo.AccessToken;
				
			

The following link, on Phil Haack’s blog, provides a detailed description of the OAuth web application flow and also provides a sample project: https://haacked.com/archive/2014/04/24/octokit-oauth/.

GitHub Enterprise

Connecting to a GitHub Enterprise instance is nearly identical to what was previously described. One simply provides an additional parameter: the URL of the GitHub Enterprise server.

				
					var client = new GitHubClient(productInformation, new Uri(enterpriseUrl))
{
  Credentials = credentials
};
				
			

Top-level Information

If one already knows the identity of the information that is required, Octokit often provides methods to directly access it. Otherwise, it may be necessary to search for that information using the Search property of the client.

This section of the article will discuss some common top-level items of information. Sometimes the information is subordinate to the top-level information (e.g. a fork is subordinate to a repository).

In this case, there is still generally a subordinate property (in the client) that will allow one to directly access the information, without searching. The GitHubClient Properties section of this article provides an overview of these subordinate properties.

Repository

To access a repository directly, without first searching for it, use the Get method. For example, to get the “octokit/octokit.net” repository:

				
					Repository repository = await client.Repository.Get("octokit", "octokit.net");
				
			

Repository Forks

The same Repository property of the client also provides access to subordinate information for that repository. So, for example, the following code gets all of the forks for the “octokit/octokit.net” repository:

				
					IReadOnlyList<Repository> allForks = await client.Repository.Forks.GetAll(
  "octokit", "octokit.net");
				
			

Repository Forks (with Paging)

While the previous code works well for a small number of items, it will fail if the number of items grows too large. Most of the “get” methods, which return large numbers of items, support an optional parameter (of type ApiOptions). This parameter allows the caller to get the results in smaller chunks (or pages).

The code in the following example also gets all of the forks for the “octokit/octokit.net” repository, but this time paging is implemented:

				
					var options = new ApiOptions { PageCount = 1, PageSize = 100, StartPage = 1 };
int maximumCount = options.PageCount.Value * options.PageSize.Value;
Console.WriteLine("Repository.Forks.GetAll (Paging):");

while (true)
{
  IReadOnlyList<Repository> forks = await client.Repository.Forks.GetAll(
    "octokit", "octokit.net", options);
  foreach (Repository fork in forks)
    Console.WriteLine(
    "{fork.Owner.Login}/{fork.Name}");

if (forks.Count < maximumCount)
break;

options.StartPage++;
}
				
			

User

To access a user directly, without first searching for it, use the Get method as follows:

				
					User user = await client.User.Get("octokit");
				
			

This same method gets users with both personal and organization account types.

Searching

The Octokit framework provides comparatively robust searching capabilities. The API can search for code/files, issues/pull requests, labels, repositories, and users/organizations.

The results of a search are broken into pages. Each call to one of these methods will return a single page of results which, by default, consists of between zero and 100 items.

This section of the article provides a quick overview and an example of how paging can be implemented. A more detailed description of the search criteria is provided later in the article, in the “Search Property” section.

Code

Sometimes it is necessary to search for a file within a repository. In these cases, the SearchCode method is used to find files.

Searching for Files

The following is a simple search request that finds the first 100 C# files, in the “octokit/octokit.net” repository, which contain the text “issue” in the file path.

				
					SearchCodeResult result = await client.Search.SearchCode(
  new SearchCodeRequest("issue")
  {
    In = new CodeInQualifier[] { CodeInQualifier.Path },
    Language = Language.CSharp,
    Repos = new RepositoryCollection { "octokit/octokit.net" }
  });
				
			

Searching for Files (with Paging)

Sometimes it is necessary to find more than 100 items. The Octokit framework allows up to 1000 items to be found. To use this feature, it is necessary to implement paging, which is accomplished as follows:

				
					const int MaximumSearchItems = 1000;

var request = new SearchCodeRequest
{
  Language = Language.CSharp,
  Repos = new RepositoryCollection { "octokit/octokit.net" }
};

int maximumPage = MaximumSearchItems / request.PerPage;
for(request.Page = 1; request.Page <= maximumPage; request.Page++)
{
  SearchCodeResult result = await client.Search.SearchCode(request);
  if (request.Page == 1)
    Console.WriteLine(
 
quot;Search.SearchCode (Paging): TotalCount={result.TotalCount}");

foreach (SearchCode code in result.Items)
Console.WriteLine(
    "{code.Path}");

if (result.IncompleteResults || result.Items.Count < request.PerPage)
break;
}
				
			

Issue

Sometimes it is necessary to search for issues within a repository. In these cases, the SearchIssue method is used to find issues.

The following is a simple search request that finds the first 100 issues, for the “octokit/octokit.net” repository, which contain the text “bug” in the title.

				
					SearchIssuesResult result = await client.Search.SearchIssues(
  new SearchIssuesRequest("bug")
  {
    In = new IssueInQualifier[] { IssueInQualifier.Title },
    Repos = new RepositoryCollection { "octokit/octokit.net" }
  });
				
			

Label

Sometimes it is necessary to search for labels within a repository. In these cases, the SearchLabel method provides a limited ability to find labels.

The following is a simple search request that finds the first 100 labels, for the “octokit/octokit.net” repository, which start with the text “category”.

				
					Repository repository = await client.Repository.Get("octokit", "octokit.net");

SearchLabelsResult result = await client.Search.SearchLabels(
  new SearchLabelsRequest("category", repository.Id));
				
			

Repository

Sometimes it is necessary to search for repositories. In these cases, the SearchRepo method is used to find repositories.

The following is a simple search request that finds the first 100 repositories that contain the text “octokit” in the repository name.

				
					SearchRepositoryResult result = await client.Search.SearchRepo(
  new SearchRepositoriesRequest("octokit")
  {
    In = new InQualifier[] { InQualifier.Name }
  });
				
			

User

Sometimes it is necessary to search for a user or organization. In these cases, the SearchUser method is used to find users or organizations.

The following is a simple search request that finds the first 100 users (of account type User) that contain the text “oct” in one of the default fields (user’s login name, full name, or e-mail address).

				
					SearchUsersResult result = await client.Search.SearchUsers(
  new SearchUsersRequest("oct")
  {
    AccountType = AccountSearchType.User
  });
				
			

Note: By specifying an account type of Org, a similar search could be conducted for organizations instead of personal users.

GitHubClient Properties

To a large extent, a GitHub client (GitHubClient) is organized into a hierarchy of properties, each of which provides a separate interface, related to an individual element of the GitHub object model.

So, for example, to access a GitHub repository, one would reference the Repository property, to obtain access to the related API (IRepositoriesClient), as follows:

				
					Repository repository = await client.Repository.Get("octokit", "octokit.net");
				
			

To access a subordinate element of a repository (e.g. a branch) one would reference the nested Repository.Branch property, to obtain access to the related API (IRepositoryBranchesAPI), as follows:

				
					Branch branch = await client.Repository.Branch.Get("octokit", "octokit.net", "master");
				
			

There are a couple of exceptions to this pattern. One exception is the previously discussed Search property, which provides access to the search API (ISearchClient). Another exception is the Miscellaneous property, which provides access to the miscellaneous API (IMiscellaneousClient). Both of these APIs deal with multiple elements of the object model.

The following table provides an overview of the hierarchy of GitHubClient properties, which provide access to the related APIs.

Member NameDescription
ActivityManage the “social” aspects of GitHub, like events, Atom Feeds, notifications of comments, starring of repositories, and events for repositories that are watched.
 EventsList the events that occurred for various GitHub entities (e.g. organizations and repositories).
 FeedsList the Atom feeds that are available to the authenticated user.
 NotificationsList notifications for conversations and comments, mark them as read, and manage the authenticated user’s subscriptions to them.
 StarringManage starring (bookmarking) for repositories and list information about bookmarked repositories.
 WatchingRegister for notifications of discussions and events related to selected repositories.
AuthorizationManage authorizations (grant, revoke, etc.) for a user, organization, or application.
CheckManage checks runs/suites for commits and get results from them.
 RunManage check runs for commits and get results from those check runs.
 SuiteManage a suite of check runs for commits and get results from those suites.
EnterpriseManage a GitHub enterprise and list information about it.
 AdminStatsList administrative statistics (mostly global counters) for a GitHub enterprise.
 LdapManage synchronizations of GitHub enterprise users and teams with an LDAP server.
 LicenseGet licensing information for the GitHub enterprise.
 OrganizationCreate organizations (e.g. departments) for the GitHub enterprise.
 PreReceiveEnvironmentManage pre-receive environments for the GitHub enterprise.
 SearchIndexingQueue search indexing jobs for the GitHub enterprise.
GistManage GitHub Gists (code snippets, notes, to-do lists, etc.).
 CommentManage comments for Gists.
GitMore directly access a Git database on GitHub (e.g. read/write raw Git objects).
 BlobManage blobs (binary large objects) within a Git database.
 CommitManage Git commits within a Git database.
 ReferenceManage Git references within a Git database.
 TagManage Git tags within a Git database.
 TreeManage Git trees within a Git database.
GitHubAppsGet information about GitHub applications and installations of the application.
 InstallationGet information about the installations of GitHub applications.
IssueManage and list issues (bug reports, suggested improvements, questions, etc.) for repositories.
 AssigneeManage and list the users assigned to an issue.
 CommentManage and list the comments associated with an issue.
 EventsList the events associated with an issue.
 LabelsManage and list the labels associated with an issue.
 MilestonesManage and list the milestones associated with an issue.
 TimelinesManage and list the timeline events associated with an issue.
MigrationManage and list migrations between GitHub and an external system.
 MigrationsManage and list migrations between GitHub and an external system.
MiscellaneousList miscellaneous information and meta-data that isn’t covered in one of the other APIs (e.g. available emojis).
OAuthCreate OAuth (Open Authorization) access tokens and get the GitHub login URL.
OrganizationManage and list organizations (groups of users).
 MemberManage and list members (users) belonging to an organization.
 OutsideCollaboratorManage and list outside collaborators (users) for an organization.
 TeamManage and list teams (groups of users) for an organization.
PullRequestManage and list pull requests for a repository.
 ReviewManage and list reviews for a pull request.
 ReviewCommentManage and list review comments for a pull request.
 ReviewRequestManage and list review requests for a pull request.
ReactionManage and list reactions to commit comments, issues, issue comments, and pull request review comments. A reaction is simple user feedback that provides an indication of approval or disapproval (e.g. thumbs up, thumbs down, confused, etc.).
 CommitCommentManage and list reactions for a commit comment.
 IssueManage and list reactions for an issue.
 IssueCommentManage and list reactions for an issue comment.
 PullRequestReviewCommentManage and list reactions to a pull request review comment.
RepositoryManage and list repositories.
 BranchManage and list branches for a repository.
 CollaboratorManage and list users who collaborate on a repository.
 CommentManage and list comments associated with a repository.
 CommitList and compare commits associated with a repository.
 ContentManage and list the content (files, etc.) associated with a repository.
 DeployKeysManage and list deployment keys associated with a repository.
 DeploymentManage and list deployments for a repository.
  StatusManage and list the statuses for a repository’s deployments.
 ForksManage and list the forks for a repository.
 HooksManage and list the webhooks (subscriptions to events) for a repository.
 InvitationManage and list the users invited to collaborate on a repository.
 MergingMerge branches in a repository.
 PageList and build web pages for a repository.
 ProjectManage and list project boards for repositories or organizations. It is worth noting that the placement of this particular API under the repository API is unusual, since a project board created for an organization would not necessarily have a related repository.
  CardManage and list the cards (annotated issues/pull requests) for a project board.
  ColumnManage and list the columns for a project board. Columns are used to group related project cards.
 PullRequestManage and list pull requests for a repository.
  ReviewManage and list reviews for a pull request.
  ReviewCommentManage and list review comments for a pull request.
  ReviewRequestManage list review requests for a pull request.
 ReleaseManage and list releases for a repository.
 StatisticsGet the statistics (mostly counters) for a repository.
 StatusManage the statuses for a repository reference (branch, tag, etc.).
 TrafficList traffic/usage statistics (and information) for a repository.
SearchSearch for GitHub entities like code, issues/pull requests, labels, repositories, and users/organizations.
UserManage and list users.
 AdministrationManage (create, delete, etc.) users and list some administrative information about users.
 EmailsManage and list the e-mail addresses for the authenticated user.
 FollowersManage and list the other users who follow a user.
 GitSshKeyManage and list the public keys (SSH/Secure Shell) for a user.
 GpgKeyManage and list the GPG (GNU Privacy Guard) keys for a user.

While it is beyond the scope of an introductory article to cover the entirety of the Octokit.net framework, the remainder of this article will provide a brief overview of some selected properties from the above table.

Issue Property

To access an issue directly, without first searching for it, use the Get method. For example, to get issue number 1 in the “octokit/octokit.net” repository:

				
					Issue issue = await client.Issue.Get("octokit", "octokit.net", 1);
				
			

Repository Property

To access a repository directly, without first searching for it, use the Get method. For example, to get the “octokit/octokit.net” repository:

				
					Repository repository = await client.Repository.Get("octokit", "octokit.net");
				
			

The same Repository property of the client also provides access to subordinate information for that repository. So, for example, the following code gets the “master” branch of the “octokit/octokit.net” repository:

				
					Branch branch = await client.Repository.Branch.Get("octokit", "octokit.net", "master");
				
			

Search Property

The Search property provides access to the ISearchClientAPI interface, which supports searching of five different entities: code/files, issues/pull requests, labels, repositories, and users/organizations. The methods used to retrieve each of these entities are SearchCodeSearchIssuesSearchLabelsSearchRepo, and SearchUsers.

Each of these methods accepts a parameter, which is derived from the BaseSearchRequest class, to specify the search criteria. The results of a search are divided into one or more pages of search results.

Each call to one of these methods will return a single page of results which, by default, consists of between zero and 100 items.

Before retrieving the first page, it is possible to adjust the maximum number of items (in each page), by setting the PerPage property. To advance to subsequent pages of results, simply increment the Page property and make a subsequent call with the same criteria.

The common properties across all types of searches, present in the BaseSearchRequest class, are as follows:

PropertyDescription
OrderThe order in which items are sorted (ascending or descending).
PageThe one-based page number. Each call to one of the search methods returns a single page of items. The PerPage property indicates the maximum number of items returned in a single page. Prior to subsequent calls, the caller advances the page by incrementing the value of the Page property. The default value for the Page property is 1, meaning that the first page of items is returned by default.
ParametersA dictionary of name/value pairs that are appended to the GitHub API’s URL as query string parameters. In general, the caller should treat this dictionary as read-only. The various properties of derived classes will alter this dictionary indirectly on the caller’s behalf.
PerPageThe number of items per page. This is the maximum number of items that will be returned by a single call to one of the search methods. The default value for the PerPage property is 100.
SortSort the search results by the specified field. This read-only property is set indirectly via the SortField property in a derived class.
TermLimit the search results to those containing the specified text. This read-only property is set indirectly via the constructor for the request class.

SearchCode Method

When invoking the SearchCode method, the following criteria are exposed by the SearchCodeRequest class. These properties are in addition to those provided by the BaseSearchRequest class, from which it is derived. Note: Sample code that initializes all of these properties follows the table.

PropertyDescription
ExtensionLimit search results to code with the specified file extension.
FileNameLimit search results to code with the specified file name.
ForksA value that determines if the search results include code in forked repositories.
InLimit the search results to code where the specified fields contain the search term (Term).
LanguageLimit the search results to code written in the specified programming language.
OrganizationLimit the search results to code for the specified organization.
PathLimit the search results to code in the specified file path.
ReposLimit the search results to code in the specified set of repositories, using an “owner/name” format for each individual repository.
SizeLimit the search results to code where the size (in bytes) falls within the specified range.
SortFieldSort the search results by the specified field.
UserLimit the search results to the specified user.

SearchCode (Simple Search)

The following is a simple search request that finds the first 100 files, in the “octokit/octokit.net” repository, which contain the text “issue” in the file path.

				
					SearchCodeResult result = await client.Search.SearchCode(
  new SearchCodeRequest("issue")
  {
    In = new CodeInQualifier[] { CodeInQualifier.Path },
    Language = Language.CSharp,
    Repos = new RepositoryCollection { "octokit/octokit.net" }
  });
				
			

SearchCode (All Fields)

The following code sample demonstrates the initialization of a request (SearchCodeRequest) where all of the properties are set.

				
					int fromNumber = 100;
int toNumber = 1000;

string extension = ".cs";
string fileName = "IssueCommentPayload";
string organization = "octokit";
string path = "Octokit/Models/Response/ActivityPayloads";
string repository = "octokit/octokit.net";
string term = "issue";
string user = "octokit";

var request = new SearchCodeRequest(term)
{
  Extension = extension,
  FileName = fileName,
  Forks = false,
  In = new CodeInQualifier[] { CodeInQualifier.Path },
  Language = Language.CSharp,
  Order = SortDirection.Descending,
  Organization = organization,
  Path = path,
  Repos = new RepositoryCollection { repository },
  Size = new Range(fromNumber, toNumber),
  SortField = CodeSearchSort.Indexed,
  User = user
};
				
			

SearchIssues Method

When invoking the SearchIssues method, the following criteria are exposed by the SearchIssuesRequest class. These properties are in addition to those provided by the BaseSearchRequest class, from which it is derived. Note: Sample code that initializes all of these properties follows the table.

PropertyDescription
ArchivedA value that determines if the search results are limited to issues in only archived or only non-archived repositories. The default is to include both archived and non-archived repositories.
AssigneeLimit the search results to issues assigned to the specified user.
AuthorLimit the search results to issues created by the specified user.
BaseLimit the search results to issues based on the branch they are merging into.
ClosedLimit the search results to issues closed during the specified range of dates.
CommenterLimit the search results to issues commented on by the specified user.
CommentsLimit the search results to issues that have a number of comments within the specified range.
CreatedLimit the search results to issues created during the specified range of dates.
ExclusionsLimit the search results to exclude the specified criteria.
 AssigneeExclude issues assigned to the specified user.
 AuthorExclude issues created by the specified user.
 BaseExclude issues based on the branch they are merging into.
 CommenterExclude issues commented on by the specified user.
 HeadExclude issues descended from the specified branch.
 InvolvesExclude issues assigned to, created by, commented on, or mentioning the specified user.
 LabelsExclude issues with the specified labels.
 LanguageExclude issues that are in repositories that match the specified programming language.
 MentionsExclude issues mentioning the specified user.
 MilestoneExclude issues with the specified milestone.
 StateExclude issues in the specified state (e.g. open or closed).
 StatusExclude issues with the specified commitment status (e.g. pending, success, error, failure, etc.).
HeadLimit the search results to issues descended from the specified branch.
InLimit the search results to issues where the specified fields contain the search term (Term).
InvolvesLimit the search results to issues assigned to, created by, commented on, or mentioning the specified user.
IsLimit the search results to issues that match one or more of the specified states. For example, issues that are open, closed, merged, unmerged, etc.
LabelsLimit the search results to issues with the specified labels. The labels are specified as a comma-separated list.
LanguageLimit the search results to issues that are in repositories that match the specified programming language.
MentionsLimit the search results to issues mentioning the specified user.
MergedLimit the search results to issues that were merged within the specified date range.
MilestoneLimit the search results to issues with the specified milestone.
NoLimit the search results to issues missing the specified metadata. For example, issues that lack a label, milestone, or assigned user.
ReposLimit the search results to issues in the specified set of repositories, using an “owner/name” format for each individual repository.
SortFieldSort the search results by the specified field.
StateLimit the search results to issues in the specified state (e.g. open or closed).
StatusLimit the search results to issues with the specified commitment status (e.g. pending, success, error, failure, etc.).
TeamLimit the search results to issues mentioning the specified team (within an organization).
TypeLimit the search results to issues of the specified type (e.g. issues or pull requests).
UpdatedLimit the search results to issues updated during the specified range of dates.
UserLimit the search results to issues in repositories owned by the specified user.

SearchIssues (Simple Search)

The following is a simple search request that finds the first 100 issues, for the “octokit/octokit.net” repository, which contain the text “bug” in the title.

				
					SearchIssuesResult result = await client.Search.SearchIssues(
  new SearchIssuesRequest("bug")
  {
    In = new IssueInQualifier[] { IssueInQualifier.Title },
    Repos = new RepositoryCollection { "octokit/octokit.net" }
  });
				
			

The SearchIssues method does support the ability to search across multiple repositories. However, its usefulness is limited. At this time (2/6/2019), the Repository property, for the resulting issues, is not populated. As a result, it is not possible to tell to which repository a resulting issue refers.

Until the API provides a remedy, it is recommended that searches are limited to a single repository (as in the example above).

				
					SearchIssues (All Fields)
				
			

The following code sample demonstrates the initialization of a request where all of the properties are set. While the search itself is nonsensical, it does provide a valid example of a complex initialization.

				
					var fromDate = new DateTime(2018, 3, 17);
var toDate = new DateTime(2019, 3, 17);

int fromNumber = 1;
int toNumber = 10;

string branch = "master";
string excludedBranch = "other";
string excludedLabel = "wth";
string excludedMilestone = "Nothing Done";
string excludedUser = "somebody";
string label = "up-for-grabs";
string milestone = "API Cleanup";
string repository = "octokit/octokit.net";
string term = "bug";
string user = "octokit";

var request = new SearchIssuesRequest(term)
{
  Archived = true,
  Assignee = user,
  Author = user,
  Base = branch,
  Closed = new DateRange(fromDate, toDate),
  Commenter = user,
  Comments = new Range(fromNumber, toNumber),
  Created = new DateRange(fromDate, SearchQualifierOperator.GreaterThan),
  Exclusions = new SearchIssuesRequestExclusions
  {
    Assignee = excludedUser,
    Author = excludedUser,
    Base = excludedBranch,
    Commenter = excludedUser,
    Head = branch,
    Involves = excludedUser,
    Labels = new string[] { excludedLabel },
    Language = Language.Ada,
    Mentions = excludedUser,
    Milestone = excludedMilestone,
    State = ItemState.Open,
    Status = CommitState.Error
  },
  Head = branch,
  In = new IssueInQualifier[] { IssueInQualifier.Title },
  Involves = user,
  Is = new IssueIsQualifier[] { IssueIsQualifier.Public },
  Labels = new string[] { label },
  Language = Language.CSharp,
  Mentions = user,
  Merged = new DateRange(toDate, SearchQualifierOperator.LessThan),
  Milestone = milestone,
  No = IssueNoMetadataQualifier.Assignee,
  Order = SortDirection.Descending,
  Repos = new RepositoryCollection() { repository },
  SortField = IssueSearchSort.Created,
  State = ItemState.Closed,
  Status = CommitState.Success,
  Type = IssueTypeQualifier.Issue,
  Updated = new DateRange(toDate, SearchQualifierOperator.LessThanOrEqualTo),
  User = user
};
				
			

SearchLabels Method

When invoking the SearchLabels method, the following criteria are exposed by the SearchLabelsRequest class. These properties are in addition to those provided by the BaseSearchRequest class, from which it is derived. Note: Sample code that initializes all of these properties follows the table.

PropertyDescription
RepositoryIdLimit the search results to labels in the repository with the specified unique identity.
SortFieldSort the search results by the specified field.

SearchLabels (Simple Search)

When compared to the other search methods, the SearchLabels method is far less friendly and useful, for the following reasons:

  • It requires that you have already previously found the unique identity of a repository.
  • Almost all of its criteria are required (instead of being optional).
  • It offers very limited criteria.
  • While available, using the parameterless constructor will result in an invalid request, since a search term is required, but not provided.

The following is a simple search request that finds the first 100 labels, for the “octokit/octokit.net” repository, that start with the text “category”.

				
					Repository repository = await client.Repository.Get("octokit", "octokit.net");

SearchLabelsResult result = await client.Search.SearchLabels(
  new SearchLabelsRequest("category", repository.Id));
				
			

SearchLabels (All Fields)

The following code sample demonstrates the initialization of a request where all of the properties are set.

				
					string term = "category";

Repository repository = await client.Repository.Get("octokit", "octokit.net");

var request = new SearchLabelsRequest(term, repository.Id)
{
  Order = SortDirection.Descending,
  SortField = LabelSearchSort.Created
};
				
			

SearchRepo Method

When invoking the SearchRepo method, the following criteria are exposed by the SearchRepositoriesRequest class. These properties are in addition to those provided by the BaseSearchRequest class, from which it is derived. Note: Sample code that initializes all of these properties follows the table.

PropertyDescription
ArchivedA value that determines if the search results are limited to only archived or only non-archived repositories. The default is to include both archived and non-archived repositories.
CreatedLimit the search results to repositories created during the specified range of dates.
ForkA value that determines if the search results include forked repositories.
ForksLimit the search results to repositories where the number of forks falls within the specified range.
InLimit the search results to repositories where the specified fields contain the search term (Term).
LanguageLimit the search results to repositories that match the specified programming language.
SizeLimit the search results to repositories where the size (in kilobytes) falls within the specified range.
SortFieldSort the search results by the specified field.
StarsLimit the search results to repositories where the number of stars falls within the specified range.
UpdatedLimit the search results to repositories updated during the specified range of dates.
UserLimit the search results to repositories owned by the specified user.

SearchRepo (Simple Search)

The following is a simple search request that finds the first 100 repositories that contain the text “octokit” in the repository name.

				
					SearchRepositoryResult result = await client.Search.SearchRepo(
  new SearchRepositoriesRequest("octokit")
  {
    In = new InQualifier[] { InQualifier.Name }
  });
				
			

SearchRepo (All Fields)

The following code sample demonstrates the initialization of a request where all of the properties are set.

				
					var fromDate = new DateTime(2012, 3, 17);
var toDate = new DateTime(2019, 3, 17);

int fromNumber = 1;
int toNumber = 10000;

string term = "octokit";
string user = "octokit";

var request = new SearchRepositoriesRequest(term)
{
  Archived = false,
  Created = new DateRange(fromDate, toDate),
  Fork = ForkQualifier.IncludeForks,
  Forks = new Range(fromNumber, toNumber),
  In = new InQualifier[] { InQualifier.Name },
  Language = Language.CSharp,
  Order = SortDirection.Descending,
  Size = new Range(fromNumber, SearchQualifierOperator.GreaterThan),
  SortField = RepoSearchSort.Stars,
  Stars = new Range(fromNumber, SearchQualifierOperator.GreaterThanOrEqualTo),
  Updated = new DateRange(fromDate, SearchQualifierOperator.GreaterThan),
  User = user
};
				
			

SearchUsers Method

When invoking the SearchUser method, the following criteria are exposed by the SearchUsersRequest class. These properties are in addition to those provided by the BaseSearchRequest class, from which it is derived. Note: Sample code that initializes all of these properties follows the table.

PropertyDescription
AccountTypeLimit the search results to users with the specified type of account (e.g. personal or organization).
CreatedLimit the search results to users created during the specified range of dates.
FollowersLimit the search results to users with the specified number of followers.
InLimit the search results to users where the specified fields contain the search term (Term).
LanguageLimit the search results to users who own repositories with the specified programming language.
LocationLimit the search results to users in the specified location.
RepositoriesLimit the search results to users who own a number of repositories that falls within the specified range.
SortFieldSort the search results by the specified field.

SearchUsers (Simple Search)

The following is a simple search request that finds the first 100 users (of account type User) that contain the text “oct” in one of the default fields (user’s login name, full name, or e-mail address).

				
					SearchUsersResult result = await client.Search.SearchUsers(
  new SearchUsersRequest("oct")
  {
    AccountType = AccountSearchType.User
  });
				
			

Note: By specifying an account type of Org, a similar search could be conducted for organizations instead of personal users.

SearchUsers (All Fields)

The following code sample demonstrates the initialization of a request where all of the properties are set.

				
					var fromDate = new DateTime(2001, 3, 17);

int fromNumber = 1;
int toNumber = 1000;

string location = "Ontario";

var request = new SearchUsersRequest("code")
{
  AccountType = AccountSearchType.User,
  Created = new DateRange(fromDate, SearchQualifierOperator.GreaterThan),
  Followers = new Range(fromNumber, SearchQualifierOperator.GreaterThanOrEqualTo),
  In = new UserInQualifier[] { UserInQualifier.Username },
  Language = Language.CSharp,
  Location = location,
  Order = SortDirection.Descending,
  Repositories = new Range(fromNumber, toNumber),
  SortField = UsersSearchSort.Followers
};
				
			

User Property

To access a user directly, without first searching for it, use the Get method as follows:

				
					User user = await client.User.Get("octokit");
				
			
This same method gets users with both personal and organization account types.

GitHub API Demo Application

A simple Windows Form application is included, with this article, to demonstrate searches using the Octokit.net framework. This application is purely intended to demonstrate searching and provide some code samples. It is not intended as a production application and has not been tested for that purpose.

When the application is first started, you will be prompted for GitHub credentials. The login screen supports three types of authentication: Unauthenticated Access, Basic Authentication, and OAuth Token Authentication.

To conduct a search, click “Edit…Find…” and select the item for which you want to search.

Fill in the criteria for your search and click OK. Below, we search for a repository with the text “octokit”.

The results will be displayed in a data grid like the following:

By default, only minimal information is displayed. It is possible to change the columns of information that are displayed and their order. To do this, click “Edit…Select Columns…”…

A dialog will appear that allows you to select and order the columns:

Additionally, by double-clicking on any item in the data grid, it is possible to see additional detail in the “Detail” tab…

The application contains a number of other features with which the user can play. From a GitHub perspective, the application is read-only. So, it is comparatively safe to use.

The majority of the code deals with user interaction. Within the code, the GitHub API usage is limited to the Searcher class and the classes derived from it: CodeSearcher, IssueSearcher, LabelSearcher, RepositorySearcher, and UserSearcher.

GitHub API Snippets Application

A simple Windows Console application is also provided. In general, most of the code samples in this article came from the Program class in this application. The user interface for the application is intentionally primitive to avoid distracting from the GitHub API samples.

A sample session is shown below.

Further Reading

For further reading, on this topic, the following links provide invaluable information:

If you’re interested in developing expert technical content that performs, let’s have a conversation today.

Facebook
Twitter
LinkedIn
Reddit
Email

POST INFORMATION

If you work in a tech space and aren’t sure if we cover you, hit the button below to get in touch with us. Tell us a little about your content goals or your project, and we’ll reach back within 2 business days. 

Share via
Copy link
Powered by Social Snap