Merge branch 'master' into collaborator-permissions

This commit is contained in:
jimmysombrero
2020-01-28 15:21:25 -06:00
committed by GitHub
237 changed files with 10463 additions and 189 deletions

View File

@@ -88,7 +88,7 @@ public class GHOrganization extends GHPerson {
*
* <p>
* You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} to
* finally createa repository.
* finally create a repository.
*
* @param name
* the name
@@ -386,7 +386,7 @@ public class GHOrganization extends GHPerson {
* @throws IOException
* the io exception
* @deprecated https://developer.github.com/v3/teams/#create-team deprecates permission field use
* {@link #createTeam(String, Collection)}
* {@link #createTeam(String)}
*/
@Deprecated
public GHTeam createTeam(String name, Permission p, Collection<GHRepository> repositories) throws IOException {
@@ -412,7 +412,7 @@ public class GHOrganization extends GHPerson {
* @throws IOException
* the io exception
* @deprecated https://developer.github.com/v3/teams/#create-team deprecates permission field use
* {@link #createTeam(String, GHRepository...)}
* {@link #createTeam(String)}
*/
@Deprecated
public GHTeam createTeam(String name, Permission p, GHRepository... repositories) throws IOException {
@@ -429,7 +429,9 @@ public class GHOrganization extends GHPerson {
* @return the gh team
* @throws IOException
* the io exception
* @deprecated Use {@link #createTeam(String)} that uses a builder pattern to let you control every aspect.
*/
@Deprecated
public GHTeam createTeam(String name, Collection<GHRepository> repositories) throws IOException {
Requester post = root.createRequest().method("POST").with("name", name);
List<String> repo_names = new ArrayList<String>();
@@ -450,11 +452,28 @@ public class GHOrganization extends GHPerson {
* @return the gh team
* @throws IOException
* the io exception
* @deprecated Use {@link #createTeam(String)} that uses a builder pattern to let you control every aspect.
*/
@Deprecated
public GHTeam createTeam(String name, GHRepository... repositories) throws IOException {
return createTeam(name, Arrays.asList(repositories));
}
/**
* Starts a builder that creates a new team.
*
* <p>
* You use the returned builder to set various properties, then call {@link GHTeamBuilder#create()} to finally
* create a team.
*
* @param name
* the name
* @return the gh create repository builder
*/
public GHTeamBuilder createTeam(String name) {
return new GHTeamBuilder(root, login, name);
}
/**
* List up repositories that has some open pull requests.
* <p>

View File

@@ -12,12 +12,22 @@ import java.util.TreeMap;
* @author Kohsuke Kawaguchi
*/
public class GHTeam implements Refreshable {
private String name, permission, slug, description;
private String name;
private String permission;
private String slug;
private String description;
private Privacy privacy;
private int id;
private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together
protected /* final */ GitHub root;
public enum Privacy {
SECRET, // only visible to organization owners and members of this team.
CLOSED // visible to all members of this organization.
}
/**
* Member's role in a team
*/
@@ -94,6 +104,15 @@ public class GHTeam implements Refreshable {
return description;
}
/**
* Gets the privacy state.
*
* @return the privacy state.
*/
public Privacy getPrivacy() {
return privacy;
}
/**
* Sets description.
*
@@ -106,6 +125,18 @@ public class GHTeam implements Refreshable {
root.createRequest().method("PATCH").with("description", description).withUrlPath(api("")).send();
}
/**
* Updates the team's privacy setting.
*
* @param privacy
* the privacy
* @throws IOException
* the io exception
*/
public void setPrivacy(Privacy privacy) throws IOException {
root.createRequest().method("PATCH").with("privacy", privacy).withUrlPath(api("")).send();
}
/**
* Gets id.
*

View File

@@ -0,0 +1,93 @@
package org.kohsuke.github;
import java.io.IOException;
/**
* Creates a team.
*
* https://developer.github.com/v3/teams/#create-team
*/
public class GHTeamBuilder {
private final GitHub root;
protected final Requester builder;
private final String orgName;
public GHTeamBuilder(GitHub root, String orgName, String name) {
this.root = root;
this.orgName = orgName;
this.builder = root.createRequest();
this.builder.with("name", name);
}
/**
* Description for this team.
*
* @param description
* description of team
* @return a builder to continue with building
*/
public GHTeamBuilder description(String description) {
this.builder.with("description", description);
return this;
}
/**
* Maintainers for this team.
*
* @param maintainers
* maintainers of team
* @return a builder to continue with building
*/
public GHTeamBuilder maintainers(String... maintainers) {
this.builder.with("maintainers", maintainers);
return this;
}
/**
* Repository names to add this team to.
*
* @param repoNames
* repoNames to add team to
* @return a builder to continue with building
*/
public GHTeamBuilder repositories(String... repoNames) {
this.builder.with("repo_names", repoNames);
return this;
}
/**
* Description for this team
*
* @param privacy
* privacy of team
* @return a builder to continue with building
*/
public GHTeamBuilder privacy(GHTeam.Privacy privacy) {
this.builder.with("privacy", privacy);
return this;
}
/**
* Parent team id for this team
*
* @param parentTeamId
* parentTeamId of team
* @return a builder to continue with building
*/
public GHTeamBuilder parentTeamId(int parentTeamId) {
this.builder.with("parent_team_id", parentTeamId);
return this;
}
/**
* Creates a team with all the parameters.
*
* @return the gh team
* @throws IOException
* if team cannot be created
*/
public GHTeam create() throws IOException {
return builder.method("POST").withUrlPath("/orgs/" + orgName + "/teams").fetch(GHTeam.class).wrapUp(root);
}
}

View File

@@ -63,6 +63,7 @@ import java.util.zip.GZIPInputStream;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.WillClose;
import javax.net.ssl.SSLHandshakeException;
import static java.util.Arrays.asList;
import static java.util.logging.Level.*;
@@ -110,7 +111,7 @@ class Requester {
/**
* If timeout issues let's retry after milliseconds.
*/
private static final int retryTimeoutMillis = 500;
private static final int retryTimeoutMillis = 100;
Requester(GitHub root) {
this.root = root;
@@ -531,7 +532,8 @@ class Requester {
// don't wrap exception in HttpException to preserve backward compatibility
throw e;
} catch (IOException e) {
if (!retrySocketException(e, retries)) {
if (!retryConnectionError(e, retries)) {
throw new HttpException(responseCode, responseMessage, uc.getURL(), e);
}
}
@@ -541,10 +543,13 @@ class Requester {
}
private boolean retrySocketException(IOException e, int retries) throws IOException {
if ((e instanceof SocketException || e instanceof SocketTimeoutException) && retries > 0) {
private boolean retryConnectionError(IOException e, int retries) throws IOException {
// There are a range of connection errors where we want to wait a moment and just automatically retry
boolean connectionError = e instanceof SocketException || e instanceof SocketTimeoutException
|| e instanceof SSLHandshakeException;
if (connectionError && retries > 0) {
LOGGER.log(INFO,
"timed out accessing " + uc.getURL() + ". Sleeping " + Requester.retryTimeoutMillis
"Error while connecting to " + uc.getURL() + ". Sleeping " + Requester.retryTimeoutMillis
+ " milliseconds before retrying... ; will try " + retries + " more time(s)",
e);
try {
@@ -558,6 +563,33 @@ class Requester {
return false;
}
private boolean retryInvalidCached404Response(int responseCode, int retries) throws IOException {
// WORKAROUND FOR ISSUE #669:
// When the Requester detects a 404 response with an ETag (only happpens when the server's 304
// is bogus and would cause cache corruption), try the query again with new request header
// that forces the server to not return 304 and return new data instead.
//
// This solution is transparent to users of this library and automatically handles a
// situation that was cause insidious and hard to debug bad responses in caching
// scenarios. If GitHub ever fixes their issue and/or begins providing accurate ETags to
// their 404 responses, this will result in at worst two requests being made for each 404
// responses. However, only the second request will count against rate limit.
if (responseCode == 404 && Objects.equals(uc.getRequestMethod(), "GET") && uc.getHeaderField("ETag") != null
&& !Objects.equals(uc.getRequestProperty("Cache-Control"), "no-cache") && retries > 0) {
LOGGER.log(FINE,
"Encountered GitHub invalid cached 404 from " + uc.getURL()
+ ". Retrying with \"Cache-Control\"=\"no-cache\"...");
uc = setupConnection(uc.getURL());
// Setting "Cache-Control" to "no-cache" stops the cache from supplying
// "If-Modified-Since" or "If-None-Match" values.
// This makes GitHub give us current data (not incorrectly cached data)
uc.setRequestProperty("Cache-Control", "no-cache");
return true;
}
return false;
}
private <T> T[] concatenatePages(Class<T[]> type, List<T[]> pages, int totalLength) {
T[] result = type.cast(Array.newInstance(type.getComponentType(), totalLength));
@@ -957,33 +989,6 @@ class Requester {
}
}
private boolean retryInvalidCached404Response(int responseCode, int retries) throws IOException {
// WORKAROUND FOR ISSUE #669:
// When the Requester detects a 404 response with an ETag (only happpens when the server's 304
// is bogus and would cause cache corruption), try the query again with new request header
// that forces the server to not return 304 and return new data instead.
//
// This solution is transparent to users of this library and automatically handles a
// situation that was cause insidious and hard to debug bad responses in caching
// scenarios. If GitHub ever fixes their issue and/or begins providing accurate ETags to
// their 404 responses, this will result in at worst two requests being made for each 404
// responses. However, only the second request will count against rate limit.
if (responseCode == 404 && Objects.equals(uc.getRequestMethod(), "GET") && uc.getHeaderField("ETag") != null
&& !Objects.equals(uc.getRequestProperty("Cache-Control"), "no-cache") && retries > 0) {
LOGGER.log(FINE,
"Encountered GitHub invalid cached 404 from " + uc.getURL()
+ ". Retrying with \"Cache-Control\"=\"no-cache\"...");
uc = setupConnection(uc.getURL());
// Setting "Cache-Control" to "no-cache" stops the cache from supplying
// "If-Modified-Since" or "If-None-Match" values.
// This makes GitHub give us current data (not incorrectly cached data)
uc.setRequestProperty("Cache-Control", "no-cache");
return true;
}
return false;
}
private <T> T setResponseHeaders(T readValue) {
if (readValue instanceof GHObject[]) {
for (GHObject ghObject : (GHObject[]) readValue) {