From d542382019b4308792c06f6e97a3acf943721d66 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Mon, 24 Sep 2018 14:24:05 -0400
Subject: [PATCH 1/9] gitlab: read secrets using serde_json

---
 src/config/mod.rs              |  2 +-
 src/handlers/gitlab/handler.rs | 20 ++++++++++++--------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/config/mod.rs b/src/config/mod.rs
index e5afdc7a..4f6903d9 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -8,7 +8,7 @@
 
 //! Configuration management data structures.
 
-mod defaults;
+pub(crate) mod defaults;
 mod checks;
 pub mod io;
 mod types;
diff --git a/src/handlers/gitlab/handler.rs b/src/handlers/gitlab/handler.rs
index 840f4fde..95845103 100644
--- a/src/handlers/gitlab/handler.rs
+++ b/src/handlers/gitlab/handler.rs
@@ -17,6 +17,7 @@ use crates::json_job_dispatch::{Director, Handler, HandlerResult, Result as JobR
 use crates::serde::de::DeserializeOwned;
 use crates::serde_json::{self, Value};
 
+use config::defaults;
 use config::Host;
 use error::*;
 use handlers::common::handlers::*;
@@ -25,24 +26,27 @@ use handlers::gitlab::traits::*;
 
 use std::sync::{Arc, RwLock};
 
+#[derive(Debug, Deserialize)]
+struct GitlabSecrets {
+    token: String,
+    #[serde(default="defaults::default_true")]
+    use_ssl: bool,
+}
+
 /// Connect to a Gitlab from its configuration block.
 pub fn connect_to_host(url: &Option<String>, secrets: &Value) -> Result<Arc<HostingService>> {
     let host = url.as_ref().map_or("gitlab.com", |u| u.as_str());
-    let token = if let Some(token) = secrets.pointer("/token").and_then(|t| t.as_str()) {
-        token
-    } else {
-        bail!("gitlab requires a token to be provided");
-    };
-    let use_ssl = secrets.pointer("/use_ssl").and_then(Value::as_bool).unwrap_or(true);
+    let secrets: GitlabSecrets = serde_json::from_value(secrets.clone())
+        .chain_err(|| format!("failed to deserialize GitLab secrets for host {}", host))?;
 
-    let ctor = if use_ssl {
+    let ctor = if secrets.use_ssl {
         Gitlab::new
     } else {
         Gitlab::new_insecure
     };
 
     let gitlab =
-        ctor(host, token).chain_err(|| format!("failed to construct service for host {}", host))?;
+        ctor(host, secrets.token).chain_err(|| format!("failed to construct service for host {}", host))?;
     Ok(GitlabService::new(gitlab).map(Arc::new)
         .chain_err(|| format!("failed to connect to host {}", host))?)
 }
-- 
GitLab


From 3d094295bea495a38a88662b89088e981e4f1c01 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Fri, 28 Sep 2018 08:52:58 -0400
Subject: [PATCH 2/9] gitlab: move ResetFailedProjects into common code

---
 src/handlers/common/jobs.rs    | 4 ++++
 src/handlers/gitlab/handler.rs | 6 +-----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/handlers/common/jobs.rs b/src/handlers/common/jobs.rs
index 474f9a9b..243eba6d 100644
--- a/src/handlers/common/jobs.rs
+++ b/src/handlers/common/jobs.rs
@@ -72,6 +72,10 @@ pub struct UpdateFollowRefs {
     pub name: String,
 }
 
+#[derive(Deserialize, Debug, Default, Clone, Copy)]
+/// Data required to reset failed projects.
+pub struct ResetFailedProjects;
+
 #[derive(Deserialize, Debug)]
 // Data required to run batch jobs on branches.
 struct BatchProject<T>(HashMap<String, T>);
diff --git a/src/handlers/gitlab/handler.rs b/src/handlers/gitlab/handler.rs
index 95845103..9d2e909c 100644
--- a/src/handlers/gitlab/handler.rs
+++ b/src/handlers/gitlab/handler.rs
@@ -21,7 +21,7 @@ use config::defaults;
 use config::Host;
 use error::*;
 use handlers::common::handlers::*;
-use handlers::common::jobs::{BatchBranchJob, ClearTestRefs, TagStage, UpdateFollowRefs};
+use handlers::common::jobs::{BatchBranchJob, ClearTestRefs, ResetFailedProjects, TagStage, UpdateFollowRefs};
 use handlers::gitlab::traits::*;
 
 use std::sync::{Arc, RwLock};
@@ -51,10 +51,6 @@ pub fn connect_to_host(url: &Option<String>, secrets: &Value) -> Result<Arc<Host
         .chain_err(|| format!("failed to connect to host {}", host))?)
 }
 
-#[derive(Deserialize, Debug, Default, Clone, Copy)]
-/// Data required to reset failed projects.
-struct ResetFailedProjects;
-
 /// The handler for Gitlab events.
 struct GitlabHandler {
     /// The host block for this handler.
-- 
GitLab


From 6bad1e53c1d74c761fbb648a7b35f0d144316460 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Mon, 24 Sep 2018 14:24:48 -0400
Subject: [PATCH 3/9] membership: simplify project membership refresh

Only the repository name was required anyways.
---
 src/handlers/common/handlers/membership.rs | 10 +++++-----
 src/handlers/gitlab/handler.rs             |  7 +------
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/handlers/common/handlers/membership.rs b/src/handlers/common/handlers/membership.rs
index ebe6567a..e3f0d312 100644
--- a/src/handlers/common/handlers/membership.rs
+++ b/src/handlers/common/handlers/membership.rs
@@ -6,7 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use crates::ghostflow::host::{self, Repo};
+use crates::ghostflow::host;
 use crates::json_job_dispatch::HandlerResult;
 use crates::json_job_dispatch::Result as JobResult;
 use crates::serde_json::Value;
@@ -37,17 +37,17 @@ pub fn handle_user_removal(_: &Value, host: &Host, membership: &MembershipRemova
 }
 
 /// Handle a project's membership needing completely refreshed.
-pub fn handle_project_membership_refresh(_: &Value, host: &Host, repo: &Repo)
+pub fn handle_project_membership_refresh(_: &Value, host: &Host, repo: &str)
                                          -> JobResult<HandlerResult> {
-    let project = try_action!(utils::get_project(host, &repo.name));
+    let project = try_action!(utils::get_project(host, &repo));
 
-    project.refresh_membership(&repo.name)
+    project.refresh_membership(&repo)
         .map(|_| HandlerResult::Accept)
         .or_else(|err| {
             Ok(HandlerResult::Fail(Error::chain(err,
                                                 format!("failed to update membership \
                                                          for {}",
-                                                        repo.name))))
+                                                        repo))))
         })
 }
 
diff --git a/src/handlers/gitlab/handler.rs b/src/handlers/gitlab/handler.rs
index 9d2e909c..59d8e480 100644
--- a/src/handlers/gitlab/handler.rs
+++ b/src/handlers/gitlab/handler.rs
@@ -153,12 +153,7 @@ impl GitlabHandler {
                 Self::parse_object(object, |hook: ProjectMemberSystemHook| {
                     let host = self.host.read()
                         .expect(HOST_LOCK_POISONED);
-                    host.service
-                        .repo(&hook.project_path_with_namespace)
-                        .map(|project| {
-                            handle_project_membership_refresh(object, &host, &project)
-                        })
-                        .unwrap_or_else(|err| Ok(HandlerResult::Fail(Box::new(err))))
+                    handle_project_membership_refresh(object, &host, &hook.project_path_with_namespace)
                 })
             },
             "user_add_to_group" |
-- 
GitLab


From 3ecccf1040dd663ae2f7dd7eda6de4e54a2fd75a Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Mon, 24 Sep 2018 14:27:11 -0400
Subject: [PATCH 4/9] handlers: simplify construction of handlers

This allows for the handler to keep a reference to the handler if extra
information is required.
---
 Cargo.lock                     |  7 +++++++
 Cargo.toml                     |  1 +
 src/config/types.rs            | 24 ++++++++++++++----------
 src/handlers/gitlab/handler.rs | 23 ++++++++++++-----------
 src/handlers/gitlab/mod.rs     |  3 +--
 src/handlers/mod.rs            | 26 ++++++++++++++------------
 src/main.rs                    | 10 +++-------
 7 files changed, 52 insertions(+), 42 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 896c8227..b647440f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -77,6 +77,11 @@ name = "bitflags"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "boxfnonce"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "build_const"
 version = "0.2.1"
