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($"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 Name Description
Activity Manage the "social" aspects of GitHub, like events, Atom Feeds, notifications of comments, starring of repositories, and events for repositories that are watched.
  Events List the events that occurred for various GitHub entities (e.g. organizations and repositories).
  Feeds List the Atom feeds that are available to the authenticated user.
  Notifications List notifications for conversations and comments, mark them as read, and manage the authenticated user’s subscriptions to them.
  Starring Manage starring (bookmarking) for repositories and list information about bookmarked repositories.
  Watching Register for notifications of discussions and events related to selected repositories.
Authorization Manage authorizations (grant, revoke, etc.) for a user, organization, or application.
Check Manage checks runs/suites for commits and get results from them.
  Run Manage check runs for commits and get results from those check runs.
  Suite Manage a suite of check runs for commits and get results from those suites.
Enterprise Manage a GitHub enterprise and list information about it.
  AdminStats List administrative statistics (mostly global counters) for a GitHub enterprise.
  Ldap Manage synchronizations of GitHub enterprise users and teams with an LDAP server.
  License Get licensing information for the GitHub enterprise.
  Organization Create organizations (e.g. departments) for the GitHub enterprise.
  PreReceiveEnvironment Manage pre-receive environments for the GitHub enterprise.
  SearchIndexing Queue search indexing jobs for the GitHub enterprise.
Gist Manage GitHub Gists (code snippets, notes, to-do lists, etc.).
  Comment Manage comments for Gists.
Git More directly access a Git database on GitHub (e.g. read/write raw Git objects).
  Blob Manage blobs (binary large objects) within a Git database.
  Commit Manage Git commits within a Git database.
  Reference Manage Git references within a Git database.
  Tag Manage Git tags within a Git database.
  Tree Manage Git trees within a Git database.
GitHubApps Get information about GitHub applications and installations of the application.
  Installation Get information about the installations of GitHub applications.
Issue Manage and list issues (bug reports, suggested improvements, questions, etc.) for repositories.
  Assignee Manage and list the users assigned to an issue.
  Comment Manage and list the comments associated with an issue.
  Events List the events associated with an issue.
  Labels Manage and list the labels associated with an issue.
  Milestones Manage and list the milestones associated with an issue.
  Timelines Manage and list the timeline events associated with an issue.
Migration Manage and list migrations between GitHub and an external system.
  Migrations Manage and list migrations between GitHub and an external system.
Miscellaneous List miscellaneous information and meta-data that isn’t covered in one of the other APIs (e.g. available emojis).
OAuth Create OAuth (Open Authorization) access tokens and get the GitHub login URL.
Organization Manage and list organizations (groups of users).
  Member Manage and list members (users) belonging to an organization.
  OutsideCollaborator Manage and list outside collaborators (users) for an organization.
  Team Manage and list teams (groups of users) for an organization.
PullRequest Manage and list pull requests for a repository.
  Review Manage and list reviews for a pull request.
  ReviewComment Manage and list review comments for a pull request.
  ReviewRequest Manage and list review requests for a pull request.
Reaction Manage 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.).
  CommitComment Manage and list reactions for a commit comment.
  Issue Manage and list reactions for an issue.
  IssueComment Manage and list reactions for an issue comment.
  PullRequestReviewComment Manage and list reactions to a pull request review comment.
Repository Manage and list repositories.
  Branch Manage and list branches for a repository.
  Collaborator Manage and list users who collaborate on a repository.
  Comment Manage and list comments associated with a repository.
  Commit List and compare commits associated with a repository.
  Content Manage and list the content (files, etc.) associated with a repository.
  DeployKeys Manage and list deployment keys associated with a repository.
  Deployment Manage and list deployments for a repository.
    Status Manage and list the statuses for a repository’s deployments.
  Forks Manage and list the forks for a repository.
  Hooks Manage and list the webhooks (subscriptions to events) for a repository.
  Invitation Manage and list the users invited to collaborate on a repository.
  Merging Merge branches in a repository.
  Page List and build web pages for a repository.
  Project Manage 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.
    Card Manage and list the cards (annotated issues/pull requests) for a project board.
    Column Manage and list the columns for a project board. Columns are used to group related project cards.
  PullRequest Manage and list pull requests for a repository.
    Review Manage and list reviews for a pull request.
    ReviewComment Manage and list review comments for a pull request.
    ReviewRequest Manage list review requests for a pull request.
  Release Manage and list releases for a repository.
  Statistics Get the statistics (mostly counters) for a repository.
  Status Manage the statuses for a repository reference (branch, tag, etc.).
  Traffic List traffic/usage statistics (and information) for a repository.
Search Search for GitHub entities like code, issues/pull requests, labels, repositories, and users/organizations.
User Manage and list users.
  Administration Manage (create, delete, etc.) users and list some administrative information about users.
  Emails Manage and list the e-mail addresses for the authenticated user.
  Followers Manage and list the other users who follow a user.
  GitSshKey Manage and list the public keys (SSH/Secure Shell) for a user.
  GpgKey Manage 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 SearchCode, SearchIssues, SearchLabels, SearchRepo, 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:

Property Description
Order The order in which items are sorted (ascending or descending).
Page The 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.
Parameters A 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.
PerPage The 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.
Sort Sort the search results by the specified field. This read-only property is set indirectly via the SortField property in a derived class.
Term Limit 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.

Property Description
Extension Limit search results to code with the specified file extension.
FileName Limit search results to code with the specified file name.
Forks A value that determines if the search results include code in forked repositories.
In Limit the search results to code where the specified fields contain the search term (Term).
Language Limit the search results to code written in the specified programming language.
Organization Limit the search results to code for the specified organization.
Path Limit the search results to code in the specified file path.
Repos Limit the search results to code in the specified set of repositories, using an "owner/name" format for each individual repository.
Size Limit the search results to code where the size (in bytes) falls within the specified range.
SortField Sort the search results by the specified field.
User Limit 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.

Property Description
Archived A 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.
Assignee Limit the search results to issues assigned to the specified user.
Author Limit the search results to issues created by the specified user.
Base Limit the search results to issues based on the branch they are merging into.
Closed Limit the search results to issues closed during the specified range of dates.
Commenter Limit the search results to issues commented on by the specified user.
Comments Limit the search results to issues that have a number of comments within the specified range.
Created Limit the search results to issues created during the specified range of dates.
Exclusions Limit the search results to exclude the specified criteria.
  Assignee Exclude issues assigned to the specified user.
  Author Exclude issues created by the specified user.
  Base Exclude issues based on the branch they are merging into.
  Commenter Exclude issues commented on by the specified user.
  Head Exclude issues descended from the specified branch.
  Involves Exclude issues assigned to, created by, commented on, or mentioning the specified user.
  Labels Exclude issues with the specified labels.
  Language Exclude issues that are in repositories that match the specified programming language.
  Mentions Exclude issues mentioning the specified user.
  Milestone Exclude issues with the specified milestone.
  State Exclude issues in the specified state (e.g. open or closed).
  Status Exclude issues with the specified commitment status (e.g. pending, success, error, failure, etc.).
Head Limit the search results to issues descended from the specified branch.
In Limit the search results to issues where the specified fields contain the search term (Term).
Involves Limit the search results to issues assigned to, created by, commented on, or mentioning the specified user.
Is Limit the search results to issues that match one or more of the specified states. For example, issues that are open, closed, merged, unmerged, etc.
Labels Limit the search results to issues with the specified labels. The labels are specified as a comma-separated list.
Language Limit the search results to issues that are in repositories that match the specified programming language.
Mentions Limit the search results to issues mentioning the specified user.
Merged Limit the search results to issues that were merged within the specified date range.
Milestone Limit the search results to issues with the specified milestone.
No Limit the search results to issues missing the specified metadata. For example, issues that lack a label, milestone, or assigned user.
Repos Limit the search results to issues in the specified set of repositories, using an "owner/name" format for each individual repository.
SortField Sort the search results by the specified field.
State Limit the search results to issues in the specified state (e.g. open or closed).
Status Limit the search results to issues with the specified commitment status (e.g. pending, success, error, failure, etc.).
Team Limit the search results to issues mentioning the specified team (within an organization).
Type Limit the search results to issues of the specified type (e.g. issues or pull requests).
Updated Limit the search results to issues updated during the specified range of dates.
User Limit 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.

Property Description
RepositoryId Limit the search results to labels in the repository with the specified unique identity.
SortField Sort 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.

Property Description
Archived A 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.
Created Limit the search results to repositories created during the specified range of dates.
Fork A value that determines if the search results include forked repositories.
Forks Limit the search results to repositories where the number of forks falls within the specified range.
In Limit the search results to repositories where the specified fields contain the search term (Term).
Language Limit the search results to repositories that match the specified programming language.
Size Limit the search results to repositories where the size (in kilobytes) falls within the specified range.
SortField Sort the search results by the specified field.
Stars Limit the search results to repositories where the number of stars falls within the specified range.
Updated Limit the search results to repositories updated during the specified range of dates.
User Limit 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.

Property Description
AccountType Limit the search results to users with the specified type of account (e.g. personal or organization).
Created Limit the search results to users created during the specified range of dates.
Followers Limit the search results to users with the specified number of followers.
In Limit the search results to users where the specified fields contain the search term (Term).
Language Limit the search results to users who own repositories with the specified programming language.
Location Limit the search results to users in the specified location.
Repositories Limit the search results to users who own a number of repositories that falls within the specified range.
SortField Sort 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:

How to work with us

  • Contact us to set up a call.
  • We will analyze your needs and recommend a content contract solution.
  • Sign on with ContentLab.
  • We deliver topic-curated, deeply technical content to you.

To get started, complete the form to the right to schedule a call with us.

Content Science Blog

Our blog devoted to the fundamentals of producing content and marketing to developers.

Ask a Developer Video Series

Our video series where developers answer questions about what makes for useful technical content.


Send this to a friend