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, ¬e, 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, ¬e, 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