@@ -384,6 +389,7 @@ dependencies = [
 name = "ghostflow-director"
 version = "0.1.0"
 dependencies = [
+ "boxfnonce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1889,6 +1895,7 @@ dependencies = [
 "checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum boxfnonce 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbec60c560f322d8e3cd403f91d8908cfd965fff53ba97154bd1b9d90149d98e"
 "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
 "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781"
 "checksum bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0ce55bd354b095246fc34caf4e9e242f5297a7fd938b090cadfea6eee614aa62"
diff --git a/Cargo.toml b/Cargo.toml
index 4bc75f1b..0b033462 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ tokio = "~0.1.8"
 tokio-uds = "~0.2"
 
 [dependencies]
+boxfnonce = "~0.1"
 chrono = "~0.4"
 clap = "^2.20"
 either = "^1.0"
diff --git a/src/config/types.rs b/src/config/types.rs
index e8fa43d3..58ed8ee1 100644
--- a/src/config/types.rs
+++ b/src/config/types.rs
@@ -16,13 +16,15 @@ use crates::ghostflow::utils::Trailer;
 use crates::git_topic_stage::Stager;
 use crates::git_workarea::{CommitId, GitContext, Identity};
 use crates::itertools::Itertools;
+use crates::json_job_dispatch::Handler;
 use crates::lazy_init::LazyTransform;
 use crates::rayon::prelude::*;
-use crates::serde_json::{self, Value};
+use crates::serde_json;
 use crates::topological_sort::TopologicalSort;
 
 use config::checks::Checks;
 use config::io;
+use handlers::HostHandler;
 use error::{ErrorKind, Result};
 
 use std::collections::hash_map::{HashMap, Keys};
@@ -41,8 +43,8 @@ pub struct Config {
     pub archive_dir: PathBuf,
     /// The directory to watch for new jobs.
     pub queue_dir: PathBuf,
-    /// Host configuration.
-    pub hosts: HashMap<String, Host>,
+    /// Handler configuration.
+    pub handlers: Vec<Box<Handler>>,
 }
 
 impl Config {
@@ -50,30 +52,32 @@ impl Config {
     ///
     /// The `connect_to_host` function constructs `HostingService` instances given an API and a URL
     /// to communicate with.
-    pub fn from_path<P, F>(path: P, connect_to_host: F) -> Result<Self>
+    pub fn from_path<P>(path: P) -> Result<Self>
         where P: AsRef<Path>,
-              F: Fn(&str, &Option<String>, &Value) -> Result<Arc<HostingService>>,
     {
         io::Config::from_path(path).and_then(|config| {
             let archive_dir = config.archive_dir().to_path_buf();
             let queue_dir = config.queue_dir().to_path_buf();
             let workdir = PathBuf::from(config.workdir);
-            let hosts = config.hosts
+            let handlers = config.hosts
                 .into_iter()
                 .map(|(name, host)| {
                     let host_workdir = workdir.join(&name);
                     let secrets = host.secrets()?;
-                    let service = connect_to_host(&host.host_api, &host.host_url, &secrets)?;
+                    let HostHandler {
+                        service,
+                        handler,
+                    } = HostHandler::new(&host.host_api, &host.host_url, &secrets, name)?;
                     let host = Host::new(host, service, host_workdir)?;
 
-                    Ok((name, host))
+                    Ok(handler.call(host))
                 })
-                .collect::<Result<HashMap<_, _>>>()?;
+                .collect::<Result<Vec<_>>>()?;
 
             Ok(Config {
                 archive_dir: archive_dir,
                 queue_dir: queue_dir,
-                hosts: hosts,
+                handlers: handlers,
             })
         })
     }
diff --git a/src/handlers/gitlab/handler.rs b/src/handlers/gitlab/handler.rs
index 59d8e480..5699b52e 100644
--- a/src/handlers/gitlab/handler.rs
+++ b/src/handlers/gitlab/handler.rs
@@ -6,8 +6,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use crates::boxfnonce::BoxFnOnce;
 use crates::either::Either;
-use crates::ghostflow::host::HostingService;
 use crates::ghostflow_gitlab::GitlabService;
 use crates::gitlab::Gitlab;
 use crates::gitlab::systemhooks::{GroupMemberSystemHook, ProjectMemberSystemHook, ProjectSystemHook};
@@ -20,6 +20,7 @@ use crates::serde_json::{self, Value};
 use config::defaults;
 use config::Host;
 use error::*;
+use handlers::HostHandler;
 use handlers::common::handlers::*;
 use handlers::common::jobs::{BatchBranchJob, ClearTestRefs, ResetFailedProjects, TagStage, UpdateFollowRefs};
 use handlers::gitlab::traits::*;
@@ -34,7 +35,7 @@ struct GitlabSecrets {
 }
 
 /// Connect to a Gitlab from its configuration block.
-pub fn connect_to_host(url: &Option<String>, secrets: &Value) -> Result<Arc<HostingService>> {
+pub fn host_handler(url: &Option<String>, secrets: &Value, name: String) -> Result<HostHandler> {
     let host = url.as_ref().map_or("gitlab.com", |u| u.as_str());
     let secrets: GitlabSecrets = serde_json::from_value(secrets.clone())
         .chain_err(|| format!("failed to deserialize GitLab secrets for host {}", host))?;
@@ -47,8 +48,13 @@ pub fn connect_to_host(url: &Option<String>, secrets: &Value) -> Result<Arc<Host
 
     let gitlab =
         ctor(host, secrets.token).chain_err(|| format!("failed to construct service for host {}", host))?;
-    Ok(GitlabService::new(gitlab).map(Arc::new)
-        .chain_err(|| format!("failed to connect to host {}", host))?)
+    let service = GitlabService::new(gitlab).map(Arc::new)
+        .chain_err(|| format!("failed to connect to host {}", host))?;
+
+    Ok(HostHandler {
+        service: service,
+        handler: BoxFnOnce::new(|host| Box::new(GitlabHandler::new(host, name)) as Box<Handler>),
+    })
 }
 
 /// The handler for Gitlab events.
@@ -63,10 +69,10 @@ const HOST_LOCK_POISONED: &str = "host lock poisoned";
 
 impl GitlabHandler {
     /// Create a new handler.
-    fn new(host: Host, name: &str) -> Self {
+    fn new(host: Host, name: String) -> Self {
         GitlabHandler {
             host: RwLock::new(host),
-            name: name.to_string(),
+            name: name,
         }
     }
 
@@ -248,8 +254,3 @@ impl Handler for GitlabHandler {
         }
     }
 }
-
-/// Create a handler for Gitlab jobs.
-pub fn create_handler(host: Host, name: &str) -> Result<Box<Handler>> {
-    Ok(Box::new(GitlabHandler::new(host, name)))
-}
diff --git a/src/handlers/gitlab/mod.rs b/src/handlers/gitlab/mod.rs
index 5b532a8c..ccfd9b0b 100644
--- a/src/handlers/gitlab/mod.rs
+++ b/src/handlers/gitlab/mod.rs
@@ -9,5 +9,4 @@
 mod traits;
 mod handler;
 
-pub use self::handler::connect_to_host;
-pub use self::handler::create_handler;
+pub use self::handler::host_handler;
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index e3919911..d7356dcb 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -8,6 +8,7 @@
 
 //! Handlers for jobs for webhooks from hosting services.
 
+use crates::boxfnonce::BoxFnOnce;
 use crates::ghostflow::host::HostingService;
 use crates::json_job_dispatch::Handler;
 use crates::serde_json::Value;
@@ -22,19 +23,20 @@ use error::*;
 
 use std::sync::Arc;
 
-/// Connect to a `HostingService`.
-pub fn connect_to_host(api: &str, url: &Option<String>, secrets: &Value)
-                       -> Result<Arc<HostingService>> {
-    match api {
-        "gitlab" => gitlab::connect_to_host(url, secrets),
-        _ => Err(format!("unknown api: {}", api).into()),
-    }
+/// A structure containing all the information necessary to communicate with a service.
+pub struct HostHandler {
+    /// The `HostingService` to use for communicating with the service.
+    pub service: Arc<HostingService>,
+    /// The handler to use for handling webhooks.
+    pub handler: BoxFnOnce<'static, (Host,), Box<Handler>>,
 }
 
-/// Create handlers for a host configuration.
-pub fn create_handler(host: Host, name: &str) -> Result<Box<Handler>> {
-    match host.api.as_str() {
-        "gitlab" => gitlab::create_handler(host, name),
-        _ => Err(format!("unknown api: {}", host.api).into()),
+impl HostHandler {
+    /// Connect to a `HostingService`.
+    pub fn new(api: &str, url: &Option<String>, secrets: &Value, name: String) -> Result<Self> {
+        match api {
+            "gitlab" => gitlab::host_handler(url, secrets, name),
+            _ => Err(format!("unknown api: {}", api).into()),
+        }
     }
 }
diff --git a/src/main.rs b/src/main.rs
index bdb415db..26133245 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -29,6 +29,7 @@ extern crate serde_derive;
 extern crate serde_json;
 
 mod crates {
+    pub extern crate boxfnonce;
     pub extern crate chrono;
     pub extern crate clap;
     pub extern crate either;
@@ -96,14 +97,9 @@ include!(concat!(env!("OUT_DIR"), "/git_info.rs"));
 
 /// Run the director with the configuration file's path.
 fn run_director(config_path: &Path) -> Result<RunResult> {
-    let mut config = Config::from_path(&config_path, handlers::connect_to_host)?;
-
     let watchdog = DirectorWatchdog {};
-    let mut handlers = Vec::new();
 
-    for (name, host) in config.hosts.drain() {
-        handlers.push(handlers::create_handler(host, &name)?)
-    }
+    let config = Config::from_path(&config_path)?;
 
     let mut director = Director::new(&config.archive_dir).chain_err(|| {
         format!("failed to create director for {}",
@@ -112,7 +108,7 @@ fn run_director(config_path: &Path) -> Result<RunResult> {
 
     watchdog.add_to_director(&mut director)
         .chain_err(|| "failed to add watchdog to director")?;
-    for handler in &handlers {
+    for handler in &config.handlers {
         handler.add_to_director(&mut director)
             .chain_err(|| "failed to add handler to director")?;
     }
-- 
GitLab


From 09114fd1e908bce487dee13658622eeaa46f04aa Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Wed, 10 Oct 2018 15:18:39 -0400
Subject: [PATCH 5/9] ghostflow: update for optional source_repo in merge
 requests

---
 Cargo.lock                                     |  4 ++--
 src/handlers/common/data.rs                    |  2 +-
 src/handlers/common/handlers/merge_requests.rs | 18 +++++++++++++-----
 src/handlers/test/ghostflow.rs                 |  2 +-
 src/handlers/test/hooks.rs                     |  2 +-
 5 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b647440f..6cedd306 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -364,7 +364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "ghostflow"
 version = "0.1.0"
-source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#ea926811378cfbf56af4913b0eaeb9b199a03062"
+source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#39e31f25508f7f5abad21d14a5aafe1861a4c872"
 dependencies = [
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -424,7 +424,7 @@ dependencies = [
 [[package]]
 name = "ghostflow-gitlab"
 version = "0.1.0"
-source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#ea926811378cfbf56af4913b0eaeb9b199a03062"
+source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#39e31f25508f7f5abad21d14a5aafe1861a4c872"
 dependencies = [
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/src/handlers/common/data.rs b/src/handlers/common/data.rs
index 87af52fe..1ccf0843 100644
--- a/src/handlers/common/data.rs
+++ b/src/handlers/common/data.rs
@@ -303,7 +303,7 @@ mod test {
             email: "user@example.com".to_string(),
         };
         let mr = MergeRequest {
-            source_repo: repo.clone(),
+            source_repo: Some(repo.clone()),
             source_branch: "topic".to_string(),
             target_repo: repo.clone(),
             target_branch: "master".to_string(),
diff --git a/src/handlers/common/handlers/merge_requests.rs b/src/handlers/common/handlers/merge_requests.rs
index 2402d107..9725daac 100644
--- a/src/handlers/common/handlers/merge_requests.rs
+++ b/src/handlers/common/handlers/merge_requests.rs
@@ -56,7 +56,7 @@ pub fn handle_merge_request_update(data: &Value, host: &Host, mr: &MergeRequestI
         if let Err(err) = fetch_res {
             error!(target: "ghostflow-director/handler",
                    "failed to fetch from the {} repository: {:?}",
-                   mr.merge_request.source_repo.url,
+                   mr.merge_request.commit.repo.url,
                    err);
 
             errors.push(format!("Failed to fetch from the repository: {}.", err));
@@ -145,9 +145,17 @@ fn handle_merged_merge_request(project: &Project, branch: &Branch, mr: &MergeReq
 }
 
 fn remove_source_branch(ctx: &GitContext, mr: &MergeRequest, messages: &mut Vec<String>) {
-    info!(target: "ghostflow-director/handler",
-          "removing the source branch for {}",
-          mr.url);
+    let url = if let Some(ref repo) = mr.source_repo {
+        info!(target: "ghostflow-director/handler",
+              "removing the source branch for {}",
+              mr.url);
+        &repo.url
+    } else {
+        info!(target: "ghostflow-director/handler",
+              "not removing the source branch for {} because the source repo is not available",
+              mr.url);
+        return;
+    };
 
     let push_res = ctx.git()
         .arg("push")
@@ -156,7 +164,7 @@ fn remove_source_branch(ctx: &GitContext, mr: &MergeRequest, messages: &mut Vec<
         .arg(format!("--force-with-lease=refs/heads/{}:{}",
                      mr.source_branch,
                      mr.commit.id))
-        .arg(&mr.source_repo.url)
+        .arg(url)
         .arg(format!(":refs/heads/{}", mr.source_branch))
         .output();
     match push_res {
diff --git a/src/handlers/test/ghostflow.rs b/src/handlers/test/ghostflow.rs
index cd163e56..23d9e4d1 100644
--- a/src/handlers/test/ghostflow.rs
+++ b/src/handlers/test/ghostflow.rs
@@ -387,7 +387,7 @@ fn ghostflow_mr(mr: &data::MergeRequest, data: &data::Data) -> Result<MergeReque
 
     Ok(MergeRequest {
         id: mr.id,
-        source_repo: ghostflow_repo(source_project, data)?,
+        source_repo: ghostflow_repo(source_project, data).ok(),
         source_branch: mr.source_branch.clone(),
         target_repo: ghostflow_repo(target_project, data)?,
         target_branch: mr.target_branch.clone(),
diff --git a/src/handlers/test/hooks.rs b/src/handlers/test/hooks.rs
index 72f49afd..3099f8cf 100644
--- a/src/handlers/test/hooks.rs
+++ b/src/handlers/test/hooks.rs
@@ -105,7 +105,7 @@ pub struct MergeRequest {
 impl From<MergeRequest> for host::MergeRequest {
     fn from(mr: MergeRequest) -> Self {
         host::MergeRequest {
-            source_repo: mr.source_repo.into(),
+            source_repo: Some(mr.source_repo.into()),
             source_branch: mr.source_branch,
             target_repo: mr.target_repo.into(),
             target_branch: mr.target_branch,
-- 
GitLab


From 3b91cba961bb2a44d28ce8b3cf291a1fcfe0cef6 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Thu, 11 Oct 2018 14:44:06 -0400
Subject: [PATCH 6/9] ghostflow: update for check name configurability

---
 Cargo.lock                                    |  4 +--
 src/config/io.rs                              |  8 ++++++
 src/config/types.rs                           | 28 +++++++++++++++++--
 src/handlers/common/data.rs                   |  7 +++--
 .../common/handlers/merge_requests.rs         |  2 +-
 .../common/handlers/notes/commands/data.rs    |  2 +-
 6 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 6cedd306..e61d2d5c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -364,7 +364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "ghostflow"
 version = "0.1.0"
-source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#39e31f25508f7f5abad21d14a5aafe1861a4c872"
+source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#9e6aac857f0a2aa5fedb7a0b2dd5141dccd9748a"
 dependencies = [
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -424,7 +424,7 @@ dependencies = [
 [[package]]
 name = "ghostflow-gitlab"
 version = "0.1.0"
-source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#39e31f25508f7f5abad21d14a5aafe1861a4c872"
+source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#9e6aac857f0a2aa5fedb7a0b2dd5141dccd9748a"
 dependencies = [
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/src/config/io.rs b/src/config/io.rs
index f64646fe..643865dd 100644
--- a/src/config/io.rs
+++ b/src/config/io.rs
@@ -298,6 +298,10 @@ pub struct Branch {
     pub into_branches: Vec<String>,
 }
 
+fn default_base_check_name() -> String {
+    "ghostflow".to_string()
+}
+
 #[derive(Deserialize, Serialize, Debug, Clone)]
 /// Configuration for a project.
 pub struct Project {
@@ -324,6 +328,10 @@ pub struct Project {
     #[serde(default)]
     /// Project maintainers.
     pub maintainers: Vec<String>,
+
+    #[serde(default="default_base_check_name")]
+    /// The base name for checks on the project.
+    pub base_check_name: String,
 }
 
 #[derive(Deserialize, Serialize, Debug)]
diff --git a/src/config/types.rs b/src/config/types.rs
index 58ed8ee1..48f5a4ad 100644
--- a/src/config/types.rs
+++ b/src/config/types.rs
@@ -207,6 +207,8 @@ pub struct Project {
     members: RwLock<HashMap<String, Membership>>,
     /// Users who should be notified on important events.
     maintainers: Vec<String>,
+    /// The base name for checks performed on the project.
+    base_check_name: String,
 }
 
 impl Project {
@@ -402,6 +404,7 @@ impl Project {
             name: name.to_string(),
             members: RwLock::new(members),
             maintainers: maintainers,
+            base_check_name: project.base_check_name,
         })
     }
 
@@ -459,6 +462,16 @@ impl Project {
             .collect()
     }
 
+    /// Get the name for statuses for this project.
+    pub fn status_name(&self, branch: &str) -> String {
+        check::Check::new(self.context.clone(),
+                          Arc::clone(&self.service),
+                          Checks::new().config(),
+                          &self.maintainers)
+            .base_name(self.base_check_name.clone())
+            .status_name(branch)
+    }
+
     /// Get the check action for a given branch.
     fn pre_check_action<'a>(&'a self, branch: &'a Branch) -> check::Check {
         check::Check::new(self.context.clone(),
@@ -466,6 +479,7 @@ impl Project {
                           branch.pre_checks.config(),
                           &self.maintainers)
             .post_when(check::PostWhen::Failure)
+            .base_name(self.base_check_name.clone())
     }
 
     /// Get the check action for a given branch.
@@ -474,6 +488,7 @@ impl Project {
                           Arc::clone(&self.service),
                           branch.checks.config(),
                           &self.maintainers)
+            .base_name(self.base_check_name.clone())
     }
 
     /// Check that a merge request is OK.
@@ -694,7 +709,7 @@ pub struct Branch {
     identity: Identity,
 
     /// The check action for the branch.
-    check: Option<CheckAction>,
+    check: CheckAction,
     /// The follow action for the branch.
     follow: Option<FollowAction>,
     /// The merge action for the branch.
@@ -731,7 +746,7 @@ impl Branch {
             context: context,
             identity: identity,
 
-            check: Some(CheckAction),
+            check: CheckAction,
             follow: None,
             merge: None,
             reformat: None,
@@ -881,8 +896,15 @@ impl Branch {
     }
 
     /// Get the check action for the branch.
+    pub fn check_action(&self) -> &CheckAction {
+        &self.check
+    }
+
+    /// Get the check action for the branch.
+    ///
+    /// Note that this exists purely to be uniform with other actions.
     pub fn check(&self) -> Option<&CheckAction> {
-        self.check.as_ref()
+        Some(self.check_action())
     }
 
     /// Get the follow action for the branch.
diff --git a/src/handlers/common/data.rs b/src/handlers/common/data.rs
index 1ccf0843..34ef99c8 100644
--- a/src/handlers/common/data.rs
+++ b/src/handlers/common/data.rs
@@ -12,7 +12,6 @@
 //! requested branches.
 
 use crates::chrono::{DateTime, Utc};
-use crates::ghostflow::actions::check;
 use crates::ghostflow::host::{CheckStatus, Comment, Commit, HostingService, Membership, MergeRequest,
                               Repo, User};
 use crates::ghostflow::utils::TrailerRef;
@@ -195,7 +194,9 @@ impl MergeRequestInfo {
     /// This will check the status messages for each target branch according to the backport
     /// information to ensure that it has been checked according to the backport information
     /// available for the merge request.
-    pub fn check_status(&self, service: &HostingService, ctx: &GitContext) -> Result<CheckStatus> {
+    pub fn check_status<F>(&self, service: &HostingService, ctx: &GitContext, status_name_fn: F) -> Result<CheckStatus>
+        where F: Fn(&str) -> String,
+    {
         let service_user_handle = &service.service_user().handle;
         let status_map = service.get_commit_statuses(&self.merge_request.commit)
             .chain_err(|| ErrorKind::Msg("failed to fetch commit statuses for the mr".to_string()))?
@@ -210,7 +211,7 @@ impl MergeRequestInfo {
             .chain(iter::once(BackportInfo::main_target(&self.merge_request.target_branch)))
             .map(|backport| {
                 // The name of the status we should expect.
-                let status_name = check::Check::status_name(&backport.branch);
+                let status_name = status_name_fn(&backport.branch);
                 // The commit that we expect to have been checked.
                 let expected_commit = backport.commit(&self.merge_request, ctx)?;
                 Ok(status_map.get(&status_name)
diff --git a/src/handlers/common/handlers/merge_requests.rs b/src/handlers/common/handlers/merge_requests.rs
index 9725daac..f3ae7f98 100644
--- a/src/handlers/common/handlers/merge_requests.rs
+++ b/src/handlers/common/handlers/merge_requests.rs
@@ -86,7 +86,7 @@ pub fn handle_merge_request_update(data: &Value, host: &Host, mr: &MergeRequestI
         // A merge request with a deleted source branch is never ok.
         false
     } else {
-        match mr.check_status(host.service.as_ref(), &project.context) {
+        match mr.check_status(host.service.as_ref(), &project.context, |name| project.status_name(name)) {
             Ok(status) =>  {
                 if status.is_checked() {
                     status.is_ok()
diff --git a/src/handlers/common/handlers/notes/commands/data.rs b/src/handlers/common/handlers/notes/commands/data.rs
index 1d5a3f6c..139e4e17 100644
--- a/src/handlers/common/handlers/notes/commands/data.rs
+++ b/src/handlers/common/handlers/notes/commands/data.rs
@@ -80,7 +80,7 @@ impl<'a> Data<'a> {
 
     pub fn check_status(&mut self) -> Either<CommandResult, CheckStatus> {
         let mr = &self.mr_note.merge_request;
-        match mr.check_status(self.host.service.as_ref(), &self.project.context) {
+        match mr.check_status(self.host.service.as_ref(), &self.project.context, |name| self.project.status_name(name)) {
             Ok(status) => Either::Right(status),
             Err(err) => {
                 error!(target: "ghostflow-director/handler",
-- 
GitLab


From 252bd593b6655ce9661f904181c246b583c1d748 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Tue, 25 Sep 2018 11:08:21 -0400
Subject: [PATCH 7/9] github: add structures for webhooks

---
 src/handlers/github/hooks.rs | 458 +++++++++++++++++++++++++++++++++++
 src/handlers/github/mod.rs   |   9 +
 src/handlers/mod.rs          |   1 +
 3 files changed, 468 insertions(+)
 create mode 100644 src/handlers/github/hooks.rs
 create mode 100644 src/handlers/github/mod.rs

diff --git a/src/handlers/github/hooks.rs b/src/handlers/github/hooks.rs
new file mode 100644
index 00000000..4e4bf634
--- /dev/null
+++ b/src/handlers/github/hooks.rs
@@ -0,0 +1,458 @@
+// Copyright 2016 Kitware, Inc.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crates::chrono::{DateTime, Utc};
+
+#[derive(Debug, Deserialize)]
+pub enum CheckAction {
+    #[serde(rename = "created")]
+    Created,
+    #[serde(rename = "requested")]
+    Requested,
+    #[serde(rename = "rerequested")]
+    Rerequested,
+    #[serde(rename = "requested_action")]
+    RequestedAction,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum CheckStatus {
+    #[serde(rename = "queued")]
+    Queued,
+    #[serde(rename = "in_progress")]
+    InProgress,
+    #[serde(rename = "completed")]
+    Completed,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum CheckRunConclusion {
+    #[serde(rename = "success")]
+    Success,
+    #[serde(rename = "failure")]
+    Failure,
+    #[serde(rename = "neutral")]
+    Neutral,
+    #[serde(rename = "cancelled")]
+    Cancelled,
+    #[serde(rename = "timed_out")]
+    TimedOut,
+    #[serde(rename = "action_required")]
+    ActionRequired,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CheckRunHookAttrs {
+    pub status: CheckStatus,
+    pub head_sha: String,
+    pub conclusion: Option<CheckRunConclusion>,
+    pub name: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CheckRunRequestedAction {
+    pub identifier: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct BranchHookAttrs {
+    #[serde(rename = "ref")]
+    pub ref_: String,
+    pub sha: String,
+    pub repo: RepositoryHookAttrs,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum PullRequestState {
+    #[serde(rename = "open")]
+    Open,
+    #[serde(rename = "closed")]
+    Closed,
+    #[serde(rename = "merged")]
+    Merged,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PullRequestHookAttrs {
+    pub number: u64,
+    pub title: String,
+    pub body: String,
+    pub head: BranchHookAttrs,
+    pub base: BranchHookAttrs,
+    pub state: PullRequestState,
+    pub merged: bool,
+    pub updated_at: DateTime<Utc>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CheckSuiteHookAttrs {
+    pub head_branch: Option<String>,
+    pub head_sha: String,
+    pub status: CheckStatus,
+    pub conclusion: Option<CheckRunConclusion>,
+    pub pull_requests: Vec<PullRequestHookAttrs>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum AppAction {
+    #[serde(rename = "revoked")]
+    Revoked,
+    // TODO
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum InstallationAction {
+    #[serde(rename = "created")]
+    Created,
+    #[serde(rename = "deleted")]
+    Deleted,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum UserAccountType {
+    Bot,
+    User,
+    Organization,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct UserHookAttrs {
+    pub login: String,
+    #[serde(rename = "type")]
+    pub type_: UserAccountType,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct InstallationHookAttrs {
+    pub id: u64,
+    pub account: UserHookAttrs,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum InstallationRepositoriesAction {
+    #[serde(rename = "added")]
+    Added,
+    #[serde(rename = "removed")]
+    Removed,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum RepositorySelection {
+    #[serde(rename = "selected")]
+    Selected,
+    #[serde(rename = "all")]
+    All,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct RepositoryHookAttrs {
+    pub full_name: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum IssueCommentAction {
+    #[serde(rename = "created")]
+    Created,
+    #[serde(rename = "edited")]
+    Edited,
+    #[serde(rename = "deleted")]
+    Deleted,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct IssuePullRequestAttrs {
+    pub url: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct IssueHookAttrs {
+    pub url: String,
+    pub number: u64,
+    pub pull_request: Option<IssuePullRequestAttrs>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CommentHookAttrs {
+    pub node_id: String,
+    pub user: UserHookAttrs,
+    pub body: String,
+    pub created_at: DateTime<Utc>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum MemberAction {
+    #[serde(rename = "added")]
+    Added,
+    #[serde(rename = "edited")]
+    Edited,
+    #[serde(rename = "deleted")]
+    Deleted,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum Permission {
+    #[serde(rename = "write")]
+    Write,
+    // TODO
+}
+
+#[derive(Debug, Deserialize)]
+pub struct MemberPermission {
+    pub from: Option<Permission>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct MemberChanges {
+    pub permission: MemberPermission,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum MembershipAction {
+    #[serde(rename = "added")]
+    Added,
+    #[serde(rename = "removed")]
+    Removed,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum MembershipScope {
+    #[serde(rename = "team")]
+    Team,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum TeamPermission {
+    #[serde(rename = "admin")]
+    Admin,
+    #[serde(rename = "pull")]
+    Pull,
+    #[serde(rename = "push")]
+    Push,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct TeamHookAttrs {
+    pub name: String,
+    pub permission: TeamPermission,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum OrganizationAction {
+    #[serde(rename = "member_added")]
+    MemberAdded,
+    #[serde(rename = "member_removed")]
+    MemberRemoved,
+    #[serde(rename = "member_invited")]
+    MemberInvited,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum MembershipState {
+    #[serde(rename = "pending")]
+    Pending,
+    // TODO
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum MembershipRole {
+    #[serde(rename = "member")]
+    Member,
+    // TODO
+}
+
+#[derive(Debug, Deserialize)]
+pub struct MembershipHookAttrs {
+    pub state: MembershipState,
+    pub role: MembershipRole,
+    pub user: UserHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct OrganizationHookAttrs {
+    pub login: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum PullRequestReviewAction {
+    #[serde(rename = "submitted")]
+    Submitted,
+    #[serde(rename = "edited")]
+    Edited,
+    #[serde(rename = "dismissed")]
+    Dismissed,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum PullRequestReviewState {
+    #[serde(rename = "commented")]
+    Commented,
+    #[serde(rename = "approved")]
+    Approved,
+    // TODO
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PullRequestReviewHookAttrs {
+    pub body: Option<String>,
+    pub submitted_at: DateTime<Utc>,
+    pub state: PullRequestReviewState,
+    pub user: UserHookAttrs,
+    pub node_id: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum PullRequestAction {
+    #[serde(rename = "assigned")]
+    Assigned,
+    #[serde(rename = "unassigned")]
+    Unassigned,
+    #[serde(rename = "review_requested")]
+    ReviewRequested,
+    #[serde(rename = "review_request_removed")]
+    ReviewRequestRemoved,
+    #[serde(rename = "labeled")]
+    Labeled,
+    #[serde(rename = "unlabeled")]
+    Unlabeled,
+    #[serde(rename = "opened")]
+    Opened,
+    #[serde(rename = "edited")]
+    Edited,
+    #[serde(rename = "closed")]
+    Closed,
+    #[serde(rename = "reopened")]
+    Reopened,
+    #[serde(rename = "synchronize")]
+    Synchronize,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PusherHookAttrs {
+    pub name: String,
+    pub email: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
+pub enum TeamAction {
+    #[serde(rename = "created")]
+    Created,
+    #[serde(rename = "deleted")]
+    Deleted,
+    #[serde(rename = "edited")]
+    Edited,
+    #[serde(rename = "added_to_repository")]
+    AddedToRepository,
+    #[serde(rename = "removed_from_repository")]
+    RemovedFromRepository,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CheckRunEvent {
+    pub action: CheckAction,
+    pub check_run: CheckRunHookAttrs,
+    pub pull_requests: Vec<PullRequestHookAttrs>,
+    pub requested_action: Option<CheckRunRequestedAction>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct CheckSuiteEvent {
+    pub action: CheckAction,
+    pub check_suite: CheckSuiteHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct GithubAppAuthorizationEvent {
+    pub action: AppAction,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct InstallationEvent {
+    pub action: InstallationAction,
+    pub installation: InstallationHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct InstallationRepositoriesEvent {
+    pub action: InstallationRepositoriesAction,
+    pub installation: InstallationHookAttrs,
+    pub repository_selection: RepositorySelection,
+    pub repositories_added: Vec<RepositoryHookAttrs>,
+    pub repositories_removed: Vec<RepositoryHookAttrs>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct IssueCommentEvent {
+    pub action: IssueCommentAction,
+    pub issue: IssueHookAttrs,
+    pub comment: CommentHookAttrs,
+    pub repository: RepositoryHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct MemberEvent {
+    pub action: MemberAction,
+    pub member: UserHookAttrs,
+    pub changes: MemberChanges,
+    pub repository: RepositoryHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct MembershipEvent {
+    pub action: MembershipAction,
+    pub scope: MembershipScope,
+    pub member: UserHookAttrs,
+    pub changes: MemberChanges,
+    pub team: TeamHookAttrs,
+    pub organization: OrganizationHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct OrganizationEvent {
+    pub action: OrganizationAction,
+    pub membership: Option<MembershipHookAttrs>,
+    pub organization: OrganizationHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PullRequestReviewEvent {
+    pub action: PullRequestReviewAction,
+    pub pull_request: PullRequestHookAttrs,
+    pub review: PullRequestReviewHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PullRequestEvent {
+    pub action: PullRequestAction,
+    pub pull_request: PullRequestHookAttrs,
+    pub number: u64,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct PushEvent {
+    #[serde(rename = "ref")]
+    pub ref_: String,
+    pub after: String,
+    pub repository: RepositoryHookAttrs,
+    pub pusher: PusherHookAttrs,
+    pub sender: UserHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct TeamEvent {
+    pub action: TeamAction,
+    pub team: TeamHookAttrs,
+    pub repository: RepositoryHookAttrs,
+    pub organization: OrganizationHookAttrs,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct TeamAddEvent {
+    pub team: TeamHookAttrs,
+    pub repository: RepositoryHookAttrs,
+    pub organization: OrganizationHookAttrs,
+}
diff --git a/src/handlers/github/mod.rs b/src/handlers/github/mod.rs
new file mode 100644
index 00000000..6445a7ea
--- /dev/null
+++ b/src/handlers/github/mod.rs
@@ -0,0 +1,9 @@
+// Copyright 2016 Kitware, Inc.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod hooks;
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index d7356dcb..824e82c9 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -14,6 +14,7 @@ use crates::json_job_dispatch::Handler;
 use crates::serde_json::Value;
 
 pub mod common;
+mod github;
 mod gitlab;
 #[cfg(test)]
 pub mod test;
-- 
GitLab


From c6526921e5fca51f5978870c2239bdc751432aa3 Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Tue, 25 Sep 2018 11:09:52 -0400
Subject: [PATCH 8/9] github: add supplemental GraphQL query definitions

---
 Cargo.lock                                   |   90 +
 Cargo.toml                                   |    1 +
 src/handlers/github/graphql/.gitattributes   |    2 +
 src/handlers/github/graphql/.gitignore       |    1 +
 src/handlers/github/graphql/query.graphql    |   16 +
 src/handlers/github/graphql/schema.graphql   | 9030 ++++++++++++++++++
 src/handlers/github/graphql/update_schema.sh |   22 +
 src/handlers/github/mod.rs                   |    1 +
 src/handlers/github/queries.rs               |   23 +
 src/main.rs                                  |    6 +
 10 files changed, 9192 insertions(+)
 create mode 100644 src/handlers/github/graphql/.gitattributes
 create mode 100644 src/handlers/github/graphql/.gitignore
 create mode 100644 src/handlers/github/graphql/query.graphql
 create mode 100644 src/handlers/github/graphql/schema.graphql
 create mode 100755 src/handlers/github/graphql/update_schema.sh
 create mode 100644 src/handlers/github/queries.rs

diff --git a/Cargo.lock b/Cargo.lock
index e61d2d5c..ecae3787 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -27,6 +27,11 @@ dependencies = [
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ascii"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "atty"
 version = "0.2.11"
@@ -144,6 +149,18 @@ dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "combine"
+version = "3.0.0-beta.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "core-foundation"
 version = "0.2.3"
@@ -402,6 +419,7 @@ dependencies = [
  "git-topic-stage 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "git-workarea 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gitlab 0.1102.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "graphql_client 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "json-job-dispatch 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy-init 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -493,6 +511,65 @@ dependencies = [
  "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "graphql-parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "combine 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "graphql_client"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "graphql_query_derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "graphql_client_codegen"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "graphql-parser 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "graphql_query_derive"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "graphql_client_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "httparse"
 version = "1.3.2"
@@ -1693,6 +1770,11 @@ name = "unicode-normalization"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-segmentation"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "unicode-width"
 version = "0.1.5"
@@ -1889,6 +1971,7 @@ dependencies = [
 "checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
+"checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
@@ -1904,6 +1987,7 @@ dependencies = [
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+"checksum combine 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8113ef991b7262e2b95d3c5051434a529431f2ac3fba6e1a55786733e62136c8"
 "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
 "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
 "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
@@ -1936,6 +2020,11 @@ dependencies = [
 "checksum git-topic-stage 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7c37834f8490269a6473cff981d6512e03609e9dad80da2c8c2b67d6dbe5b7"
 "checksum git-workarea 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a31842b69888bfaa2757023b92d5ca8589ad2c64a51e434f153d43cc8d503b6"
 "checksum gitlab 0.1102.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fb30e2dfc4df1cf8a7dd2196bf89bd0dc9c075112959062c080f9b453067a"
+"checksum graphql-parser 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "263a7dfe403ee91afccf006378caaaf692f6a4cb79982cffc1e99479779d5d5a"
+"checksum graphql_client 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5ac52b8616d35ac86557fb0317ca0b0ec674a3681c29e732fde06aab17faac"
+"checksum graphql_client_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf715c9254776bec2fbb3dbba05ca8434ecf98e32d1e12d5a2c8c62db181d54"
+"checksum graphql_query_derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e90e8b23d9b369d261757740c8720a4f80d0286aee3ebf7c58eed30078440b9"
+"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
 "checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7"
@@ -2068,6 +2157,7 @@ dependencies = [
 "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
+"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
diff --git a/Cargo.toml b/Cargo.toml
index 0b033462..009840ff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,6 +31,7 @@ git-checks = "^3.5"
 git-topic-stage = "^3.0"
 git-workarea = "^3.0"
 gitlab = "=0.1102.2"
+graphql_client = "~0.5"
 itertools = "~0.7"
 json-job-dispatch = "^1.2"
 lazy-init = "~0.3"
diff --git a/src/handlers/github/graphql/.gitattributes b/src/handlers/github/graphql/.gitattributes
new file mode 100644
index 00000000..8569ce29
--- /dev/null
+++ b/src/handlers/github/graphql/.gitattributes
@@ -0,0 +1,2 @@
+# This file is downloaded from GitHub. Ignore any whitespace errors in it.
+schema.graphql  -whitespace
diff --git a/src/handlers/github/graphql/.gitignore b/src/handlers/github/graphql/.gitignore
new file mode 100644
index 00000000..d23bcc7f
--- /dev/null
+++ b/src/handlers/github/graphql/.gitignore
@@ -0,0 +1 @@
+.gh-token
diff --git a/src/handlers/github/graphql/query.graphql b/src/handlers/github/graphql/query.graphql
new file mode 100644
index 00000000..eae7f9e3
--- /dev/null
+++ b/src/handlers/github/graphql/query.graphql
@@ -0,0 +1,16 @@
+# Copyright 2016 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+query PullRequestInfo($owner: String!, $name: String!, $pull: Int!) {
+    repository(owner: $owner, name: $name) {
+        pullRequest(number: $pull) {
+            state
+            updatedAt
+        }
+    }
+}
diff --git a/src/handlers/github/graphql/schema.graphql b/src/handlers/github/graphql/schema.graphql
new file mode 100644
index 00000000..19ab3ae0
--- /dev/null
+++ b/src/handlers/github/graphql/schema.graphql
@@ -0,0 +1,9030 @@
+# Autogenerated input type of AcceptTopicSuggestion
+input AcceptTopicSuggestionInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of the suggested topic.
+  name: String!
+
+  # The Node ID of the repository.
+  repositoryId: ID!
+}
+
+# Autogenerated return type of AcceptTopicSuggestion
+type AcceptTopicSuggestionPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The accepted topic.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `topic` will change from `Topic!` to `Topic`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  topic: Topic!
+}
+
+# Represents an object which can take actions on GitHub. Typically a User or Bot.
+interface Actor {
+  # A URL pointing to the actor's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+
+  # The username of the actor.
+  login: String!
+
+  # The HTTP path for this actor.
+  resourcePath: URI!
+
+  # The HTTP URL for this actor.
+  url: URI!
+}
+
+# Autogenerated input type of AddComment
+input AddCommentInput {
+  # The contents of the comment.
+  body: String!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the subject to modify.
+  subjectId: ID!
+}
+
+# Autogenerated return type of AddComment
+type AddCommentPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The edge from the subject's comment connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `commentEdge` will change from `IssueCommentEdge!` to `IssueCommentEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  commentEdge: IssueCommentEdge!
+
+  # The subject
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `subject` will change from `Node!` to `Node`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  subject: Node!
+
+  # The edge from the subject's timeline connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `timelineEdge` will change from `IssueTimelineItemEdge!` to `IssueTimelineItemEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  timelineEdge: IssueTimelineItemEdge!
+}
+
+# Autogenerated input type of AddProjectCard
+input AddProjectCardInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The content of the card. Must be a member of the ProjectCardItem union
+  contentId: ID
+
+  # The note on the card.
+  note: String
+
+  # The Node ID of the ProjectColumn.
+  projectColumnId: ID!
+}
+
+# Autogenerated return type of AddProjectCard
+type AddProjectCardPayload {
+  # The edge from the ProjectColumn's card connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `cardEdge` will change from `ProjectCardEdge!` to `ProjectCardEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  cardEdge: ProjectCardEdge!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The ProjectColumn
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `projectColumn` will change from `Project!` to `Project`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  projectColumn: Project!
+}
+
+# Autogenerated input type of AddProjectColumn
+input AddProjectColumnInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of the column.
+  name: String!
+
+  # The Node ID of the project.
+  projectId: ID!
+}
+
+# Autogenerated return type of AddProjectColumn
+type AddProjectColumnPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The edge from the project's column connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `columnEdge` will change from `ProjectColumnEdge!` to `ProjectColumnEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  columnEdge: ProjectColumnEdge!
+
+  # The project
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `project` will change from `Project!` to `Project`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  project: Project!
+}
+
+# Autogenerated input type of AddPullRequestReviewComment
+input AddPullRequestReviewCommentInput {
+  # The text of the comment.
+  body: String!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The SHA of the commit to comment on.
+  commitOID: GitObjectID
+
+  # The comment id to reply to.
+  inReplyTo: ID
+
+  # The relative path of the file to comment on.
+  path: String
+
+  # The line index in the diff to comment on.
+  position: Int
+
+  # The Node ID of the review to modify.
+  pullRequestReviewId: ID!
+}
+
+# Autogenerated return type of AddPullRequestReviewComment
+type AddPullRequestReviewCommentPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The newly created comment.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `comment` will change from `PullRequestReviewComment!` to `PullRequestReviewComment`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  comment: PullRequestReviewComment!
+
+  # The edge from the review's comment connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `commentEdge` will change from
+  # `PullRequestReviewCommentEdge!` to `PullRequestReviewCommentEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  commentEdge: PullRequestReviewCommentEdge!
+}
+
+# Autogenerated input type of AddPullRequestReview
+input AddPullRequestReviewInput {
+  # The contents of the review body comment.
+  body: String
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The review line comments.
+  comments: [DraftPullRequestReviewComment]
+
+  # The commit OID the review pertains to.
+  commitOID: GitObjectID
+
+  # The event to perform on the pull request review.
+  event: PullRequestReviewEvent
+
+  # The Node ID of the pull request to modify.
+  pullRequestId: ID!
+}
+
+# Autogenerated return type of AddPullRequestReview
+type AddPullRequestReviewPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The newly created pull request review.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReview` will change from `PullRequestReview!` to `PullRequestReview`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReview: PullRequestReview!
+
+  # The edge from the pull request's review connection.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `reviewEdge` will change from `PullRequestReviewEdge!` to `PullRequestReviewEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  reviewEdge: PullRequestReviewEdge!
+}
+
+# Autogenerated input type of AddReaction
+input AddReactionInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of the emoji to react with.
+  content: ReactionContent!
+
+  # The Node ID of the subject to modify.
+  subjectId: ID!
+}
+
+# Autogenerated return type of AddReaction
+type AddReactionPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The reaction object.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `reaction` will change from `Reaction!` to `Reaction`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  reaction: Reaction!
+
+  # The reactable subject.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `subject` will change from `Reactable!` to `Reactable`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  subject: Reactable!
+}
+
+# Autogenerated input type of AddStar
+input AddStarInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Starrable ID to star.
+  starrableId: ID!
+}
+
+# Autogenerated return type of AddStar
+type AddStarPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The starrable.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `starrable` will change from `Starrable!` to `Starrable`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  starrable: Starrable!
+}
+
+# Represents a 'added_to_project' event on a given issue or pull request.
+type AddedToProjectEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# A GitHub App.
+type App implements Node {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The description of the app.
+  description: String
+  id: ID!
+
+  # The hex color code, without the leading '#', for the logo background.
+  logoBackgroundColor: String!
+
+  # A URL pointing to the app's logo.
+  logoUrl(
+    # The size of the resulting image.
+    size: Int
+  ): URI!
+
+  # The name of the app.
+  name: String!
+
+  # A slug based on the name of the app for use in URLs.
+  slug: String!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The URL to the app's homepage.
+  url: URI!
+}
+
+# An edge in a connection.
+type AppEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: App
+}
+
+# An object that can have users assigned to it.
+interface Assignable {
+  # A list of Users assigned to this object.
+  assignees(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+}
+
+# Represents an 'assigned' event on any assignable object.
+type AssignedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the assignable associated with the event.
+  assignable: Assignable!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the user who was assigned.
+  user: User
+}
+
+# Represents a 'base_ref_changed' event on a given issue or pull request.
+type BaseRefChangedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# Represents a 'base_ref_force_pushed' event on a given pull request.
+type BaseRefForcePushedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the after commit SHA for the 'base_ref_force_pushed' event.
+  afterCommit: Commit
+
+  # Identifies the before commit SHA for the 'base_ref_force_pushed' event.
+  beforeCommit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # Identifies the fully qualified ref name for the 'base_ref_force_pushed' event.
+  ref: Ref
+}
+
+# Represents a Git blame.
+type Blame {
+  # The list of ranges from a Git blame.
+  ranges: [BlameRange!]!
+}
+
+# Represents a range of information from a Git blame.
+type BlameRange {
+  # Identifies the recency of the change, from 1 (new) to 10 (old). This is
+  # calculated as a 2-quantile and determines the length of distance between the
+  # median age of all the changes in the file and the recency of the current
+  # range's change.
+  age: Int!
+
+  # Identifies the line author
+  commit: Commit!
+
+  # The ending line for the range
+  endingLine: Int!
+
+  # The starting line for the range
+  startingLine: Int!
+}
+
+# Represents a Git blob.
+type Blob implements GitObject & Node {
+  # An abbreviated version of the Git object ID
+  abbreviatedOid: String!
+
+  # Byte size of Blob object
+  byteSize: Int!
+
+  # The HTTP path for this Git object
+  commitResourcePath: URI!
+
+  # The HTTP URL for this Git object
+  commitUrl: URI!
+  id: ID!
+
+  # Indicates whether the Blob is binary or text
+  isBinary: Boolean!
+
+  # Indicates whether the contents is truncated
+  isTruncated: Boolean!
+
+  # The Git object ID
+  oid: GitObjectID!
+
+  # The Repository the Git object belongs to
+  repository: Repository!
+
+  # UTF8 text data or null if the Blob is binary
+  text: String
+}
+
+# A special type of user which takes actions on behalf of GitHub Apps.
+type Bot implements Actor & Node & UniformResourceLocatable {
+  # A URL pointing to the GitHub App's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # The username of the actor.
+  login: String!
+
+  # The HTTP path for this bot
+  resourcePath: URI!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this bot
+  url: URI!
+}
+
+# An object that can be closed
+interface Closable {
+  # `true` if the object is closed (definition of closed may depend on type)
+  closed: Boolean!
+
+  # Identifies the date and time when the object was closed.
+  closedAt: DateTime
+}
+
+# Represents a 'closed' event on any `Closable`.
+type ClosedEvent implements Node & UniformResourceLocatable {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Object that was closed.
+  closable: Closable!
+
+  # Object which triggered the creation of this event.
+  closer: Closer
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # The HTTP path for this closed event.
+  resourcePath: URI!
+
+  # The HTTP URL for this closed event.
+  url: URI!
+}
+
+# The object which triggered a `ClosedEvent`.
+union Closer = Commit | PullRequest
+
+# The Code of Conduct for a repository
+type CodeOfConduct {
+  # The body of the CoC
+  body: String
+
+  # The key for the CoC
+  key: String!
+
+  # The formal name of the CoC
+  name: String!
+
+  # The path to the CoC
+  url: URI
+}
+
+# Collaborators affiliation level with a subject.
+enum CollaboratorAffiliation {
+  # All collaborators the authenticated user can see.
+  ALL
+
+  # All collaborators with permissions to an organization-owned subject, regardless of organization membership status.
+  DIRECT
+
+  # All outside collaborators of an organization-owned subject.
+  OUTSIDE
+}
+
+# Types that can be inside Collection Items.
+union CollectionItemContent = Organization | Repository | User
+
+# Represents a comment.
+interface Comment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # The body as Markdown.
+  body: String!
+
+  # The body rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body rendered to text.
+  bodyText: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# A comment author association with repository.
+enum CommentAuthorAssociation {
+  # Author has been invited to collaborate on the repository.
+  COLLABORATOR
+
+  # Author has previously committed to the repository.
+  CONTRIBUTOR
+
+  # Author has not previously committed to GitHub.
+  FIRST_TIMER
+
+  # Author has not previously committed to the repository.
+  FIRST_TIME_CONTRIBUTOR
+
+  # Author is a member of the organization that owns the repository.
+  MEMBER
+
+  # Author has no association with the repository.
+  NONE
+
+  # Author is the owner of the repository.
+  OWNER
+}
+
+# The possible errors that will prevent a user from updating a comment.
+enum CommentCannotUpdateReason {
+  # You must be the author or have write access to this repository to update this comment.
+  INSUFFICIENT_ACCESS
+
+  # Unable to create comment because issue is locked.
+  LOCKED
+
+  # You must be logged in to update this comment.
+  LOGIN_REQUIRED
+
+  # Repository is under maintenance.
+  MAINTENANCE
+
+  # At least one email address must be verified to update this comment.
+  VERIFIED_EMAIL_REQUIRED
+}
+
+# Represents a 'comment_deleted' event on a given issue or pull request.
+type CommentDeletedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# Represents a Git commit.
+type Commit implements GitObject & Node & Subscribable {
+  # An abbreviated version of the Git object ID
+  abbreviatedOid: String!
+
+  # The number of additions in this commit.
+  additions: Int!
+
+  # Authorship details of the commit.
+  author: GitActor
+
+  # Check if the committer and the author match.
+  authoredByCommitter: Boolean!
+
+  # The datetime when this commit was authored.
+  authoredDate: DateTime!
+
+  # Fetches `git blame` information.
+  blame(
+    # The file whose Git blame information you want.
+    path: String!
+  ): Blame!
+
+  # The number of changed files in this commit.
+  changedFiles: Int!
+
+  # Comments made on the commit.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): CommitCommentConnection!
+
+  # The HTTP path for this Git object
+  commitResourcePath: URI!
+
+  # The HTTP URL for this Git object
+  commitUrl: URI!
+
+  # The datetime when this commit was committed.
+  committedDate: DateTime!
+
+  # Check if commited via GitHub web UI.
+  committedViaWeb: Boolean!
+
+  # Committership details of the commit.
+  committer: GitActor
+
+  # The number of deletions in this commit.
+  deletions: Int!
+
+  # The linear commit history starting from (and including) this commit, in the same order as `git log`.
+  history(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # If non-null, filters history to only show commits with matching authorship.
+    author: CommitAuthor
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # If non-null, filters history to only show commits touching files under this path.
+    path: String
+
+    # Allows specifying a beginning time or date for fetching commits.
+    since: GitTimestamp
+
+    # Allows specifying an ending time or date for fetching commits.
+    until: GitTimestamp
+  ): CommitHistoryConnection!
+  id: ID!
+
+  # The Git commit message
+  message: String!
+
+  # The Git commit message body
+  messageBody: String!
+
+  # The commit message body rendered to HTML.
+  messageBodyHTML: HTML!
+
+  # The Git commit message headline
+  messageHeadline: String!
+
+  # The commit message headline rendered to HTML.
+  messageHeadlineHTML: HTML!
+
+  # The Git object ID
+  oid: GitObjectID!
+
+  # The parents of a commit.
+  parents(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): CommitConnection!
+
+  # The datetime when this commit was pushed.
+  pushedDate: DateTime
+
+  # The Repository this commit belongs to
+  repository: Repository!
+
+  # The HTTP path for this commit
+  resourcePath: URI!
+
+  # Commit signing information, if present.
+  signature: GitSignature
+
+  # Status information for this commit
+  status: Status
+
+  # Returns a URL to download a tarball archive for a repository.
+  # Note: For private repositories, these links are temporary and expire after five minutes.
+  tarballUrl: URI!
+
+  # Commit's root Tree
+  tree: Tree!
+
+  # The HTTP path for the tree of this commit
+  treeResourcePath: URI!
+
+  # The HTTP URL for the tree of this commit
+  treeUrl: URI!
+
+  # The HTTP URL for this commit
+  url: URI!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+
+  # Returns a URL to download a zipball archive for a repository.
+  # Note: For private repositories, these links are temporary and expire after five minutes.
+  zipballUrl: URI!
+}
+
+# Specifies an author for filtering Git commits.
+input CommitAuthor {
+  # Email addresses to filter by. Commits authored by any of the specified email addresses will be returned.
+  emails: [String!]
+
+  # ID of a User to filter by. If non-null, only commits authored by this user
+  # will be returned. This field takes precedence over emails.
+  id: ID
+}
+
+# Represents a comment on a given Commit.
+type CommitComment implements Comment & Deletable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # Identifies the comment body.
+  body: String!
+
+  # Identifies the comment body rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body rendered to text.
+  bodyText: String!
+
+  # Identifies the commit associated with the comment, if the commit exists.
+  commit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies the file path associated with the comment.
+  path: String
+
+  # Identifies the line position associated with the comment.
+  position: Int
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path permalink for this commit comment.
+  resourcePath: URI!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL permalink for this commit comment.
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# The connection type for CommitComment.
+type CommitCommentConnection {
+  # A list of edges.
+  edges: [CommitCommentEdge]
+
+  # A list of nodes.
+  nodes: [CommitComment]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type CommitCommentEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: CommitComment
+}
+
+# A thread of comments on a commit.
+type CommitCommentThread implements Node & RepositoryNode {
+  # The comments that exist in this thread.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): CommitCommentConnection!
+
+  # The commit the comments were made on.
+  commit: Commit!
+  id: ID!
+
+  # The file the comments were made on.
+  path: String
+
+  # The position in the diff for the commit that the comment was made on.
+  position: Int
+
+  # The repository associated with this node.
+  repository: Repository!
+}
+
+# The connection type for Commit.
+type CommitConnection {
+  # A list of edges.
+  edges: [CommitEdge]
+
+  # A list of nodes.
+  nodes: [Commit]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type CommitEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Commit
+}
+
+# The connection type for Commit.
+type CommitHistoryConnection {
+  edges: [CommitEdge]
+
+  # A list of nodes.
+  nodes: [Commit]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a 'converted_note_to_issue' event on a given issue or pull request.
+type ConvertedNoteToIssueEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# Autogenerated input type of CreateProject
+input CreateProjectInput {
+  # The description of project.
+  body: String
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of project.
+  name: String!
+
+  # The owner ID to create the project under.
+  ownerId: ID!
+}
+
+# Autogenerated return type of CreateProject
+type CreateProjectPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The new project.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `project` will change from `Project!` to `Project`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  project: Project!
+}
+
+# Represents a mention made by one issue or pull request to another.
+type CrossReferencedEvent implements Node & UniformResourceLocatable {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Reference originated in a different repository.
+  isCrossRepository: Boolean!
+
+  # Identifies when the reference was made.
+  referencedAt: DateTime!
+
+  # The HTTP path for this pull request.
+  resourcePath: URI!
+
+  # Issue or pull request that made the reference.
+  source: ReferencedSubject!
+
+  # Issue or pull request to which the reference was made.
+  target: ReferencedSubject!
+
+  # The HTTP URL for this pull request.
+  url: URI!
+
+  # Checks if the target will be closed when the source is merged.
+  willCloseTarget: Boolean!
+}
+
+# An ISO-8601 encoded date string.
+scalar Date
+
+# An ISO-8601 encoded UTC date string.
+scalar DateTime
+
+# Autogenerated input type of DeclineTopicSuggestion
+input DeclineTopicSuggestionInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of the suggested topic.
+  name: String!
+
+  # The reason why the suggested topic is declined.
+  reason: TopicSuggestionDeclineReason!
+
+  # The Node ID of the repository.
+  repositoryId: ID!
+}
+
+# Autogenerated return type of DeclineTopicSuggestion
+type DeclineTopicSuggestionPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The declined topic.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `topic` will change from `Topic!` to `Topic`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  topic: Topic!
+}
+
+# The possible default permissions for repositories.
+enum DefaultRepositoryPermissionField {
+  # Can read, write, and administrate repos by default
+  ADMIN
+
+  # No access
+  NONE
+
+  # Can read repos by default
+  READ
+
+  # Can read and write repos by default
+  WRITE
+}
+
+# Entities that can be deleted.
+interface Deletable {
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+}
+
+# Autogenerated input type of DeleteProjectCard
+input DeleteProjectCardInput {
+  # The id of the card to delete.
+  cardId: ID!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+}
+
+# Autogenerated return type of DeleteProjectCard
+type DeleteProjectCardPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The column the deleted card was in.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `column` will change from `ProjectColumn!` to `ProjectColumn`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  column: ProjectColumn!
+
+  # The deleted card ID.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `deletedCardId` will change from `ID!` to `ID`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  deletedCardId: ID!
+}
+
+# Autogenerated input type of DeleteProjectColumn
+input DeleteProjectColumnInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The id of the column to delete.
+  columnId: ID!
+}
+
+# Autogenerated return type of DeleteProjectColumn
+type DeleteProjectColumnPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The deleted column ID.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `deletedColumnId` will change from `ID!` to `ID`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  deletedColumnId: ID!
+
+  # The project the deleted column was in.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `project` will change from `Project!` to `Project`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  project: Project!
+}
+
+# Autogenerated input type of DeleteProject
+input DeleteProjectInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Project ID to update.
+  projectId: ID!
+}
+
+# Autogenerated return type of DeleteProject
+type DeleteProjectPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The repository or organization the project was removed from.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `owner` will change from `ProjectOwner!` to `ProjectOwner`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  owner: ProjectOwner!
+}
+
+# Autogenerated input type of DeletePullRequestReview
+input DeletePullRequestReviewInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the pull request review to delete.
+  pullRequestReviewId: ID!
+}
+
+# Autogenerated return type of DeletePullRequestReview
+type DeletePullRequestReviewPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The deleted pull request review.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReview` will change from `PullRequestReview!` to `PullRequestReview`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReview: PullRequestReview!
+}
+
+# Represents a 'demilestoned' event on a given issue or pull request.
+type DemilestonedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the milestone title associated with the 'demilestoned' event.
+  milestoneTitle: String!
+
+  # Object referenced by event.
+  subject: MilestoneItem!
+}
+
+# A repository deploy key.
+type DeployKey implements Node {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # The deploy key.
+  key: String!
+
+  # Whether or not the deploy key is read only.
+  readOnly: Boolean!
+
+  # The deploy key title.
+  title: String!
+
+  # Whether or not the deploy key has been verified.
+  verified: Boolean!
+}
+
+# The connection type for DeployKey.
+type DeployKeyConnection {
+  # A list of edges.
+  edges: [DeployKeyEdge]
+
+  # A list of nodes.
+  nodes: [DeployKey]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type DeployKeyEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: DeployKey
+}
+
+# Represents a 'deployed' event on a given pull request.
+type DeployedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The deployment associated with the 'deployed' event.
+  deployment: Deployment!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # The ref associated with the 'deployed' event.
+  ref: Ref
+}
+
+# Represents triggered deployment instance.
+type Deployment implements Node {
+  # Identifies the commit sha of the deployment.
+  commit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the actor who triggered the deployment.
+  creator: Actor
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The deployment description.
+  description: String
+
+  # The environment to which this deployment was made.
+  environment: String
+  id: ID!
+
+  # The latest status of this deployment.
+  latestStatus: DeploymentStatus
+
+  # Extra information that a deployment system might need.
+  payload: String
+
+  # Identifies the Ref of the deployment, if the deployment was created by ref.
+  ref: Ref
+
+  # Identifies the repository associated with the deployment.
+  repository: Repository!
+
+  # The current state of the deployment.
+  state: DeploymentState
+
+  # A list of statuses associated with the deployment.
+  statuses(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): DeploymentStatusConnection
+
+  # The deployment task.
+  task: String
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+}
+
+# The connection type for Deployment.
+type DeploymentConnection {
+  # A list of edges.
+  edges: [DeploymentEdge]
+
+  # A list of nodes.
+  nodes: [Deployment]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type DeploymentEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Deployment
+}
+
+# Represents a 'deployment_environment_changed' event on a given pull request.
+type DeploymentEnvironmentChangedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The deployment status that updated the deployment environment.
+  deploymentStatus: DeploymentStatus!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+}
+
+# The possible states in which a deployment can be.
+enum DeploymentState {
+  # The pending deployment was not updated after 30 minutes.
+  ABANDONED
+
+  # The deployment is currently active.
+  ACTIVE
+
+  # An inactive transient deployment.
+  DESTROYED
+
+  # The deployment experienced an error.
+  ERROR
+
+  # The deployment has failed.
+  FAILURE
+
+  # The deployment is inactive.
+  INACTIVE
+
+  # The deployment is pending.
+  PENDING
+}
+
+# Describes the status of a given deployment attempt.
+type DeploymentStatus implements Node {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the actor who triggered the deployment.
+  creator: Actor
+
+  # Identifies the deployment associated with status.
+  deployment: Deployment!
+
+  # Identifies the description of the deployment.
+  description: String
+
+  # Identifies the environment URL of the deployment.
+  environmentUrl: URI
+  id: ID!
+
+  # Identifies the log URL of the deployment.
+  logUrl: URI
+
+  # Identifies the current state of the deployment.
+  state: DeploymentStatusState!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+}
+
+# The connection type for DeploymentStatus.
+type DeploymentStatusConnection {
+  # A list of edges.
+  edges: [DeploymentStatusEdge]
+
+  # A list of nodes.
+  nodes: [DeploymentStatus]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type DeploymentStatusEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: DeploymentStatus
+}
+
+# The possible states for a deployment status.
+enum DeploymentStatusState {
+  # The deployment experienced an error.
+  ERROR
+
+  # The deployment has failed.
+  FAILURE
+
+  # The deployment is inactive.
+  INACTIVE
+
+  # The deployment is pending.
+  PENDING
+
+  # The deployment was successful.
+  SUCCESS
+}
+
+# Autogenerated input type of DismissPullRequestReview
+input DismissPullRequestReviewInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The contents of the pull request review dismissal message.
+  message: String!
+
+  # The Node ID of the pull request review to modify.
+  pullRequestReviewId: ID!
+}
+
+# Autogenerated return type of DismissPullRequestReview
+type DismissPullRequestReviewPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The dismissed pull request review.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReview` will change from `PullRequestReview!` to `PullRequestReview`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReview: PullRequestReview!
+}
+
+# Specifies a review comment to be left with a Pull Request Review.
+input DraftPullRequestReviewComment {
+  # Body of the comment to leave.
+  body: String!
+
+  # Path to the file being commented on.
+  path: String!
+
+  # Position in the file to leave a comment on.
+  position: Int!
+}
+
+# An external identity provisioned by SAML SSO or SCIM.
+type ExternalIdentity implements Node {
+  # The GUID for this identity
+  guid: String!
+  id: ID!
+
+  # Organization invitation for this SCIM-provisioned external identity
+  organizationInvitation: OrganizationInvitation
+
+  # SAML Identity attributes
+  samlIdentity: ExternalIdentitySamlAttributes
+
+  # SCIM Identity attributes
+  scimIdentity: ExternalIdentityScimAttributes
+
+  # User linked to this external identity. Will be NULL if this identity has not been claimed by an organization member.
+  user: User
+}
+
+# The connection type for ExternalIdentity.
+type ExternalIdentityConnection {
+  # A list of edges.
+  edges: [ExternalIdentityEdge]
+
+  # A list of nodes.
+  nodes: [ExternalIdentity]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ExternalIdentityEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ExternalIdentity
+}
+
+# SAML attributes for the External Identity
+type ExternalIdentitySamlAttributes {
+  # The NameID of the SAML identity
+  nameId: String
+}
+
+# SCIM attributes for the External Identity
+type ExternalIdentityScimAttributes {
+  # The userName of the SCIM identity
+  username: String
+}
+
+# The connection type for User.
+type FollowerConnection {
+  # A list of edges.
+  edges: [UserEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# The connection type for User.
+type FollowingConnection {
+  # A list of edges.
+  edges: [UserEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# A Gist.
+type Gist implements Node & Starrable {
+  # A list of comments associated with the gist
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): GistCommentConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The gist description.
+  description: String
+  id: ID!
+
+  # Whether the gist is public or not.
+  isPublic: Boolean!
+
+  # The gist name.
+  name: String!
+
+  # The gist owner.
+  owner: RepositoryOwner
+
+  # Identifies when the gist was last pushed to.
+  pushedAt: DateTime
+
+  # A list of users who have starred this starrable.
+  stargazers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: StarOrder
+  ): StargazerConnection!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # Returns a boolean indicating whether the viewing user has starred this starrable.
+  viewerHasStarred: Boolean!
+}
+
+# Represents a comment on an Gist.
+type GistComment implements Comment & Deletable & Node & Updatable & UpdatableComment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the gist.
+  authorAssociation: CommentAuthorAssociation!
+
+  # Identifies the comment body.
+  body: String!
+
+  # The comment body rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body rendered to text.
+  bodyText: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The actor who edited the comment.
+  editor: Actor
+
+  # The associated gist.
+  gist: Gist!
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# The connection type for GistComment.
+type GistCommentConnection {
+  # A list of edges.
+  edges: [GistCommentEdge]
+
+  # A list of nodes.
+  nodes: [GistComment]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type GistCommentEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: GistComment
+}
+
+# The connection type for Gist.
+type GistConnection {
+  # A list of edges.
+  edges: [GistEdge]
+
+  # A list of nodes.
+  nodes: [Gist]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type GistEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Gist
+}
+
+# Ordering options for gist connections
+input GistOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order repositories by.
+  field: GistOrderField!
+}
+
+# Properties by which gist connections can be ordered.
+enum GistOrderField {
+  # Order gists by creation time
+  CREATED_AT
+
+  # Order gists by push time
+  PUSHED_AT
+
+  # Order gists by update time
+  UPDATED_AT
+}
+
+# The privacy of a Gist
+enum GistPrivacy {
+  # Gists that are public and secret
+  ALL
+
+  # Public
+  PUBLIC
+
+  # Secret
+  SECRET
+}
+
+# Represents an actor in a Git commit (ie. an author or committer).
+type GitActor {
+  # A URL pointing to the author's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+
+  # The timestamp of the Git action (authoring or committing).
+  date: GitTimestamp
+
+  # The email in the Git commit.
+  email: String
+
+  # The name in the Git commit.
+  name: String
+
+  # The GitHub user corresponding to the email field. Null if no such user exists.
+  user: User
+}
+
+# Represents information about the GitHub instance.
+type GitHubMetadata {
+  # Returns a String that's a SHA of `github-services`
+  gitHubServicesSha: GitObjectID!
+
+  # IP addresses that users connect to for git operations
+  gitIpAddresses: [String!]
+
+  # IP addresses that service hooks are sent from
+  hookIpAddresses: [String!]
+
+  # IP addresses that the importer connects from
+  importerIpAddresses: [String!]
+
+  # Whether or not users are verified
+  isPasswordAuthenticationVerifiable: Boolean!
+
+  # IP addresses for GitHub Pages' A records
+  pagesIpAddresses: [String!]
+}
+
+# Represents a Git object.
+interface GitObject {
+  # An abbreviated version of the Git object ID
+  abbreviatedOid: String!
+
+  # The HTTP path for this Git object
+  commitResourcePath: URI!
+
+  # The HTTP URL for this Git object
+  commitUrl: URI!
+  id: ID!
+
+  # The Git object ID
+  oid: GitObjectID!
+
+  # The Repository the Git object belongs to
+  repository: Repository!
+}
+
+# A Git object ID.
+scalar GitObjectID
+
+# Git SSH string
+scalar GitSSHRemote
+
+# Information about a signature (GPG or S/MIME) on a Commit or Tag.
+interface GitSignature {
+  # Email used to sign this object.
+  email: String!
+
+  # True if the signature is valid and verified by GitHub.
+  isValid: Boolean!
+
+  # Payload for GPG signing object. Raw ODB object without the signature header.
+  payload: String!
+
+  # ASCII-armored signature header from object.
+  signature: String!
+
+  # GitHub user corresponding to the email signing this commit.
+  signer: User
+
+  # The state of this signature. `VALID` if signature is valid and verified by
+  # GitHub, otherwise represents reason why signature is considered invalid.
+  state: GitSignatureState!
+
+  # True if the signature was made with GitHub's signing key.
+  wasSignedByGitHub: Boolean!
+}
+
+# The state of a Git signature.
+enum GitSignatureState {
+  # The signing certificate or its chain could not be verified
+  BAD_CERT
+
+  # Invalid email used for signing
+  BAD_EMAIL
+
+  # Signing key expired
+  EXPIRED_KEY
+
+  # Internal error - the GPG verification service misbehaved
+  GPGVERIFY_ERROR
+
+  # Internal error - the GPG verification service is unavailable at the moment
+  GPGVERIFY_UNAVAILABLE
+
+  # Invalid signature
+  INVALID
+
+  # Malformed signature
+  MALFORMED_SIG
+
+  # The usage flags for the key that signed this don't allow signing
+  NOT_SIGNING_KEY
+
+  # Email used for signing not known to GitHub
+  NO_USER
+
+  # Valid siganture, though certificate revocation check failed
+  OCSP_ERROR
+
+  # Valid signature, pending certificate revocation checking
+  OCSP_PENDING
+
+  # One or more certificates in chain has been revoked
+  OCSP_REVOKED
+
+  # Key used for signing not known to GitHub
+  UNKNOWN_KEY
+
+  # Unknown signature type
+  UNKNOWN_SIG_TYPE
+
+  # Unsigned
+  UNSIGNED
+
+  # Email used for signing unverified on GitHub
+  UNVERIFIED_EMAIL
+
+  # Valid signature and verified by GitHub
+  VALID
+}
+
+# An ISO-8601 encoded date string. Unlike the DateTime type, GitTimestamp is not converted in UTC.
+scalar GitTimestamp
+
+# Represents a GPG signature on a Commit or Tag.
+type GpgSignature implements GitSignature {
+  # Email used to sign this object.
+  email: String!
+
+  # True if the signature is valid and verified by GitHub.
+  isValid: Boolean!
+
+  # Hex-encoded ID of the key that signed this object.
+  keyId: String
+
+  # Payload for GPG signing object. Raw ODB object without the signature header.
+  payload: String!
+
+  # ASCII-armored signature header from object.
+  signature: String!
+
+  # GitHub user corresponding to the email signing this commit.
+  signer: User
+
+  # The state of this signature. `VALID` if signature is valid and verified by
+  # GitHub, otherwise represents reason why signature is considered invalid.
+  state: GitSignatureState!
+
+  # True if the signature was made with GitHub's signing key.
+  wasSignedByGitHub: Boolean!
+}
+
+# A string containing HTML code.
+scalar HTML
+
+# Represents a 'head_ref_deleted' event on a given pull request.
+type HeadRefDeletedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the Ref associated with the `head_ref_deleted` event.
+  headRef: Ref
+
+  # Identifies the name of the Ref associated with the `head_ref_deleted` event.
+  headRefName: String!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+}
+
+# Represents a 'head_ref_force_pushed' event on a given pull request.
+type HeadRefForcePushedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the after commit SHA for the 'head_ref_force_pushed' event.
+  afterCommit: Commit
+
+  # Identifies the before commit SHA for the 'head_ref_force_pushed' event.
+  beforeCommit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # Identifies the fully qualified ref name for the 'head_ref_force_pushed' event.
+  ref: Ref
+}
+
+# Represents a 'head_ref_restored' event on a given pull request.
+type HeadRefRestoredEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+}
+
+# An Issue is a place to discuss ideas, enhancements, tasks, and bugs for a project.
+type Issue implements Assignable & Closable & Comment & Labelable & Lockable & Node & Reactable & RepositoryNode & Subscribable & UniformResourceLocatable & Updatable & UpdatableComment {
+  # Reason that the conversation was locked.
+  activeLockReason: LockReason
+
+  # A list of Users assigned to this object.
+  assignees(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # Identifies the body of the issue.
+  body: String!
+
+  # Identifies the body of the issue rendered to HTML.
+  bodyHTML: HTML!
+
+  # Identifies the body of the issue rendered to text.
+  bodyText: String!
+
+  # `true` if the object is closed (definition of closed may depend on type)
+  closed: Boolean!
+
+  # Identifies the date and time when the object was closed.
+  closedAt: DateTime
+
+  # A list of comments associated with the Issue.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): IssueCommentConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # A list of labels associated with the object.
+  labels(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): LabelConnection
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # `true` if the object is locked
+  locked: Boolean!
+
+  # Identifies the milestone associated with the issue.
+  milestone: Milestone
+
+  # Identifies the issue number.
+  number: Int!
+
+  # A list of Users that are participating in the Issue conversation.
+  participants(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # List of project cards associated with this issue.
+  projectCards(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # A list of archived states to filter the cards by
+    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProjectCardConnection!
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path for this issue
+  resourcePath: URI!
+
+  # Identifies the state of the issue.
+  state: IssueState!
+
+  # A list of events, comments, commits, etc. associated with the issue.
+  timeline(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows filtering timeline events by a `since` timestamp.
+    since: DateTime
+  ): IssueTimelineConnection!
+
+  # Identifies the issue title.
+  title: String!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this issue
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+}
+
+# Represents a comment on an Issue.
+type IssueComment implements Comment & Deletable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # The body as Markdown.
+  body: String!
+
+  # The body rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body rendered to text.
+  bodyText: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # Identifies the issue associated with the comment.
+  issue: Issue!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # Returns the pull request associated with the comment, if this comment was made on a
+  # pull request.
+  pullRequest: PullRequest
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path for this issue comment
+  resourcePath: URI!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this issue comment
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# The connection type for IssueComment.
+type IssueCommentConnection {
+  # A list of edges.
+  edges: [IssueCommentEdge]
+
+  # A list of nodes.
+  nodes: [IssueComment]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type IssueCommentEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: IssueComment
+}
+
+# The connection type for Issue.
+type IssueConnection {
+  # A list of edges.
+  edges: [IssueEdge]
+
+  # A list of nodes.
+  nodes: [Issue]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type IssueEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Issue
+}
+
+# Used for return value of Repository.issueOrPullRequest.
+union IssueOrPullRequest = Issue | PullRequest
+
+# Ways in which lists of issues can be ordered upon return.
+input IssueOrder {
+  # The direction in which to order issues by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order issues by.
+  field: IssueOrderField!
+}
+
+# Properties by which issue connections can be ordered.
+enum IssueOrderField {
+  # Order issues by comment count
+  COMMENTS
+
+  # Order issues by creation time
+  CREATED_AT
+
+  # Order issues by update time
+  UPDATED_AT
+}
+
+# The possible PubSub channels for an issue.
+enum IssuePubSubTopic {
+  # The channel ID for marking an issue as read.
+  MARKASREAD
+
+  # The channel ID for updating items on the issue timeline.
+  TIMELINE
+
+  # The channel ID for observing issue updates.
+  UPDATED
+}
+
+# The possible states of an issue.
+enum IssueState {
+  # An issue that has been closed
+  CLOSED
+
+  # An issue that is still open
+  OPEN
+}
+
+# The connection type for IssueTimelineItem.
+type IssueTimelineConnection {
+  # A list of edges.
+  edges: [IssueTimelineItemEdge]
+
+  # A list of nodes.
+  nodes: [IssueTimelineItem]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An item in an issue timeline
+union IssueTimelineItem = AssignedEvent | ClosedEvent | Commit | CrossReferencedEvent | DemilestonedEvent | IssueComment | LabeledEvent | LockedEvent | MilestonedEvent | ReferencedEvent | RenamedTitleEvent | ReopenedEvent | SubscribedEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent
+
+# An edge in a connection.
+type IssueTimelineItemEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: IssueTimelineItem
+}
+
+# An item in an issue timeline
+union IssueTimelineItems = AddedToProjectEvent | AssignedEvent | ClosedEvent | CommentDeletedEvent | ConvertedNoteToIssueEvent | CrossReferencedEvent | DemilestonedEvent | IssueComment | LabeledEvent | LockedEvent | MentionedEvent | MilestonedEvent | MovedColumnsInProjectEvent | ReferencedEvent | RemovedFromProjectEvent | RenamedTitleEvent | ReopenedEvent | SubscribedEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent
+
+# An edge in a connection.
+type IssueTimelineItemsEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: IssueTimelineItems
+}
+
+# The possible item types found in a timeline.
+enum IssueTimelineItemsItemType {
+  # Represents a 'added_to_project' event on a given issue or pull request.
+  ADDED_TO_PROJECT_EVENT
+
+  # Represents an 'assigned' event on any assignable object.
+  ASSIGNED_EVENT
+
+  # Represents a 'closed' event on any `Closable`.
+  CLOSED_EVENT
+
+  # Represents a 'comment_deleted' event on a given issue or pull request.
+  COMMENT_DELETED_EVENT
+
+  # Represents a 'converted_note_to_issue' event on a given issue or pull request.
+  CONVERTED_NOTE_TO_ISSUE_EVENT
+
+  # Represents a mention made by one issue or pull request to another.
+  CROSS_REFERENCED_EVENT
+
+  # Represents a 'demilestoned' event on a given issue or pull request.
+  DEMILESTONED_EVENT
+
+  # Represents a comment on an Issue.
+  ISSUE_COMMENT
+
+  # Represents a 'labeled' event on a given issue or pull request.
+  LABELED_EVENT
+
+  # Represents a 'locked' event on a given issue or pull request.
+  LOCKED_EVENT
+
+  # Represents a 'mentioned' event on a given issue or pull request.
+  MENTIONED_EVENT
+
+  # Represents a 'milestoned' event on a given issue or pull request.
+  MILESTONED_EVENT
+
+  # Represents a 'moved_columns_in_project' event on a given issue or pull request.
+  MOVED_COLUMNS_IN_PROJECT_EVENT
+
+  # Represents a 'referenced' event on a given `ReferencedSubject`.
+  REFERENCED_EVENT
+
+  # Represents a 'removed_from_project' event on a given issue or pull request.
+  REMOVED_FROM_PROJECT_EVENT
+
+  # Represents a 'renamed' event on a given issue or pull request
+  RENAMED_TITLE_EVENT
+
+  # Represents a 'reopened' event on any `Closable`.
+  REOPENED_EVENT
+
+  # Represents a 'subscribed' event on a given `Subscribable`.
+  SUBSCRIBED_EVENT
+
+  # Represents an 'unassigned' event on any assignable object.
+  UNASSIGNED_EVENT
+
+  # Represents an 'unlabeled' event on a given issue or pull request.
+  UNLABELED_EVENT
+
+  # Represents an 'unlocked' event on a given issue or pull request.
+  UNLOCKED_EVENT
+
+  # Represents an 'unsubscribed' event on a given `Subscribable`.
+  UNSUBSCRIBED_EVENT
+}
+
+# A label for categorizing Issues or Milestones with a given Repository.
+type Label implements Node {
+  # Identifies the label color.
+  color: String!
+
+  # Identifies the date and time when the label was created.
+  createdAt: DateTime
+
+  # A brief description of this label.
+  description: String
+  id: ID!
+
+  # Indicates whether or not this is a default label.
+  isDefault: Boolean!
+
+  # A list of issues associated with this label.
+  issues(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for issues returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the issues by.
+    states: [IssueState!]
+  ): IssueConnection!
+
+  # Identifies the label name.
+  name: String!
+
+  # A list of pull requests associated with this label.
+  pullRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # The base ref name to filter the pull requests by.
+    baseRefName: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # The head ref name to filter the pull requests by.
+    headRefName: String
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for pull requests returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the pull requests by.
+    states: [PullRequestState!]
+  ): PullRequestConnection!
+
+  # The repository associated with this label.
+  repository: Repository!
+
+  # The HTTP path for this label.
+  resourcePath: URI!
+
+  # Identifies the date and time when the label was last updated.
+  updatedAt: DateTime
+
+  # The HTTP URL for this label.
+  url: URI!
+}
+
+# The connection type for Label.
+type LabelConnection {
+  # A list of edges.
+  edges: [LabelEdge]
+
+  # A list of nodes.
+  nodes: [Label]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type LabelEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Label
+}
+
+# An object that can have labels assigned to it.
+interface Labelable {
+  # A list of labels associated with the object.
+  labels(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): LabelConnection
+}
+
+# Represents a 'labeled' event on a given issue or pull request.
+type LabeledEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the label associated with the 'labeled' event.
+  label: Label!
+
+  # Identifies the `Labelable` associated with the event.
+  labelable: Labelable!
+}
+
+# Represents a given language found in repositories.
+type Language implements Node {
+  # The color defined for the current language.
+  color: String
+  id: ID!
+
+  # The name of the current language.
+  name: String!
+}
+
+# A list of languages associated with the parent.
+type LanguageConnection {
+  # A list of edges.
+  edges: [LanguageEdge]
+
+  # A list of nodes.
+  nodes: [Language]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+
+  # The total size in bytes of files written in that language.
+  totalSize: Int!
+}
+
+# Represents the language of a repository.
+type LanguageEdge {
+  cursor: String!
+  node: Language!
+
+  # The number of bytes of code written in the language.
+  size: Int!
+}
+
+# Ordering options for language connections.
+input LanguageOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order languages by.
+  field: LanguageOrderField!
+}
+
+# Properties by which language connections can be ordered.
+enum LanguageOrderField {
+  # Order languages by the size of all files containing the language
+  SIZE
+}
+
+# A repository's open source license
+type License implements Node {
+  # The full text of the license
+  body: String!
+
+  # The conditions set by the license
+  conditions: [LicenseRule]!
+
+  # A human-readable description of the license
+  description: String
+
+  # Whether the license should be featured
+  featured: Boolean!
+
+  # Whether the license should be displayed in license pickers
+  hidden: Boolean!
+  id: ID!
+
+  # Instructions on how to implement the license
+  implementation: String
+
+  # The lowercased SPDX ID of the license
+  key: String!
+
+  # The limitations set by the license
+  limitations: [LicenseRule]!
+
+  # The license full name specified by <https://spdx.org/licenses>
+  name: String!
+
+  # Customary short name if applicable (e.g, GPLv3)
+  nickname: String
+
+  # The permissions set by the license
+  permissions: [LicenseRule]!
+
+  # Whether the license is a pseudo-license placeholder (e.g., other, no-license)
+  pseudoLicense: Boolean!
+
+  # Short identifier specified by <https://spdx.org/licenses>
+  spdxId: String
+
+  # URL to the license on <https://choosealicense.com>
+  url: URI
+}
+
+# Describes a License's conditions, permissions, and limitations
+type LicenseRule {
+  # A description of the rule
+  description: String!
+
+  # The machine-readable rule key
+  key: String!
+
+  # The human-readable rule label
+  label: String!
+}
+
+# Autogenerated input type of LockLockable
+input LockLockableInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # A reason for why the issue or pull request will be locked.
+  lockReason: LockReason
+
+  # ID of the issue or pull request to be locked.
+  lockableId: ID!
+}
+
+# Autogenerated return type of LockLockable
+type LockLockablePayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The item that was locked.
+  lockedRecord: Lockable
+}
+
+# The possible reasons that an issue or pull request was locked.
+enum LockReason {
+  # The issue or pull request was locked because the conversation was off-topic.
+  OFF_TOPIC
+
+  # The issue or pull request was locked because the conversation was resolved.
+  RESOLVED
+
+  # The issue or pull request was locked because the conversation was spam.
+  SPAM
+
+  # The issue or pull request was locked because the conversation was too heated.
+  TOO_HEATED
+}
+
+# An object that can be locked.
+interface Lockable {
+  # Reason that the conversation was locked.
+  activeLockReason: LockReason
+
+  # `true` if the object is locked
+  locked: Boolean!
+}
+
+# Represents a 'locked' event on a given issue or pull request.
+type LockedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Reason that the conversation was locked (optional).
+  lockReason: LockReason
+
+  # Object that was locked.
+  lockable: Lockable!
+}
+
+# A public description of a Marketplace category.
+type MarketplaceCategory implements Node {
+  # The category's description.
+  description: String
+
+  # The technical description of how apps listed in this category work with GitHub.
+  howItWorks: String
+  id: ID!
+
+  # The category's name.
+  name: String!
+
+  # How many Marketplace listings have this as their primary category.
+  primaryListingCount: Int!
+
+  # The HTTP path for this Marketplace category.
+  resourcePath: URI!
+
+  # How many Marketplace listings have this as their secondary category.
+  secondaryListingCount: Int!
+
+  # The short name of the category used in its URL.
+  slug: String!
+
+  # The HTTP URL for this Marketplace category.
+  url: URI!
+}
+
+# A listing in the GitHub integration marketplace.
+type MarketplaceListing implements Node {
+  # The GitHub App this listing represents.
+  app: App
+
+  # URL to the listing owner's company site.
+  companyUrl: URI
+
+  # The HTTP path for configuring access to the listing's integration or OAuth app
+  configurationResourcePath: URI!
+
+  # The HTTP URL for configuring access to the listing's integration or OAuth app
+  configurationUrl: URI!
+
+  # URL to the listing's documentation.
+  documentationUrl: URI
+
+  # The listing's detailed description.
+  extendedDescription: String
+
+  # The listing's detailed description rendered to HTML.
+  extendedDescriptionHTML: HTML!
+
+  # The listing's introductory description.
+  fullDescription: String!
+
+  # The listing's introductory description rendered to HTML.
+  fullDescriptionHTML: HTML!
+
+  # Whether this listing has been submitted for review from GitHub for approval to be displayed in the Marketplace.
+  hasApprovalBeenRequested: Boolean!
+
+  # Does this listing have any plans with a free trial?
+  hasPublishedFreeTrialPlans: Boolean!
+
+  # Does this listing have a terms of service link?
+  hasTermsOfService: Boolean!
+
+  # A technical description of how this app works with GitHub.
+  howItWorks: String
+
+  # The listing's technical description rendered to HTML.
+  howItWorksHTML: HTML!
+  id: ID!
+
+  # URL to install the product to the viewer's account or organization.
+  installationUrl: URI
+
+  # Whether this listing's app has been installed for the current viewer
+  installedForViewer: Boolean!
+
+  # Whether this listing has been approved for display in the Marketplace.
+  isApproved: Boolean!
+
+  # Whether this listing has been removed from the Marketplace.
+  isDelisted: Boolean!
+
+  # Whether this listing is still an editable draft that has not been submitted
+  # for review and is not publicly visible in the Marketplace.
+  isDraft: Boolean!
+
+  # Whether the product this listing represents is available as part of a paid plan.
+  isPaid: Boolean!
+
+  # Whether this listing has been rejected by GitHub for display in the Marketplace.
+  isRejected: Boolean!
+
+  # The hex color code, without the leading '#', for the logo background.
+  logoBackgroundColor: String!
+
+  # URL for the listing's logo image.
+  logoUrl(
+    # The size in pixels of the resulting square image.
+    size: Int = 400
+  ): URI
+
+  # The listing's full name.
+  name: String!
+
+  # The listing's very short description without a trailing period or ampersands.
+  normalizedShortDescription: String!
+
+  # URL to the listing's detailed pricing.
+  pricingUrl: URI
+
+  # The category that best describes the listing.
+  primaryCategory: MarketplaceCategory!
+
+  # URL to the listing's privacy policy.
+  privacyPolicyUrl: URI!
+
+  # The HTTP path for the Marketplace listing.
+  resourcePath: URI!
+
+  # The URLs for the listing's screenshots.
+  screenshotUrls: [String]!
+
+  # An alternate category that describes the listing.
+  secondaryCategory: MarketplaceCategory
+
+  # The listing's very short description.
+  shortDescription: String!
+
+  # The short name of the listing used in its URL.
+  slug: String!
+
+  # URL to the listing's status page.
+  statusUrl: URI
+
+  # An email address for support for this listing's app.
+  supportEmail: String
+
+  # Either a URL or an email address for support for this listing's app.
+  supportUrl: URI!
+
+  # URL to the listing's terms of service.
+  termsOfServiceUrl: URI
+
+  # The HTTP URL for the Marketplace listing.
+  url: URI!
+
+  # Can the current viewer add plans for this Marketplace listing.
+  viewerCanAddPlans: Boolean!
+
+  # Can the current viewer approve this Marketplace listing.
+  viewerCanApprove: Boolean!
+
+  # Can the current viewer delist this Marketplace listing.
+  viewerCanDelist: Boolean!
+
+  # Can the current viewer edit this Marketplace listing.
+  viewerCanEdit: Boolean!
+
+  # Can the current viewer edit the primary and secondary category of this
+  # Marketplace listing.
+  viewerCanEditCategories: Boolean!
+
+  # Can the current viewer edit the plans for this Marketplace listing.
+  viewerCanEditPlans: Boolean!
+
+  # Can the current viewer return this Marketplace listing to draft state
+  # so it becomes editable again.
+  viewerCanRedraft: Boolean!
+
+  # Can the current viewer reject this Marketplace listing by returning it to
+  # an editable draft state or rejecting it entirely.
+  viewerCanReject: Boolean!
+
+  # Can the current viewer request this listing be reviewed for display in
+  # the Marketplace.
+  viewerCanRequestApproval: Boolean!
+
+  # Indicates whether the current user has an active subscription to this Marketplace listing.
+  viewerHasPurchased: Boolean!
+
+  # Indicates if the current user has purchased a subscription to this Marketplace listing
+  # for all of the organizations the user owns.
+  viewerHasPurchasedForAllOrganizations: Boolean!
+
+  # Does the current viewer role allow them to administer this Marketplace listing.
+  viewerIsListingAdmin: Boolean!
+}
+
+# Look up Marketplace Listings
+type MarketplaceListingConnection {
+  # A list of edges.
+  edges: [MarketplaceListingEdge]
+
+  # A list of nodes.
+  nodes: [MarketplaceListing]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type MarketplaceListingEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: MarketplaceListing
+}
+
+# Represents a 'mentioned' event on a given issue or pull request.
+type MentionedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# Whether or not a PullRequest can be merged.
+enum MergeableState {
+  # The pull request cannot be merged due to merge conflicts.
+  CONFLICTING
+
+  # The pull request can be merged.
+  MERGEABLE
+
+  # The mergeability of the pull request is still being calculated.
+  UNKNOWN
+}
+
+# Represents a 'merged' event on a given pull request.
+type MergedEvent implements Node & UniformResourceLocatable {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the commit associated with the `merge` event.
+  commit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the Ref associated with the `merge` event.
+  mergeRef: Ref
+
+  # Identifies the name of the Ref associated with the `merge` event.
+  mergeRefName: String!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # The HTTP path for this merged event.
+  resourcePath: URI!
+
+  # The HTTP URL for this merged event.
+  url: URI!
+}
+
+# Represents a Milestone object on a given repository.
+type Milestone implements Closable & Node & UniformResourceLocatable {
+  # `true` if the object is closed (definition of closed may depend on type)
+  closed: Boolean!
+
+  # Identifies the date and time when the object was closed.
+  closedAt: DateTime
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the actor who created the milestone.
+  creator: Actor
+
+  # Identifies the description of the milestone.
+  description: String
+
+  # Identifies the due date of the milestone.
+  dueOn: DateTime
+  id: ID!
+
+  # A list of issues associated with the milestone.
+  issues(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for issues returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the issues by.
+    states: [IssueState!]
+  ): IssueConnection!
+
+  # Identifies the number of the milestone.
+  number: Int!
+
+  # A list of pull requests associated with the milestone.
+  pullRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # The base ref name to filter the pull requests by.
+    baseRefName: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # The head ref name to filter the pull requests by.
+    headRefName: String
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for pull requests returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the pull requests by.
+    states: [PullRequestState!]
+  ): PullRequestConnection!
+
+  # The repository associated with this milestone.
+  repository: Repository!
+
+  # The HTTP path for this milestone
+  resourcePath: URI!
+
+  # Identifies the state of the milestone.
+  state: MilestoneState!
+
+  # Identifies the title of the milestone.
+  title: String!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this milestone
+  url: URI!
+}
+
+# The connection type for Milestone.
+type MilestoneConnection {
+  # A list of edges.
+  edges: [MilestoneEdge]
+
+  # A list of nodes.
+  nodes: [Milestone]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type MilestoneEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Milestone
+}
+
+# Types that can be inside a Milestone.
+union MilestoneItem = Issue | PullRequest
+
+# Ordering options for milestone connections.
+input MilestoneOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order milestones by.
+  field: MilestoneOrderField!
+}
+
+# Properties by which milestone connections can be ordered.
+enum MilestoneOrderField {
+  # Order milestones by when they were created.
+  CREATED_AT
+
+  # Order milestones by when they are due.
+  DUE_DATE
+
+  # Order milestones by their number.
+  NUMBER
+
+  # Order milestones by when they were last updated.
+  UPDATED_AT
+}
+
+# The possible states of a milestone.
+enum MilestoneState {
+  # A milestone that has been closed.
+  CLOSED
+
+  # A milestone that is still open.
+  OPEN
+}
+
+# Represents a 'milestoned' event on a given issue or pull request.
+type MilestonedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the milestone title associated with the 'milestoned' event.
+  milestoneTitle: String!
+
+  # Object referenced by event.
+  subject: MilestoneItem!
+}
+
+# Autogenerated input type of MoveProjectCard
+input MoveProjectCardInput {
+  # Place the new card after the card with this id. Pass null to place it at the top.
+  afterCardId: ID
+
+  # The id of the card to move.
+  cardId: ID!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The id of the column to move it into.
+  columnId: ID!
+}
+
+# Autogenerated return type of MoveProjectCard
+type MoveProjectCardPayload {
+  # The new edge of the moved card.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `cardEdge` will change from `ProjectCardEdge!` to `ProjectCardEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  cardEdge: ProjectCardEdge!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+}
+
+# Autogenerated input type of MoveProjectColumn
+input MoveProjectColumnInput {
+  # Place the new column after the column with this id. Pass null to place it at the front.
+  afterColumnId: ID
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The id of the column to move.
+  columnId: ID!
+}
+
+# Autogenerated return type of MoveProjectColumn
+type MoveProjectColumnPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The new edge of the moved column.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `columnEdge` will change from `ProjectColumnEdge!` to `ProjectColumnEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  columnEdge: ProjectColumnEdge!
+}
+
+# Represents a 'moved_columns_in_project' event on a given issue or pull request.
+type MovedColumnsInProjectEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# The root query for implementing GraphQL mutations.
+type Mutation {
+  # Applies a suggested topic to the repository.
+  acceptTopicSuggestion(input: AcceptTopicSuggestionInput!): AcceptTopicSuggestionPayload
+
+  # Adds a comment to an Issue or Pull Request.
+  addComment(input: AddCommentInput!): AddCommentPayload
+
+  # Adds a card to a ProjectColumn. Either `contentId` or `note` must be provided but **not** both.
+  addProjectCard(input: AddProjectCardInput!): AddProjectCardPayload
+
+  # Adds a column to a Project.
+  addProjectColumn(input: AddProjectColumnInput!): AddProjectColumnPayload
+
+  # Adds a review to a Pull Request.
+  addPullRequestReview(input: AddPullRequestReviewInput!): AddPullRequestReviewPayload
+
+  # Adds a comment to a review.
+  addPullRequestReviewComment(input: AddPullRequestReviewCommentInput!): AddPullRequestReviewCommentPayload
+
+  # Adds a reaction to a subject.
+  addReaction(input: AddReactionInput!): AddReactionPayload
+
+  # Adds a star to a Starrable.
+  addStar(input: AddStarInput!): AddStarPayload
+
+  # Creates a new project.
+  createProject(input: CreateProjectInput!): CreateProjectPayload
+
+  # Rejects a suggested topic for the repository.
+  declineTopicSuggestion(input: DeclineTopicSuggestionInput!): DeclineTopicSuggestionPayload
+
+  # Deletes a project.
+  deleteProject(input: DeleteProjectInput!): DeleteProjectPayload
+
+  # Deletes a project card.
+  deleteProjectCard(input: DeleteProjectCardInput!): DeleteProjectCardPayload
+
+  # Deletes a project column.
+  deleteProjectColumn(input: DeleteProjectColumnInput!): DeleteProjectColumnPayload
+
+  # Deletes a pull request review.
+  deletePullRequestReview(input: DeletePullRequestReviewInput!): DeletePullRequestReviewPayload
+
+  # Dismisses an approved or rejected pull request review.
+  dismissPullRequestReview(input: DismissPullRequestReviewInput!): DismissPullRequestReviewPayload
+
+  # Lock a lockable object
+  lockLockable(input: LockLockableInput!): LockLockablePayload
+
+  # Moves a project card to another place.
+  moveProjectCard(input: MoveProjectCardInput!): MoveProjectCardPayload
+
+  # Moves a project column to another place.
+  moveProjectColumn(input: MoveProjectColumnInput!): MoveProjectColumnPayload
+
+  # Removes outside collaborator from all repositories in an organization.
+  removeOutsideCollaborator(input: RemoveOutsideCollaboratorInput!): RemoveOutsideCollaboratorPayload
+
+  # Removes a reaction from a subject.
+  removeReaction(input: RemoveReactionInput!): RemoveReactionPayload
+
+  # Removes a star from a Starrable.
+  removeStar(input: RemoveStarInput!): RemoveStarPayload
+
+  # Set review requests on a pull request.
+  requestReviews(input: RequestReviewsInput!): RequestReviewsPayload
+
+  # Submits a pending pull request review.
+  submitPullRequestReview(input: SubmitPullRequestReviewInput!): SubmitPullRequestReviewPayload
+
+  # Unlock a lockable object
+  unlockLockable(input: UnlockLockableInput!): UnlockLockablePayload
+
+  # Updates an existing project.
+  updateProject(input: UpdateProjectInput!): UpdateProjectPayload
+
+  # Updates an existing project card.
+  updateProjectCard(input: UpdateProjectCardInput!): UpdateProjectCardPayload
+
+  # Updates an existing project column.
+  updateProjectColumn(input: UpdateProjectColumnInput!): UpdateProjectColumnPayload
+
+  # Updates the body of a pull request review.
+  updatePullRequestReview(input: UpdatePullRequestReviewInput!): UpdatePullRequestReviewPayload
+
+  # Updates a pull request review comment.
+  updatePullRequestReviewComment(input: UpdatePullRequestReviewCommentInput!): UpdatePullRequestReviewCommentPayload
+
+  # Updates the state for subscribable subjects.
+  updateSubscription(input: UpdateSubscriptionInput!): UpdateSubscriptionPayload
+
+  # Replaces the repository's topics with the given topics.
+  updateTopics(input: UpdateTopicsInput!): UpdateTopicsPayload
+}
+
+# An object with an ID.
+interface Node {
+  # ID of the object.
+  id: ID!
+}
+
+# Possible directions in which to order a list of items when provided an `orderBy` argument.
+enum OrderDirection {
+  # Specifies an ascending order for a given `orderBy` argument.
+  ASC
+
+  # Specifies a descending order for a given `orderBy` argument.
+  DESC
+}
+
+# An account on GitHub, with one or more owners, that has repositories, members and teams.
+type Organization implements Actor & Node & ProjectOwner & RegistryPackageOwner & RegistryPackageSearch & RepositoryOwner & UniformResourceLocatable {
+  # A URL pointing to the organization's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The organization's public profile description.
+  description: String
+
+  # The organization's public email.
+  email: String
+  id: ID!
+
+  # Whether the organization has verified its profile email and website.
+  isVerified: Boolean!
+
+  # The organization's public profile location.
+  location: String
+
+  # The organization's login name.
+  login: String!
+
+  # A list of users who are members of this organization.
+  members(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # The organization's public profile name.
+  name: String
+
+  # The HTTP path creating a new team
+  newTeamResourcePath: URI!
+
+  # The HTTP URL creating a new team
+  newTeamUrl: URI!
+
+  # The billing email for the organization.
+  organizationBillingEmail: String
+
+  # A list of repositories this user has pinned to their profile
+  pinnedRepositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # Find project by number.
+  project(
+    # The project number to find.
+    number: Int!
+  ): Project
+
+  # A list of projects under the owner.
+  projects(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for projects returned from the connection
+    orderBy: ProjectOrder
+
+    # Query to search projects by, currently only searching by name.
+    search: String
+
+    # A list of states to filter the projects by.
+    states: [ProjectState!]
+  ): ProjectConnection!
+
+  # The HTTP path listing organization's projects
+  projectsResourcePath: URI!
+
+  # The HTTP URL listing organization's projects
+  projectsUrl: URI!
+
+  # A list of repositories that the user owns.
+  repositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they are forks of another repository
+    isFork: Boolean
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # Find Repository.
+  repository(
+    # Name of Repository to find.
+    name: String!
+  ): Repository
+
+  # When true the organization requires all members, billing managers, and outside
+  # collaborators to enable two-factor authentication.
+  requiresTwoFactorAuthentication: Boolean
+
+  # The HTTP path for this organization.
+  resourcePath: URI!
+
+  # The Organization's SAML Identity Providers
+  samlIdentityProvider: OrganizationIdentityProvider
+
+  # Find an organization's team by its slug.
+  team(
+    # The name or slug of the team to find.
+    slug: String!
+  ): Team
+
+  # A list of teams in this organization.
+  teams(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # If true, filters teams that are mapped to an LDAP Group (Enterprise only)
+    ldapMapped: Boolean
+
+    # Ordering options for teams returned from the connection
+    orderBy: TeamOrder
+
+    # If non-null, filters teams according to privacy
+    privacy: TeamPrivacy
+
+    # If non-null, filters teams with query on team name and team slug
+    query: String
+
+    # If non-null, filters teams according to whether the viewer is an admin or member on team
+    role: TeamRole
+
+    # If true, restrict to only root teams
+    rootTeamsOnly: Boolean = false
+
+    # User logins to filter by
+    userLogins: [String!]
+  ): TeamConnection!
+
+  # The HTTP path listing organization's teams
+  teamsResourcePath: URI!
+
+  # The HTTP URL listing organization's teams
+  teamsUrl: URI!
+
+  # The HTTP URL for this organization.
+  url: URI!
+
+  # Organization is adminable by the viewer.
+  viewerCanAdminister: Boolean!
+
+  # Can the current viewer create new projects on this owner.
+  viewerCanCreateProjects: Boolean!
+
+  # Viewer can create repositories on this organization
+  viewerCanCreateRepositories: Boolean!
+
+  # Viewer can create teams on this organization.
+  viewerCanCreateTeams: Boolean!
+
+  # Viewer is an active member of this organization.
+  viewerIsAMember: Boolean!
+
+  # The organization's public profile URL.
+  websiteUrl: URI
+}
+
+# The connection type for Organization.
+type OrganizationConnection {
+  # A list of edges.
+  edges: [OrganizationEdge]
+
+  # A list of nodes.
+  nodes: [Organization]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type OrganizationEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Organization
+}
+
+# An Identity Provider configured to provision SAML and SCIM identities for Organizations
+type OrganizationIdentityProvider implements Node {
+  # The digest algorithm used to sign SAML requests for the Identity Provider.
+  digestMethod: URI
+
+  # External Identities provisioned by this Identity Provider
+  externalIdentities(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ExternalIdentityConnection!
+  id: ID!
+
+  # The x509 certificate used by the Identity Provder to sign assertions and responses.
+  idpCertificate: X509Certificate
+
+  # The Issuer Entity ID for the SAML Identity Provider
+  issuer: String
+
+  # Organization this Identity Provider belongs to
+  organization: Organization
+
+  # The signature algorithm used to sign SAML requests for the Identity Provider.
+  signatureMethod: URI
+
+  # The URL endpoint for the Identity Provider's SAML SSO.
+  ssoUrl: URI
+}
+
+# An Invitation for a user to an organization.
+type OrganizationInvitation implements Node {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The email address of the user invited to the organization.
+  email: String
+  id: ID!
+
+  # The type of invitation that was sent (e.g. email, user).
+  invitationType: OrganizationInvitationType!
+
+  # The user who was invited to the organization.
+  invitee: User
+
+  # The user who created the invitation.
+  inviter: User!
+
+  # The organization the invite is for
+  organization: Organization!
+
+  # The user's pending role in the organization (e.g. member, owner).
+  role: OrganizationInvitationRole!
+}
+
+# The connection type for OrganizationInvitation.
+type OrganizationInvitationConnection {
+  # A list of edges.
+  edges: [OrganizationInvitationEdge]
+
+  # A list of nodes.
+  nodes: [OrganizationInvitation]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type OrganizationInvitationEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: OrganizationInvitation
+}
+
+# The possible organization invitation roles.
+enum OrganizationInvitationRole {
+  # The user is invited to be an admin of the organization.
+  ADMIN
+
+  # The user is invited to be a billing manager of the organization.
+  BILLING_MANAGER
+
+  # The user is invited to be a direct member of the organization.
+  DIRECT_MEMBER
+
+  # The user's previous role will be reinstated.
+  REINSTATE
+}
+
+# The possible organization invitation types.
+enum OrganizationInvitationType {
+  # The invitation was to an email address.
+  EMAIL
+
+  # The invitation was to an existing user.
+  USER
+}
+
+# Information about pagination in a connection.
+type PageInfo {
+  # When paginating forwards, the cursor to continue.
+  endCursor: String
+
+  # When paginating forwards, are there more items?
+  hasNextPage: Boolean!
+
+  # When paginating backwards, are there more items?
+  hasPreviousPage: Boolean!
+
+  # When paginating backwards, the cursor to continue.
+  startCursor: String
+}
+
+# Projects manage issues, pull requests and notes within a project owner.
+type Project implements Closable & Node & Updatable {
+  # The project's description body.
+  body: String
+
+  # The projects description body rendered to HTML.
+  bodyHTML: HTML!
+
+  # `true` if the object is closed (definition of closed may depend on type)
+  closed: Boolean!
+
+  # Identifies the date and time when the object was closed.
+  closedAt: DateTime
+
+  # List of columns in the project
+  columns(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProjectColumnConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The actor who originally created the project.
+  creator: Actor
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # The project's name.
+  name: String!
+
+  # The project's number.
+  number: Int!
+
+  # The project's owner. Currently limited to repositories and organizations.
+  owner: ProjectOwner!
+
+  # List of pending cards in this project
+  pendingCards(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # A list of archived states to filter the cards by
+    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProjectCardConnection!
+
+  # The HTTP path for this project
+  resourcePath: URI!
+
+  # Whether the project is open or closed.
+  state: ProjectState!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this project
+  url: URI!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+}
+
+# A card in a project.
+type ProjectCard implements Node {
+  # The project column this card is associated under. A card may only belong to one
+  # project column at a time. The column field will be null if the card is created
+  # in a pending state and has yet to be associated with a column. Once cards are
+  # associated with a column, they will not become pending in the future.
+  column: ProjectColumn
+
+  # The card content item
+  content: ProjectCardItem
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The actor who created this card
+  creator: Actor
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # Whether the card is archived
+  isArchived: Boolean!
+
+  # The card note
+  note: String
+
+  # The project that contains this card.
+  project: Project!
+
+  # The HTTP path for this card
+  resourcePath: URI!
+
+  # The state of ProjectCard
+  state: ProjectCardState
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this card
+  url: URI!
+}
+
+# The possible archived states of a project card.
+enum ProjectCardArchivedState {
+  # A project card that is archived
+  ARCHIVED
+
+  # A project card that is not archived
+  NOT_ARCHIVED
+}
+
+# The connection type for ProjectCard.
+type ProjectCardConnection {
+  # A list of edges.
+  edges: [ProjectCardEdge]
+
+  # A list of nodes.
+  nodes: [ProjectCard]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ProjectCardEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ProjectCard
+}
+
+# Types that can be inside Project Cards.
+union ProjectCardItem = Issue | PullRequest
+
+# Various content states of a ProjectCard
+enum ProjectCardState {
+  # The card has content only.
+  CONTENT_ONLY
+
+  # The card has a note only.
+  NOTE_ONLY
+
+  # The card is redacted.
+  REDACTED
+}
+
+# A column inside a project.
+type ProjectColumn implements Node {
+  # List of cards in the column
+  cards(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # A list of archived states to filter the cards by
+    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProjectCardConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # The project column's name.
+  name: String!
+
+  # The project that contains this column.
+  project: Project!
+
+  # The semantic purpose of the column
+  purpose: ProjectColumnPurpose
+
+  # The HTTP path for this project column
+  resourcePath: URI!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this project column
+  url: URI!
+}
+
+# The connection type for ProjectColumn.
+type ProjectColumnConnection {
+  # A list of edges.
+  edges: [ProjectColumnEdge]
+
+  # A list of nodes.
+  nodes: [ProjectColumn]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ProjectColumnEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ProjectColumn
+}
+
+# The semantic purpose of the column - todo, in progress, or done.
+enum ProjectColumnPurpose {
+  # The column contains cards which are complete
+  DONE
+
+  # The column contains cards which are currently being worked on
+  IN_PROGRESS
+
+  # The column contains cards still to be worked on
+  TODO
+}
+
+# A list of projects associated with the owner.
+type ProjectConnection {
+  # A list of edges.
+  edges: [ProjectEdge]
+
+  # A list of nodes.
+  nodes: [Project]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ProjectEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Project
+}
+
+# Ways in which lists of projects can be ordered upon return.
+input ProjectOrder {
+  # The direction in which to order projects by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order projects by.
+  field: ProjectOrderField!
+}
+
+# Properties by which project connections can be ordered.
+enum ProjectOrderField {
+  # Order projects by creation time
+  CREATED_AT
+
+  # Order projects by name
+  NAME
+
+  # Order projects by update time
+  UPDATED_AT
+}
+
+# Represents an owner of a Project.
+interface ProjectOwner {
+  id: ID!
+
+  # Find project by number.
+  project(
+    # The project number to find.
+    number: Int!
+  ): Project
+
+  # A list of projects under the owner.
+  projects(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for projects returned from the connection
+    orderBy: ProjectOrder
+
+    # Query to search projects by, currently only searching by name.
+    search: String
+
+    # A list of states to filter the projects by.
+    states: [ProjectState!]
+  ): ProjectConnection!
+
+  # The HTTP path listing owners projects
+  projectsResourcePath: URI!
+
+  # The HTTP URL listing owners projects
+  projectsUrl: URI!
+
+  # Can the current viewer create new projects on this owner.
+  viewerCanCreateProjects: Boolean!
+}
+
+# State of the project; either 'open' or 'closed'
+enum ProjectState {
+  # The project is closed.
+  CLOSED
+
+  # The project is open.
+  OPEN
+}
+
+# A repository protected branch.
+type ProtectedBranch implements Node {
+  # The actor who created this protected branch.
+  creator: Actor
+
+  # Will new commits pushed to this branch dismiss pull request review approvals.
+  hasDismissableStaleReviews: Boolean!
+
+  # Are reviews required to update this branch.
+  hasRequiredReviews: Boolean!
+
+  # Are status checks required to update this branch.
+  hasRequiredStatusChecks: Boolean!
+
+  # Is pushing to this branch restricted.
+  hasRestrictedPushes: Boolean!
+
+  # Is dismissal of pull request reviews restricted.
+  hasRestrictedReviewDismissals: Boolean!
+
+  # Are branches required to be up to date before merging.
+  hasStrictRequiredStatusChecks: Boolean!
+  id: ID!
+
+  # Can admins overwrite branch protection.
+  isAdminEnforced: Boolean!
+
+  # The name of the protected branch rule.
+  name: String!
+
+  # A list push allowances for this protected branch.
+  pushAllowances(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): PushAllowanceConnection!
+
+  # The repository associated with this protected branch.
+  repository: Repository!
+
+  # List of required status check contexts that must pass for commits to be accepted to this branch.
+  requiredStatusCheckContexts: [String]
+
+  # A list review dismissal allowances for this protected branch.
+  reviewDismissalAllowances(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ReviewDismissalAllowanceConnection!
+}
+
+# The connection type for ProtectedBranch.
+type ProtectedBranchConnection {
+  # A list of edges.
+  edges: [ProtectedBranchEdge]
+
+  # A list of nodes.
+  nodes: [ProtectedBranch]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ProtectedBranchEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ProtectedBranch
+}
+
+# A user's public key.
+type PublicKey implements Node {
+  id: ID!
+
+  # The public key string
+  key: String!
+}
+
+# The connection type for PublicKey.
+type PublicKeyConnection {
+  # A list of edges.
+  edges: [PublicKeyEdge]
+
+  # A list of nodes.
+  nodes: [PublicKey]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PublicKeyEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PublicKey
+}
+
+# A repository pull request.
+type PullRequest implements Assignable & Closable & Comment & Labelable & Lockable & Node & Reactable & RepositoryNode & Subscribable & UniformResourceLocatable & Updatable & UpdatableComment {
+  # Reason that the conversation was locked.
+  activeLockReason: LockReason
+
+  # The number of additions in this pull request.
+  additions: Int!
+
+  # A list of Users assigned to this object.
+  assignees(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # Identifies the base Ref associated with the pull request.
+  baseRef: Ref
+
+  # Identifies the name of the base Ref associated with the pull request, even if the ref has been deleted.
+  baseRefName: String!
+
+  # Identifies the oid of the base ref associated with the pull request, even if the ref has been deleted.
+  baseRefOid: GitObjectID!
+
+  # The body as Markdown.
+  body: String!
+
+  # The body rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body rendered to text.
+  bodyText: String!
+
+  # The number of changed files in this pull request.
+  changedFiles: Int!
+
+  # `true` if the pull request is closed
+  closed: Boolean!
+
+  # Identifies the date and time when the object was closed.
+  closedAt: DateTime
+
+  # A list of comments associated with the pull request.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): IssueCommentConnection!
+
+  # A list of commits present in this pull request's head branch not present in the base branch.
+  commits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): PullRequestCommitConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The number of deletions in this pull request.
+  deletions: Int!
+
+  # The actor who edited this pull request's body.
+  editor: Actor
+
+  # Identifies the head Ref associated with the pull request.
+  headRef: Ref
+
+  # Identifies the name of the head Ref associated with the pull request, even if the ref has been deleted.
+  headRefName: String!
+
+  # Identifies the oid of the head ref associated with the pull request, even if the ref has been deleted.
+  headRefOid: GitObjectID!
+
+  # The repository associated with this pull request's head Ref.
+  headRepository: Repository
+
+  # The owner of the repository associated with this pull request's head Ref.
+  headRepositoryOwner: RepositoryOwner
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The head and base repositories are different.
+  isCrossRepository: Boolean!
+
+  # A list of labels associated with the object.
+  labels(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): LabelConnection
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # `true` if the pull request is locked
+  locked: Boolean!
+
+  # Indicates whether maintainers can modify the pull request.
+  maintainerCanModify: Boolean!
+
+  # The commit that was created when this pull request was merged.
+  mergeCommit: Commit
+
+  # Whether or not the pull request can be merged based on the existence of merge conflicts.
+  mergeable: MergeableState!
+
+  # Whether or not the pull request was merged.
+  merged: Boolean!
+
+  # The date and time that the pull request was merged.
+  mergedAt: DateTime
+
+  # The actor who merged the pull request.
+  mergedBy: Actor
+
+  # Identifies the milestone associated with the pull request.
+  milestone: Milestone
+
+  # Identifies the pull request number.
+  number: Int!
+
+  # A list of Users that are participating in the Pull Request conversation.
+  participants(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # The permalink to the pull request.
+  permalink: URI!
+
+  # The commit that GitHub automatically generated to test if this pull request
+  # could be merged. This field will not return a value if the pull request is
+  # merged, or if the test merge commit is still being generated. See the
+  # `mergeable` field for more details on the mergeability of the pull request.
+  potentialMergeCommit: Commit
+
+  # List of project cards associated with this pull request.
+  projectCards(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # A list of archived states to filter the cards by
+    archivedStates: [ProjectCardArchivedState] = [ARCHIVED, NOT_ARCHIVED]
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProjectCardConnection!
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path for this pull request.
+  resourcePath: URI!
+
+  # The HTTP path for reverting this pull request.
+  revertResourcePath: URI!
+
+  # The HTTP URL for reverting this pull request.
+  revertUrl: URI!
+
+  # A list of review requests associated with the pull request.
+  reviewRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ReviewRequestConnection
+
+  # A list of reviews associated with the pull request.
+  reviews(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Filter by author of the review.
+    author: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # A list of states to filter the reviews.
+    states: [PullRequestReviewState!]
+  ): PullRequestReviewConnection
+
+  # Identifies the state of the pull request.
+  state: PullRequestState!
+
+  # A list of reviewer suggestions based on commit history and past review comments.
+  suggestedReviewers: [SuggestedReviewer]!
+
+  # A list of events, comments, commits, etc. associated with the pull request.
+  timeline(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows filtering timeline events by a `since` timestamp.
+    since: DateTime
+  ): PullRequestTimelineConnection!
+
+  # Identifies the pull request title.
+  title: String!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this pull request.
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+}
+
+# Represents a Git commit part of a pull request.
+type PullRequestCommit implements Node & UniformResourceLocatable {
+  # The Git commit object
+  commit: Commit!
+  id: ID!
+
+  # The pull request this commit belongs to
+  pullRequest: PullRequest!
+
+  # The HTTP path for this pull request commit
+  resourcePath: URI!
+
+  # The HTTP URL for this pull request commit
+  url: URI!
+}
+
+# The connection type for PullRequestCommit.
+type PullRequestCommitConnection {
+  # A list of edges.
+  edges: [PullRequestCommitEdge]
+
+  # A list of nodes.
+  nodes: [PullRequestCommit]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PullRequestCommitEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequestCommit
+}
+
+# The connection type for PullRequest.
+type PullRequestConnection {
+  # A list of edges.
+  edges: [PullRequestEdge]
+
+  # A list of nodes.
+  nodes: [PullRequest]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PullRequestEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequest
+}
+
+# Ways in which lists of issues can be ordered upon return.
+input PullRequestOrder {
+  # The direction in which to order pull requests by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order pull requests by.
+  field: PullRequestOrderField!
+}
+
+# Properties by which pull_requests connections can be ordered.
+enum PullRequestOrderField {
+  # Order pull_requests by creation time
+  CREATED_AT
+
+  # Order pull_requests by update time
+  UPDATED_AT
+}
+
+# The possible PubSub channels for a pull request.
+enum PullRequestPubSubTopic {
+  # The channel ID for observing head ref updates.
+  HEAD_REF
+
+  # The channel ID for marking an pull request as read.
+  MARKASREAD
+
+  # The channel ID for updating items on the pull request timeline.
+  TIMELINE
+
+  # The channel ID for observing pull request updates.
+  UPDATED
+}
+
+# A review object for a given pull request.
+type PullRequestReview implements Comment & Deletable & Node & RepositoryNode & Updatable & UpdatableComment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # Identifies the pull request review body.
+  body: String!
+
+  # The body of this review rendered to HTML.
+  bodyHTML: HTML!
+
+  # The body of this review rendered as plain text.
+  bodyText: String!
+
+  # A list of review comments for the current pull request review.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): PullRequestReviewCommentConnection!
+
+  # Identifies the commit associated with this pull request review.
+  commit: Commit
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # Identifies the pull request associated with this pull request review.
+  pullRequest: PullRequest!
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path permalink for this PullRequestReview.
+  resourcePath: URI!
+
+  # Identifies the current state of the pull request review.
+  state: PullRequestReviewState!
+
+  # Identifies when the Pull Request Review was submitted
+  submittedAt: DateTime
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL permalink for this PullRequestReview.
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# A review comment associated with a given repository pull request.
+type PullRequestReviewComment implements Comment & Deletable & Node & Reactable & RepositoryNode & Updatable & UpdatableComment {
+  # The actor who authored the comment.
+  author: Actor
+
+  # Author's association with the subject of the comment.
+  authorAssociation: CommentAuthorAssociation!
+
+  # The comment body of this review comment.
+  body: String!
+
+  # The comment body of this review comment rendered to HTML.
+  bodyHTML: HTML!
+
+  # The comment body of this review comment rendered as plain text.
+  bodyText: String!
+
+  # Identifies the commit associated with the comment.
+  commit: Commit!
+
+  # Identifies when the comment was created.
+  createdAt: DateTime!
+
+  # Check if this comment was created via an email reply.
+  createdViaEmail: Boolean!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The diff hunk to which the comment applies.
+  diffHunk: String!
+
+  # Identifies when the comment was created in a draft state.
+  draftedAt: DateTime!
+
+  # The actor who edited the comment.
+  editor: Actor
+  id: ID!
+
+  # Check if this comment was edited and includes an edit with the creation data
+  includesCreatedEdit: Boolean!
+
+  # The moment the editor made the last edit
+  lastEditedAt: DateTime
+
+  # Identifies the original commit associated with the comment.
+  originalCommit: Commit
+
+  # The original line index in the diff to which the comment applies.
+  originalPosition: Int!
+
+  # The path to which the comment applies.
+  path: String!
+
+  # The line index in the diff to which the comment applies.
+  position: Int
+
+  # Identifies when the comment was published at.
+  publishedAt: DateTime
+
+  # The pull request associated with this review comment.
+  pullRequest: PullRequest!
+
+  # The pull request review associated with this review comment.
+  pullRequestReview: PullRequestReview
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # The comment this is a reply to.
+  replyTo: PullRequestReviewComment
+
+  # The repository associated with this node.
+  repository: Repository!
+
+  # The HTTP path permalink for this review comment.
+  resourcePath: URI!
+
+  # Identifies when the comment was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL permalink for this review comment.
+  url: URI!
+
+  # A list of edits to this content.
+  userContentEdits(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserContentEditConnection
+
+  # Check if the current viewer can delete this object.
+  viewerCanDelete: Boolean!
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+
+  # Did the viewer author this comment.
+  viewerDidAuthor: Boolean!
+}
+
+# The connection type for PullRequestReviewComment.
+type PullRequestReviewCommentConnection {
+  # A list of edges.
+  edges: [PullRequestReviewCommentEdge]
+
+  # A list of nodes.
+  nodes: [PullRequestReviewComment]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PullRequestReviewCommentEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequestReviewComment
+}
+
+# The connection type for PullRequestReview.
+type PullRequestReviewConnection {
+  # A list of edges.
+  edges: [PullRequestReviewEdge]
+
+  # A list of nodes.
+  nodes: [PullRequestReview]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PullRequestReviewEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequestReview
+}
+
+# The possible events to perform on a pull request review.
+enum PullRequestReviewEvent {
+  # Submit feedback and approve merging these changes.
+  APPROVE
+
+  # Submit general feedback without explicit approval.
+  COMMENT
+
+  # Dismiss review so it now longer effects merging.
+  DISMISS
+
+  # Submit feedback that must be addressed before merging.
+  REQUEST_CHANGES
+}
+
+# The possible states of a pull request review.
+enum PullRequestReviewState {
+  # A review allowing the pull request to merge.
+  APPROVED
+
+  # A review blocking the pull request from merging.
+  CHANGES_REQUESTED
+
+  # An informational review.
+  COMMENTED
+
+  # A review that has been dismissed.
+  DISMISSED
+
+  # A review that has not yet been submitted.
+  PENDING
+}
+
+# A threaded list of comments for a given pull request.
+type PullRequestReviewThread implements Node {
+  # A list of pull request comments associated with the thread.
+  comments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): PullRequestReviewCommentConnection!
+  id: ID!
+
+  # Identifies the pull request associated with this thread.
+  pullRequest: PullRequest!
+
+  # Identifies the repository associated with this thread.
+  repository: Repository!
+}
+
+# The possible states of a pull request.
+enum PullRequestState {
+  # A pull request that has been closed without being merged.
+  CLOSED
+
+  # A pull request that has been closed by being merged.
+  MERGED
+
+  # A pull request that is still open.
+  OPEN
+}
+
+# The connection type for PullRequestTimelineItem.
+type PullRequestTimelineConnection {
+  # A list of edges.
+  edges: [PullRequestTimelineItemEdge]
+
+  # A list of nodes.
+  nodes: [PullRequestTimelineItem]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An item in an pull request timeline
+union PullRequestTimelineItem = AssignedEvent | BaseRefForcePushedEvent | ClosedEvent | Commit | CommitCommentThread | CrossReferencedEvent | DemilestonedEvent | DeployedEvent | DeploymentEnvironmentChangedEvent | HeadRefDeletedEvent | HeadRefForcePushedEvent | HeadRefRestoredEvent | IssueComment | LabeledEvent | LockedEvent | MergedEvent | MilestonedEvent | PullRequestReview | PullRequestReviewComment | PullRequestReviewThread | ReferencedEvent | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent | ReviewRequestRemovedEvent | ReviewRequestedEvent | SubscribedEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent
+
+# An edge in a connection.
+type PullRequestTimelineItemEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequestTimelineItem
+}
+
+# An item in a pull request timeline
+union PullRequestTimelineItems = AddedToProjectEvent | AssignedEvent | BaseRefChangedEvent | BaseRefForcePushedEvent | ClosedEvent | CommentDeletedEvent | ConvertedNoteToIssueEvent | CrossReferencedEvent | DemilestonedEvent | DeployedEvent | DeploymentEnvironmentChangedEvent | HeadRefDeletedEvent | HeadRefForcePushedEvent | HeadRefRestoredEvent | IssueComment | LabeledEvent | LockedEvent | MentionedEvent | MergedEvent | MilestonedEvent | MovedColumnsInProjectEvent | PullRequestCommit | PullRequestReview | PullRequestReviewThread | ReferencedEvent | RemovedFromProjectEvent | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent | ReviewRequestRemovedEvent | ReviewRequestedEvent | SubscribedEvent | UnassignedEvent | UnlabeledEvent | UnlockedEvent | UnsubscribedEvent
+
+# An edge in a connection.
+type PullRequestTimelineItemsEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PullRequestTimelineItems
+}
+
+# The possible item types found in a timeline.
+enum PullRequestTimelineItemsItemType {
+  # Represents a 'added_to_project' event on a given issue or pull request.
+  ADDED_TO_PROJECT_EVENT
+
+  # Represents an 'assigned' event on any assignable object.
+  ASSIGNED_EVENT
+
+  # Represents a 'base_ref_changed' event on a given issue or pull request.
+  BASE_REF_CHANGED_EVENT
+
+  # Represents a 'base_ref_force_pushed' event on a given pull request.
+  BASE_REF_FORCE_PUSHED_EVENT
+
+  # Represents a 'closed' event on any `Closable`.
+  CLOSED_EVENT
+
+  # Represents a 'comment_deleted' event on a given issue or pull request.
+  COMMENT_DELETED_EVENT
+
+  # Represents a 'converted_note_to_issue' event on a given issue or pull request.
+  CONVERTED_NOTE_TO_ISSUE_EVENT
+
+  # Represents a mention made by one issue or pull request to another.
+  CROSS_REFERENCED_EVENT
+
+  # Represents a 'demilestoned' event on a given issue or pull request.
+  DEMILESTONED_EVENT
+
+  # Represents a 'deployed' event on a given pull request.
+  DEPLOYED_EVENT
+
+  # Represents a 'deployment_environment_changed' event on a given pull request.
+  DEPLOYMENT_ENVIRONMENT_CHANGED_EVENT
+
+  # Represents a 'head_ref_deleted' event on a given pull request.
+  HEAD_REF_DELETED_EVENT
+
+  # Represents a 'head_ref_force_pushed' event on a given pull request.
+  HEAD_REF_FORCE_PUSHED_EVENT
+
+  # Represents a 'head_ref_restored' event on a given pull request.
+  HEAD_REF_RESTORED_EVENT
+
+  # Represents a comment on an Issue.
+  ISSUE_COMMENT
+
+  # Represents a 'labeled' event on a given issue or pull request.
+  LABELED_EVENT
+
+  # Represents a 'locked' event on a given issue or pull request.
+  LOCKED_EVENT
+
+  # Represents a 'mentioned' event on a given issue or pull request.
+  MENTIONED_EVENT
+
+  # Represents a 'merged' event on a given pull request.
+  MERGED_EVENT
+
+  # Represents a 'milestoned' event on a given issue or pull request.
+  MILESTONED_EVENT
+
+  # Represents a 'moved_columns_in_project' event on a given issue or pull request.
+  MOVED_COLUMNS_IN_PROJECT_EVENT
+
+  # Represents a Git commit part of a pull request.
+  PULL_REQUEST_COMMIT
+
+  # Represents a commit comment thread part of a pull request.
+  PULL_REQUEST_COMMIT_COMMENT_THREAD
+
+  # A review object for a given pull request.
+  PULL_REQUEST_REVIEW
+
+  # A threaded list of comments for a given pull request.
+  PULL_REQUEST_REVIEW_THREAD
+
+  # Represents the latest point in the pull request timeline for which the viewer has seen the pull request's commits.
+  PULL_REQUEST_REVISION_MARKER
+
+  # Represents a 'referenced' event on a given `ReferencedSubject`.
+  REFERENCED_EVENT
+
+  # Represents a 'removed_from_project' event on a given issue or pull request.
+  REMOVED_FROM_PROJECT_EVENT
+
+  # Represents a 'renamed' event on a given issue or pull request
+  RENAMED_TITLE_EVENT
+
+  # Represents a 'reopened' event on any `Closable`.
+  REOPENED_EVENT
+
+  # Represents a 'review_dismissed' event on a given issue or pull request.
+  REVIEW_DISMISSED_EVENT
+
+  # Represents an 'review_requested' event on a given pull request.
+  REVIEW_REQUESTED_EVENT
+
+  # Represents an 'review_request_removed' event on a given pull request.
+  REVIEW_REQUEST_REMOVED_EVENT
+
+  # Represents a 'subscribed' event on a given `Subscribable`.
+  SUBSCRIBED_EVENT
+
+  # Represents an 'unassigned' event on any assignable object.
+  UNASSIGNED_EVENT
+
+  # Represents an 'unlabeled' event on a given issue or pull request.
+  UNLABELED_EVENT
+
+  # Represents an 'unlocked' event on a given issue or pull request.
+  UNLOCKED_EVENT
+
+  # Represents an 'unsubscribed' event on a given `Subscribable`.
+  UNSUBSCRIBED_EVENT
+}
+
+# A team or user who has the ability to push to a protected branch.
+type PushAllowance implements Node {
+  # The actor that can push.
+  actor: PushAllowanceActor
+  id: ID!
+
+  # Identifies the protected branch associated with the allowed user or team.
+  protectedBranch: ProtectedBranch!
+}
+
+# Types that can be an actor.
+union PushAllowanceActor = Team | User
+
+# The connection type for PushAllowance.
+type PushAllowanceConnection {
+  # A list of edges.
+  edges: [PushAllowanceEdge]
+
+  # A list of nodes.
+  nodes: [PushAllowance]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type PushAllowanceEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: PushAllowance
+}
+
+# The query root of GitHub's GraphQL interface.
+type Query {
+  # Look up a code of conduct by its key
+  codeOfConduct(
+    # The code of conduct's key
+    key: String!
+  ): CodeOfConduct
+
+  # Look up a code of conduct by its key
+  codesOfConduct: [CodeOfConduct]
+
+  # Look up an open source license by its key
+  license(
+    # The license's downcased SPDX ID
+    key: String!
+  ): License
+
+  # Return a list of known open source licenses
+  licenses: [License]!
+
+  # Get alphabetically sorted list of Marketplace categories
+  marketplaceCategories(
+    # Exclude categories with no listings.
+    excludeEmpty: Boolean
+
+    # Exclude subcategories
+    excludeSubcategories: Boolean
+
+    # Return only the specified categories.
+    includeCategories: [String!]
+  ): [MarketplaceCategory!]!
+
+  # Look up a Marketplace category by its slug.
+  marketplaceCategory(
+    # The URL slug of the category.
+    slug: String!
+
+    # Also check topic aliases for the category slug
+    useTopicAliases: Boolean
+  ): MarketplaceCategory
+
+  # Look up a single Marketplace listing
+  marketplaceListing(
+    # Select the listing that matches this slug. It's the short name of the listing used in its URL.
+    slug: String!
+  ): MarketplaceListing
+
+  # Look up Marketplace listings
+  marketplaceListings(
+    # Select listings that can be administered by the specified user.
+    adminId: ID
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Select listings visible to the viewer even if they are not approved. If omitted or
+    # false, only approved listings will be returned.
+    allStates: Boolean
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Select only listings with the given category.
+    categorySlug: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Select listings for products owned by the specified organization.
+    organizationId: ID
+
+    # Select only listings where the primary category matches the given category slug.
+    primaryCategoryOnly: Boolean = false
+
+    # Select the listings with these slugs, if they are visible to the viewer.
+    slugs: [String]
+
+    # Also check topic aliases for the category slug
+    useTopicAliases: Boolean
+
+    # Select listings to which user has admin access. If omitted, listings visible to the
+    # viewer are returned.
+    viewerCanAdmin: Boolean
+
+    # Select only listings that offer a free trial.
+    withFreeTrialsOnly: Boolean = false
+  ): MarketplaceListingConnection!
+
+  # Return information about the GitHub instance
+  meta: GitHubMetadata!
+
+  # Fetches an object given its ID.
+  node(
+    # ID of the object.
+    id: ID!
+  ): Node
+
+  # Lookup nodes by a list of IDs.
+  nodes(
+    # The list of node IDs.
+    ids: [ID!]!
+  ): [Node]!
+
+  # Lookup a organization by login.
+  organization(
+    # The organization's login.
+    login: String!
+  ): Organization
+
+  # The client's rate limit information.
+  rateLimit(
+    # If true, calculate the cost for the query without evaluating it
+    dryRun: Boolean = false
+  ): RateLimit
+
+  # Hack to workaround https://github.com/facebook/relay/issues/112 re-exposing the root query object
+  relay: Query!
+
+  # Lookup a given repository by the owner and repository name.
+  repository(
+    # The name of the repository
+    name: String!
+
+    # The login field of a user or organization
+    owner: String!
+  ): Repository
+
+  # Lookup a repository owner (ie. either a User or an Organization) by login.
+  repositoryOwner(
+    # The username to lookup the owner by.
+    login: String!
+  ): RepositoryOwner
+
+  # Lookup resource by a URL.
+  resource(
+    # The URL.
+    url: URI!
+  ): UniformResourceLocatable
+
+  # Perform a search across resources.
+  search(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # The search string to look for.
+    query: String!
+
+    # The types of search items to search within.
+    type: SearchType!
+  ): SearchResultItemConnection!
+
+  # Look up a topic by name.
+  topic(
+    # The topic's name.
+    name: String!
+  ): Topic
+
+  # Lookup a user by login.
+  user(
+    # The user's login.
+    login: String!
+  ): User
+
+  # The currently authenticated user.
+  viewer: User!
+}
+
+# Represents the client's rate limit.
+type RateLimit {
+  # The point cost for the current query counting against the rate limit.
+  cost: Int!
+
+  # The maximum number of points the client is permitted to consume in a 60 minute window.
+  limit: Int!
+
+  # The maximum number of nodes this query may return
+  nodeCount: Int!
+
+  # The number of points remaining in the current rate limit window.
+  remaining: Int!
+
+  # The time at which the current rate limit window resets in UTC epoch seconds.
+  resetAt: DateTime!
+}
+
+# Represents a subject that can be reacted on.
+interface Reactable {
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # A list of reactions grouped by content left on the subject.
+  reactionGroups: [ReactionGroup!]
+
+  # A list of Reactions left on the Issue.
+  reactions(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Allows filtering Reactions by emoji.
+    content: ReactionContent
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Allows specifying the order in which reactions are returned.
+    orderBy: ReactionOrder
+  ): ReactionConnection!
+
+  # Can user react to this subject
+  viewerCanReact: Boolean!
+}
+
+# The connection type for User.
+type ReactingUserConnection {
+  # A list of edges.
+  edges: [ReactingUserEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a user that's made a reaction.
+type ReactingUserEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+  node: User!
+
+  # The moment when the user made the reaction.
+  reactedAt: DateTime!
+}
+
+# An emoji reaction to a particular piece of content.
+type Reaction implements Node {
+  # Identifies the emoji reaction.
+  content: ReactionContent!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # The reactable piece of content
+  reactable: Reactable!
+
+  # Identifies the user who created this reaction.
+  user: User
+}
+
+# A list of reactions that have been left on the subject.
+type ReactionConnection {
+  # A list of edges.
+  edges: [ReactionEdge]
+
+  # A list of nodes.
+  nodes: [Reaction]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+
+  # Whether or not the authenticated user has left a reaction on the subject.
+  viewerHasReacted: Boolean!
+}
+
+# Emojis that can be attached to Issues, Pull Requests and Comments.
+enum ReactionContent {
+  # Represents the 😕 emoji.
+  CONFUSED
+
+  # Represents the ❤️ emoji.
+  HEART
+
+  # Represents the 🎉 emoji.
+  HOORAY
+
+  # Represents the 😄 emoji.
+  LAUGH
+
+  # Represents the 👎 emoji.
+  THUMBS_DOWN
+
+  # Represents the 👍 emoji.
+  THUMBS_UP
+}
+
+# An edge in a connection.
+type ReactionEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Reaction
+}
+
+# A group of emoji reactions to a particular piece of content.
+type ReactionGroup {
+  # Identifies the emoji reaction.
+  content: ReactionContent!
+
+  # Identifies when the reaction was created.
+  createdAt: DateTime
+
+  # The subject that was reacted to.
+  subject: Reactable!
+
+  # Users who have reacted to the reaction subject with the emotion represented by this reaction group
+  users(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ReactingUserConnection!
+
+  # Whether or not the authenticated user has left a reaction on the subject.
+  viewerHasReacted: Boolean!
+}
+
+# Ways in which lists of reactions can be ordered upon return.
+input ReactionOrder {
+  # The direction in which to order reactions by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order reactions by.
+  field: ReactionOrderField!
+}
+
+# A list of fields that reactions can be ordered by.
+enum ReactionOrderField {
+  # Allows ordering a list of reactions by when they were created.
+  CREATED_AT
+}
+
+# Represents a Git reference.
+type Ref implements Node {
+  # A list of pull requests with this ref as the head ref.
+  associatedPullRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # The base ref name to filter the pull requests by.
+    baseRefName: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # The head ref name to filter the pull requests by.
+    headRefName: String
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for pull requests returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the pull requests by.
+    states: [PullRequestState!]
+  ): PullRequestConnection!
+  id: ID!
+
+  # The ref name.
+  name: String!
+
+  # The ref's prefix, such as `refs/heads/` or `refs/tags/`.
+  prefix: String!
+
+  # The repository the ref belongs to.
+  repository: Repository!
+
+  # The object the ref points to.
+  target: GitObject!
+}
+
+# The connection type for Ref.
+type RefConnection {
+  # A list of edges.
+  edges: [RefEdge]
+
+  # A list of nodes.
+  nodes: [Ref]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type RefEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Ref
+}
+
+# Ways in which lists of git refs can be ordered upon return.
+input RefOrder {
+  # The direction in which to order refs by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order refs by.
+  field: RefOrderField!
+}
+
+# Properties by which ref connections can be ordered.
+enum RefOrderField {
+  # Order refs by their alphanumeric name
+  ALPHABETICAL
+
+  # Order refs by underlying commit date if the ref prefix is refs/tags/
+  TAG_COMMIT_DATE
+}
+
+# Represents a 'referenced' event on a given `ReferencedSubject`.
+type ReferencedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the commit associated with the 'referenced' event.
+  commit: Commit
+
+  # Identifies the repository associated with the 'referenced' event.
+  commitRepository: Repository!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Reference originated in a different repository.
+  isCrossRepository: Boolean!
+
+  # Checks if the commit message itself references the subject. Can be false in the case of a commit comment reference.
+  isDirectReference: Boolean!
+
+  # Object referenced by event.
+  subject: ReferencedSubject!
+}
+
+# Any referencable object
+union ReferencedSubject = Issue | PullRequest
+
+# Represents an owner of a registry package.
+interface RegistryPackageOwner {
+  id: ID!
+}
+
+# Represents an interface to search packages on an object.
+interface RegistryPackageSearch {
+  id: ID!
+}
+
+# A release contains the content for a release.
+type Release implements Node & UniformResourceLocatable {
+  # The author of the release
+  author: User
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the description of the release.
+  description: String
+  id: ID!
+
+  # Whether or not the release is a draft
+  isDraft: Boolean!
+
+  # Whether or not the release is a prerelease
+  isPrerelease: Boolean!
+
+  # Identifies the title of the release.
+  name: String
+
+  # Identifies the date and time when the release was created.
+  publishedAt: DateTime
+
+  # List of releases assets which are dependent on this release.
+  releaseAssets(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # A list of names to filter the assets by.
+    name: String
+  ): ReleaseAssetConnection!
+
+  # The HTTP path for this issue
+  resourcePath: URI!
+
+  # The Git tag the release points to
+  tag: Ref
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this issue
+  url: URI!
+}
+
+# A release asset contains the content for a release asset.
+type ReleaseAsset implements Node {
+  # The asset's content-type
+  contentType: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The number of times this asset was downloaded
+  downloadCount: Int!
+
+  # Identifies the URL where you can download the release asset via the browser.
+  downloadUrl: URI!
+  id: ID!
+
+  # Identifies the title of the release asset.
+  name: String!
+
+  # Release that the asset is associated with
+  release: Release
+
+  # The size (in bytes) of the asset
+  size: Int!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The user that performed the upload
+  uploadedBy: User!
+
+  # Identifies the URL of the release asset.
+  url: URI!
+}
+
+# The connection type for ReleaseAsset.
+type ReleaseAssetConnection {
+  # A list of edges.
+  edges: [ReleaseAssetEdge]
+
+  # A list of nodes.
+  nodes: [ReleaseAsset]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ReleaseAssetEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ReleaseAsset
+}
+
+# The connection type for Release.
+type ReleaseConnection {
+  # A list of edges.
+  edges: [ReleaseEdge]
+
+  # A list of nodes.
+  nodes: [Release]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ReleaseEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Release
+}
+
+# Ways in which lists of releases can be ordered upon return.
+input ReleaseOrder {
+  # The direction in which to order releases by the specified field.
+  direction: OrderDirection!
+
+  # The field in which to order releases by.
+  field: ReleaseOrderField!
+}
+
+# Properties by which release connections can be ordered.
+enum ReleaseOrderField {
+  # Order releases by creation time
+  CREATED_AT
+
+  # Order releases alphabetically by name
+  NAME
+}
+
+# Autogenerated input type of RemoveOutsideCollaborator
+input RemoveOutsideCollaboratorInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The ID of the organization to remove the outside collaborator from.
+  organizationId: ID!
+
+  # The ID of the outside collaborator to remove.
+  userId: ID!
+}
+
+# Autogenerated return type of RemoveOutsideCollaborator
+type RemoveOutsideCollaboratorPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The user that was removed as an outside collaborator.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `removedUser` will change from `User!` to `User`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  removedUser: User!
+}
+
+# Autogenerated input type of RemoveReaction
+input RemoveReactionInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of the emoji reaction to remove.
+  content: ReactionContent!
+
+  # The Node ID of the subject to modify.
+  subjectId: ID!
+}
+
+# Autogenerated return type of RemoveReaction
+type RemoveReactionPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The reaction object.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `reaction` will change from `Reaction!` to `Reaction`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  reaction: Reaction!
+
+  # The reactable subject.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `subject` will change from `Reactable!` to `Reactable`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  subject: Reactable!
+}
+
+# Autogenerated input type of RemoveStar
+input RemoveStarInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Starrable ID to unstar.
+  starrableId: ID!
+}
+
+# Autogenerated return type of RemoveStar
+type RemoveStarPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The starrable.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `starrable` will change from `Starrable!` to `Starrable`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  starrable: Starrable!
+}
+
+# Represents a 'removed_from_project' event on a given issue or pull request.
+type RemovedFromProjectEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+}
+
+# Represents a 'renamed' event on a given issue or pull request
+type RenamedTitleEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the current title of the issue or pull request.
+  currentTitle: String!
+  id: ID!
+
+  # Identifies the previous title of the issue or pull request.
+  previousTitle: String!
+
+  # Subject that was renamed.
+  subject: RenamedTitleSubject!
+}
+
+# An object which has a renamable title
+union RenamedTitleSubject = Issue | PullRequest
+
+# Represents a 'reopened' event on any `Closable`.
+type ReopenedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Object that was reopened.
+  closable: Closable!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+}
+
+# A repository contains the content for a project.
+type Repository implements Node & ProjectOwner & RegistryPackageOwner & RepositoryInfo & Starrable & Subscribable & UniformResourceLocatable {
+  # A list of users that can be assigned to issues in this repository.
+  assignableUsers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # Returns the code of conduct for this repository
+  codeOfConduct: CodeOfConduct
+
+  # A list of collaborators associated with the repository.
+  collaborators(
+    # Collaborators affiliation level with a repository.
+    affiliation: CollaboratorAffiliation
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): RepositoryCollaboratorConnection
+
+  # A list of commit comments associated with the repository.
+  commitComments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): CommitCommentConnection!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The Ref associated with the repository's default branch.
+  defaultBranchRef: Ref
+
+  # A list of deploy keys that are on this repository.
+  deployKeys(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): DeployKeyConnection!
+
+  # Deployments associated with the repository
+  deployments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Environments to list deployments for
+    environments: [String!]
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): DeploymentConnection!
+
+  # The description of the repository.
+  description: String
+
+  # The description of the repository rendered to HTML.
+  descriptionHTML: HTML!
+
+  # The number of kilobytes this repository occupies on disk.
+  diskUsage: Int
+
+  # Returns how many forks there are of this repository in the whole network.
+  forkCount: Int!
+
+  # A list of direct forked repositories.
+  forks(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # Indicates if the repository has issues feature enabled.
+  hasIssuesEnabled: Boolean!
+
+  # Indicates if the repository has wiki feature enabled.
+  hasWikiEnabled: Boolean!
+
+  # The repository's URL.
+  homepageUrl: URI
+  id: ID!
+
+  # Indicates if the repository is unmaintained.
+  isArchived: Boolean!
+
+  # Identifies if the repository is a fork.
+  isFork: Boolean!
+
+  # Indicates if the repository has been locked or not.
+  isLocked: Boolean!
+
+  # Identifies if the repository is a mirror.
+  isMirror: Boolean!
+
+  # Identifies if the repository is private.
+  isPrivate: Boolean!
+
+  # Returns a single issue from the current repository by number.
+  issue(
+    # The number for the issue to be returned.
+    number: Int!
+  ): Issue
+
+  # Returns a single issue-like object from the current repository by number.
+  issueOrPullRequest(
+    # The number for the issue to be returned.
+    number: Int!
+  ): IssueOrPullRequest
+
+  # A list of issues that have been opened in the repository.
+  issues(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for issues returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the issues by.
+    states: [IssueState!]
+  ): IssueConnection!
+
+  # Returns a single label by name
+  label(
+    # Label name
+    name: String!
+  ): Label
+
+  # A list of labels associated with the repository.
+  labels(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # If provided, searches labels by name and description.
+    query: String
+  ): LabelConnection
+
+  # A list containing a breakdown of the language composition of the repository.
+  languages(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: LanguageOrder
+  ): LanguageConnection
+
+  # The license associated with the repository
+  licenseInfo: License
+
+  # The reason the repository has been locked.
+  lockReason: RepositoryLockReason
+
+  # A list of Users that can be mentioned in the context of the repository.
+  mentionableUsers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+
+  # Whether or not PRs are merged with a merge commit on this repository.
+  mergeCommitAllowed: Boolean!
+
+  # Returns a single milestone from the current repository by number.
+  milestone(
+    # The number for the milestone to be returned.
+    number: Int!
+  ): Milestone
+
+  # A list of milestones associated with the repository.
+  milestones(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for milestones.
+    orderBy: MilestoneOrder
+
+    # Filter by the state of the milestones.
+    states: [MilestoneState!]
+  ): MilestoneConnection
+
+  # The repository's original mirror URL.
+  mirrorUrl: URI
+
+  # The name of the repository.
+  name: String!
+
+  # The repository's name with owner.
+  nameWithOwner: String!
+
+  # A Git object in the repository
+  object(
+    # A Git revision expression suitable for rev-parse
+    expression: String
+
+    # The Git object ID
+    oid: GitObjectID
+  ): GitObject
+
+  # The User owner of the repository.
+  owner: RepositoryOwner!
+
+  # The repository parent, if this is a fork.
+  parent: Repository
+
+  # The primary language of the repository's code.
+  primaryLanguage: Language
+
+  # Find project by number.
+  project(
+    # The project number to find.
+    number: Int!
+  ): Project
+
+  # A list of projects under the owner.
+  projects(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for projects returned from the connection
+    orderBy: ProjectOrder
+
+    # Query to search projects by, currently only searching by name.
+    search: String
+
+    # A list of states to filter the projects by.
+    states: [ProjectState!]
+  ): ProjectConnection!
+
+  # The HTTP path listing the repository's projects
+  projectsResourcePath: URI!
+
+  # The HTTP URL listing the repository's projects
+  projectsUrl: URI!
+
+  # A list of protected branches that are on this repository.
+  protectedBranches(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): ProtectedBranchConnection!
+
+  # Returns a single pull request from the current repository by number.
+  pullRequest(
+    # The number for the pull request to be returned.
+    number: Int!
+  ): PullRequest
+
+  # A list of pull requests that have been opened in the repository.
+  pullRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # The base ref name to filter the pull requests by.
+    baseRefName: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # The head ref name to filter the pull requests by.
+    headRefName: String
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for pull requests returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the pull requests by.
+    states: [PullRequestState!]
+  ): PullRequestConnection!
+
+  # Identifies when the repository was last pushed to.
+  pushedAt: DateTime
+
+  # Whether or not rebase-merging is enabled on this repository.
+  rebaseMergeAllowed: Boolean!
+
+  # Fetch a given ref from the repository
+  ref(
+    # The ref to retrieve. Fully qualified matches are checked in order
+    # (`refs/heads/master`) before falling back onto checks for short name matches (`master`).
+    qualifiedName: String!
+  ): Ref
+
+  # Fetch a list of refs from the repository
+  refs(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # DEPRECATED: use orderBy. The ordering direction.
+    direction: OrderDirection
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for refs returned from the connection.
+    orderBy: RefOrder
+
+    # A ref name prefix like `refs/heads/`, `refs/tags/`, etc.
+    refPrefix: String!
+  ): RefConnection
+
+  # Lookup a single release given various criteria.
+  release(
+    # The name of the Tag the Release was created from
+    tagName: String!
+  ): Release
+
+  # List of releases which are dependent on this repository.
+  releases(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: ReleaseOrder
+  ): ReleaseConnection!
+
+  # A list of applied repository-topic associations for this repository.
+  repositoryTopics(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): RepositoryTopicConnection!
+
+  # The HTTP path for this repository
+  resourcePath: URI!
+
+  # A description of the repository, rendered to HTML without any links in it.
+  shortDescriptionHTML(
+    # How many characters to return.
+    limit: Int = 200
+  ): HTML!
+
+  # Whether or not squash-merging is enabled on this repository.
+  squashMergeAllowed: Boolean!
+
+  # The SSH URL to clone this repository
+  sshUrl: GitSSHRemote!
+
+  # A list of users who have starred this starrable.
+  stargazers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: StarOrder
+  ): StargazerConnection!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this repository
+  url: URI!
+
+  # Indicates whether the viewer has admin permissions on this repository.
+  viewerCanAdminister: Boolean!
+
+  # Can the current viewer create new projects on this owner.
+  viewerCanCreateProjects: Boolean!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Indicates whether the viewer can update the topics of this repository.
+  viewerCanUpdateTopics: Boolean!
+
+  # Returns a boolean indicating whether the viewing user has starred this starrable.
+  viewerHasStarred: Boolean!
+
+  # The users permission level on the repository. Will return null if authenticated as an GitHub App.
+  viewerPermission: RepositoryPermission
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+
+  # A list of users watching the repository.
+  watchers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): UserConnection!
+}
+
+# The affiliation of a user to a repository
+enum RepositoryAffiliation {
+  # Repositories that the user has been added to as a collaborator.
+  COLLABORATOR
+
+  # Repositories that the user has access to through being a member of an
+  # organization. This includes every repository on every team that the user is on.
+  ORGANIZATION_MEMBER
+
+  # Repositories that are owned by the authenticated user.
+  OWNER
+}
+
+# The affiliation type between collaborator and repository.
+enum RepositoryCollaboratorAffiliation {
+  # All collaborators of the repository.
+  ALL
+
+  # All outside collaborators of an organization-owned repository.
+  OUTSIDE
+}
+
+# The connection type for User.
+type RepositoryCollaboratorConnection {
+  # A list of edges.
+  edges: [RepositoryCollaboratorEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a user who is a collaborator of a repository.
+type RepositoryCollaboratorEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+  node: User!
+
+  # The permission the user has on the repository.
+  permission: RepositoryPermission!
+}
+
+# A list of repositories owned by the subject.
+type RepositoryConnection {
+  # A list of edges.
+  edges: [RepositoryEdge]
+
+  # A list of nodes.
+  nodes: [Repository]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+
+  # The total size in kilobytes of all repositories in the connection.
+  totalDiskUsage: Int!
+}
+
+# The reason a repository is listed as 'contributed'.
+enum RepositoryContributionType {
+  # Created a commit
+  COMMIT
+
+  # Created an issue
+  ISSUE
+
+  # Created a pull request
+  PULL_REQUEST
+
+  # Reviewed a pull request
+  PULL_REQUEST_REVIEW
+
+  # Created the repository
+  REPOSITORY
+}
+
+# An edge in a connection.
+type RepositoryEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Repository
+}
+
+# A subset of repository info.
+interface RepositoryInfo {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The description of the repository.
+  description: String
+
+  # The description of the repository rendered to HTML.
+  descriptionHTML: HTML!
+
+  # Returns how many forks there are of this repository in the whole network.
+  forkCount: Int!
+
+  # Indicates if the repository has issues feature enabled.
+  hasIssuesEnabled: Boolean!
+
+  # Indicates if the repository has wiki feature enabled.
+  hasWikiEnabled: Boolean!
+
+  # The repository's URL.
+  homepageUrl: URI
+
+  # Indicates if the repository is unmaintained.
+  isArchived: Boolean!
+
+  # Identifies if the repository is a fork.
+  isFork: Boolean!
+
+  # Indicates if the repository has been locked or not.
+  isLocked: Boolean!
+
+  # Identifies if the repository is a mirror.
+  isMirror: Boolean!
+
+  # Identifies if the repository is private.
+  isPrivate: Boolean!
+
+  # The license associated with the repository
+  licenseInfo: License
+
+  # The reason the repository has been locked.
+  lockReason: RepositoryLockReason
+
+  # The repository's original mirror URL.
+  mirrorUrl: URI
+
+  # The name of the repository.
+  name: String!
+
+  # The repository's name with owner.
+  nameWithOwner: String!
+
+  # The User owner of the repository.
+  owner: RepositoryOwner!
+
+  # Identifies when the repository was last pushed to.
+  pushedAt: DateTime
+
+  # The HTTP path for this repository
+  resourcePath: URI!
+
+  # A description of the repository, rendered to HTML without any links in it.
+  shortDescriptionHTML(
+    # How many characters to return.
+    limit: Int = 200
+  ): HTML!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this repository
+  url: URI!
+}
+
+# An invitation for a user to be added to a repository.
+type RepositoryInvitation implements Node {
+  id: ID!
+
+  # The user who received the invitation.
+  invitee: User!
+
+  # The user who created the invitation.
+  inviter: User!
+
+  # The permission granted on this repository by this invitation.
+  permission: RepositoryPermission!
+
+  # The Repository the user is invited to.
+  repository: RepositoryInfo
+}
+
+# An edge in a connection.
+type RepositoryInvitationEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: RepositoryInvitation
+}
+
+# The possible reasons a given repository could be in a locked state.
+enum RepositoryLockReason {
+  # The repository is locked due to a billing related reason.
+  BILLING
+
+  # The repository is locked due to a migration.
+  MIGRATING
+
+  # The repository is locked due to a move.
+  MOVING
+
+  # The repository is locked due to a rename.
+  RENAME
+}
+
+# Represents a object that belongs to a repository.
+interface RepositoryNode {
+  # The repository associated with this node.
+  repository: Repository!
+}
+
+# Ordering options for repository connections
+input RepositoryOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order repositories by.
+  field: RepositoryOrderField!
+}
+
+# Properties by which repository connections can be ordered.
+enum RepositoryOrderField {
+  # Order repositories by creation time
+  CREATED_AT
+
+  # Order repositories by name
+  NAME
+
+  # Order repositories by push time
+  PUSHED_AT
+
+  # Order repositories by number of stargazers
+  STARGAZERS
+
+  # Order repositories by update time
+  UPDATED_AT
+}
+
+# Represents an owner of a Repository.
+interface RepositoryOwner {
+  # A URL pointing to the owner's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+  id: ID!
+
+  # The username used to login.
+  login: String!
+
+  # A list of repositories this user has pinned to their profile
+  pinnedRepositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # A list of repositories that the user owns.
+  repositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they are forks of another repository
+    isFork: Boolean
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # Find Repository.
+  repository(
+    # Name of Repository to find.
+    name: String!
+  ): Repository
+
+  # The HTTP URL for the owner.
+  resourcePath: URI!
+
+  # The HTTP URL for the owner.
+  url: URI!
+}
+
+# The access level to a repository
+enum RepositoryPermission {
+  # Can read, clone, push, and add collaborators
+  ADMIN
+
+  # Can read and clone
+  READ
+
+  # Can read, clone and push
+  WRITE
+}
+
+# The privacy of a repository
+enum RepositoryPrivacy {
+  # Private
+  PRIVATE
+
+  # Public
+  PUBLIC
+}
+
+# A repository-topic connects a repository to a topic.
+type RepositoryTopic implements Node & UniformResourceLocatable {
+  id: ID!
+
+  # The HTTP path for this repository-topic.
+  resourcePath: URI!
+
+  # The topic.
+  topic: Topic!
+
+  # The HTTP URL for this repository-topic.
+  url: URI!
+}
+
+# The connection type for RepositoryTopic.
+type RepositoryTopicConnection {
+  # A list of edges.
+  edges: [RepositoryTopicEdge]
+
+  # A list of nodes.
+  nodes: [RepositoryTopic]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type RepositoryTopicEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: RepositoryTopic
+}
+
+# Autogenerated input type of RequestReviews
+input RequestReviewsInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the pull request to modify.
+  pullRequestId: ID!
+
+  # The Node IDs of the team to request.
+  teamIds: [ID!]
+
+  # Add users to the set rather than replace.
+  union: Boolean
+
+  # The Node IDs of the user to request.
+  userIds: [ID!]
+}
+
+# Autogenerated return type of RequestReviews
+type RequestReviewsPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The pull request that is getting requests.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequest` will change from `PullRequest!` to `PullRequest`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequest: PullRequest!
+
+  # The edge from the pull request to the requested reviewers.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `requestedReviewersEdge` will change from `UserEdge!` to `UserEdge`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  requestedReviewersEdge: UserEdge!
+}
+
+# Types that can be requested reviewers.
+union RequestedReviewer = Team | User
+
+# A team or user who has the ability to dismiss a review on a protected branch.
+type ReviewDismissalAllowance implements Node {
+  # The actor that can dismiss.
+  actor: ReviewDismissalAllowanceActor
+  id: ID!
+
+  # Identifies the protected branch associated with the allowed user or team.
+  protectedBranch: ProtectedBranch!
+}
+
+# Types that can be an actor.
+union ReviewDismissalAllowanceActor = Team | User
+
+# The connection type for ReviewDismissalAllowance.
+type ReviewDismissalAllowanceConnection {
+  # A list of edges.
+  edges: [ReviewDismissalAllowanceEdge]
+
+  # A list of nodes.
+  nodes: [ReviewDismissalAllowance]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ReviewDismissalAllowanceEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ReviewDismissalAllowance
+}
+
+# Represents a 'review_dismissed' event on a given issue or pull request.
+type ReviewDismissedEvent implements Node & UniformResourceLocatable {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # Identifies the message associated with the 'review_dismissed' event.
+  message: String!
+
+  # The message associated with the event, rendered to HTML.
+  messageHtml: HTML!
+
+  # Identifies the previous state of the review with the 'review_dismissed' event.
+  previousReviewState: PullRequestReviewState!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # Identifies the commit which caused the review to become stale.
+  pullRequestCommit: PullRequestCommit
+
+  # The HTTP path for this review dismissed event.
+  resourcePath: URI!
+
+  # Identifies the review associated with the 'review_dismissed' event.
+  review: PullRequestReview
+
+  # The HTTP URL for this review dismissed event.
+  url: URI!
+}
+
+# A request for a user to review a pull request.
+type ReviewRequest implements Node {
+  # Identifies the primary key from the database.
+  databaseId: Int
+  id: ID!
+
+  # Identifies the pull request associated with this review request.
+  pullRequest: PullRequest!
+
+  # The reviewer that is requested.
+  requestedReviewer: RequestedReviewer
+}
+
+# The connection type for ReviewRequest.
+type ReviewRequestConnection {
+  # A list of edges.
+  edges: [ReviewRequestEdge]
+
+  # A list of nodes.
+  nodes: [ReviewRequest]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type ReviewRequestEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: ReviewRequest
+}
+
+# Represents an 'review_request_removed' event on a given pull request.
+type ReviewRequestRemovedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # Identifies the reviewer whose review request was removed.
+  requestedReviewer: RequestedReviewer
+}
+
+# Represents an 'review_requested' event on a given pull request.
+type ReviewRequestedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # PullRequest referenced by event.
+  pullRequest: PullRequest!
+
+  # Identifies the reviewer whose review was requested.
+  requestedReviewer: RequestedReviewer
+}
+
+# The results of a search.
+union SearchResultItem = Issue | MarketplaceListing | Organization | PullRequest | Repository | User
+
+# A list of results that matched against a search query.
+type SearchResultItemConnection {
+  # The number of pieces of code that matched the search query.
+  codeCount: Int!
+
+  # A list of edges.
+  edges: [SearchResultItemEdge]
+
+  # The number of issues that matched the search query.
+  issueCount: Int!
+
+  # A list of nodes.
+  nodes: [SearchResultItem]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # The number of repositories that matched the search query.
+  repositoryCount: Int!
+
+  # The number of users that matched the search query.
+  userCount: Int!
+
+  # The number of wiki pages that matched the search query.
+  wikiCount: Int!
+}
+
+# An edge in a connection.
+type SearchResultItemEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: SearchResultItem
+
+  # Text matches on the result found.
+  textMatches: [TextMatch]
+}
+
+# Represents the individual results of a search.
+enum SearchType {
+  # Returns results matching issues in repositories.
+  ISSUE
+
+  # Returns results matching repositories.
+  REPOSITORY
+
+  # Returns results matching users and organizations on GitHub.
+  USER
+}
+
+# Represents an S/MIME signature on a Commit or Tag.
+type SmimeSignature implements GitSignature {
+  # Email used to sign this object.
+  email: String!
+
+  # True if the signature is valid and verified by GitHub.
+  isValid: Boolean!
+
+  # Payload for GPG signing object. Raw ODB object without the signature header.
+  payload: String!
+
+  # ASCII-armored signature header from object.
+  signature: String!
+
+  # GitHub user corresponding to the email signing this commit.
+  signer: User
+
+  # The state of this signature. `VALID` if signature is valid and verified by
+  # GitHub, otherwise represents reason why signature is considered invalid.
+  state: GitSignatureState!
+
+  # True if the signature was made with GitHub's signing key.
+  wasSignedByGitHub: Boolean!
+}
+
+# Ways in which star connections can be ordered.
+input StarOrder {
+  # The direction in which to order nodes.
+  direction: OrderDirection!
+
+  # The field in which to order nodes by.
+  field: StarOrderField!
+}
+
+# Properties by which star connections can be ordered.
+enum StarOrderField {
+  # Allows ordering a list of stars by when they were created.
+  STARRED_AT
+}
+
+# The connection type for User.
+type StargazerConnection {
+  # A list of edges.
+  edges: [StargazerEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a user that's starred a repository.
+type StargazerEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+  node: User!
+
+  # Identifies when the item was starred.
+  starredAt: DateTime!
+}
+
+# Things that can be starred.
+interface Starrable {
+  id: ID!
+
+  # A list of users who have starred this starrable.
+  stargazers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: StarOrder
+  ): StargazerConnection!
+
+  # Returns a boolean indicating whether the viewing user has starred this starrable.
+  viewerHasStarred: Boolean!
+}
+
+# The connection type for Repository.
+type StarredRepositoryConnection {
+  # A list of edges.
+  edges: [StarredRepositoryEdge]
+
+  # A list of nodes.
+  nodes: [Repository]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a starred repository.
+type StarredRepositoryEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+  node: Repository!
+
+  # Identifies when the item was starred.
+  starredAt: DateTime!
+}
+
+# Represents a commit status.
+type Status implements Node {
+  # The commit this status is attached to.
+  commit: Commit
+
+  # Looks up an individual status context by context name.
+  context(
+    # The context name.
+    name: String!
+  ): StatusContext
+
+  # The individual status contexts for this commit.
+  contexts: [StatusContext!]!
+  id: ID!
+
+  # The combined commit status.
+  state: StatusState!
+}
+
+# Represents an individual commit status context
+type StatusContext implements Node {
+  # This commit this status context is attached to.
+  commit: Commit
+
+  # The name of this status context.
+  context: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The actor who created this status context.
+  creator: Actor
+
+  # The description for this status context.
+  description: String
+  id: ID!
+
+  # The state of this status context.
+  state: StatusState!
+
+  # The URL for this status context.
+  targetUrl: URI
+}
+
+# The possible commit status states.
+enum StatusState {
+  # Status is errored.
+  ERROR
+
+  # Status is expected.
+  EXPECTED
+
+  # Status is failing.
+  FAILURE
+
+  # Status is pending.
+  PENDING
+
+  # Status is successful.
+  SUCCESS
+}
+
+# Autogenerated input type of SubmitPullRequestReview
+input SubmitPullRequestReviewInput {
+  # The text field to set on the Pull Request Review.
+  body: String
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The event to send to the Pull Request Review.
+  event: PullRequestReviewEvent!
+
+  # The Pull Request Review ID to submit.
+  pullRequestReviewId: ID!
+}
+
+# Autogenerated return type of SubmitPullRequestReview
+type SubmitPullRequestReviewPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The submitted pull request review.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReview` will change from `PullRequestReview!` to `PullRequestReview`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReview: PullRequestReview!
+}
+
+# Entities that can be subscribed to for web and email notifications.
+interface Subscribable {
+  id: ID!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+}
+
+# Represents a 'subscribed' event on a given `Subscribable`.
+type SubscribedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Object referenced by event.
+  subscribable: Subscribable!
+}
+
+# The possible states of a subscription.
+enum SubscriptionState {
+  # The User is never notified.
+  IGNORED
+
+  # The User is notified of all conversations.
+  SUBSCRIBED
+
+  # The User is only notified when particpating or @mentioned.
+  UNSUBSCRIBED
+}
+
+# A suggestion to review a pull request based on a user's commit history and review comments.
+type SuggestedReviewer {
+  # Is this suggestion based on past commits?
+  isAuthor: Boolean!
+
+  # Is this suggestion based on past review comments?
+  isCommenter: Boolean!
+
+  # Identifies the user suggested to review the pull request.
+  reviewer: User!
+}
+
+# Represents a Git tag.
+type Tag implements GitObject & Node {
+  # An abbreviated version of the Git object ID
+  abbreviatedOid: String!
+
+  # The HTTP path for this Git object
+  commitResourcePath: URI!
+
+  # The HTTP URL for this Git object
+  commitUrl: URI!
+  id: ID!
+
+  # The Git tag message.
+  message: String
+
+  # The Git tag name.
+  name: String!
+
+  # The Git object ID
+  oid: GitObjectID!
+
+  # The Repository the Git object belongs to
+  repository: Repository!
+
+  # Details about the tag author.
+  tagger: GitActor
+
+  # The Git object the tag points to.
+  target: GitObject!
+}
+
+# A team of users in an organization.
+type Team implements Node & Subscribable {
+  # A list of teams that are ancestors of this team.
+  ancestors(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): TeamConnection!
+
+  # A URL pointing to the team's avatar.
+  avatarUrl(
+    # The size in pixels of the resulting square image.
+    size: Int = 400
+  ): URI
+
+  # List of child teams belonging to this team
+  childTeams(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Whether to list immediate child teams or all descendant child teams.
+    immediateOnly: Boolean = true
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: TeamOrder
+
+    # User logins to filter by
+    userLogins: [String!]
+  ): TeamConnection!
+
+  # The slug corresponding to the organization and team.
+  combinedSlug: String!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # The description of the team.
+  description: String
+
+  # The HTTP path for editing this team
+  editTeamResourcePath: URI!
+
+  # The HTTP URL for editing this team
+  editTeamUrl: URI!
+  id: ID!
+
+  # A list of pending invitations for users to this team
+  invitations(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): OrganizationInvitationConnection
+
+  # A list of users who are members of this team.
+  members(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Filter by membership type
+    membership: TeamMembershipType = ALL
+
+    # Order for the connection.
+    orderBy: TeamMemberOrder
+
+    # The search string to look for.
+    query: String
+
+    # Filter by team member role
+    role: TeamMemberRole
+  ): TeamMemberConnection!
+
+  # The HTTP path for the team' members
+  membersResourcePath: URI!
+
+  # The HTTP URL for the team' members
+  membersUrl: URI!
+
+  # The name of the team.
+  name: String!
+
+  # The HTTP path creating a new team
+  newTeamResourcePath: URI!
+
+  # The HTTP URL creating a new team
+  newTeamUrl: URI!
+
+  # The organization that owns this team.
+  organization: Organization!
+
+  # The parent team of the team.
+  parentTeam: Team
+
+  # The level of privacy the team has.
+  privacy: TeamPrivacy!
+
+  # A list of repositories this team has access to.
+  repositories(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for the connection.
+    orderBy: TeamRepositoryOrder
+
+    # The search string to look for.
+    query: String
+  ): TeamRepositoryConnection!
+
+  # The HTTP path for this team's repositories
+  repositoriesResourcePath: URI!
+
+  # The HTTP URL for this team's repositories
+  repositoriesUrl: URI!
+
+  # The HTTP path for this team
+  resourcePath: URI!
+
+  # The slug corresponding to the team.
+  slug: String!
+
+  # The HTTP path for this team's teams
+  teamsResourcePath: URI!
+
+  # The HTTP URL for this team's teams
+  teamsUrl: URI!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this team
+  url: URI!
+
+  # Team is adminable by the viewer.
+  viewerCanAdminister: Boolean!
+
+  # Check if the viewer is able to change their subscription status for the repository.
+  viewerCanSubscribe: Boolean!
+
+  # Identifies if the viewer is watching, not watching, or ignoring the subscribable entity.
+  viewerSubscription: SubscriptionState
+}
+
+# The connection type for Team.
+type TeamConnection {
+  # A list of edges.
+  edges: [TeamEdge]
+
+  # A list of nodes.
+  nodes: [Team]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type TeamEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Team
+}
+
+# The connection type for User.
+type TeamMemberConnection {
+  # A list of edges.
+  edges: [TeamMemberEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a user who is a member of a team.
+type TeamMemberEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The HTTP path to the organization's member access page.
+  memberAccessResourcePath: URI!
+
+  # The HTTP URL to the organization's member access page.
+  memberAccessUrl: URI!
+  node: User!
+
+  # The role the member has on the team.
+  role: TeamMemberRole!
+}
+
+# Ordering options for team member connections
+input TeamMemberOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order team members by.
+  field: TeamMemberOrderField!
+}
+
+# Properties by which team member connections can be ordered.
+enum TeamMemberOrderField {
+  # Order team members by creation time
+  CREATED_AT
+
+  # Order team members by login
+  LOGIN
+}
+
+# The possible team member roles; either 'maintainer' or 'member'.
+enum TeamMemberRole {
+  # A team maintainer has permission to add and remove team members.
+  MAINTAINER
+
+  # A team member has no administrative permissions on the team.
+  MEMBER
+}
+
+# Defines which types of team members are included in the returned list. Can be one of IMMEDIATE, CHILD_TEAM or ALL.
+enum TeamMembershipType {
+  # Includes immediate and child team members for the team.
+  ALL
+
+  # Includes only child team members for the team.
+  CHILD_TEAM
+
+  # Includes only immediate members of the team.
+  IMMEDIATE
+}
+
+# Ways in which team connections can be ordered.
+input TeamOrder {
+  # The direction in which to order nodes.
+  direction: OrderDirection!
+
+  # The field in which to order nodes by.
+  field: TeamOrderField!
+}
+
+# Properties by which team connections can be ordered.
+enum TeamOrderField {
+  # Allows ordering a list of teams by name.
+  NAME
+}
+
+# The possible team privacy values.
+enum TeamPrivacy {
+  # A secret team can only be seen by its members.
+  SECRET
+
+  # A visible team can be seen and @mentioned by every member of the organization.
+  VISIBLE
+}
+
+# The connection type for Repository.
+type TeamRepositoryConnection {
+  # A list of edges.
+  edges: [TeamRepositoryEdge]
+
+  # A list of nodes.
+  nodes: [Repository]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# Represents a team repository.
+type TeamRepositoryEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+  node: Repository!
+
+  # The permission level the team has on the repository
+  permission: RepositoryPermission!
+}
+
+# Ordering options for team repository connections
+input TeamRepositoryOrder {
+  # The ordering direction.
+  direction: OrderDirection!
+
+  # The field to order repositories by.
+  field: TeamRepositoryOrderField!
+}
+
+# Properties by which team repository connections can be ordered.
+enum TeamRepositoryOrderField {
+  # Order repositories by creation time
+  CREATED_AT
+
+  # Order repositories by name
+  NAME
+
+  # Order repositories by permission
+  PERMISSION
+
+  # Order repositories by push time
+  PUSHED_AT
+
+  # Order repositories by number of stargazers
+  STARGAZERS
+
+  # Order repositories by update time
+  UPDATED_AT
+}
+
+# The role of a user on a team.
+enum TeamRole {
+  # User has admin rights on the team.
+  ADMIN
+
+  # User is a member of the team.
+  MEMBER
+}
+
+# A text match within a search result.
+type TextMatch {
+  # The specific text fragment within the property matched on.
+  fragment: String!
+
+  # Highlights within the matched fragment.
+  highlights: [TextMatchHighlight!]!
+
+  # The property matched on.
+  property: String!
+}
+
+# Represents a single highlight in a search result match.
+type TextMatchHighlight {
+  # The indice in the fragment where the matched text begins.
+  beginIndice: Int!
+
+  # The indice in the fragment where the matched text ends.
+  endIndice: Int!
+
+  # The text matched.
+  text: String!
+}
+
+# A topic aggregates entities that are related to a subject.
+type Topic implements Node {
+  id: ID!
+
+  # The topic's name.
+  name: String!
+
+  # A list of related topics, including aliases of this topic, sorted with the most relevant
+  # first.
+  relatedTopics: [Topic!]!
+}
+
+# The connection type for Topic.
+type TopicConnection {
+  # A list of edges.
+  edges: [TopicEdge]
+
+  # A list of nodes.
+  nodes: [Topic]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type TopicEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: Topic
+}
+
+# Reason that the suggested topic is declined.
+enum TopicSuggestionDeclineReason {
+  # The suggested topic is not relevant to the repository.
+  NOT_RELEVANT
+
+  # The viewer does not like the suggested topic.
+  PERSONAL_PREFERENCE
+
+  # The suggested topic is too general for the repository.
+  TOO_GENERAL
+
+  # The suggested topic is too specific for the repository (e.g. #ruby-on-rails-version-4-2-1).
+  TOO_SPECIFIC
+}
+
+# Represents a Git tree.
+type Tree implements GitObject & Node {
+  # An abbreviated version of the Git object ID
+  abbreviatedOid: String!
+
+  # The HTTP path for this Git object
+  commitResourcePath: URI!
+
+  # The HTTP URL for this Git object
+  commitUrl: URI!
+
+  # A list of tree entries.
+  entries: [TreeEntry!]
+  id: ID!
+
+  # The Git object ID
+  oid: GitObjectID!
+
+  # The Repository the Git object belongs to
+  repository: Repository!
+}
+
+# Represents a Git tree entry.
+type TreeEntry {
+  # Entry file mode.
+  mode: Int!
+
+  # Entry file name.
+  name: String!
+
+  # Entry file object.
+  object: GitObject
+
+  # Entry file Git object ID.
+  oid: GitObjectID!
+
+  # The Repository the tree entry belongs to
+  repository: Repository!
+
+  # Entry file type.
+  type: String!
+}
+
+# An RFC 3986, RFC 3987, and RFC 6570 (level 4) compliant URI string.
+scalar URI
+
+# Represents an 'unassigned' event on any assignable object.
+type UnassignedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the assignable associated with the event.
+  assignable: Assignable!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the subject (user) who was unassigned.
+  user: User
+}
+
+# Represents a type that can be retrieved by a URL.
+interface UniformResourceLocatable {
+  # The HTML path to this resource.
+  resourcePath: URI!
+
+  # The URL to this resource.
+  url: URI!
+}
+
+# Represents an unknown signature on a Commit or Tag.
+type UnknownSignature implements GitSignature {
+  # Email used to sign this object.
+  email: String!
+
+  # True if the signature is valid and verified by GitHub.
+  isValid: Boolean!
+
+  # Payload for GPG signing object. Raw ODB object without the signature header.
+  payload: String!
+
+  # ASCII-armored signature header from object.
+  signature: String!
+
+  # GitHub user corresponding to the email signing this commit.
+  signer: User
+
+  # The state of this signature. `VALID` if signature is valid and verified by
+  # GitHub, otherwise represents reason why signature is considered invalid.
+  state: GitSignatureState!
+
+  # True if the signature was made with GitHub's signing key.
+  wasSignedByGitHub: Boolean!
+}
+
+# Represents an 'unlabeled' event on a given issue or pull request.
+type UnlabeledEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Identifies the label associated with the 'unlabeled' event.
+  label: Label!
+
+  # Identifies the `Labelable` associated with the event.
+  labelable: Labelable!
+}
+
+# Autogenerated input type of UnlockLockable
+input UnlockLockableInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # ID of the issue or pull request to be unlocked.
+  lockableId: ID!
+}
+
+# Autogenerated return type of UnlockLockable
+type UnlockLockablePayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The item that was unlocked.
+  unlockedRecord: Lockable
+}
+
+# Represents an 'unlocked' event on a given issue or pull request.
+type UnlockedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Object that was unlocked.
+  lockable: Lockable!
+}
+
+# Represents an 'unsubscribed' event on a given `Subscribable`.
+type UnsubscribedEvent implements Node {
+  # Identifies the actor who performed the event.
+  actor: Actor
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+  id: ID!
+
+  # Object referenced by event.
+  subscribable: Subscribable!
+}
+
+# Entities that can be updated.
+interface Updatable {
+  # Check if the current viewer can update this object.
+  viewerCanUpdate: Boolean!
+}
+
+# Comments that can be updated.
+interface UpdatableComment {
+  # Reasons why the current viewer can not update this comment.
+  viewerCannotUpdateReasons: [CommentCannotUpdateReason!]!
+}
+
+# Autogenerated input type of UpdateProjectCard
+input UpdateProjectCardInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # Whether or not the ProjectCard should be archived
+  isArchived: Boolean
+
+  # The note of ProjectCard.
+  note: String
+
+  # The ProjectCard ID to update.
+  projectCardId: ID!
+}
+
+# Autogenerated return type of UpdateProjectCard
+type UpdateProjectCardPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The updated ProjectCard.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `projectCard` will change from `ProjectCard!` to `ProjectCard`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  projectCard: ProjectCard!
+}
+
+# Autogenerated input type of UpdateProjectColumn
+input UpdateProjectColumnInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of project column.
+  name: String!
+
+  # The ProjectColumn ID to update.
+  projectColumnId: ID!
+}
+
+# Autogenerated return type of UpdateProjectColumn
+type UpdateProjectColumnPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The updated project column.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `projectColumn` will change from `ProjectColumn!` to `ProjectColumn`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  projectColumn: ProjectColumn!
+}
+
+# Autogenerated input type of UpdateProject
+input UpdateProjectInput {
+  # The description of project.
+  body: String
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The name of project.
+  name: String
+
+  # The Project ID to update.
+  projectId: ID!
+
+  # Whether the project is public or not.
+  public: Boolean
+
+  # Whether the project is open or closed.
+  state: ProjectState
+}
+
+# Autogenerated return type of UpdateProject
+type UpdateProjectPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The updated project.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `project` will change from `Project!` to `Project`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  project: Project!
+}
+
+# Autogenerated input type of UpdatePullRequestReviewComment
+input UpdatePullRequestReviewCommentInput {
+  # The text of the comment.
+  body: String!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the comment to modify.
+  pullRequestReviewCommentId: ID!
+}
+
+# Autogenerated return type of UpdatePullRequestReviewComment
+type UpdatePullRequestReviewCommentPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The updated comment.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReviewComment` will change from
+  # `PullRequestReviewComment!` to `PullRequestReviewComment`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReviewComment: PullRequestReviewComment!
+}
+
+# Autogenerated input type of UpdatePullRequestReview
+input UpdatePullRequestReviewInput {
+  # The contents of the pull request review body.
+  body: String!
+
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the pull request review to modify.
+  pullRequestReviewId: ID!
+}
+
+# Autogenerated return type of UpdatePullRequestReview
+type UpdatePullRequestReviewPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The updated pull request review.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `pullRequestReview` will change from `PullRequestReview!` to `PullRequestReview`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  pullRequestReview: PullRequestReview!
+}
+
+# Autogenerated input type of UpdateSubscription
+input UpdateSubscriptionInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The new state of the subscription.
+  state: SubscriptionState!
+
+  # The Node ID of the subscribable object to modify.
+  subscribableId: ID!
+}
+
+# Autogenerated return type of UpdateSubscription
+type UpdateSubscriptionPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The input subscribable entity.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `subscribable` will change from `Subscribable!` to `Subscribable`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  subscribable: Subscribable!
+}
+
+# Autogenerated input type of UpdateTopics
+input UpdateTopicsInput {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # The Node ID of the repository.
+  repositoryId: ID!
+
+  # An array of topic names.
+  topicNames: [String!]!
+}
+
+# Autogenerated return type of UpdateTopics
+type UpdateTopicsPayload {
+  # A unique identifier for the client performing the mutation.
+  clientMutationId: String
+
+  # Names of the provided topics that are not valid.
+  invalidTopicNames: [String!]
+
+  # The updated repository.
+  #
+  # **Upcoming Change on 2019-01-01 UTC**
+  # **Description:** Type for `repository` will change from `Repository!` to `Repository`.
+  # **Reason:** In preparation for an upcoming change to the way we report
+  # mutation errors, non-nullable payload fields are becoming nullable.
+  repository: Repository!
+}
+
+# A user is an individual's account on GitHub that owns repositories and can make new content.
+type User implements Actor & Node & RegistryPackageOwner & RegistryPackageSearch & RepositoryOwner & UniformResourceLocatable {
+  # A URL pointing to the user's public avatar.
+  avatarUrl(
+    # The size of the resulting square image.
+    size: Int
+  ): URI!
+
+  # The user's public profile bio.
+  bio: String
+
+  # The user's public profile bio as HTML.
+  bioHTML: HTML!
+
+  # A list of commit comments made by this user.
+  commitComments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): CommitCommentConnection!
+
+  # The user's public profile company.
+  company: String
+
+  # The user's public profile company as HTML.
+  companyHTML: HTML!
+
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the primary key from the database.
+  databaseId: Int
+
+  # The user's publicly visible profile email.
+  email: String!
+
+  # A list of users the given user is followed by.
+  followers(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): FollowerConnection!
+
+  # A list of users the given user is following.
+  following(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): FollowingConnection!
+
+  # Find gist by repo name.
+  gist(
+    # The gist name to find.
+    name: String!
+  ): Gist
+
+  # A list of gist comments made by this user.
+  gistComments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): GistCommentConnection!
+
+  # A list of the Gists the user has created.
+  gists(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for gists returned from the connection
+    orderBy: GistOrder
+
+    # Filters Gists according to privacy.
+    privacy: GistPrivacy
+  ): GistConnection!
+  id: ID!
+
+  # Whether or not this user is a participant in the GitHub Security Bug Bounty.
+  isBountyHunter: Boolean!
+
+  # Whether or not this user is a participant in the GitHub Campus Experts Program.
+  isCampusExpert: Boolean!
+
+  # Whether or not this user is a GitHub Developer Program member.
+  isDeveloperProgramMember: Boolean!
+
+  # Whether or not this user is a GitHub employee.
+  isEmployee: Boolean!
+
+  # Whether or not the user has marked themselves as for hire.
+  isHireable: Boolean!
+
+  # Whether or not this user is a site administrator.
+  isSiteAdmin: Boolean!
+
+  # Whether or not this user is the viewing user.
+  isViewer: Boolean!
+
+  # A list of issue comments made by this user.
+  issueComments(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): IssueCommentConnection!
+
+  # A list of issues associated with this user.
+  issues(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for issues returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the issues by.
+    states: [IssueState!]
+  ): IssueConnection!
+
+  # The user's public profile location.
+  location: String
+
+  # The username used to login.
+  login: String!
+
+  # The user's public profile name.
+  name: String
+
+  # Find an organization by its login that the user belongs to.
+  organization(
+    # The login of the organization to find.
+    login: String!
+  ): Organization
+
+  # A list of organizations the user belongs to.
+  organizations(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): OrganizationConnection!
+
+  # A list of repositories this user has pinned to their profile
+  pinnedRepositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # A list of public keys associated with this user.
+  publicKeys(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+  ): PublicKeyConnection!
+
+  # A list of pull requests associated with this user.
+  pullRequests(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # The base ref name to filter the pull requests by.
+    baseRefName: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # The head ref name to filter the pull requests by.
+    headRefName: String
+
+    # A list of label names to filter the pull requests by.
+    labels: [String!]
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for pull requests returned from the connection.
+    orderBy: IssueOrder
+
+    # A list of states to filter the pull requests by.
+    states: [PullRequestState!]
+  ): PullRequestConnection!
+
+  # A list of repositories that the user owns.
+  repositories(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they are forks of another repository
+    isFork: Boolean
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # A list of repositories that the user recently contributed to.
+  repositoriesContributedTo(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # If non-null, include only the specified types of contributions. The
+    # GitHub.com UI uses [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]
+    contributionTypes: [RepositoryContributionType]
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If true, include user repositories
+    includeUserRepositories: Boolean
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # Find Repository.
+  repository(
+    # Name of Repository to find.
+    name: String!
+  ): Repository
+
+  # The HTTP path for this user
+  resourcePath: URI!
+
+  # Repositories the user has starred.
+  starredRepositories(
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Order for connection
+    orderBy: StarOrder
+
+    # Filters starred repositories to only return repositories owned by the viewer.
+    ownedByViewer: Boolean
+  ): StarredRepositoryConnection!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+
+  # The HTTP URL for this user
+  url: URI!
+
+  # Whether or not the viewer is able to follow the user.
+  viewerCanFollow: Boolean!
+
+  # Whether or not this user is followed by the viewer.
+  viewerIsFollowing: Boolean!
+
+  # A list of repositories the given user is watching.
+  watching(
+    # Affiliation options for repositories returned from the connection
+    affiliations: [RepositoryAffiliation] = [OWNER, COLLABORATOR, ORGANIZATION_MEMBER]
+
+    # Returns the elements in the list that come after the specified cursor.
+    after: String
+
+    # Returns the elements in the list that come before the specified cursor.
+    before: String
+
+    # Returns the first _n_ elements from the list.
+    first: Int
+
+    # If non-null, filters repositories according to whether they have been locked
+    isLocked: Boolean
+
+    # Returns the last _n_ elements from the list.
+    last: Int
+
+    # Ordering options for repositories returned from the connection
+    orderBy: RepositoryOrder
+
+    # If non-null, filters repositories according to privacy
+    privacy: RepositoryPrivacy
+  ): RepositoryConnection!
+
+  # A URL pointing to the user's public website/blog.
+  websiteUrl: URI
+}
+
+# The connection type for User.
+type UserConnection {
+  # A list of edges.
+  edges: [UserEdge]
+
+  # A list of nodes.
+  nodes: [User]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edit on user content
+type UserContentEdit implements Node {
+  # Identifies the date and time when the object was created.
+  createdAt: DateTime!
+
+  # Identifies the date and time when the object was deleted.
+  deletedAt: DateTime
+
+  # The actor who deleted this content
+  deletedBy: Actor
+
+  # A summary of the changes for this edit
+  diff: String
+
+  # When this content was edited
+  editedAt: DateTime!
+
+  # The actor who edited this content
+  editor: Actor
+  id: ID!
+
+  # Identifies the date and time when the object was last updated.
+  updatedAt: DateTime!
+}
+
+# A list of edits to content.
+type UserContentEditConnection {
+  # A list of edges.
+  edges: [UserContentEditEdge]
+
+  # A list of nodes.
+  nodes: [UserContentEdit]
+
+  # Information to aid in pagination.
+  pageInfo: PageInfo!
+
+  # Identifies the total count of items in the connection.
+  totalCount: Int!
+}
+
+# An edge in a connection.
+type UserContentEditEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: UserContentEdit
+}
+
+# An edge in a connection.
+type UserEdge {
+  # A cursor for use in pagination.
+  cursor: String!
+
+  # The item at the end of the edge.
+  node: User
+}
+
+# A valid x509 certificate string
+scalar X509Certificate
+
+schema {
+  query: Query
+  mutation: Mutation
+}
diff --git a/src/handlers/github/graphql/update_schema.sh b/src/handlers/github/graphql/update_schema.sh
new file mode 100755
index 00000000..77b66bcc
--- /dev/null
+++ b/src/handlers/github/graphql/update_schema.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+set -e
+
+readonly token="$( cat ".gh-token" )"
+
+curl \
+  --header "Accept: application/vnd.github.v4.idl" \
+  --header "Authorization: bearer $token" \
+  "https://api.github.com/graphql" | \
+  jq .data --raw-output \
+  > schema.graphql
+
+# Double newline because the main schema is without a newline at the end of the
+# file.
+cat >>schema.graphql <<EOF
+
+schema {
+  query: Query
+  mutation: Mutation
+}
+EOF
diff --git a/src/handlers/github/mod.rs b/src/handlers/github/mod.rs
index 6445a7ea..b26bf3bb 100644
--- a/src/handlers/github/mod.rs
+++ b/src/handlers/github/mod.rs
@@ -7,3 +7,4 @@
 // except according to those terms.
 
 mod hooks;
+mod queries;
diff --git a/src/handlers/github/queries.rs b/src/handlers/github/queries.rs
new file mode 100644
index 00000000..c12cab3e
--- /dev/null
+++ b/src/handlers/github/queries.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 Kitware, Inc.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// We are ignoring warnings about `GraphQLQuery` not being used in this module.
+#![allow(unused_imports)]
+
+use crates::chrono::{self, Utc};
+
+type DateTime = chrono::DateTime<Utc>;
+
+#[derive(GraphQLQuery)]
+#[graphql(
+    schema_path = "src/handlers/github/graphql/schema.graphql",
+    query_path = "src/handlers/github/graphql/query.graphql",
+    deprecated = "warn",
+    response_derives = "Debug, Clone",
+)]
+pub struct PullRequestInfo;
diff --git a/src/main.rs b/src/main.rs
index 26133245..59248ee5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,6 +19,9 @@ extern crate clap;
 #[macro_use]
 extern crate error_chain;
 
+#[macro_use]
+extern crate graphql_client;
+
 #[macro_use]
 extern crate log;
 
@@ -40,6 +43,7 @@ mod crates {
     pub extern crate git_topic_stage;
     pub extern crate git_workarea;
     pub extern crate gitlab;
+    pub extern crate graphql_client;
     pub extern crate itertools;
     pub extern crate json_job_dispatch;
     pub extern crate lazy_init;
@@ -84,6 +88,8 @@ use config::{Config, ConfigRead};
 mod error;
 use error::*;
 
+// Required to be in the root for `graphql-client`.
+use crates::serde;
 pub mod handlers;
 
 #[cfg(test)]
-- 
GitLab


From 6e9923cb3ce21351d673c6fc73ba27270362965b Mon Sep 17 00:00:00 2001
From: Ben Boeckel <ben.boeckel@kitware.com>
Date: Tue, 25 Sep 2018 11:12:18 -0400
Subject: [PATCH 9/9] github: implement a handler for GitHub

---
 Cargo.lock                     |  87 ++++++++
 Cargo.toml                     |   5 +
 src/handlers/github/handler.rs | 368 +++++++++++++++++++++++++++++++++
 src/handlers/github/mod.rs     |   4 +
 src/handlers/github/traits.rs  | 158 ++++++++++++++
 src/handlers/mod.rs            |   1 +
 src/main.rs                    |   2 +
 7 files changed, 625 insertions(+)
 create mode 100644 src/handlers/github/handler.rs
 create mode 100644 src/handlers/github/traits.rs

diff --git a/Cargo.lock b/Cargo.lock
index ecae3787..7ff73691 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -302,6 +302,14 @@ dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "error-chain"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "failure"
 version = "0.1.2"
@@ -412,8 +420,10 @@ dependencies = [
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "ghostflow 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)",
+ "ghostflow-github 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)",
  "ghostflow-gitlab 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)",
  "git-checks 3.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "git-topic-stage 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -439,6 +449,27 @@ dependencies = [
  "yaml-merge-keys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ghostflow-github"
+version = "0.1.0"
+source = "git+https://gitlab.kitware.com/utils/rust-ghostflow.git#9e6aac857f0a2aa5fedb7a0b2dd5141dccd9748a"
+dependencies = [
+ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ghostflow 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)",
+ "git-workarea 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "graphql_client 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pem 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ttl_cache 0.4.2 (git+https://github.com/mathstuf/rust-ttl_cache.git?branch=add-ttl-value)",
+]
+
 [[package]]
 name = "ghostflow-gitlab"
 version = "0.1.0"
@@ -700,6 +731,20 @@ dependencies = [
  "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "jsonwebtoken"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "kernel32-sys"
 version = "0.2.2"
@@ -982,6 +1027,17 @@ dependencies = [
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "pem"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "percent-encoding"
 version = "1.0.1"
@@ -1207,6 +1263,17 @@ dependencies = [
  "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ring"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rust-crypto"
 version = "0.2.36"
@@ -1731,6 +1798,14 @@ dependencies = [
  "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ttl_cache"
+version = "0.4.2"
+source = "git+https://github.com/mathstuf/rust-ttl_cache.git?branch=add-ttl-value#e2f9383607a37ff7ba6d7961781c7fc357ee1a7b"
+dependencies = [
+ "linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "typenum"
 version = "1.10.0"
@@ -1793,6 +1868,11 @@ dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "untrusted"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "url"
 version = "1.7.1"
@@ -2004,6 +2084,7 @@ dependencies = [
 "checksum encoding_rs 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2a91912d6f37c6a8fef8a2316a862542d036f13c923ad518b5aca7bcaac7544c"
 "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
 "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
+"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
 "checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
 "checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f"
@@ -2015,6 +2096,7 @@ dependencies = [
 "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
 "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
 "checksum ghostflow 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)" = "<none>"
+"checksum ghostflow-github 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)" = "<none>"
 "checksum ghostflow-gitlab 0.1.0 (git+https://gitlab.kitware.com/utils/rust-ghostflow.git)" = "<none>"
 "checksum git-checks 3.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "08b11fde22b1b1223089531bc6426a11f3e8d230b13074faedc1ea549f7a016c"
 "checksum git-topic-stage 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7c37834f8490269a6473cff981d6512e03609e9dad80da2c8c2b67d6dbe5b7"
@@ -2037,6 +2119,7 @@ dependencies = [
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
 "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
 "checksum json-job-dispatch 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "782422e18950940653a558e33e14db460fd481b4cdd01a594616e81bef66726f"
+"checksum jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d438ea707d465c230305963b67f8357a1d56fcfad9434797d7cb1c46c2e41df"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy-init 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e71f2233af239a915476da8ee21a57331d82b9880c78220451ece7cb5862d313"
@@ -2071,6 +2154,7 @@ dependencies = [
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
 "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c"
+"checksum pem 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33e3dad66bf8397426e3b41499ea6b0d41bca56f4b39b17216fcc456408b4dd1"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6"
 "checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad"
@@ -2096,6 +2180,7 @@ dependencies = [
 "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
 "checksum reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "738769ec83daf6c1929dc9dae7d69ed3779b55ae5c356e989dcd3aa677d8486e"
+"checksum ring 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe642b9dd1ba0038d78c4a3999d1ee56178b4d415c1e1fbaba83b06dce012f0"
 "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
 "checksum rust-lzma 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6765d37542f590bad98db0514eda612995a71100d91ac3929710bf93b5ba90a5"
 "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
@@ -2151,6 +2236,7 @@ dependencies = [
 "checksum topological-sort 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
 "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2"
 "checksum ttl_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "693a12739894d5ac20824fcfb97a289c25c20c7a88f09355036902ad41acbbd8"
+"checksum ttl_cache 0.4.2 (git+https://github.com/mathstuf/rust-ttl_cache.git?branch=add-ttl-value)" = "<none>"
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
@@ -2161,6 +2247,7 @@ dependencies = [
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
 "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum utf8-cstr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55bcbb425141152b10d5693095950b51c3745d019363fc2929ffd8f61449b628"
diff --git a/Cargo.toml b/Cargo.toml
index 009840ff..16d3f6da 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,8 +25,10 @@ clap = "^2.20"
 either = "^1.0"
 env_logger = "~0.5"
 error-chain = ">= 0.9, < 0.11"
+failure = "~0.1"
 #ghostflow = "~0.1"
 #ghostflow-gitlab = "~0.1"
+#ghostflow-github = "~0.1"
 git-checks = "^3.5"
 git-topic-stage = "^3.0"
 git-workarea = "^3.0"
@@ -53,5 +55,8 @@ git = "https://gitlab.kitware.com/utils/rust-ghostflow.git"
 [dependencies.ghostflow-gitlab]
 git = "https://gitlab.kitware.com/utils/rust-ghostflow.git"
 
+[dependencies.ghostflow-github]
+git = "https://gitlab.kitware.com/utils/rust-ghostflow.git"
+
 [[bin]]
 name = "ghostflow-director"
diff --git a/src/handlers/github/handler.rs b/src/handlers/github/handler.rs
new file mode 100644
index 00000000..cabc39b6
--- /dev/null
+++ b/src/handlers/github/handler.rs
@@ -0,0 +1,368 @@
+// Copyright 2016 Kitware, Inc.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crates::boxfnonce::BoxFnOnce;
+use crates::either::Either;
+use crates::ghostflow_github::{Github, GithubService};
+use crates::failure::ResultExt as FailureResultExt;
+use crates::itertools::Itertools;
+use crates::json_job_dispatch::{Director, Handler, HandlerResult, Result as JobResult};
+use crates::serde::de::DeserializeOwned;
+use crates::serde_json::{self, Value};
+
+use config::Host;
+use error::*;
+use handlers::HostHandler;
+use handlers::common::handlers::*;
+use handlers::common::jobs::{BatchBranchJob, ClearTestRefs, ResetFailedProjects, TagStage, UpdateFollowRefs};
+use handlers::github::hooks::*;
+use handlers::github::traits::*;
+
+use std::fs;
+use std::sync::{Arc, RwLock};
+
+#[derive(Debug, Deserialize)]
+enum GithubSecrets {
+    #[serde(rename = "app")]
+    App {
+        app_id: i64,
+        private_key_path: String,
+        installation_id: i64,
+    },
+}
+
+/// Connect to a Gitlab from its configuration block.
+pub fn host_handler(url: &Option<String>, secrets: &Value, name: String) -> Result<HostHandler> {
+    let host = url.as_ref().map(AsRef::as_ref).unwrap_or("api.github.com");
+
+    if host != "api.github.com" {
+        warn!(
+            target: "github",
+            "Enterprise deployments are not known to work ({})",
+            host,
+        );
+    }
+
+    let secrets: GithubSecrets = serde_json::from_value(secrets.clone())
+        .chain_err(|| format!("failed to deserialize GitHub secrets for host {}", host))?;
+    let github = match secrets {
+        GithubSecrets::App { app_id, private_key_path, installation_id } => {
+            let private_key = fs::read(private_key_path)
+                .chain_err(|| format!("failed to read the private key for host {}", host))?;
+            Github::new_app(host, app_id, private_key, installation_id)
+                .compat()
+                .chain_err(|| format!("failed to construct service for host {}", host))?
+        },
+    };
+
+    let service = GithubService::new(github).map(Arc::new)
+        .chain_err(|| format!("failed to connect to host {}", host))?;
+
+    Ok(HostHandler {
+        service: service.clone(),
+        handler: BoxFnOnce::new(|host| Box::new(GithubHandler::new(host, service, name)) as Box<Handler>),
+    })
+}
+
+/// The handler for Github events.
+struct GithubHandler {
+    /// The host block for this handler.
+    host: RwLock<Host>,
+    /// The specific `GithubService` for this connection.
+    ///
+    /// This is required because we need to make our own query due to a lack of information in
+    /// webhooks.
+    github: Arc<GithubService>,
+    /// The name to use for this handler.
+    name: String,
+}
+
+const HOST_LOCK_POISONED: &str = "host lock poisoned";
+
+impl GithubHandler {
+    /// Create a new handler.
+    fn new(host: Host, github: Arc<GithubService>, name: String) -> Self {
+        GithubHandler {
+            host: RwLock::new(host),
+            github: github,
+            name: name,
+        }
+    }
+
+    /// Verify that the kind is valid.
+    fn verify_kind<'a>(&self, kind: &'a str) -> Either<&'a str, HandlerResult> {
+        let mut split = kind.split(':');
+
+        if let Some(level) = split.next() {
+            if level != self.name {
+                return Either::Right(HandlerResult::Reject(format!("handler mismatch: {}", level)));
+            }
+        } else {
+            return Either::Right(HandlerResult::Reject("handler mismatch".to_string()));
+        }
+
+        if let Some(kind) = split.next() {
+            Either::Left(kind)
+        } else {
+            Either::Right(HandlerResult::Reject("missing kind".to_string()))
+        }
+    }
+
+    /// Parse an object into a type.
+    fn parse_object<F, T>(object: &Value, callback: F) -> JobResult<HandlerResult>
+        where T: DeserializeOwned,
+              F: Fn(T) -> JobResult<HandlerResult>,
+    {
+        match serde_json::from_value::<T>(object.clone()) {
+            Ok(hook) => callback(hook),
+            Err(err) => Ok(HandlerResult::Fail(Box::new(err))),
+        }
+    }
+
+    /// Handle a job.
+    fn handle_kind(&self, kind: &str, object: &Value, can_defer: bool) -> JobResult<HandlerResult> {
+        match kind {
+            "check_run" => {
+                Self::parse_object(object, |hook: CheckRunEvent| {
+                    info!(
+                        target: "github",
+                        "check run {} {:?} on {}",
+                        hook.check_run.name,
+                        hook.action,
+                        hook.pull_requests.iter().map(|pr| format!("{}#{}", pr.base.repo.full_name, pr.number)).format(", "),
+                    );
+
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            "check_suite" => {
+                Self::parse_object(object, |hook: CheckSuiteEvent| {
+                    info!(
+                        target: "github",
+                        "check suite {:?} on {}",
+                        hook.action,
+                        hook.check_suite.pull_requests.iter().map(|pr| format!("{}#{}", pr.base.repo.full_name, pr.number)).format(", "),
+                    );
+
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            "github_app_authorization" => {
+                Self::parse_object(object, |hook: GithubAppAuthorizationEvent| {
+                    info!(
+                        target: "github",
+                        "application authorization {:?}",
+                        hook.action,
+                    );
+
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            "installation" => {
+                Self::parse_object(object, |hook: InstallationEvent| {
+                    info!(
+                        target: "github",
+                        "installation hook {:?}: {} by {}",
+                        hook.action,
+                        hook.installation.id,
+                        hook.installation.account.login,
+                    );
+
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            "installation_repositories" => {
+                Self::parse_object(object, |hook: InstallationRepositoriesEvent| {
+                    info!(
+                        target: "github",
+                        "installation hook {:?} for {:?} repositories: {} by {}: {}{}",
+                        hook.action,
+                        hook.repository_selection,
+                        hook.installation.id,
+                        hook.installation.account.login,
+                        hook.repositories_added.iter().map(|repo| &repo.full_name).format(" +"),
+                        hook.repositories_removed.iter().map(|repo| &repo.full_name).format(" -"),
+                    );
+
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            "issue_comment" => {
+                Self::parse_object(object, |hook: IssueCommentEvent| {
+                    GithubMergeRequestNoteInfo::from_web_hook(self.github.as_ref(), &hook)
+                        .map(|note| {
+                            if let Some(note) = note {
+                                let host = self.host.read()
+                                    .expect(HOST_LOCK_POISONED);
+                                handle_merge_request_note(object, &host, &note, can_defer)
+                            } else {
+                                Ok(HandlerResult::Reject(format!("comment on non-pr: {}#{}",
+                                                                 hook.repository.full_name,
+                                                                 hook.issue.number)))
+                            }
+                        })
+                        .unwrap_or_else(|err| Ok(HandlerResult::Fail(Box::new(err))))
+                })
+            },
+            "member" => {
+                Self::parse_object(object, |hook: MemberEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    handle_project_membership_refresh(object, &host, &hook.repository.full_name)
+                })
+            },
+            "membership" => {
+                Self::parse_object(object, |hook: MembershipEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    handle_group_membership_refresh(object, &host, &hook.organization.login)
+                })
+            },
+            "organization" => {
+                Self::parse_object(object, |hook: OrganizationEvent| {
+                    if let OrganizationAction::MemberInvited = hook.action {
+                        return Ok(HandlerResult::Accept);
+                    }
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    handle_group_membership_refresh(object, &host, &hook.organization.login)
+                })
+            },
+            "pull_request_review" => {
+                Self::parse_object(object, |hook: PullRequestReviewEvent| {
+                    GithubMergeRequestNoteInfo::from_web_hook_review(self.github.as_ref(), &hook)
+                        .map(|note| {
+                            let host = self.host.read()
+                                .expect(HOST_LOCK_POISONED);
+                            handle_merge_request_note(object, &host, &note, can_defer)
+                        })
+                        .unwrap_or_else(|err| Ok(HandlerResult::Fail(Box::new(err))))
+                })
+            },
+            "pull_request" => {
+                Self::parse_object(object, |hook: PullRequestEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    GithubMergeRequestInfo::from_web_hook(host.service.as_ref(), &hook)
+                        .map(|mr| handle_merge_request_update(object, &host, &mr))
+                        .unwrap_or_else(|err| Ok(HandlerResult::Fail(Box::new(err))))
+                })
+            },
+            "push" => {
+                Self::parse_object(object, |hook: PushEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    GithubPushInfo::from_web_hook(host.service.as_ref(), hook)
+                        .map(|push| handle_push(object, &host, &push))
+                        .unwrap_or_else(|err| Ok(HandlerResult::Fail(Box::new(err))))
+                })
+            },
+            "team" => {
+                Self::parse_object(object, |hook: TeamEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    handle_project_membership_refresh(object, &host, &hook.repository.full_name)
+                })
+            },
+            "team_add" => {
+                Self::parse_object(object, |hook: TeamAddEvent| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    handle_project_membership_refresh(object, &host, &hook.repository.full_name)
+                })
+            },
+            "clear_test_refs" => {
+                Self::parse_object(object, |data: BatchBranchJob<ClearTestRefs>| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    Ok(handle_clear_test_refs(object, &host, data))
+                })
+            },
+            "tag_stage" => {
+                Self::parse_object(object, |data: BatchBranchJob<TagStage>| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    Ok(handle_stage_tag(object, &host, data))
+                })
+            },
+            "update_follow_refs" => {
+                Self::parse_object(object, |data: BatchBranchJob<UpdateFollowRefs>| {
+                    let host = self.host.read()
+                        .expect(HOST_LOCK_POISONED);
+                    Ok(handle_update_follow_refs(object, &host, data))
+                })
+            },
+            "reset_failed_projects" => {
+                Self::parse_object(object, |_: ResetFailedProjects| {
+                    self.host
+                        .write()
+                        .expect(HOST_LOCK_POISONED)
+                        .reset_failed_projects();
+                    Ok(HandlerResult::Accept)
+                })
+            },
+            _ => Ok(HandlerResult::Reject(format!("unhandled kind: {}", kind))),
+        }
+    }
+}
+
+impl Handler for GithubHandler {
+    fn add_to_director<'a>(&'a self, director: &mut Director<'a>) -> JobResult<()> {
+        let mut add_handler = |kind| director.add_handler(&format!("{}:{}", self.name, kind), self);
+
+        add_handler("check_run")?;
+        add_handler("check_suite")?;
+        add_handler("github_app_authorization")?;
+        add_handler("installation")?;
+        add_handler("installation_repositories")?;
+        add_handler("issue_comment")?;
+        add_handler("member")?;
+        add_handler("membership")?;
+        add_handler("organization")?;
+        add_handler("pull_request_review")?;
+        add_handler("pull_request")?;
+        add_handler("push")?;
+        add_handler("team")?;
+        add_handler("team_add")?;
+
+        add_handler("clear_test_refs")?;
+        add_handler("tag_stage")?;
+        add_handler("update_follow_refs")?;
+
+        add_handler("reset_failed_projects")?;
+
+        Ok(())
+    }
+
+    fn handle(&self, kind: &str, object: &Value) -> JobResult<HandlerResult> {
+        let kind = match self.verify_kind(kind) {
+            Either::Left(kind) => kind,
+            Either::Right(res) => return Ok(res),
+        };
+
+        self.handle_kind(kind, object, true)
+    }
+
+    fn handle_retry(&self, kind: &str, object: &Value, reasons: Vec<String>)
+                    -> JobResult<HandlerResult> {
+        let kind = match self.verify_kind(kind) {
+            Either::Left(kind) => kind,
+            Either::Right(res) => return Ok(res),
+        };
+
+        if reasons.len() > self.retry_limit(kind) {
+            Ok(HandlerResult::Reject(format!("retry limit ({}) reached for {}",
+                                             reasons.len(),
+                                             kind)))
+        } else if reasons.len() == self.retry_limit(kind) {
+            self.handle_kind(kind, object, false)
+        } else {
+            self.handle_kind(kind, object, true)
+        }
+    }
+}
diff --git a/src/handlers/github/mod.rs b/src/handlers/github/mod.rs
index b26bf3bb..76d4b586 100644
--- a/src/handlers/github/mod.rs
+++ b/src/handlers/github/mod.rs
@@ -8,3 +8,7 @@
 
 mod hooks;
 mod queries;
+mod traits;
+mod handler;
+
+pub use self::handler::host_handler;
diff --git a/src/handlers/github/traits.rs b/src/handlers/github/traits.rs
new file mode 100644
index 00000000..4744d0fa
--- /dev/null
+++ b/src/handlers/github/traits.rs
@@ -0,0 +1,158 @@
+// Copyright 2016 Kitware, Inc.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crates::chrono::Utc;
+use crates::failure::ResultExt as FailureResultExt;
+use crates::ghostflow_github::GithubService;
+use crates::ghostflow::host::{Comment, Commit, ErrorKind, HostingService, Result, ResultExt};
+use crates::git_workarea::CommitId;
+use crates::graphql_client::GraphQLQuery;
+
+use handlers::common::data::*;
+use handlers::github::hooks::*;
+use handlers::github::queries;
+
+/// Information for a Github merge request.
+pub struct GithubMergeRequestInfo;
+
+impl GithubMergeRequestInfo {
+    /// Create a merge request information block from a webhook.
+    pub fn from_web_hook(service: &HostingService, hook: &PullRequestEvent)
+                         -> Result<MergeRequestInfo> {
+        let is_open = match hook.pull_request.state {
+            PullRequestState::Open => true,
+            PullRequestState::Closed |
+            PullRequestState::Merged => false,
+        };
+        let mr = service.merge_request(&hook.pull_request.base.repo.full_name, hook.pull_request.number)?;
+
+        Ok(MergeRequestInfo {
+            merge_request: mr,
+            was_merged: hook.action == PullRequestAction::Closed && hook.pull_request.merged,
+            is_open: is_open,
+            date: hook.pull_request.updated_at,
+        })
+    }
+}
+
+/// Information for a Github merge request comment.
+pub struct GithubMergeRequestNoteInfo;
+
+impl GithubMergeRequestNoteInfo {
+    /// Create a merge request comment information block from a webhook.
+    pub fn from_web_hook(service: &GithubService, hook: &IssueCommentEvent)
+                         -> Result<Option<MergeRequestNoteInfo>> {
+        if hook.issue.pull_request.is_none() {
+            return Ok(None);
+        }
+
+        let note = Comment {
+            id: hook.comment.node_id.clone(),
+            is_system: false, // XXX(github): Do we get these?
+            is_branch_update: false,
+            created_at: hook.comment.created_at,
+            author: service.user(&hook.comment.user.login)?,
+            content: hook.comment.body.clone(),
+        };
+        let mr = service.merge_request(&hook.repository.full_name, hook.issue.number)?;
+
+        let (owner, name) = GithubService::split_project(&hook.repository.full_name)?;
+        let vars = queries::pull_request_info::Variables {
+            owner: owner.to_string(),
+            name: name.to_string(),
+            pull: hook.issue.number as i64,
+        };
+        let query = queries::PullRequestInfo::build_query(vars);
+        let pr_info = service.github()
+            .send::<queries::PullRequestInfo>(&query)
+            .compat()
+            .chain_err(|| ErrorKind::Host)
+            .and_then(|rsp| {
+                Ok(rsp.repository
+                    .ok_or_else(|| ErrorKind::Msg(format!("no repository for '{}'", hook.repository.full_name)))?)
+            })
+            .and_then(|rsp| {
+                Ok(rsp.pull_request
+                    .ok_or_else(|| ErrorKind::Msg(format!("no pull for '{}#{}'", hook.repository.full_name, hook.issue.number)))?)
+            })?;
+        let is_open = match pr_info.state {
+            queries::pull_request_info::PullRequestState::OPEN => true,
+            queries::pull_request_info::PullRequestState::CLOSED |
+            queries::pull_request_info::PullRequestState::MERGED => false,
+            queries::pull_request_info::PullRequestState::Other(s) => {
+                warn!(
+                    target: "github",
+                    "unknown pull request state: {}",
+                    s,
+                );
+                true
+            },
+        };
+        let mr_info = MergeRequestInfo {
+            merge_request: mr,
+            was_merged: false,
+            is_open: is_open,
+            date: pr_info.updated_at,
+        };
+
+        Ok(Some(MergeRequestNoteInfo {
+            merge_request: mr_info,
+            note: note,
+        }))
+    }
+
+    /// Create a merge request comment information block from a webhook.
+    pub fn from_web_hook_review(service: &GithubService, hook: &PullRequestReviewEvent)
+                                -> Result<MergeRequestNoteInfo> {
+        let note = Comment {
+            id: hook.review.node_id.clone(),
+            is_system: false,
+            is_branch_update: false,
+            created_at: hook.review.submitted_at,
+            author: service.user(&hook.review.user.login)?,
+            content: hook.review.body.as_ref().map(Clone::clone).unwrap_or_else(String::new),
+        };
+        let mr = service.merge_request(&hook.pull_request.base.repo.full_name, hook.pull_request.number)?;
+        let is_open = match hook.pull_request.state {
+            PullRequestState::Open => true,
+            PullRequestState::Closed |
+            PullRequestState::Merged => false,
+        };
+        let mr_info = MergeRequestInfo {
+            merge_request: mr,
+            was_merged: false,
+            is_open: is_open,
+            date: hook.pull_request.updated_at,
+        };
+
+        Ok(MergeRequestNoteInfo {
+            merge_request: mr_info,
+            note: note,
+        })
+    }
+}
+
+/// Information for a Github push.
+pub struct GithubPushInfo;
+
+impl GithubPushInfo {
+    /// Create a push information block from a webhook.
+    pub fn from_web_hook(service: &HostingService, hook: PushEvent) -> Result<PushInfo> {
+        Ok(PushInfo {
+            commit: Commit {
+                repo: service.repo(&hook.repository.full_name)?,
+                refname: Some(hook.ref_),
+                id: CommitId::new(&hook.after),
+            },
+            author: service.user(&hook.sender.login)?,
+            // XXX(github): GitHub does not send the time of the push to us.
+            // https://platform.github.community/t/pushevent-webhook-is-missing-when-the-push-occurred/7337
+            date: Utc::now(),
+        })
+    }
+}
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index 824e82c9..3c12abf7 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -37,6 +37,7 @@ impl HostHandler {
     pub fn new(api: &str, url: &Option<String>, secrets: &Value, name: String) -> Result<Self> {
         match api {
             "gitlab" => gitlab::host_handler(url, secrets, name),
+            "github" => github::host_handler(url, secrets, name),
             _ => Err(format!("unknown api: {}", api).into()),
         }
     }
diff --git a/src/main.rs b/src/main.rs
index 59248ee5..9501118a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,7 +37,9 @@ mod crates {
     pub extern crate clap;
     pub extern crate either;
     pub extern crate env_logger;
+    pub extern crate failure;
     pub extern crate ghostflow;
+    pub extern crate ghostflow_github;
     pub extern crate ghostflow_gitlab;
     pub extern crate git_checks;
     pub extern crate git_topic_stage;
-- 
GitLab