diff --git a/.gitignore b/.gitignore
index cb9b4d6a4a..3c2c3c6427 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,7 @@ target
*.iml
*.ipr
*.iws
+.classpath
+.project
+.settings/
+.DS_Store
diff --git a/pom.xml b/pom.xml
index 4d623c86fa..7e204af06d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
github-api
- 1.86
+ 1.87
GitHub API for Java
http://github-api.kohsuke.org/
GitHub API for Java
@@ -16,7 +16,7 @@
scm:git:git@github.com/kohsuke/${project.artifactId}.git
scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git
http://${project.artifactId}.kohsuke.org/
- github-api-1.86
+ github-api-1.87
@@ -34,6 +34,12 @@
+
+ maven-surefire-plugin
+
+ 2
+
+
org.codehaus.mojo
animal-sniffer-maven-plugin
diff --git a/src/main/java/org/kohsuke/github/BranchProtection.java b/src/main/java/org/kohsuke/github/BranchProtection.java
deleted file mode 100644
index 4ae03b162a..0000000000
--- a/src/main/java/org/kohsuke/github/BranchProtection.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.kohsuke.github;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Kohsuke Kawaguchi
- * @see GHBranch#disableProtection()
- */
-@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
-class BranchProtection {
- boolean enabled;
- RequiredStatusChecks requiredStatusChecks;
-
- static class RequiredStatusChecks {
- EnforcementLevel enforcement_level;
- List contexts = new ArrayList();
- }
-}
diff --git a/src/main/java/org/kohsuke/github/EnforcementLevel.java b/src/main/java/org/kohsuke/github/EnforcementLevel.java
index 1b29195299..81c86428c4 100644
--- a/src/main/java/org/kohsuke/github/EnforcementLevel.java
+++ b/src/main/java/org/kohsuke/github/EnforcementLevel.java
@@ -3,8 +3,11 @@
import java.util.Locale;
/**
+ * This was added during preview API period but it has changed since then.
+ *
* @author Kohsuke Kawaguchi
*/
+@Deprecated
public enum EnforcementLevel {
OFF, NON_ADMINS, EVERYONE;
diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java
index f54bea9f47..c2e5b29441 100644
--- a/src/main/java/org/kohsuke/github/GHBranch.java
+++ b/src/main/java/org/kohsuke/github/GHBranch.java
@@ -4,21 +4,18 @@
import java.io.IOException;
import java.net.URL;
-import java.util.Arrays;
import java.util.Collection;
-import org.kohsuke.github.BranchProtection.RequiredStatusChecks;
-
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* A branch in a repository.
- *
+ *
* @author Yusuke Kokubo
*/
-@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
+@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
public class GHBranch {
private GitHub root;
@@ -33,7 +30,7 @@ public class GHBranch {
public static class Commit {
String sha;
-
+
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url;
}
@@ -69,6 +66,10 @@ public URL getProtectionUrl() {
return GitHub.parseURL(protection_url);
}
+ @Preview @Deprecated
+ public GHBranchProtection getProtection() throws IOException {
+ return root.retrieve().withPreview(LOKI).to(protection_url, GHBranchProtection.class);
+ }
/**
* The commit that this branch currently points to.
@@ -82,9 +83,7 @@ public String getSHA1() {
*/
@Preview @Deprecated
public void disableProtection() throws IOException {
- BranchProtection bp = new BranchProtection();
- bp.enabled = false;
- setProtection(bp);
+ new Requester(root).method("DELETE").withPreview(LOKI).to(protection_url);
}
/**
@@ -93,28 +92,31 @@ public void disableProtection() throws IOException {
* @see GHCommitStatus#getContext()
*/
@Preview @Deprecated
- public void enableProtection(EnforcementLevel level, Collection contexts) throws IOException {
- BranchProtection bp = new BranchProtection();
- bp.enabled = true;
- bp.requiredStatusChecks = new RequiredStatusChecks();
- bp.requiredStatusChecks.enforcement_level = level;
- bp.requiredStatusChecks.contexts.addAll(contexts);
- setProtection(bp);
- }
-
- @Preview @Deprecated
- public void enableProtection(EnforcementLevel level, String... contexts) throws IOException {
- enableProtection(level, Arrays.asList(contexts));
+ public GHBranchProtectionBuilder enableProtection() {
+ return new GHBranchProtectionBuilder(this);
}
- private void setProtection(BranchProtection bp) throws IOException {
- new Requester(root).method("PATCH").withPreview(LOKI)._with("protection",bp).to(getApiRoute());
+ // backward compatibility with previous signature
+ @Deprecated
+ public void enableProtection(EnforcementLevel level, Collection contexts) throws IOException {
+ switch (level) {
+ case OFF:
+ disableProtection();
+ break;
+ case NON_ADMINS:
+ case EVERYONE:
+ enableProtection()
+ .addRequiredChecks(contexts)
+ .includeAdmins(level==EnforcementLevel.EVERYONE)
+ .enable();
+ break;
+ }
}
String getApiRoute() {
return owner.getApiTailUrl("/branches/"+name);
}
-
+
@Override
public String toString() {
final String url = owner != null ? owner.getUrl().toString() : "unknown";
diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java
new file mode 100644
index 0000000000..3216366115
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java
@@ -0,0 +1,152 @@
+package org.kohsuke.github;
+
+import java.util.Collection;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
+ "URF_UNREAD_FIELD" }, justification = "JSON API")
+public class GHBranchProtection {
+ @JsonProperty("enforce_admins")
+ private EnforceAdmins enforceAdmins;
+
+ @JsonProperty("required_pull_request_reviews")
+ private RequiredReviews requiredReviews;
+
+ @JsonProperty("required_status_checks")
+ private RequiredStatusChecks requiredStatusChecks;
+
+ @JsonProperty
+ private Restrictions restrictions;
+
+ @JsonProperty
+ private String url;
+
+ public EnforceAdmins getEnforceAdmins() {
+ return enforceAdmins;
+ }
+
+ public RequiredReviews getRequiredReviews() {
+ return requiredReviews;
+ }
+
+ public RequiredStatusChecks getRequiredStatusChecks() {
+ return requiredStatusChecks;
+ }
+
+ public Restrictions getRestrictions() {
+ return restrictions;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public static class EnforceAdmins {
+ @JsonProperty
+ private boolean enabled;
+
+ @JsonProperty
+ private String url;
+
+ public String getUrl() {
+ return url;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+ }
+
+ public static class RequiredReviews {
+ @JsonProperty("dismissal_restrictions")
+ private Restrictions dismissalRestriction;
+
+ @JsonProperty("dismiss_stale_reviews")
+ private boolean dismissStaleReviews;
+
+ @JsonProperty("require_code_owner_reviews")
+ private boolean requireCodeOwnerReviews;
+
+ @JsonProperty
+ private String url;
+
+ public Restrictions getDismissalRestrictions() {
+ return dismissalRestriction;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public boolean isDismissStaleReviews() {
+ return dismissStaleReviews;
+ }
+
+ public boolean isRequireCodeOwnerReviews() {
+ return requireCodeOwnerReviews;
+ }
+ }
+
+ public static class RequiredStatusChecks {
+ @JsonProperty
+ private Collection contexts;
+
+ @JsonProperty
+ private boolean strict;
+
+ @JsonProperty
+ private String url;
+
+ public Collection getContexts() {
+ return contexts;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public boolean isRequiresBranchUpToDate() {
+ return strict;
+ }
+ }
+
+ public static class Restrictions {
+ @JsonProperty
+ private Collection teams;
+
+ @JsonProperty("teams_url")
+ private String teamsUrl;
+
+ @JsonProperty
+ private String url;
+
+ @JsonProperty
+ private Collection users;
+
+ @JsonProperty("users_url")
+ private String usersUrl;
+
+ public Collection getTeams() {
+ return teams;
+ }
+
+ public String getTeamsUrl() {
+ return teamsUrl;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public Collection getUsers() {
+ return users;
+ }
+
+ public String getUsersUrl() {
+ return usersUrl;
+ }
+ }
+}
diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java
new file mode 100644
index 0000000000..5fccf7eb8c
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java
@@ -0,0 +1,203 @@
+package org.kohsuke.github;
+
+import static org.kohsuke.github.Previews.LOKI;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Builder to configure the branch protection settings.
+ *
+ * @see GHBranch#enableProtection()
+ */
+@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
+ "URF_UNREAD_FIELD" }, justification = "JSON API")
+public class GHBranchProtectionBuilder {
+ private final GHBranch branch;
+
+ private boolean enforceAdmins;
+ private Map prReviews;
+ private Restrictions restrictions;
+ private StatusChecks statusChecks;
+
+ GHBranchProtectionBuilder(GHBranch branch) {
+ this.branch = branch;
+ }
+
+ public GHBranchProtectionBuilder addRequiredChecks(Collection checks) {
+ getStatusChecks().contexts.addAll(checks);
+ return this;
+ }
+
+ public GHBranchProtectionBuilder addRequiredChecks(String... checks) {
+ addRequiredChecks(Arrays.asList(checks));
+ return this;
+ }
+
+ public GHBranchProtectionBuilder dismissStaleReviews() {
+ getPrReviews().put("dismiss_stale_reviews", true);
+ return this;
+ }
+
+ public GHBranchProtection enable() throws IOException {
+ return requester().method("PUT")
+ .withNullable("required_status_checks", statusChecks)
+ .withNullable("required_pull_request_reviews", prReviews)
+ .withNullable("restrictions", restrictions)
+ .withNullable("enforce_admins", enforceAdmins)
+ .to(branch.getProtectionUrl().toString(), GHBranchProtection.class);
+ }
+
+ public GHBranchProtectionBuilder includeAdmins() {
+ return includeAdmins(true);
+ }
+
+ public GHBranchProtectionBuilder includeAdmins(boolean v) {
+ enforceAdmins = v;
+ return this;
+ }
+
+ public GHBranchProtectionBuilder requireBranchIsUpToDate() {
+ return requireBranchIsUpToDate(true);
+ }
+
+ public GHBranchProtectionBuilder requireBranchIsUpToDate(boolean v) {
+ getStatusChecks().strict = v;
+ return this;
+ }
+
+ public GHBranchProtectionBuilder requireCodeOwnReviews() {
+ return requireCodeOwnReviews(true);
+ }
+
+ public GHBranchProtectionBuilder requireCodeOwnReviews(boolean v) {
+ getPrReviews().put("require_code_owner_reviews", v);
+ return this;
+ }
+
+ public GHBranchProtectionBuilder requireReviews() {
+ getPrReviews();
+ return this;
+ }
+
+ public GHBranchProtectionBuilder restrictPushAccess() {
+ getRestrictions();
+ return this;
+ }
+
+ public GHBranchProtectionBuilder teamPushAccess(Collection teams) {
+ for (GHTeam team : teams) {
+ teamPushAccess(team);
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder teamPushAccess(GHTeam... teams) {
+ for (GHTeam team : teams) {
+ getRestrictions().teams.add(team.getSlug());
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder teamReviewDismissals(Collection teams) {
+ for (GHTeam team : teams) {
+ teamReviewDismissals(team);
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder teamReviewDismissals(GHTeam... teams) {
+ for (GHTeam team : teams) {
+ addReviewRestriction(team.getSlug(), true);
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder userPushAccess(Collection users) {
+ for (GHUser user : users) {
+ userPushAccess(user);
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder userPushAccess(GHUser... users) {
+ for (GHUser user : users) {
+ getRestrictions().users.add(user.getLogin());
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder userReviewDismissals(Collection users) {
+ for (GHUser team : users) {
+ userReviewDismissals(team);
+ }
+ return this;
+ }
+
+ public GHBranchProtectionBuilder userReviewDismissals(GHUser... users) {
+ for (GHUser user : users) {
+ addReviewRestriction(user.getLogin(), false);
+ }
+ return this;
+ }
+
+ private void addReviewRestriction(String restriction, boolean isTeam) {
+ getPrReviews();
+
+ if (!prReviews.containsKey("dismissal_restrictions")) {
+ prReviews.put("dismissal_restrictions", new Restrictions());
+ }
+
+ Restrictions restrictions = (Restrictions) prReviews.get("dismissal_restrictions");
+
+ if (isTeam) {
+ restrictions.teams.add(restriction);
+ } else {
+ restrictions.users.add(restriction);
+ }
+ }
+
+ private Map getPrReviews() {
+ if (prReviews == null) {
+ prReviews = new HashMap();
+ }
+ return prReviews;
+ }
+
+ private Restrictions getRestrictions() {
+ if (restrictions == null) {
+ restrictions = new Restrictions();
+ }
+ return restrictions;
+ }
+
+ private StatusChecks getStatusChecks() {
+ if (statusChecks == null) {
+ statusChecks = new StatusChecks();
+ }
+ return statusChecks;
+ }
+
+ private Requester requester() {
+ return new Requester(branch.getRoot()).withPreview(LOKI);
+ }
+
+ private static class Restrictions {
+ private Set teams = new HashSet();
+ private Set users = new HashSet();
+ }
+
+ private static class StatusChecks {
+ final List contexts = new ArrayList();
+ boolean strict;
+ }
+}
diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java
new file mode 100644
index 0000000000..65136dc0a4
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java
@@ -0,0 +1,137 @@
+package org.kohsuke.github;
+
+import java.io.IOException;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Search commits.
+ *
+ * @author Marc de Verdelhan
+ * @see GitHub#searchCommits()
+ */
+@Preview @Deprecated
+public class GHCommitSearchBuilder extends GHSearchBuilder {
+ /*package*/ GHCommitSearchBuilder(GitHub root) {
+ super(root,CommitSearchResult.class);
+ req.withPreview(Previews.CLOAK);
+ }
+
+ /**
+ * Search terms.
+ */
+ public GHCommitSearchBuilder q(String term) {
+ super.q(term);
+ return this;
+ }
+
+ public GHCommitSearchBuilder author(String v) {
+ return q("author:"+v);
+ }
+
+ public GHCommitSearchBuilder committer(String v) {
+ return q("committer:"+v);
+ }
+
+ public GHCommitSearchBuilder authorName(String v) {
+ return q("author-name:"+v);
+ }
+
+ public GHCommitSearchBuilder committerName(String v) {
+ return q("committer-name:"+v);
+ }
+
+ public GHCommitSearchBuilder authorEmail(String v) {
+ return q("author-email:"+v);
+ }
+
+ public GHCommitSearchBuilder committerEmail(String v) {
+ return q("committer-email:"+v);
+ }
+
+ public GHCommitSearchBuilder authorDate(String v) {
+ return q("author-date:"+v);
+ }
+
+ public GHCommitSearchBuilder committerDate(String v) {
+ return q("committer-date:"+v);
+ }
+
+ public GHCommitSearchBuilder merge(boolean merge) {
+ return q("merge:"+Boolean.valueOf(merge).toString().toLowerCase());
+ }
+
+ public GHCommitSearchBuilder hash(String v) {
+ return q("hash:"+v);
+ }
+
+ public GHCommitSearchBuilder parent(String v) {
+ return q("parent:"+v);
+ }
+
+ public GHCommitSearchBuilder tree(String v) {
+ return q("tree:"+v);
+ }
+
+ public GHCommitSearchBuilder is(String v) {
+ return q("is:"+v);
+ }
+
+ public GHCommitSearchBuilder user(String v) {
+ return q("user:"+v);
+ }
+
+ public GHCommitSearchBuilder org(String v) {
+ return q("org:"+v);
+ }
+
+ public GHCommitSearchBuilder repo(String v) {
+ return q("repo:"+v);
+ }
+
+ public GHCommitSearchBuilder order(GHDirection v) {
+ req.with("order",v);
+ return this;
+ }
+
+ public GHCommitSearchBuilder sort(Sort sort) {
+ req.with("sort",sort);
+ return this;
+ }
+
+ public enum Sort { AUTHOR_DATE, COMMITTER_DATE }
+
+ private static class CommitSearchResult extends SearchResult {
+ private GHCommit[] items;
+
+ @Override
+ /*package*/ GHCommit[] getItems(GitHub root) {
+ for (GHCommit commit : items) {
+ String repoName = getRepoName(commit.url);
+ try {
+ GHRepository repo = root.getRepository(repoName);
+ commit.wrapUp(repo);
+ } catch (IOException ioe) {}
+ }
+ return items;
+ }
+ }
+
+ /**
+ * @param commitUrl a commit URL
+ * @return the repo name ("username/reponame")
+ */
+ private static String getRepoName(String commitUrl) {
+ if (StringUtils.isBlank(commitUrl)) {
+ return null;
+ }
+ int indexOfUsername = (GitHub.GITHUB_URL + "/repos/").length();
+ String[] tokens = commitUrl.substring(indexOfUsername).split("/", 3);
+ return tokens[0] + '/' + tokens[1];
+ }
+
+ @Override
+ protected String getApiUrl() {
+ return "/search/commits";
+ }
+}
diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java
index b33cb991eb..970b6afbf7 100644
--- a/src/main/java/org/kohsuke/github/GHEvent.java
+++ b/src/main/java/org/kohsuke/github/GHEvent.java
@@ -21,17 +21,30 @@ public enum GHEvent {
FORK_APPLY,
GIST,
GOLLUM,
+ INSTALLATION,
+ INSTALLATION_REPOSITORIES,
ISSUE_COMMENT,
ISSUES,
+ LABEL,
+ MARKETPLACE_PURCHASE,
MEMBER,
+ MEMBERSHIP,
+ MILESTONE,
+ ORGANIZATION,
+ ORG_BLOCK,
PAGE_BUILD,
+ PROJECT_CARD,
+ PROJECT_COLUMN,
+ PROJECT,
PUBLIC,
PULL_REQUEST,
+ PULL_REQUEST_REVIEW,
PULL_REQUEST_REVIEW_COMMENT,
PUSH,
RELEASE,
REPOSITORY, // only valid for org hooks
STATUS,
+ TEAM,
TEAM_ADD,
WATCH,
PING,
diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java
index 73b2eb4364..4aa32e1946 100644
--- a/src/main/java/org/kohsuke/github/GHHook.java
+++ b/src/main/java/org/kohsuke/github/GHHook.java
@@ -41,6 +41,13 @@ public Map getConfig() {
return Collections.unmodifiableMap(config);
}
+ /**
+ * @see Ping hook
+ */
+ public void ping() throws IOException {
+ new Requester(getRoot()).method("POST").to(getApiRoute() + "/pings");
+ }
+
/**
* Deletes this hook.
*/
diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java
index 04898039bc..078603d6fa 100644
--- a/src/main/java/org/kohsuke/github/GHPullRequest.java
+++ b/src/main/java/org/kohsuke/github/GHPullRequest.java
@@ -25,8 +25,14 @@
import java.io.IOException;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
+import java.util.List;
+import javax.annotation.CheckForNull;
+
+import static org.kohsuke.github.Previews.BLACK_CAT;
/**
* A pull request.
@@ -208,7 +214,7 @@ private void populate() throws IOException {
}
/**
- * Retrieves all the commits associated to this pull request.
+ * Retrieves all the files associated to this pull request.
*/
public PagedIterable listFiles() {
return new PagedIterable() {
@@ -223,6 +229,27 @@ protected void wrapUp(GHPullRequestFileDetail[] page) {
};
}
+ /**
+ * Retrieves all the reviews associated to this pull request.
+ */
+ public PagedIterable listReviews() {
+ return new PagedIterable() {
+ public PagedIterator _iterator(int pageSize) {
+ return new PagedIterator(root.retrieve()
+ .withPreview(BLACK_CAT)
+ .asIterator(String.format("%s/reviews", getApiRoute()),
+ GHPullRequestReview[].class, pageSize)) {
+ @Override
+ protected void wrapUp(GHPullRequestReview[] page) {
+ for (GHPullRequestReview r: page) {
+ r.wrapUp(GHPullRequest.this);
+ }
+ }
+ };
+ }
+ };
+ }
+
/**
* Obtains all the review comments associated with this pull request.
*/
@@ -259,6 +286,34 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) {
};
}
+ @Preview
+ @Deprecated
+ public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
+ GHPullRequestReviewComment... comments)
+ throws IOException {
+ return createReview(body, event, Arrays.asList(comments));
+ }
+
+ @Preview
+ @Deprecated
+ public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
+ List comments)
+ throws IOException {
+// if (event == null) {
+// event = GHPullRequestReviewState.PENDING;
+// }
+ List draftComments = new ArrayList(comments.size());
+ for (GHPullRequestReviewComment c : comments) {
+ draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), c.getPosition()));
+ }
+ return new Requester(root).method("POST")
+ .with("body", body)
+ //.with("event", event.name())
+ ._with("comments", draftComments)
+ .withPreview(BLACK_CAT)
+ .to(getApiRoute() + "/reviews", GHPullRequestReview.class).wrapUp(this);
+ }
+
public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException {
return new Requester(root).method("POST")
.with("body", body)
@@ -300,4 +355,28 @@ private void fetchIssue() throws IOException {
fetchedIssueDetails = true;
}
}
+
+ private static class DraftReviewComment {
+ private String body;
+ private String path;
+ private int position;
+
+ public DraftReviewComment(String body, String path, int position) {
+ this.body = body;
+ this.path = path;
+ this.position = position;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+ }
}
diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java
new file mode 100644
index 0000000000..b25f28b59a
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java
@@ -0,0 +1,149 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2017, CloudBees, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package org.kohsuke.github;
+
+import java.io.IOException;
+import java.net.URL;
+
+import static org.kohsuke.github.Previews.BLACK_CAT;
+
+/**
+ * Review to the pull request
+ *
+ * @see GHPullRequest#listReviews()
+ * @see GHPullRequest#createReview(String, GHPullRequestReviewState, GHPullRequestReviewComment...)
+ */
+public class GHPullRequestReview extends GHObject {
+ GHPullRequest owner;
+
+ private String body;
+ private GHUser user;
+ private String commit_id;
+ private GHPullRequestReviewState state;
+
+ /*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) {
+ this.owner = owner;
+ return this;
+ }
+
+ /**
+ * Gets the pull request to which this review is associated.
+ */
+ public GHPullRequest getParent() {
+ return owner;
+ }
+
+ /**
+ * The comment itself.
+ */
+ public String getBody() {
+ return body;
+ }
+
+ /**
+ * Gets the user who posted this review.
+ */
+ public GHUser getUser() throws IOException {
+ return owner.root.getUser(user.getLogin());
+ }
+
+ public String getCommitId() {
+ return commit_id;
+ }
+
+ public GHPullRequestReviewState getState() {
+ return state;
+ }
+
+ @Override
+ public URL getHtmlUrl() {
+ return null;
+ }
+
+ protected String getApiRoute() {
+ return owner.getApiRoute()+"/reviews/"+id;
+ }
+
+ /**
+ * Updates the comment.
+ */
+ @Preview
+ @Deprecated
+ public void submit(String body, GHPullRequestReviewState event) throws IOException {
+ new Requester(owner.root).method("POST")
+ .with("body", body)
+ .with("event", event.action())
+ .withPreview("application/vnd.github.black-cat-preview+json")
+ .to(getApiRoute()+"/events",this);
+ this.body = body;
+ this.state = event;
+ }
+
+ /**
+ * Deletes this review.
+ */
+ @Preview
+ @Deprecated
+ public void delete() throws IOException {
+ new Requester(owner.root).method("DELETE")
+ .withPreview(BLACK_CAT)
+ .to(getApiRoute());
+ }
+
+ /**
+ * Dismisses this review.
+ */
+ @Preview
+ @Deprecated
+ public void dismiss(String message) throws IOException {
+ new Requester(owner.root).method("PUT")
+ .with("message", message)
+ .withPreview(BLACK_CAT)
+ .to(getApiRoute()+"/dismissals");
+ state = GHPullRequestReviewState.DISMISSED;
+ }
+
+ /**
+ * Obtains all the review comments associated with this pull request review.
+ */
+ @Preview
+ @Deprecated
+ public PagedIterable listReviewComments() throws IOException {
+ return new PagedIterable() {
+ public PagedIterator _iterator(int pageSize) {
+ return new PagedIterator(
+ owner.root.retrieve()
+ .withPreview(BLACK_CAT)
+ .asIterator(getApiRoute() + "/comments",
+ GHPullRequestReviewComment[].class, pageSize)) {
+ protected void wrapUp(GHPullRequestReviewComment[] page) {
+ for (GHPullRequestReviewComment c : page)
+ c.wrapUp(owner);
+ }
+ };
+ }
+ };
+ }
+
+}
diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java
index 05784b5078..33097bc29d 100644
--- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java
+++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java
@@ -44,6 +44,14 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
private int position;
private int originalPosition;
+ public static GHPullRequestReviewComment draft(String body, String path, int position) {
+ GHPullRequestReviewComment result = new GHPullRequestReviewComment();
+ result.body = body;
+ result.path = path;
+ result.position = position;
+ return result;
+ }
+
/*package*/ GHPullRequestReviewComment wrapUp(GHPullRequest owner) {
this.owner = owner;
return this;
diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java
new file mode 100644
index 0000000000..fca3fabfb3
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java
@@ -0,0 +1,19 @@
+package org.kohsuke.github;
+
+public enum GHPullRequestReviewState {
+ PENDING(null),
+ APPROVED("APPROVE"),
+ REQUEST_CHANGES("REQUEST_CHANGES"),
+ COMMENTED("COMMENT"),
+ DISMISSED(null);
+
+ private final String _action;
+
+ GHPullRequestReviewState(String action) {
+ _action = action;
+ }
+
+ public String action() {
+ return _action;
+ }
+}
diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java
index 74fbb4d665..d40549fd78 100644
--- a/src/main/java/org/kohsuke/github/GHRepository.java
+++ b/src/main/java/org/kohsuke/github/GHRepository.java
@@ -60,7 +60,7 @@
* @author Kohsuke Kawaguchi
*/
@SuppressWarnings({"UnusedDeclaration"})
-@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
+@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHRepository extends GHObject {
/*package almost final*/ GitHub root;
@@ -298,6 +298,14 @@ public GHRef createRef(String name, String sha) throws IOException {
public List getReleases() throws IOException {
return listReleases().asList();
}
+
+ public GHRelease getLatestRelease() throws IOException {
+ try {
+ return root.retrieve().to(getApiTailUrl("releases/latest"), GHRelease.class).wrap(this);
+ } catch (FileNotFoundException e) {
+ return null; // no latest release
+ }
+ }
public PagedIterable listReleases() throws IOException {
return new PagedIterable() {
@@ -434,8 +442,8 @@ public String getMasterBranch() {
public int getSize() {
return size;
}
-
-
+
+
/**
* Gets the collaborators on this repository.
* This set always appear to include the owner.
@@ -486,9 +494,8 @@ public Set getCollaboratorNames() throws IOException {
* @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown
* @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown
*/
- @Deprecated @Preview
public GHPermissionType getPermission(String user) throws IOException {
- GHPermission perm = root.retrieve().withPreview(KORRA).to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class);
+ GHPermission perm = root.retrieve().to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class);
perm.wrapUp(root);
return perm.getPermissionType();
}
@@ -498,7 +505,6 @@ public GHPermissionType getPermission(String user) throws IOException {
* @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown
* @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown
*/
- @Deprecated @Preview
public GHPermissionType getPermission(GHUser u) throws IOException {
return getPermission(u.getLogin());
}
@@ -784,6 +790,26 @@ public GHRef[] getRefs() throws IOException {
return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", getOwnerName(), name), GHRef[].class), root);
}
+
+ /**
+ * Retrieves all refs for the github repository.
+ *
+ * @return paged iterable of all refs
+ * @throws IOException on failure communicating with GitHub, potentially due to an invalid ref type being requested
+ */
+ public PagedIterable listRefs() throws IOException {
+ final String url = String.format("/repos/%s/%s/git/refs", getOwnerName(), name);
+ return new PagedIterable() {
+ public PagedIterator _iterator(int pageSize) {
+ return new PagedIterator(root.retrieve().asIterator(url, GHRef[].class, pageSize)) {
+ protected void wrapUp(GHRef[] page) {
+ // no-op
+ }
+ };
+ }
+ };
+ }
+
/**
* Retrieves all refs of the given type for the current GitHub repository.
* @param refType the type of reg to search for e.g. tags or commits
@@ -793,6 +819,27 @@ public GHRef[] getRefs() throws IOException {
public GHRef[] getRefs(String refType) throws IOException {
return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refType), GHRef[].class),root);
}
+
+ /**
+ * Retrieves all refs of the given type for the current GitHub repository.
+ *
+ * @param refType the type of reg to search for e.g. tags or commits
+ * @return paged iterable of all refs of the specified type
+ * @throws IOException on failure communicating with GitHub, potentially due to an invalid ref type being requested
+ */
+ public PagedIterable listRefs(String refType) throws IOException {
+ final String url = String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refType);
+ return new PagedIterable() {
+ public PagedIterator _iterator(int pageSize) {
+ return new PagedIterator(root.retrieve().asIterator(url, GHRef[].class, pageSize)) {
+ protected void wrapUp(GHRef[] page) {
+ // no-op
+ }
+ };
+ }
+ };
+ }
+
/**
* Retrive a ref of the given type for the current GitHub repository.
*
@@ -810,6 +857,18 @@ public GHRef getRef(String refName) throws IOException {
refName = refName.replaceAll("#", "%23");
return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refName), GHRef.class).wrap(root);
}
+
+ /**
+ * Returns the annotated tag object. Only valid if the {@link GHRef#getObject()} has a
+ * {@link GHRef.GHObject#getType()} of {@code tag}.
+ *
+ * @param sha the sha of the tag object
+ * @return the annotated tag object
+ */
+ public GHTagObject getTagObject(String sha) throws IOException {
+ return root.retrieve().to(getApiTailUrl("git/tags/" + sha), GHTagObject.class).wrap(this);
+ }
+
/**
* Retrive a tree of the given type for the current GitHub repository.
*
@@ -1146,7 +1205,7 @@ public GHHook createWebHook(URL url) throws IOException {
* @deprecated
* Use {@link #getHooks()} and {@link #createHook(String, Map, Collection, boolean)}
*/
- @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
+ @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
justification = "It causes a performance degradation, but we have already exposed it to the API")
public Set getPostCommitHooks() {
return postCommitHooks;
@@ -1155,7 +1214,7 @@ public Set getPostCommitHooks() {
/**
* Live set view of the post-commit hook.
*/
- @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
+ @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
justification = "It causes a performance degradation, but we have already exposed it to the API")
@SkipFromToString
private final Set postCommitHooks = new AbstractSet() {
@@ -1223,7 +1282,7 @@ public boolean remove(Object url) {
*/
public Map getBranches() throws IOException {
Map r = new TreeMap();
- for (GHBranch p : root.retrieve().to(getApiTailUrl("branches"), GHBranch[].class)) {
+ for (GHBranch p : root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches"), GHBranch[].class)) {
p.wrap(this);
r.put(p.getName(),p);
}
@@ -1231,7 +1290,7 @@ public Map getBranches() throws IOException {
}
public GHBranch getBranch(String name) throws IOException {
- return root.retrieve().to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this);
+ return root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this);
}
/**
@@ -1453,7 +1512,7 @@ public int hashCode() {
public boolean equals(Object obj) {
// We ignore contributions in the calculation
return super.equals(obj);
- }
+ }
}
/**
diff --git a/src/main/java/org/kohsuke/github/GHTagObject.java b/src/main/java/org/kohsuke/github/GHTagObject.java
new file mode 100644
index 0000000000..a95571c479
--- /dev/null
+++ b/src/main/java/org/kohsuke/github/GHTagObject.java
@@ -0,0 +1,60 @@
+package org.kohsuke.github;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Represents an annotated tag in a {@link GHRepository}
+ *
+ * @see GHRepository#getAnnotatedTag()
+ */
+@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
+ "NP_UNWRITTEN_FIELD"}, justification = "JSON API")
+public class GHTagObject {
+ private GHRepository owner;
+ private GitHub root;
+
+ private String tag;
+ private String sha;
+ private String url;
+ private String message;
+ private GitUser tagger;
+ private GHRef.GHObject object;
+
+ /*package*/ GHTagObject wrap(GHRepository owner) {
+ this.owner = owner;
+ this.root = owner.root;
+ return this;
+ }
+
+ public GHRepository getOwner() {
+ return owner;
+ }
+
+ public GitHub getRoot() {
+ return root;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getSha() {
+ return sha;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public GitUser getTagger() {
+ return tagger;
+ }
+
+ public GHRef.GHObject getObject() {
+ return object;
+ }
+}
diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java
index 896fb36c63..49c860e4dc 100644
--- a/src/main/java/org/kohsuke/github/GitHub.java
+++ b/src/main/java/org/kohsuke/github/GitHub.java
@@ -719,6 +719,14 @@ private boolean isPrivateModeEnabled() {
}
}
+ /**
+ * Search commits.
+ */
+ @Preview @Deprecated
+ public GHCommitSearchBuilder searchCommits() {
+ return new GHCommitSearchBuilder(this);
+ }
+
/**
* Search issues.
*/
diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java
index 238b062b8b..2bc6dccbc8 100644
--- a/src/main/java/org/kohsuke/github/Previews.java
+++ b/src/main/java/org/kohsuke/github/Previews.java
@@ -7,5 +7,6 @@
static final String LOKI = "application/vnd.github.loki-preview+json";
static final String DRAX = "application/vnd.github.drax-preview+json";
static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview";
- static final String KORRA = "application/vnd.github.korra-preview";
+ static final String CLOAK = "application/vnd.github.cloak-preview";
+ static final String BLACK_CAT = "application/vnd.github.black-cat-preview+json";
}
diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java
index d7d6239190..576d313f5d 100644
--- a/src/main/java/org/kohsuke/github/Requester.java
+++ b/src/main/java/org/kohsuke/github/Requester.java
@@ -170,6 +170,11 @@ public Requester with(@WillClose/*later*/ InputStream body) {
return this;
}
+ public Requester withNullable(String key, Object value) {
+ args.add(new Entry(key, value));
+ return this;
+ }
+
public Requester _with(String key, Object value) {
if (value!=null) {
args.add(new Entry(key,value));
@@ -314,7 +319,7 @@ public InputStream asStream(String tailApiUrl) throws IOException {
setupConnection(root.getApiURL(tailApiUrl));
buildRequest();
-
+
try {
return wrapStream(uc.getInputStream());
} catch (IOException e) {
diff --git a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java
index f32087c0d1..a7afb38fd7 100644
--- a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java
+++ b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java
@@ -1,5 +1,8 @@
package org.kohsuke.github;
+import java.io.FileInputStream;
+import java.util.Properties;
+import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
@@ -19,9 +22,17 @@ public abstract class AbstractGitHubApiTestBase extends Assert {
public void setUp() throws Exception {
File f = new File(System.getProperty("user.home"), ".github.kohsuke2");
if (f.exists()) {
+ Properties props = new Properties();
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(f);
+ props.load(in);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
// use the non-standard credential preferentially, so that developers of this library do not have
// to clutter their event stream.
- gitHub = GitHubBuilder.fromPropertyFile(f.getPath()).withRateLimitHandler(RateLimitHandler.FAIL).build();
+ gitHub = GitHubBuilder.fromProperties(props).withRateLimitHandler(RateLimitHandler.FAIL).build();
} else {
gitHub = GitHubBuilder.fromCredentials().withRateLimitHandler(RateLimitHandler.FAIL).build();
}
diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java
index a20b2eccf3..248bd0ef11 100755
--- a/src/test/java/org/kohsuke/github/AppTest.java
+++ b/src/test/java/org/kohsuke/github/AppTest.java
@@ -685,6 +685,15 @@ public void testMemberPagenation() throws IOException {
assertFalse(all.isEmpty());
}
+ @Test
+ public void testCommitSearch() throws IOException {
+ PagedSearchIterable r = gitHub.searchCommits().author("kohsuke").list();
+ assertTrue(r.getTotalCount() > 0);
+
+ GHCommit firstCommit = r.iterator().next();
+ assertTrue(firstCommit.getFiles().size() > 0);
+ }
+
@Test
public void testIssueSearch() throws IOException {
PagedSearchIterable r = gitHub.searchIssues().mentions("kohsuke").isOpen().list();
diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java
new file mode 100644
index 0000000000..b7ae713d87
--- /dev/null
+++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java
@@ -0,0 +1,82 @@
+package org.kohsuke.github;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.kohsuke.github.GHBranchProtection.EnforceAdmins;
+import org.kohsuke.github.GHBranchProtection.RequiredReviews;
+import org.kohsuke.github.GHBranchProtection.RequiredStatusChecks;
+
+import java.io.FileNotFoundException;
+
+public class GHBranchProtectionTest extends AbstractGitHubApiTestBase {
+ private static final String BRANCH = "bp-test";
+ private static final String BRANCH_REF = "heads/" + BRANCH;
+
+ private GHBranch branch;
+
+ private GHRepository repo;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ repo = gitHub.getRepository("github-api-test-org/GHContentIntegrationTest").fork();
+
+ try {
+ repo.getRef(BRANCH_REF);
+ } catch (FileNotFoundException e) {
+ repo.createRef("refs/" + BRANCH_REF, repo.getBranch("master").getSHA1());
+ }
+
+ branch = repo.getBranch(BRANCH);
+
+ if (branch.isProtected()) {
+ branch.disableProtection();
+ }
+
+ branch = repo.getBranch(BRANCH);
+ assertFalse(branch.isProtected());
+ }
+
+ @Test
+ public void testEnableBranchProtections() throws Exception {
+ // team/user restrictions require an organization repo to test against
+ GHBranchProtection protection = branch.enableProtection()
+ .addRequiredChecks("test-status-check")
+ .requireBranchIsUpToDate()
+ .requireCodeOwnReviews()
+ .dismissStaleReviews()
+ .includeAdmins()
+ .enable();
+
+ RequiredStatusChecks statusChecks = protection.getRequiredStatusChecks();
+ assertNotNull(statusChecks);
+ assertTrue(statusChecks.isRequiresBranchUpToDate());
+ assertTrue(statusChecks.getContexts().contains("test-status-check"));
+
+ RequiredReviews requiredReviews = protection.getRequiredReviews();
+ assertNotNull(requiredReviews);
+ assertTrue(requiredReviews.isDismissStaleReviews());
+ assertTrue(requiredReviews.isRequireCodeOwnerReviews());
+
+ EnforceAdmins enforceAdmins = protection.getEnforceAdmins();
+ assertNotNull(enforceAdmins);
+ assertTrue(enforceAdmins.isEnabled());
+ }
+
+ @Test
+ public void testEnableProtectionOnly() throws Exception {
+ branch.enableProtection().enable();
+ assertTrue(repo.getBranch(BRANCH).isProtected());
+ }
+
+ @Test
+ public void testEnableRequireReviewsOnly() throws Exception {
+ GHBranchProtection protection = branch.enableProtection()
+ .requireReviews()
+ .enable();
+
+ assertNotNull(protection.getRequiredReviews());
+ }
+}
diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java
index c642d662e7..8e3873708b 100644
--- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java
+++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java
@@ -20,13 +20,6 @@ public void setUp() throws Exception {
repo = gitHub.getRepository("github-api-test-org/GHContentIntegrationTest").fork();
}
- @Test
- public void testBranchProtection() throws Exception {
- GHBranch b = repo.getBranch("master");
- b.enableProtection(EnforcementLevel.NON_ADMINS, "foo/bar");
- b.disableProtection();
- }
-
@Test
public void testGetFileContent() throws Exception {
GHContent content = repo.getFileContent("ghcontent-ro/a-file-with-content");
diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java
index c7ce77d289..ce09b2ab13 100644
--- a/src/test/java/org/kohsuke/github/PullRequestTest.java
+++ b/src/test/java/org/kohsuke/github/PullRequestTest.java
@@ -7,6 +7,9 @@
import java.util.Collection;
import java.util.List;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
/**
* @author Kohsuke Kawaguchi
*/
@@ -26,6 +29,33 @@ public void createPullRequestComment() throws Exception {
p.comment("Some comment");
}
+ @Test
+ public void testPullRequestReviews() throws Exception {
+ String name = rnd.next();
+ GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test");
+ GHPullRequestReview draftReview = p.createReview("Some draft review", null,
+ GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1)
+ );
+ assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING));
+ assertThat(draftReview.getBody(), is("Some draft review"));
+ assertThat(draftReview.getCommitId(), notNullValue());
+ List reviews = p.listReviews().asList();
+ assertThat(reviews.size(), is(1));
+ GHPullRequestReview review = reviews.get(0);
+ assertThat(review.getState(), is(GHPullRequestReviewState.PENDING));
+ assertThat(review.getBody(), is("Some draft review"));
+ assertThat(review.getCommitId(), notNullValue());
+ review.submit("Some review comment", GHPullRequestReviewState.COMMENTED);
+ List comments = review.listReviewComments().asList();
+ assertEquals(1, comments.size());
+ GHPullRequestReviewComment comment = comments.get(0);
+ assertEquals("Some niggle", comment.getBody());
+ review = p.createReview("Some new review", null,
+ GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1)
+ );
+ review.delete();
+ }
+
@Test
public void testPullRequestReviewComments() throws Exception {
String name = rnd.next();
diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java
index 9955c34956..728f94a834 100644
--- a/src/test/java/org/kohsuke/github/RepositoryTest.java
+++ b/src/test/java/org/kohsuke/github/RepositoryTest.java
@@ -67,6 +67,32 @@ public void getPermission() throws Exception {
}
}
}
+
+
+
+ @Test
+ public void LatestRepositoryExist() {
+ try {
+ // add the repository that have latest release
+ GHRelease release = gitHub.getRepository("kamontat/CheckIDNumber").getLatestRelease();
+ assertEquals("v3.0", release.getTagName());
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void LatestRepositoryNotExist() {
+ try {
+ // add the repository that `NOT` have latest release
+ GHRelease release = gitHub.getRepository("kamontat/Java8Example").getLatestRelease();
+ assertNull(release);
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
private GHRepository getRepository() throws IOException {
return gitHub.getOrganization("github-api-test-org").getRepository("jenkins");