Merge remote-tracking branch 'upstream/master' into download-repository-archives

This commit is contained in:
Liam Newman
2020-12-31 09:55:28 -08:00
278 changed files with 10715 additions and 2476 deletions

View File

@@ -14,6 +14,10 @@ Example:
This the default behavior.
Example for a single test case:
`mvn install -Dtest=WireMockStatusReporterTest#user_whenProxying_AuthCorrectlyConfigured`
### Setting up credential
@@ -27,21 +31,37 @@ This the default behavior.
`WireMockStatusReporterTest: GitHub proxying and user auth correctly configured for user login: <your login>`
Whenever you run tests with `-Dtest.github.useProxy`, they will try to get data from local files but will fallback to proxying to github if not found.
Whenever you run tests with `-Dtest.github.useProxy`, they will try to get data from local files but will fallback to proxying to GitHub if not found.
### Writing a new test
Once you have credentials setup, you add new test classes and test methods as you would normally.
Keep `useProxy` enabled and iterate on your tests as needed. Remember, while proxying your tests are interacting with GitHub - you will need to clean up your state between runs.
When you are ready to create a snapshot of your test data,
run your test with `test.github.takeSnapshot` ("-Dtest.github.takeSnapshot" as a Java VM option). For example:
#### Running tests using GitHub test proxy
`mvn install -Dtest.github.takeSnapshot -Dtest=YourTestClassName`
Keep `useProxy` enabled and iterate on your tests as needed. With `useProxy` enabled your tests will interact with
GitHub - you will need to clean up your server-state between runs. This can be done manually to start with.
Once your test code is somewhat stable, use `getGitHubBeforeAfter()` to get a `GitHub` instance for test setup and cleanup.
Interactions with that `GitHub` instance will not be recorded as part of the test, keeping the test data files to a minimum.
The above command would create snapshot WireMock data files under the path `src/test/resources/org/kohsuhke/github/YourTestClassName/wiremock`.
Each method would get a separate director that would hold the data files for that test method.
#### Running tests against your personal GitHub user account
By default, test helper methods such as `getTempRepository()` target the `hub4j-test-org` GitHub organization.
Please request access to this org to record your tests before submitting a PR. This helps keep the project stable and nimble.
Until you have access (or if you don't want access), you can set the following additional system property to target
your personal github account.
`mvn install -Dtest.github.org=false -Dtest=YourTestClassName`
#### Taking a snapshot
When you are ready to create a snapshot of your test data, run your test with `test.github.takeSnapshot` ("-Dtest.github.takeSnapshot" as
a Java VM option). For example:
`mvn install -Dtest.github.takeSnapshot -Dtest.github.org=false -Dtest=YourTestClassName`
The above command will create snapshot WireMock data files under the path `src/test/resources/org/kohsuhke/github/YourTestClassName/wiremock`.
Each method will get a separate directory that will hold the data files for that test method.
Add all files including the generated data to your commit and submit a PR.

94
pom.xml
View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
<version>1.117-SNAPSHOT</version>
<version>1.118-SNAPSHOT</version>
<name>GitHub API for Java</name>
<url>https://github-api.kohsuke.org/</url>
<description>GitHub API for Java</description>
@@ -33,14 +33,13 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spotbugs-maven-plugin.version>4.0.4</spotbugs-maven-plugin.version>
<spotbugs.version>4.1.2</spotbugs.version>
<spotbugs-maven-plugin.version>4.1.4</spotbugs-maven-plugin.version>
<spotbugs.version>4.1.3</spotbugs.version>
<spotbugs-maven-plugin.failOnError>true</spotbugs-maven-plugin.failOnError>
<hamcrest.version>2.2</hamcrest.version>
<okhttp3.version>4.4.1</okhttp3.version>
<okio.version>2.5.0</okio.version>
<formatter-maven-plugin.goal>format</formatter-maven-plugin.goal>
<impsort-maven-plugin.goal>sort</impsort-maven-plugin.goal>
<spotless-maven-plugin.goal>apply</spotless-maven-plugin.goal>
<!-- Using this as the minimum bar for code coverage. Adding methods without covering them will fail this. -->
<jacoco.coverage.target.bundle.method>0.60</jacoco.coverage.target.bundle.method>
<jacoco.coverage.target.class.method>0.25</jacoco.coverage.target.class.method>
@@ -261,7 +260,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
<dependencies>
<dependency>
<groupId>org.apache.bcel</groupId>
@@ -343,37 +342,34 @@
</executions>
</plugin>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.12.1</version>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.6.1</version>
<executions>
<execution>
<id>spotless-check</id>
<phase>process-sources</phase>
<goals>
<goal>${formatter-maven-plugin.goal}</goal>
<goal>${spotless-maven-plugin.goal}</goal>
</goals>
<configuration>
<configFile>src/main/resources/eclipse/formatter.xml</configFile>
<cachedir>${project.build.directory}/.cache</cachedir>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.revelc.code</groupId>
<artifactId>impsort-maven-plugin</artifactId>
<version>1.4.1</version>
<configuration>
<groups>*,java.,javax.</groups>
<removeUnused>true</removeUnused>
<staticAfter>true</staticAfter>
<java>
<eclipse>
<file>${basedir}/src/build/eclipse/formatter.xml</file>
</eclipse>
<importOrder>
<file>${basedir}/src/build/eclipse/eclipse.importorder</file>
</importOrder>
<removeUnusedImports />
<trimTrailingWhitespace />
<endWithNewline />
</java>
</configuration>
<executions>
<execution>
<goals>
<goal>${impsort-maven-plugin.goal}</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
@@ -410,6 +406,12 @@
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
<version>0.15.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
@@ -481,7 +483,25 @@
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.9.0.202009080501-r</version>
<version>5.10.0.202012080955-r</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -519,7 +539,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.6.0</version>
<version>3.6.28</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -540,6 +560,12 @@
<version>2.8.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
@@ -565,8 +591,7 @@
</os>
</activation>
<properties>
<formatter-maven-plugin.goal>validate</formatter-maven-plugin.goal>
<impsort-maven-plugin.goal>check</impsort-maven-plugin.goal>
<spotless-maven-plugin.goal>check</spotless-maven-plugin.goal>
</properties>
</profile>
<profile>
@@ -591,8 +616,7 @@
<profile>
<id>release</id>
<properties>
<formatter-maven-plugin.goal>validate</formatter-maven-plugin.goal>
<impsort-maven-plugin.goal>check</impsort-maven-plugin.goal>
<spotless-maven-plugin.goal>check</spotless-maven-plugin.goal>
</properties>
<build>
<plugins>

View File

@@ -0,0 +1,6 @@
#Organize Import Order
# Import this file in Window -> Preferences -> Java -> Code Style -> Organize Imports -> Import...
0=
1=java
2=javax
3=\#

View File

@@ -12,14 +12,14 @@ import javax.annotation.Nonnull;
* <p>
* Batching looks like this:
* </p>
*
*
* <pre>
* update().someName(value).otherName(value).done()
* </pre>
* <p>
* Single changes look like this:
* </p>
*
*
* <pre>
* set().someName(value);
* set().otherName(value);
@@ -38,7 +38,7 @@ import javax.annotation.Nonnull;
* Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@link S}
* the same as {@link R}, this builder will commit changes after each call to {@link #with(String, Object)}.
*/
abstract class AbstractBuilder<R, S> {
abstract class AbstractBuilder<R, S> extends GitHubInteractiveObject {
@Nonnull
private final Class<R> returnType;
@@ -75,6 +75,7 @@ abstract class AbstractBuilder<R, S> {
@Nonnull Class<S> intermediateReturnType,
@Nonnull GitHub root,
@CheckForNull R baseInstance) {
super(root);
this.requester = root.createRequest();
this.returnType = finalReturnType;
this.commitChangesImmediately = returnType.equals(intermediateReturnType);
@@ -97,7 +98,7 @@ abstract class AbstractBuilder<R, S> {
* if there is an I/O Exception
*/
@Nonnull
@Preview
@BetaApi
@Deprecated
public R done() throws IOException {
R result;
@@ -127,7 +128,7 @@ abstract class AbstractBuilder<R, S> {
* if an I/O error occurs
*/
@Nonnull
@Preview
@BetaApi
@Deprecated
protected S with(@Nonnull String name, Object value) throws IOException {
requester.with(name, value);
@@ -148,7 +149,7 @@ abstract class AbstractBuilder<R, S> {
* if an I/O error occurs
*/
@Nonnull
@Preview
@BetaApi
@Deprecated
protected S continueOrDone() throws IOException {
// This little bit of roughness in this base class means all inheriting builders get to create Updater and

View File

@@ -0,0 +1,18 @@
package org.kohsuke.github;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Indicates that the method/class/etc marked is a beta implementation of an sdk feature.
* <p>
* These APIs are subject to change and not a part of the backward compatibility commitment. Always used in conjunction
* with 'deprecated' to raise awareness to clients.
* </p>
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BetaApi {
}

View File

@@ -15,7 +15,6 @@ import static org.kohsuke.github.Previews.MACHINE_MAN;
*/
public class GHApp extends GHObject {
private GitHub root;
private GHUser owner;
private String name;
private String description;
@@ -189,7 +188,7 @@ public class GHApp extends GHObject {
* @return a list of App installations
* @see <a href="https://developer.github.com/v3/apps/#list-installations">List installations</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public PagedIterable<GHAppInstallation> listInstallations() {
return root.createRequest()
@@ -210,7 +209,7 @@ public class GHApp extends GHObject {
* on error
* @see <a href="https://developer.github.com/v3/apps/#get-an-installation">Get an installation</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHAppInstallation getInstallationById(long id) throws IOException {
return root.createRequest()
@@ -233,7 +232,7 @@ public class GHApp extends GHObject {
* @see <a href="https://developer.github.com/v3/apps/#get-an-organization-installation">Get an organization
* installation</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHAppInstallation getInstallationByOrganization(String name) throws IOException {
return root.createRequest()
@@ -258,7 +257,7 @@ public class GHApp extends GHObject {
* @see <a href="https://developer.github.com/v3/apps/#get-a-repository-installation">Get a repository
* installation</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHAppInstallation getInstallationByRepository(String ownerName, String repositoryName) throws IOException {
return root.createRequest()
@@ -280,7 +279,7 @@ public class GHApp extends GHObject {
* on error
* @see <a href="https://developer.github.com/v3/apps/#get-a-user-installation">Get a user installation</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHAppInstallation getInstallationByUser(String name) throws IOException {
return root.createRequest()

View File

@@ -14,12 +14,11 @@ import static org.kohsuke.github.Previews.MACHINE_MAN;
* @see GHAppInstallation#createToken(Map) GHAppInstallation#createToken(Map)
* @see GHAppInstallation#createToken() GHAppInstallation#createToken()
*/
public class GHAppCreateTokenBuilder {
private final GitHub root;
public class GHAppCreateTokenBuilder extends GitHubInteractiveObject {
protected final Requester builder;
private final String apiUrlTail;
@Preview
@BetaApi
@Deprecated
GHAppCreateTokenBuilder(GitHub root, String apiUrlTail) {
this.root = root;
@@ -27,7 +26,7 @@ public class GHAppCreateTokenBuilder {
this.builder = root.createRequest();
}
@Preview
@BetaApi
@Deprecated
GHAppCreateTokenBuilder(GitHub root, String apiUrlTail, Map<String, GHPermissionType> permissions) {
this(root, apiUrlTail);
@@ -43,7 +42,7 @@ public class GHAppCreateTokenBuilder {
* Array containing the repositories Ids
* @return a GHAppCreateTokenBuilder
*/
@Preview
@BetaApi
@Deprecated
public GHAppCreateTokenBuilder repositoryIds(List<Long> repositoryIds) {
this.builder.with("repository_ids", repositoryIds);
@@ -58,7 +57,7 @@ public class GHAppCreateTokenBuilder {
* Map containing the permission names and types.
* @return a GHAppCreateTokenBuilder
*/
@Preview
@BetaApi
@Deprecated
public GHAppCreateTokenBuilder permissions(Map<String, GHPermissionType> permissions) {
Map<String, String> retMap = new HashMap<>();
@@ -78,7 +77,7 @@ public class GHAppCreateTokenBuilder {
* @throws IOException
* on error
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHAppInstallationToken create() throws IOException {
return builder.method("POST")

View File

@@ -3,11 +3,13 @@ package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import static org.kohsuke.github.Previews.GAMBIT;
import static org.kohsuke.github.Previews.MACHINE_MAN;
/**
* A Github App Installation.
@@ -20,7 +22,6 @@ import static org.kohsuke.github.Previews.GAMBIT;
* @see GHApp#getInstallationByUser(String) GHApp#getInstallationByUser(String)
*/
public class GHAppInstallation extends GHObject {
private GitHub root;
private GHUser account;
@JsonProperty("access_tokens_url")
@@ -117,6 +118,36 @@ public class GHAppInstallation extends GHObject {
return repositoriesUrl;
}
/**
* List repositories that this app installation can access.
*
* @return the paged iterable
*/
@Preview(MACHINE_MAN)
@Deprecated
public PagedSearchIterable<GHRepository> listRepositories() {
GitHubRequest request;
try {
request = root.createRequest().withPreview(MACHINE_MAN).withUrlPath("/installation/repositories").build();
} catch (MalformedURLException e) {
throw new GHException("", e);
}
return new PagedSearchIterable<>(root, request, GHAppInstallationRepositoryResult.class);
}
private static class GHAppInstallationRepositoryResult extends SearchResult<GHRepository> {
private GHRepository[] repositories;
@Override
GHRepository[] getItems(GitHub root) {
for (GHRepository item : repositories)
item.wrap(root);
return repositories;
}
}
/**
* Sets repositories url.
*
@@ -290,7 +321,7 @@ public class GHAppInstallation extends GHObject {
* on error
* @see <a href="https://developer.github.com/v3/apps/#delete-an-installation">Delete an installation</a>
*/
@Preview
@Preview(GAMBIT)
@Deprecated
public void deleteInstallation() throws IOException {
root.createRequest()
@@ -312,7 +343,7 @@ public class GHAppInstallation extends GHObject {
* @return a GHAppCreateTokenBuilder instance
* @deprecated Use {@link GHAppInstallation#createToken()} instead.
*/
@Preview
@BetaApi
@Deprecated
public GHAppCreateTokenBuilder createToken(Map<String, GHPermissionType> permissions) {
return new GHAppCreateTokenBuilder(root,
@@ -329,7 +360,7 @@ public class GHAppInstallation extends GHObject {
*
* @return a GHAppCreateTokenBuilder instance
*/
@Preview
@BetaApi
@Deprecated
public GHAppCreateTokenBuilder createToken() {
return new GHAppCreateTokenBuilder(root, String.format("/app/installations/%d/access_tokens", getId()));

View File

@@ -14,9 +14,7 @@ import java.util.Map;
* @author Paulo Miguel Almeida
* @see GHAppInstallation#createToken(Map) GHAppInstallation#createToken(Map)
*/
public class GHAppInstallationToken {
private GitHub root;
public class GHAppInstallationToken extends GitHubInteractiveObject {
private String token;
protected String expires_at;
private Map<String, String> permissions;

View File

@@ -9,7 +9,6 @@ import java.net.URL;
* @see GHRelease#getAssets() GHRelease#getAssets()
*/
public class GHAsset extends GHObject {
GitHub root;
GHRepository owner;
private String name;
private String label;

View File

@@ -33,7 +33,6 @@ public class GHAuthorization extends GHObject {
public static final String WRITE_KEY = "write:public_key";
public static final String ADMIN_KEY = "admin:public_key";
private GitHub root;
private List<String> scopes;
private String token;
private String token_last_eight;

View File

@@ -20,8 +20,7 @@ import javax.annotation.CheckForNull;
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;
public class GHBranch extends GitHubInteractiveObject {
private GHRepository owner;
private String name;
@@ -78,7 +77,7 @@ public class GHBranch {
*
* @return true if the push to this branch is restricted via branch protection.
*/
@Preview
@Preview(Previews.LUKE_CAGE)
@Deprecated
public boolean isProtected() {
return protection;
@@ -89,7 +88,7 @@ public class GHBranch {
*
* @return API URL that deals with the protection of this branch.
*/
@Preview
@Preview(Previews.LUKE_CAGE)
@Deprecated
public URL getProtectionUrl() {
return GitHubClient.parseURL(protection_url);
@@ -102,6 +101,8 @@ public class GHBranch {
* @throws IOException
* the io exception
*/
@Preview(Previews.LUKE_CAGE)
@Deprecated
public GHBranchProtection getProtection() throws IOException {
return root.createRequest()
.withPreview(Previews.LUKE_CAGE)
@@ -135,7 +136,7 @@ public class GHBranch {
* @return GHBranchProtectionBuilder for enabling protection
* @see GHCommitStatus#getContext() GHCommitStatus#getContext()
*/
@Preview
@Preview(Previews.LUKE_CAGE)
@Deprecated
public GHBranchProtectionBuilder enableProtection() {
return new GHBranchProtectionBuilder(this);

View File

@@ -17,14 +17,12 @@ import static org.kohsuke.github.Previews.ZZZAX;
value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
"URF_UNREAD_FIELD" },
justification = "JSON API")
public class GHBranchProtection {
public class GHBranchProtection extends GitHubInteractiveObject {
private static final String REQUIRE_SIGNATURES_URI = "/required_signatures";
@JsonProperty
private EnforceAdmins enforceAdmins;
private GitHub root;
@JsonProperty("required_pull_request_reviews")
private RequiredReviews requiredReviews;
@@ -43,7 +41,7 @@ public class GHBranchProtection {
* @throws IOException
* the io exception
*/
@Preview
@Preview(ZZZAX)
@Deprecated
public void enabledSignedCommits() throws IOException {
requester().method("POST").withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class);
@@ -55,7 +53,7 @@ public class GHBranchProtection {
* @throws IOException
* the io exception
*/
@Preview
@Preview(ZZZAX)
@Deprecated
public void disableSignedCommits() throws IOException {
requester().method("DELETE").withUrlPath(url + REQUIRE_SIGNATURES_URI).send();
@@ -86,7 +84,7 @@ public class GHBranchProtection {
* @throws IOException
* the io exception
*/
@Preview
@Preview(ZZZAX)
@Deprecated
public boolean getRequiredSignatures() throws IOException {
return requester().withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class).enabled;

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
@@ -21,7 +22,6 @@ public class GHCheckRun extends GHObject {
@JsonProperty("repository")
GHRepository owner;
GitHub root;
private String status;
private String conclusion;
@@ -292,4 +292,15 @@ public class GHCheckRun extends GHObject {
NOTICE, WARNING, FAILURE
}
/**
* Updates this check run.
*
* @return a builder which you should customize, then call {@link GHCheckRunBuilder#create}
*/
@Preview(Previews.ANTIOPE)
@Deprecated
public @NonNull GHCheckRunBuilder update() {
return new GHCheckRunBuilder(owner, getId());
}
}

View File

@@ -37,30 +37,45 @@ import java.util.List;
import java.util.Locale;
/**
* Drafts a check run.
* Drafts or updates a check run.
*
* @see GHCheckRun
* @see GHRepository#createCheckRun
* @see <a href="https://developer.github.com/v3/checks/runs/#create-a-check-run">documentation</a>
* @see GHCheckRun#update()
* @see <a href="https://developer.github.com/v3/checks/runs/#update-a-check-run">documentation</a>
*/
@SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "Jackson serializes these even without a getter")
@Preview
@Preview(Previews.ANTIOPE)
@Deprecated
public final class GHCheckRunBuilder {
private final GHRepository repo;
private final Requester requester;
protected final GHRepository repo;
protected final Requester requester;
private Output output;
private List<Action> actions;
GHCheckRunBuilder(GHRepository repo, String name, String headSHA) {
private GHCheckRunBuilder(GHRepository repo, Requester requester) {
this.repo = repo;
requester = repo.root.createRequest()
.withPreview(Previews.ANTIOPE)
.method("POST")
.with("name", name)
.with("head_sha", headSHA)
.withUrlPath(repo.getApiTailUrl("check-runs"));
this.requester = requester;
}
GHCheckRunBuilder(GHRepository repo, String name, String headSHA) {
this(repo,
repo.root.createRequest()
.withPreview(Previews.ANTIOPE)
.method("POST")
.with("name", name)
.with("head_sha", headSHA)
.withUrlPath(repo.getApiTailUrl("check-runs")));
}
GHCheckRunBuilder(GHRepository repo, long checkId) {
this(repo,
repo.root.createRequest()
.withPreview(Previews.ANTIOPE)
.method("PATCH")
.withUrlPath(repo.getApiTailUrl("check-runs/" + checkId)));
}
public @NonNull GHCheckRunBuilder withDetailsURL(@CheckForNull String detailsURL) {

View File

@@ -8,7 +8,7 @@ import javax.annotation.Nonnull;
* Iterable for check-runs listing.
*/
class GHCheckRunsIterable extends PagedIterable<GHCheckRun> {
private GitHub root;
private final transient GitHub root;
private final GitHubRequest request;
private GHCheckRunsPage result;

View File

@@ -21,7 +21,6 @@ public class GHCheckSuite extends GHObject {
@JsonProperty("repository")
GHRepository owner;
GitHub root;
private String nodeId;
private String headBranch;

View File

@@ -11,6 +11,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import static org.kohsuke.github.Previews.ANTIOPE;
import static org.kohsuke.github.Previews.GROOT;
/**
@@ -65,7 +66,7 @@ public class GHCommit {
* @return the authored date
*/
public Date getAuthoredDate() {
return GitHubClient.parseDate(author.date);
return author.getDate();
}
/**
@@ -84,7 +85,7 @@ public class GHCommit {
* @return the commit date
*/
public Date getCommitDate() {
return GitHubClient.parseDate(committer.date);
return committer.getDate();
}
/**
@@ -121,7 +122,6 @@ public class GHCommit {
* @deprecated Use {@link GitUser} instead.
*/
public static class GHAuthor extends GitUser {
private String date;
}
/**
@@ -453,7 +453,7 @@ public class GHCommit {
*
* @return {@link PagedIterable} with the pull requests which contain this commit
*/
@Preview
@Preview(GROOT)
@Deprecated
public PagedIterable<GHPullRequest> listPullRequests() {
return owner.root.createRequest()
@@ -469,7 +469,7 @@ public class GHCommit {
* @throws IOException
* the io exception
*/
@Preview
@Preview(GROOT)
@Deprecated
public PagedIterable<GHBranch> listBranchesWhereHead() throws IOException {
return owner.root.createRequest()
@@ -565,7 +565,7 @@ public class GHCommit {
* @throws IOException
* on error
*/
@Preview
@Preview(ANTIOPE)
@Deprecated
public PagedIterable<GHCheckRun> getCheckRuns() throws IOException {
return owner.getCheckRuns(sha);
@@ -573,7 +573,7 @@ public class GHCommit {
/**
* Some of the fields are not always filled in when this object is retrieved as a part of another API call.
*
*
* @throws IOException
* on error
*/

View File

@@ -121,7 +121,7 @@ public class GHCommitComment extends GHObject implements Reactable {
this.body = body;
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public GHReaction createReaction(ReactionContent content) throws IOException {
return owner.root.createRequest()
@@ -133,7 +133,7 @@ public class GHCommitComment extends GHObject implements Reactable {
.wrap(owner.root);
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public PagedIterable<GHReaction> listReactions() {
return owner.root.createRequest()

View File

@@ -10,7 +10,7 @@ import java.io.IOException;
* @author Marc de Verdelhan
* @see GitHub#searchCommits() GitHub#searchCommits()
*/
@Preview
@Preview(Previews.CLOAK)
@Deprecated
public class GHCommitSearchBuilder extends GHSearchBuilder<GHCommit> {
GHCommitSearchBuilder(GitHub root) {

View File

@@ -18,8 +18,6 @@ public class GHCommitStatus extends GHObject {
String context;
GHUser creator;
private GitHub root;
GHCommitStatus wrapUp(GitHub root) {
if (creator != null)
creator.wrapUp(root);

View File

@@ -15,15 +15,13 @@ import java.util.Base64;
* @see GHRepository#getFileContent(String) GHRepository#getFileContent(String)
*/
@SuppressWarnings({ "UnusedDeclaration" })
public class GHContent implements Refreshable {
public class GHContent extends GitHubInteractiveObject implements Refreshable {
/*
* In normal use of this class, repository field is set via wrap(), but in the code search API, there's a nested
* 'repository' field that gets populated from JSON.
*/
private GHRepository repository;
private GitHub root;
private String type;
private String encoding;
private long size;
@@ -102,7 +100,7 @@ public class GHContent implements Refreshable {
/**
* Gets target of a symlink. This will only be set if {@code "symlink".equals(getType())}
*
*
* @return the target
*/
public String getTarget() {

View File

@@ -1,168 +1,25 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.BAPTISE;
import static org.kohsuke.github.Previews.BAPTISTE;
/**
* Creates a repository
*
* @author Kohsuke Kawaguchi
*/
public class GHCreateRepositoryBuilder {
private final GitHub root;
protected final Requester builder;
private String apiUrlTail;
public class GHCreateRepositoryBuilder extends GHRepositoryBuilder<GHCreateRepositoryBuilder> {
GHCreateRepositoryBuilder(GitHub root, String apiUrlTail, String name) {
this.root = root;
this.apiUrlTail = apiUrlTail;
this.builder = root.createRequest();
this.builder.with("name", name);
}
public GHCreateRepositoryBuilder(String name, GitHub root, String apiTail) {
super(GHCreateRepositoryBuilder.class, root, null);
requester.method("POST").withUrlPath(apiTail);
/**
* Description for repository
*
* @param description
* description of repository
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder description(String description) {
this.builder.with("description", description);
return this;
}
/**
* Homepage for repository
*
* @param homepage
* homepage of repository
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder homepage(URL homepage) {
return homepage(homepage.toExternalForm());
}
/**
* Homepage for repository
*
* @param homepage
* homepage of repository
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder homepage(String homepage) {
this.builder.with("homepage", homepage);
return this;
}
/**
* Creates a private repository
*
* @param enabled
* private if true
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder private_(boolean enabled) {
this.builder.with("private", enabled);
return this;
}
/**
* Enables issue tracker
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder issues(boolean enabled) {
this.builder.with("has_issues", enabled);
return this;
}
/**
* Enables projects
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder projects(boolean enabled) {
this.builder.with("has_projects", enabled);
return this;
}
/**
* Enables wiki
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder wiki(boolean enabled) {
this.builder.with("has_wiki", enabled);
return this;
}
/**
* Enables downloads
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder downloads(boolean enabled) {
this.builder.with("has_downloads", enabled);
return this;
}
/**
* If true, create an initial commit with empty README.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder autoInit(boolean enabled) {
this.builder.with("auto_init", enabled);
return this;
}
/**
* Allow or disallow squash-merging pull requests.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder allowSquashMerge(boolean enabled) {
this.builder.with("allow_squash_merge", enabled);
return this;
}
/**
* Allow or disallow merging pull requests with a merge commit.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder allowMergeCommit(boolean enabled) {
this.builder.with("allow_merge_commit", enabled);
return this;
}
/**
* Allow or disallow rebase-merging pull requests.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
*/
public GHCreateRepositoryBuilder allowRebaseMerge(boolean enabled) {
this.builder.with("allow_rebase_merge", enabled);
return this;
try {
name(name);
} catch (IOException e) {
// not going to happen here
}
}
/**
@@ -171,10 +28,11 @@ public class GHCreateRepositoryBuilder {
* @param language
* template to base the ignore file on
* @return a builder to continue with building See https://developer.github.com/v3/repos/#create
* @throws IOException
* In case of any networking error or error from the server.
*/
public GHCreateRepositoryBuilder gitignoreTemplate(String language) {
this.builder.with("gitignore_template", language);
return this;
public GHCreateRepositoryBuilder gitignoreTemplate(String language) throws IOException {
return with("gitignore_template", language);
}
/**
@@ -183,10 +41,24 @@ public class GHCreateRepositoryBuilder {
* @param license
* template to base the license file on
* @return a builder to continue with building See https://developer.github.com/v3/repos/#create
* @throws IOException
* In case of any networking error or error from the server.
*/
public GHCreateRepositoryBuilder licenseTemplate(String license) {
this.builder.with("license_template", license);
return this;
public GHCreateRepositoryBuilder licenseTemplate(String license) throws IOException {
return with("license_template", license);
}
/**
* If true, create an initial commit with empty README.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
*/
public GHCreateRepositoryBuilder autoInit(boolean enabled) throws IOException {
return with("auto_init", enabled);
}
/**
@@ -195,10 +67,12 @@ public class GHCreateRepositoryBuilder {
* @param team
* team to grant access to
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
*/
public GHCreateRepositoryBuilder team(GHTeam team) {
public GHCreateRepositoryBuilder team(GHTeam team) throws IOException {
if (team != null)
this.builder.with("team_id", team.getId());
return with("team_id", team.getId());
return this;
}
@@ -208,13 +82,13 @@ public class GHCreateRepositoryBuilder {
* @param enabled
* true if enabled
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
* @deprecated Use {@link #isTemplate(boolean)} method instead
*/
@Preview
@Deprecated
public GHCreateRepositoryBuilder templateRepository(boolean enabled) {
this.builder.withPreview(BAPTISE);
this.builder.with("is_template", enabled);
return this;
public GHCreateRepositoryBuilder templateRepository(boolean enabled) throws IOException {
return isTemplate(enabled);
}
/**
@@ -223,14 +97,15 @@ public class GHCreateRepositoryBuilder {
* @param owner
* organization or personage
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
*/
public GHCreateRepositoryBuilder owner(String owner) {
this.builder.with("owner", owner);
return this;
public GHCreateRepositoryBuilder owner(String owner) throws IOException {
return with("owner", owner);
}
/**
* Create repository from template repository.
* Create repository from template repository
*
* @param templateOwner
* template repository owner
@@ -239,11 +114,10 @@ public class GHCreateRepositoryBuilder {
* @return a builder to continue with building
* @see <a href="https://developer.github.com/v3/previews/">GitHub API Previews</a>
*/
@Preview
@Preview(BAPTISTE)
@Deprecated
public GHCreateRepositoryBuilder fromTemplateRepository(String templateOwner, String templateRepo) {
this.builder.withPreview(BAPTISE);
this.apiUrlTail = "/repos/" + templateOwner + "/" + templateRepo + "/generate";
requester.withPreview(BAPTISTE).withUrlPath("/repos/" + templateOwner + "/" + templateRepo + "/generate");
return this;
}
@@ -252,10 +126,9 @@ public class GHCreateRepositoryBuilder {
*
* @return the gh repository
* @throws IOException
* if repsitory cannot be created
* if repository cannot be created
*/
public GHRepository create() throws IOException {
return builder.method("POST").withUrlPath(apiUrlTail).fetch(GHRepository.class).wrap(root);
return done();
}
}

View File

@@ -14,7 +14,6 @@ import java.util.Map;
*/
public class GHDeployment extends GHObject {
private GHRepository owner;
private GitHub root;
protected String sha;
protected String ref;
protected String task;
@@ -24,6 +23,9 @@ public class GHDeployment extends GHObject {
protected String statuses_url;
protected String repository_url;
protected GHUser creator;
protected String original_environment;
protected boolean transient_environment;
protected boolean production_environment;
GHDeployment wrap(GHRepository owner) {
this.owner = owner;
@@ -82,13 +84,26 @@ public class GHDeployment extends GHObject {
/**
* Gets payload without assuming its type. It could be a String or a Map.
*
*
* @return the payload
*/
public Object getPayloadObject() {
return payload;
}
/**
* The environment defined when the deployment was first created.
*
* @deprecated until preview feature has graduated to stable
*
* @return the original deployment environment
*/
@Deprecated
@Preview(Previews.FLASH)
public String getOriginalEnvironment() {
return original_environment;
}
/**
* Gets environment.
*
@@ -98,6 +113,33 @@ public class GHDeployment extends GHObject {
return environment;
}
/**
* Specifies if the given environment is specific to the deployment and will no longer exist at some point in the
* future.
*
* @deprecated until preview feature has graduated to stable
*
* @return the environment is transient
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public boolean isTransientEnvironment() {
return transient_environment;
}
/**
* Specifies if the given environment is one that end-users directly interact with.
*
* @deprecated until preview feature has graduated to stable
*
* @return the environment is used by end-users directly
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public boolean isProductionEnvironment() {
return production_environment;
}
/**
* Gets creator.
*
@@ -154,6 +196,8 @@ public class GHDeployment extends GHObject {
public PagedIterable<GHDeploymentStatus> listStatuses() {
return root.createRequest()
.withUrlPath(statuses_url)
.withPreview(Previews.ANT_MAN)
.withPreview(Previews.FLASH)
.toIterable(GHDeploymentStatus[].class, item -> item.wrap(owner));
}

View File

@@ -19,7 +19,10 @@ public class GHDeploymentBuilder {
*/
public GHDeploymentBuilder(GHRepository repo) {
this.repo = repo;
this.builder = repo.root.createRequest().method("POST");
this.builder = repo.root.createRequest()
.withPreview(Previews.ANT_MAN)
.withPreview(Previews.FLASH)
.method("POST");
}
/**
@@ -40,6 +43,7 @@ public class GHDeploymentBuilder {
*
* @param branch
* the branch
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder ref(String branch) {
@@ -52,6 +56,7 @@ public class GHDeploymentBuilder {
*
* @param task
* the task
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder task(String task) {
@@ -64,6 +69,7 @@ public class GHDeploymentBuilder {
*
* @param autoMerge
* the auto merge
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder autoMerge(boolean autoMerge) {
@@ -76,6 +82,7 @@ public class GHDeploymentBuilder {
*
* @param requiredContexts
* the required contexts
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder requiredContexts(List<String> requiredContexts) {
@@ -88,6 +95,7 @@ public class GHDeploymentBuilder {
*
* @param payload
* the payload
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder payload(String payload) {
@@ -100,6 +108,7 @@ public class GHDeploymentBuilder {
*
* @param environment
* the environment
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder environment(String environment) {
@@ -107,11 +116,47 @@ public class GHDeploymentBuilder {
return this;
}
/**
* Specifies if the given environment is specific to the deployment and will no longer exist at some point in the
* future.
*
* @deprecated until preview feature has graduated to stable
*
* @param transientEnvironment
* the environment is transient
*
* @return the gh deployment builder
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public GHDeploymentBuilder transientEnvironment(boolean transientEnvironment) {
builder.with("transient_environment", transientEnvironment);
return this;
}
/**
* Specifies if the given environment is one that end-users directly interact with.
*
* @deprecated until preview feature has graduated to stable
*
* @param productionEnvironment
* the environment is used by end-users directly
*
* @return the gh deployment builder
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public GHDeploymentBuilder productionEnvironment(boolean productionEnvironment) {
builder.with("production_environment", productionEnvironment);
return this;
}
/**
* Description gh deployment builder.
*
* @param description
* the description
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder description(String description) {
@@ -123,6 +168,7 @@ public class GHDeploymentBuilder {
* Create gh deployment.
*
* @return the gh deployment
*
* @throws IOException
* the io exception
*/

View File

@@ -4,5 +4,35 @@ package org.kohsuke.github;
* Represents the state of deployment
*/
public enum GHDeploymentState {
PENDING, SUCCESS, ERROR, FAILURE
PENDING,
SUCCESS,
ERROR,
FAILURE,
/**
* The state of the deployment currently reflects it's in progress.
*
* @deprecated until preview feature has graduated to stable
*/
@Deprecated
@Preview(Previews.FLASH)
IN_PROGRESS,
/**
* The state of the deployment currently reflects it's queued up for processing.
*
* @deprecated until preview feature has graduated to stable
*/
@Deprecated
@Preview(Previews.FLASH)
QUEUED,
/**
* The state of the deployment currently reflects it's no longer active.
*
* @deprecated until preview feature has graduated to stable
*/
@Deprecated
@Preview(Previews.ANT_MAN)
INACTIVE
}

View File

@@ -8,19 +8,21 @@ import java.util.Locale;
*/
public class GHDeploymentStatus extends GHObject {
private GHRepository owner;
private GitHub root;
protected GHUser creator;
protected String state;
protected String description;
protected String target_url;
protected String log_url;
protected String deployment_url;
protected String repository_url;
protected String environment_url;
/**
* Wrap gh deployment status.
*
* @param owner
* the owner
*
* @return the gh deployment status
*/
public GHDeploymentStatus wrap(GHRepository owner) {
@@ -34,12 +36,30 @@ public class GHDeploymentStatus extends GHObject {
/**
* Gets target url.
*
* @deprecated Target url is deprecated in favor of {@link #getLogUrl() getLogUrl}
*
* @return the target url
*/
@Deprecated
public URL getTargetUrl() {
return GitHubClient.parseURL(target_url);
}
/**
* Gets target url.
* <p>
* This method replaces {@link #getTargetUrl() getTargetUrl}}.
*
* @deprecated until preview feature has graduated to stable
*
* @return the target url
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public URL getLogUrl() {
return GitHubClient.parseURL(log_url);
}
/**
* Gets deployment url.
*
@@ -49,6 +69,19 @@ public class GHDeploymentStatus extends GHObject {
return GitHubClient.parseURL(deployment_url);
}
/**
* Gets deployment environment url.
*
* @deprecated until preview feature has graduated to stable
*
* @return the deployment environment url
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public URL getEnvironmentUrl() {
return GitHubClient.parseURL(environment_url);
}
/**
* Gets repository url.
*

View File

@@ -21,6 +21,7 @@ public class GHDeploymentStatusBuilder {
* the deployment id
* @param state
* the state
*
* @deprecated Use {@link GHDeployment#createStatus(GHDeploymentState)}
*/
@Deprecated
@@ -31,15 +32,38 @@ public class GHDeploymentStatusBuilder {
GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) {
this.repo = repo;
this.deploymentId = deploymentId;
this.builder = repo.root.createRequest().method("POST");
this.builder = repo.root.createRequest()
.withPreview(Previews.ANT_MAN)
.withPreview(Previews.FLASH)
.method("POST");
this.builder.with("state", state);
}
/**
* Add an inactive status to all prior non-transient, non-production environment deployments with the same
* repository and environment name as the created status's deployment.
*
* @deprecated until preview feature has graduated to stable
*
* @param autoInactive
* Add inactive status flag
*
* @return the gh deployment status builder
*/
@Deprecated
@Preview({ Previews.ANT_MAN, Previews.FLASH })
public GHDeploymentStatusBuilder autoInactive(boolean autoInactive) {
this.builder.with("auto_inactive", autoInactive);
return this;
}
/**
* Description gh deployment status builder.
*
* @param description
* the description
*
* @return the gh deployment status builder
*/
public GHDeploymentStatusBuilder description(String description) {
@@ -47,13 +71,70 @@ public class GHDeploymentStatusBuilder {
return this;
}
/**
* Name for the target deployment environment, which can be changed when setting a deploy status.
*
* @deprecated until preview feature has graduated to stable
*
* @param environment
* the environment name
*
* @return the gh deployment status builder
*/
@Deprecated
@Preview(Previews.FLASH)
public GHDeploymentStatusBuilder environment(String environment) {
this.builder.with("environment", environment);
return this;
}
/**
* The URL for accessing the environment
*
* @deprecated until preview feature has graduated to stable
*
* @param environmentUrl
* the environment url
*
* @return the gh deployment status builder
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public GHDeploymentStatusBuilder environmentUrl(String environmentUrl) {
this.builder.with("environment_url", environmentUrl);
return this;
}
/**
* The full URL of the deployment's output.
* <p>
* This method replaces {@link #targetUrl(String) targetUrl}.
*
* @deprecated until preview feature has graduated to stable
*
* @param logUrl
* the deployment output url
*
* @return the gh deployment status builder
*/
@Deprecated
@Preview(Previews.ANT_MAN)
public GHDeploymentStatusBuilder logUrl(String logUrl) {
this.builder.with("log_url", logUrl);
return this;
}
/**
* Target url gh deployment status builder.
*
* @deprecated Target url is deprecated in favor of {@link #logUrl(String) logUrl}
*
* @param targetUrl
* the target url
*
* @return the gh deployment status builder
*/
@Deprecated
public GHDeploymentStatusBuilder targetUrl(String targetUrl) {
this.builder.with("target_url", targetUrl);
return this;
@@ -63,6 +144,7 @@ public class GHDeploymentStatusBuilder {
* Create gh deployment status.
*
* @return the gh deployment status
*
* @throws IOException
* the io exception
*/

View File

@@ -1,6 +1,5 @@
package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.IOException;
@@ -18,8 +17,6 @@ import javax.annotation.Nonnull;
*/
public class GHDiscussion extends GHObject {
@JacksonInject
private GitHub root;
private GHTeam team;
private long number;
private String body, title, htmlUrl;
@@ -130,7 +127,7 @@ public class GHDiscussion extends GHObject {
*
* @return a {@link GHDiscussion.Updater}
*/
@Preview
@Preview(Previews.SQUIRREL_GIRL)
@Deprecated
public GHDiscussion.Updater update() {
return new GHDiscussion.Updater(this);
@@ -141,7 +138,7 @@ public class GHDiscussion extends GHObject {
*
* @return a {@link GHDiscussion.Setter}
*/
@Preview
@Preview(Previews.SQUIRREL_GIRL)
@Deprecated
public GHDiscussion.Setter set() {
return new GHDiscussion.Setter(this);

View File

@@ -12,9 +12,7 @@ import java.util.Date;
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API")
public class GHEventInfo {
private GitHub root;
public class GHEventInfo extends GitHubInteractiveObject {
// we don't want to expose Jackson dependency to the user. This needs databinding
private ObjectNode payload;

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,6 @@ import java.util.Map.Entry;
public class GHGist extends GHObject {
final GHUser owner;
final GitHub root;
private String forks_url, commits_url, id, git_pull_url, git_push_url, html_url;
@@ -123,7 +122,7 @@ public class GHGist extends GHObject {
/**
* Get the html url.
*
*
* @return the github html url
*/
public URL getHtmlUrl() {

View File

@@ -13,7 +13,6 @@ import javax.annotation.Nonnull;
* @see GitHub#createGist() GitHub#createGist()
*/
public class GHGistBuilder {
private final GitHub root;
private final Requester req;
private final LinkedHashMap<String, Object> files = new LinkedHashMap<String, Object>();
@@ -24,7 +23,6 @@ public class GHGistBuilder {
* the root
*/
public GHGistBuilder(GitHub root) {
this.root = root;
req = root.createRequest().method("POST");
}

View File

@@ -12,8 +12,7 @@ import java.util.Map;
* functionality
*/
class GHHooks {
static abstract class Context {
private final GitHub root;
static abstract class Context extends GitHubInteractiveObject {
private Context(GitHub root) {
this.root = root;

View File

@@ -16,7 +16,6 @@ import java.net.URL;
"UUF_UNUSED_FIELD" },
justification = "JSON API")
public class GHInvitation extends GHObject {
/* package almost final */ GitHub root;
private int id;
private GHRepository repository;

View File

@@ -53,7 +53,6 @@ import static org.kohsuke.github.Previews.SQUIRREL_GIRL;
public class GHIssue extends GHObject implements Reactable {
private static final String ASSIGNEES = "assignees";
GitHub root;
GHRepository owner;
// API v3
@@ -448,7 +447,7 @@ public class GHIssue extends GHObject implements Reactable {
.toIterable(GHIssueComment[].class, item -> item.wrapUp(this));
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public GHReaction createReaction(ReactionContent content) throws IOException {
return root.createRequest()
@@ -460,7 +459,7 @@ public class GHIssue extends GHObject implements Reactable {
.wrap(root);
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public PagedIterable<GHReaction> listReactions() {
return root.createRequest()

View File

@@ -126,7 +126,7 @@ public class GHIssueComment extends GHObject implements Reactable {
owner.root.createRequest().method("DELETE").withUrlPath(getApiRoute()).send();
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public GHReaction createReaction(ReactionContent content) throws IOException {
return owner.root.createRequest()
@@ -138,7 +138,7 @@ public class GHIssueComment extends GHObject implements Reactable {
.wrap(owner.root);
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public PagedIterable<GHReaction> listReactions() {
return owner.root.createRequest()

View File

@@ -9,9 +9,7 @@ import java.util.Date;
*
* @author Martin van Zijl
*/
public class GHIssueEvent {
private GitHub root;
public class GHIssueEvent extends GitHubInteractiveObject {
private long id;
private String node_id;
private String url;

View File

@@ -31,4 +31,4 @@ package org.kohsuke.github;
*/
public enum GHIssueState {
OPEN, CLOSED, ALL
}
}

View File

@@ -9,9 +9,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API")
public class GHKey {
/* package almost final */ GitHub root;
public class GHKey extends GitHubInteractiveObject {
protected String url, key, title;
protected boolean verified;
protected int id;

View File

@@ -20,7 +20,7 @@ import javax.annotation.Nonnull;
* @see GHIssue#getLabels() GHIssue#getLabels()
* @see GHRepository#listLabels() GHRepository#listLabels()
*/
public class GHLabel {
public class GHLabel extends GitHubInteractiveObject {
@Nonnull
private String url, name, color;
@@ -28,9 +28,6 @@ public class GHLabel {
@CheckForNull
private String description;
@Nonnull
private final GitHub root;
@JsonCreator
private GHLabel(@JacksonInject @Nonnull GitHub root) {
this.root = root;
@@ -132,7 +129,7 @@ public class GHLabel {
* @throws IOException
* the io exception
*/
@Preview
@BetaApi
@Deprecated
static Creator create(GHRepository repository) throws IOException {
return new Creator(repository);
@@ -179,7 +176,7 @@ public class GHLabel {
*
* @return a {@link Updater}
*/
@Preview
@BetaApi
@Deprecated
public Updater update() {
return new Updater(this);
@@ -187,10 +184,10 @@ public class GHLabel {
/**
* Begins a single property update.
*
*
* @return a {@link Setter}
*/
@Preview
@BetaApi
@Deprecated
public Setter set() {
return new Setter(this);
@@ -227,7 +224,7 @@ public class GHLabel {
*
* {@link #done()} is called automatically after the property is set.
*/
@Preview
@BetaApi
@Deprecated
public static class Setter extends GHLabelBuilder<GHLabel> {
private Setter(@Nonnull GHLabel base) {
@@ -241,7 +238,7 @@ public class GHLabel {
*
* Consumer must call {@link #done()} to commit changes.
*/
@Preview
@BetaApi
@Deprecated
public static class Updater extends GHLabelBuilder<Updater> {
private Updater(@Nonnull GHLabel base) {
@@ -255,7 +252,7 @@ public class GHLabel {
*
* Consumer must call {@link #done()} to create the new instance.
*/
@Preview
@BetaApi
@Deprecated
public static class Creator extends GHLabelBuilder<Creator> {
private Creator(@Nonnull GHRepository repository) {

View File

@@ -38,21 +38,21 @@ class GHLabelBuilder<S> extends AbstractBuilder<GHLabel, S> {
}
@Nonnull
@Preview
@BetaApi
@Deprecated
public S name(String value) throws IOException {
return with("name", value);
}
@Nonnull
@Preview
@BetaApi
@Deprecated
public S color(String value) throws IOException {
return with("color", value);
}
@Nonnull
@Preview
@BetaApi
@Deprecated
public S description(String value) throws IOException {
return with("description", value);

View File

@@ -44,9 +44,6 @@ import java.util.Objects;
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public class GHLicense extends GHObject {
@SuppressFBWarnings("IS2_INCONSISTENT_SYNC")
// root is set before the object is returned to the app
/* package almost final */ GitHub root;
// these fields are always present, even in the short form
protected String key, name;

View File

@@ -9,9 +9,7 @@ import java.net.URL;
* @see GitHub#getMyMarketplacePurchases()
* @see GHMarketplaceListAccountBuilder#createRequest()
*/
public class GHMarketplaceAccount {
protected GitHub root;
public class GHMarketplaceAccount extends GitHubInteractiveObject {
private String url;
private long id;
private String login;

View File

@@ -8,8 +8,7 @@ import java.io.IOException;
* @author Paulo Miguel Almeida
* @see GHMarketplacePlan#listAccounts()
*/
public class GHMarketplaceListAccountBuilder {
private final GitHub root;
public class GHMarketplaceListAccountBuilder extends GitHubInteractiveObject {
private final Requester builder;
private final long planId;

View File

@@ -10,8 +10,7 @@ import java.util.Date;
* @author Paulo Miguel Almeida
* @see GHMarketplaceListAccountBuilder#createRequest()
*/
public class GHMarketplacePendingChange {
private GitHub root;
public class GHMarketplacePendingChange extends GitHubInteractiveObject {
private long id;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization")
private Long unitCount;

View File

@@ -11,9 +11,7 @@ import java.util.List;
* @author Paulo Miguel Almeida
* @see GitHub#listMarketplacePlans()
*/
public class GHMarketplacePlan {
private GitHub root;
public class GHMarketplacePlan extends GitHubInteractiveObject {
private String url;
private String accountsUrl;
private long id;

View File

@@ -10,9 +10,8 @@ import java.util.Date;
* @author Paulo Miguel Almeida
* @see GHMarketplaceListAccountBuilder#createRequest() GHMarketplaceListAccountBuilder#createRequest()
*/
public class GHMarketplacePurchase {
public class GHMarketplacePurchase extends GitHubInteractiveObject {
private GitHub root;
private String billingCycle;
private String nextBillingDate;
private boolean onFreeTrial;

View File

@@ -10,8 +10,7 @@ import java.util.Date;
* @author Paulo Miguel Almeida
* @see GitHub#getMyMarketplacePurchases()
*/
public class GHMarketplaceUserPurchase {
protected GitHub root;
public class GHMarketplaceUserPurchase extends GitHubInteractiveObject {
private String billingCycle;
private String nextBillingDate;
private boolean onFreeTrial;

View File

@@ -10,9 +10,7 @@ import java.util.Locale;
* @author Kohsuke Kawaguchi
* @see GHMyself#listOrgMemberships() GHMyself#listOrgMemberships()
*/
public class GHMembership /* extends GHObject --- but it doesn't have id, created_at, etc. */ {
GitHub root;
public class GHMembership extends GitHubInteractiveObject {
String url;
String state;
String role;

View File

@@ -11,7 +11,6 @@ import java.util.Locale;
* @author Yusuke Kokubo
*/
public class GHMilestone extends GHObject {
GitHub root;
GHRepository owner;
GHUser creator;

View File

@@ -7,4 +7,4 @@ package org.kohsuke.github;
*/
public enum GHMilestoneState {
OPEN, CLOSED
}
}

View File

@@ -23,9 +23,7 @@ import java.util.NoSuchElementException;
* @see GitHub#listNotifications() GitHub#listNotifications()
* @see GHRepository#listNotifications() GHRepository#listNotifications()
*/
public class GHNotificationStream implements Iterable<GHThread> {
private final GitHub root;
public class GHNotificationStream extends GitHubInteractiveObject implements Iterable<GHThread> {
private Boolean all, participating;
private String since;
private String apiUrl;

View File

@@ -20,7 +20,7 @@ import javax.annotation.CheckForNull;
*/
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public abstract class GHObject {
public abstract class GHObject extends GitHubInteractiveObject {
/**
* Capture response HTTP headers on the state object.
*/
@@ -38,7 +38,7 @@ public abstract class GHObject {
/**
* Called by Jackson
*
*
* @param responseInfo
* the {@link GitHubResponse.ResponseInfo} to get headers from.
*/

View File

@@ -97,7 +97,7 @@ public class GHOrganization extends GHPerson {
* @return the gh create repository builder
*/
public GHCreateRepositoryBuilder createRepository(String name) {
return new GHCreateRepositoryBuilder(root, "/orgs/" + login + "/repos", name);
return new GHCreateRepositoryBuilder(name, root, "/orgs/" + login + "/repos");
}
/**
@@ -181,7 +181,7 @@ public class GHOrganization extends GHPerson {
/**
* Finds a team that has the given slug in its {@link GHTeam#getSlug()}
*
*
* @param slug
* the slug
* @return the team by slug

View File

@@ -28,7 +28,7 @@ import java.util.Locale;
/**
* Permission for a user in a repository.
*
*
* @see <a href="https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level">API</a>
*/
class GHPermission {

View File

@@ -18,7 +18,6 @@ import java.util.TreeMap;
* @author Kohsuke Kawaguchi
*/
public abstract class GHPerson extends GHObject {
/* package almost final */ GitHub root;
// core data fields that exist even for "small" user data (such as the user info in pull request)
protected String login, avatar_url;
@@ -236,7 +235,7 @@ public abstract class GHPerson extends GHObject {
/**
* Gets the Twitter Username of this user, like "GitHub"
*
*
* @return the Twitter username
* @throws IOException
* the io exception

View File

@@ -37,7 +37,6 @@ import static org.kohsuke.github.Previews.INERTIA;
* @see <a href="https://developer.github.com/v3/projects/">Projects</a>
*/
public class GHProject extends GHObject {
protected GitHub root;
protected GHObject owner;
private String owner_url;
@@ -311,4 +310,4 @@ public class GHProject extends GHObject {
.fetch(GHProjectColumn.class)
.wrap(this);
}
}
}

View File

@@ -14,7 +14,6 @@ import static org.kohsuke.github.Previews.INERTIA;
* @author Gunnar Skjold
*/
public class GHProjectCard extends GHObject {
private GitHub root;
private GHProject project;
private GHProjectColumn column;

View File

@@ -12,7 +12,6 @@ import static org.kohsuke.github.Previews.INERTIA;
* @author Gunnar Skjold
*/
public class GHProjectColumn extends GHObject {
protected GitHub root;
protected GHProject project;
private String name;

View File

@@ -576,7 +576,7 @@ public class GHPullRequest extends GHIssue implements Refreshable {
* @throws IOException
* the io exception
*/
@Preview
@Preview(LYDIAN)
@Deprecated
public void updateBranch() throws IOException {
root.createRequest()

View File

@@ -0,0 +1,86 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Wrapper to define changed fields on pull_request action="edited"
*
* @see GHEventPayload.PullRequest
*/
@SuppressFBWarnings("UWF_UNWRITTEN_FIELD")
public class GHPullRequestChanges {
private GHCommitPointer base;
private GHFrom title;
private GHFrom body;
/**
* Old target branch for pull request.
*
* @return old target branch info (or null if not changed)
*/
public GHCommitPointer getBase() {
return base;
}
/**
* Old pull request title.
*
* @return old pull request title (or null if not changed)
*/
public GHFrom getTitle() {
return title;
}
/**
* Old pull request body.
*
* @return old pull request body (or null if not changed)
*/
public GHFrom getBody() {
return body;
}
/**
* @see org.kohsuke.github.GHCommitPointer
*/
public static class GHCommitPointer {
private GHFrom ref;
private GHFrom sha;
/**
* Named ref to the commit. This (from value) appears to be a "short ref" that doesn't include "refs/heads/"
* portion.
*
* @return the ref
*/
public GHFrom getRef() {
return ref;
}
/**
* SHA1 of the commit.
*
* @return sha
*/
public GHFrom getSha() {
return sha;
}
}
/**
* Wrapper for changed values.
*/
public static class GHFrom {
private String from;
/**
* Previous value that was changed.
*
* @return previous value
*/
public String getFrom() {
return from;
}
}
}

View File

@@ -198,7 +198,7 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
.wrapUp(owner);
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public GHReaction createReaction(ReactionContent content) throws IOException {
return owner.root.createRequest()
@@ -210,7 +210,7 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
.wrap(owner.root);
}
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public PagedIterable<GHReaction> listReactions() {
return owner.root.createRequest()

View File

@@ -7,8 +7,7 @@ package org.kohsuke.github;
* the type parameter
* @author Kohsuke Kawaguchi
*/
public abstract class GHQueryBuilder<T> {
protected final GitHub root;
public abstract class GHQueryBuilder<T> extends GitHubInteractiveObject {
protected final Requester req;
GHQueryBuilder(GitHub root) {

View File

@@ -266,7 +266,7 @@ public class GHRateLimit {
/**
* Merge a {@link GHRateLimit} with another one to create a new {@link GHRateLimit} keeping the latest
* {@link Record}s from each.
*
*
* @param newLimit
* {@link GHRateLimit} with potentially updated {@link Record}s.
* @return a merged {@link GHRateLimit} with the latest {@link Record}s from these two instances. If the merged
@@ -458,7 +458,7 @@ public class GHRateLimit {
* {@link Record}s with earlier {@link #getResetEpochSeconds()} are replaced by those with later.
* {@link Record}s with the same {@link #getResetEpochSeconds()} are replaced by those with less remaining
* count.
*
*
* {@link UnknownLimitRecord}s compare with each other like regular {@link Record}s.
*
* {@link Record}s are replaced by {@link UnknownLimitRecord}s only when the current {@link Record} is expired

View File

@@ -11,10 +11,9 @@ import static org.kohsuke.github.Previews.*;
* @author Kohsuke Kawaguchi
* @see Reactable
*/
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public class GHReaction extends GHObject {
private GitHub root;
private GHUser user;
private ReactionContent content;

View File

@@ -11,9 +11,7 @@ import java.net.URL;
*
* @author Michael Clarke
*/
public class GHRef {
/* package almost final */ GitHub root;
public class GHRef extends GitHubInteractiveObject {
private String ref, url;
private GHObject object;

View File

@@ -15,14 +15,15 @@ import static java.lang.String.*;
* Release in a github repository.
*
* @see GHRepository#getReleases() GHRepository#getReleases()
* @see GHRepository#listReleases() () GHRepository#listReleases()
* @see GHRepository#createRelease(String) GHRepository#createRelease(String)
*/
public class GHRelease extends GHObject {
GitHub root;
GHRepository owner;
private String html_url;
private String assets_url;
private List<GHAsset> assets;
private String upload_url;
private String tag_name;
private String target_commitish;
@@ -249,18 +250,44 @@ public class GHRelease extends GHObject {
}
/**
* Gets assets.
* Get the cached assets.
*
* @return the assets
*
* @deprecated This should be the default behavior of {@link #getAssets()} in a future release. This method is
* introduced in addition to enable a transition to using cached asset information while keeping the
* existing logic in place for backwards compatibility.
*/
@Deprecated
public List<GHAsset> assets() {
return assets;
}
/**
* Re-fetch the assets of this release.
*
* @return the assets
* @throws IOException
* the io exception
* @deprecated The behavior of this method will change in a future release. It will then provide cached assets as
* provided by {@link #assets()}. Use {@link #listAssets()} instead to fetch up-to-date information of
* assets.
*/
@Deprecated
public List<GHAsset> getAssets() throws IOException {
return listAssets().toList();
}
/**
* Re-fetch the assets of this release.
*
* @return the assets
* @throws IOException
* the io exception
*/
public List<GHAsset> getAssets() throws IOException {
public PagedIterable<GHAsset> listAssets() throws IOException {
Requester builder = owner.root.createRequest();
return builder.withUrlPath(getApiTailUrl("assets"))
.toIterable(GHAsset[].class, item -> item.wrap(this))
.toList();
return builder.withUrlPath(getApiTailUrl("assets")).toIterable(GHAsset[].class, item -> item.wrap(this));
}
/**

View File

@@ -54,6 +54,8 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.WeakHashMap;
import javax.annotation.Nonnull;
import static java.util.Arrays.*;
import static java.util.Objects.requireNonNull;
import static org.kohsuke.github.Previews.*;
@@ -67,7 +69,6 @@ import static org.kohsuke.github.Previews.*;
@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 */ transient GitHub root;
private String nodeId, description, homepage, name, full_name;
@@ -164,6 +165,8 @@ public class GHRepository extends GHObject {
.with("task", task)
.with("environment", environment)
.withUrlPath(getApiTailUrl("deployments"))
.withPreview(ANT_MAN)
.withPreview(FLASH)
.toIterable(GHDeployment[].class, item -> item.wrap(this));
}
@@ -179,6 +182,8 @@ public class GHRepository extends GHObject {
public GHDeployment getDeployment(long id) throws IOException {
return root.createRequest()
.withUrlPath(getApiTailUrl("deployments/" + id))
.withPreview(ANT_MAN)
.withPreview(FLASH)
.fetch(GHDeployment.class)
.wrap(this);
}
@@ -705,7 +710,7 @@ public class GHRepository extends GHObject {
* @return the boolean
*/
@Deprecated
@Preview
@Preview(BAPTISTE)
public boolean isTemplate() {
// isTemplate is still in preview, we do not want to retrieve it unless needed.
if (isTemplate == null) {
@@ -815,6 +820,13 @@ public class GHRepository extends GHObject {
return size;
}
/**
* Affiliation of a repository collaborator
*/
public enum CollaboratorAffiliation {
ALL, DIRECT, OUTSIDE
}
/**
* Gets the collaborators on this repository. This set always appear to include the owner.
*
@@ -838,6 +850,19 @@ public class GHRepository extends GHObject {
return listUsers("collaborators");
}
/**
* Lists up the collaborators on this repository.
*
* @param affiliation
* Filter users by affiliation
* @return Users paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHUser> listCollaborators(CollaboratorAffiliation affiliation) throws IOException {
return listUsers(root.createRequest().with("affiliation", affiliation), "collaborators");
}
/**
* Lists all
* <a href="https://help.github.com/articles/assigning-issues-and-pull-requests-to-other-github-users/">the
@@ -885,6 +910,29 @@ public class GHRepository extends GHObject {
return r;
}
/**
* Gets the names of the collaborators on this repository. This method deviates from the principle of this library
* but it works a lot faster than {@link #getCollaborators()}.
*
* @param affiliation
* Filter users by affiliation
* @return the collaborator names
* @throws IOException
* the io exception
*/
public Set<String> getCollaboratorNames(CollaboratorAffiliation affiliation) throws IOException {
Set<String> r = new HashSet<>();
// no initializer - we just want to the logins
PagedIterable<GHUser> users = root.createRequest()
.withUrlPath(getApiTailUrl("collaborators"))
.with("affiliation", affiliation)
.toIterable(GHUser[].class, null);
for (GHUser u : users.toArray()) {
r.add(u.login);
}
return r;
}
/**
* Obtain permission for a given user in this repository.
*
@@ -1040,14 +1088,6 @@ public class GHRepository extends GHObject {
.send();
}
private void edit(String key, String value) throws IOException {
Requester requester = root.createRequest();
if (!key.equals("name")) {
requester.with("name", name); // even when we don't change the name, we need to send it in
}
requester.with(key, value).method("PATCH").withUrlPath(getApiTailUrl("")).send();
}
/**
* Enables or disables the issue tracker for this repository.
*
@@ -1057,7 +1097,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void enableIssueTracker(boolean v) throws IOException {
edit("has_issues", String.valueOf(v));
set().issues(v);
}
/**
@@ -1069,7 +1109,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void enableProjects(boolean v) throws IOException {
edit("has_projects", String.valueOf(v));
set().projects(v);
}
/**
@@ -1081,7 +1121,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void enableWiki(boolean v) throws IOException {
edit("has_wiki", String.valueOf(v));
set().wiki(v);
}
/**
@@ -1093,7 +1133,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void enableDownloads(boolean v) throws IOException {
edit("has_downloads", String.valueOf(v));
set().downloads(v);
}
/**
@@ -1105,7 +1145,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void renameTo(String name) throws IOException {
edit("name", name);
set().name(name);
}
/**
@@ -1117,7 +1157,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setDescription(String value) throws IOException {
edit("description", value);
set().description(value);
}
/**
@@ -1129,7 +1169,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setHomepage(String value) throws IOException {
edit("homepage", value);
set().homepage(value);
}
/**
@@ -1141,7 +1181,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setDefaultBranch(String value) throws IOException {
edit("default_branch", value);
set().defaultBranch(value);
}
/**
@@ -1153,7 +1193,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setPrivate(boolean value) throws IOException {
edit("private", Boolean.toString(value));
set().private_(value);
}
/**
@@ -1165,7 +1205,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void allowSquashMerge(boolean value) throws IOException {
edit("allow_squash_merge", Boolean.toString(value));
set().allowSquashMerge(value);
}
/**
@@ -1177,7 +1217,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void allowMergeCommit(boolean value) throws IOException {
edit("allow_merge_commit", Boolean.toString(value));
set().allowMergeCommit(value);
}
/**
@@ -1189,7 +1229,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void allowRebaseMerge(boolean value) throws IOException {
edit("allow_rebase_merge", Boolean.toString(value));
set().allowRebaseMerge(value);
}
/**
@@ -1201,7 +1241,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void deleteBranchOnMerge(boolean value) throws IOException {
edit("delete_branch_on_merge", Boolean.toString(value));
set().deleteBranchOnMerge(value);
}
/**
@@ -1238,12 +1278,30 @@ public class GHRepository extends GHObject {
* In case of any networking error or error from the server.
*/
public void archive() throws IOException {
edit("archived", "true");
// Generall would not update this record,
// but do so here since this will result in any other update actions failing
set().archive();
// Generally would not update this record,
// but doing so here since this will result in any other update actions failing
archived = true;
}
/**
* Creates a builder that can be used to bulk update repository settings.
*
* @return the repository updater
*/
public Updater update() {
return new Updater(this);
}
/**
* Creates a builder that can be used to bulk update repository settings.
*
* @return the repository updater
*/
public Setter set() {
return new Setter(this);
}
/**
* Sort orders for listing forks
*/
@@ -1879,7 +1937,7 @@ public class GHRepository extends GHObject {
* @see <a href="https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref">List check runs
* for a specific ref</a>
*/
@Preview
@Preview(ANTIOPE)
@Deprecated
public PagedIterable<GHCheckRun> getCheckRuns(String ref) throws IOException {
GitHubRequest request = root.createRequest()
@@ -1953,12 +2011,25 @@ public class GHRepository extends GHObject {
* the commit hash
* @return a builder which you should customize, then call {@link GHCheckRunBuilder#create}
*/
@Preview
@Preview(ANTIOPE)
@Deprecated
public @NonNull GHCheckRunBuilder createCheckRun(@NonNull String name, @NonNull String headSHA) {
return new GHCheckRunBuilder(this, name, headSHA);
}
/**
* Updates an existing check run.
*
* @param checkId
* the existing checkId
* @return a builder which you should customize, then call {@link GHCheckRunBuilder#create}
*/
@Preview(BAPTISTE)
@Deprecated
public @NonNull GHCheckRunBuilder updateCheckRun(long checkId) {
return new GHCheckRunBuilder(this, checkId);
}
/**
* Lists repository events.
*
@@ -2076,9 +2147,11 @@ public class GHRepository extends GHObject {
}
private PagedIterable<GHUser> listUsers(final String suffix) {
return root.createRequest()
.withUrlPath(getApiTailUrl(suffix))
.toIterable(GHUser[].class, item -> item.wrapUp(root));
return listUsers(root.createRequest(), suffix);
}
private PagedIterable<GHUser> listUsers(Requester requester, final String suffix) {
return requester.withUrlPath(getApiTailUrl(suffix)).toIterable(GHUser[].class, item -> item.wrapUp(root));
}
/**
@@ -2141,7 +2214,12 @@ public class GHRepository extends GHObject {
justification = "It causes a performance degradation, but we have already exposed it to the API")
@Deprecated
public Set<URL> getPostCommitHooks() {
return postCommitHooks;
synchronized (this) {
if (postCommitHooks == null) {
postCommitHooks = setupPostCommitHooks();
}
return postCommitHooks;
}
}
/**
@@ -2150,57 +2228,63 @@ public class GHRepository extends GHObject {
@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<URL> postCommitHooks = new AbstractSet<URL>() {
private List<URL> getPostCommitHooks() {
try {
List<URL> r = new ArrayList<>();
for (GHHook h : getHooks()) {
if (h.getName().equals("web")) {
r.add(new URL(h.getConfig().get("url")));
private /* final */ transient Set<URL> postCommitHooks;
@SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
justification = "It causes a performance degradation, but we have already exposed it to the API")
private Set<URL> setupPostCommitHooks() {
return new AbstractSet<URL>() {
private List<URL> getPostCommitHooks() {
try {
List<URL> r = new ArrayList<>();
for (GHHook h : getHooks()) {
if (h.getName().equals("web")) {
r.add(new URL(h.getConfig().get("url")));
}
}
return r;
} catch (IOException e) {
throw new GHException("Failed to retrieve post-commit hooks", e);
}
return r;
} catch (IOException e) {
throw new GHException("Failed to retrieve post-commit hooks", e);
}
}
@Override
public Iterator<URL> iterator() {
return getPostCommitHooks().iterator();
}
@Override
public int size() {
return getPostCommitHooks().size();
}
@Override
public boolean add(URL url) {
try {
createWebHook(url);
return true;
} catch (IOException e) {
throw new GHException("Failed to update post-commit hooks", e);
@Override
public Iterator<URL> iterator() {
return getPostCommitHooks().iterator();
}
}
@Override
public boolean remove(Object url) {
try {
String _url = ((URL) url).toExternalForm();
for (GHHook h : getHooks()) {
if (h.getName().equals("web") && h.getConfig().get("url").equals(_url)) {
h.delete();
return true;
@Override
public int size() {
return getPostCommitHooks().size();
}
@Override
public boolean add(URL url) {
try {
createWebHook(url);
return true;
} catch (IOException e) {
throw new GHException("Failed to update post-commit hooks", e);
}
}
@Override
public boolean remove(Object url) {
try {
String _url = ((URL) url).toExternalForm();
for (GHHook h : getHooks()) {
if (h.getName().equals("web") && h.getConfig().get("url").equals(_url)) {
h.delete();
return true;
}
}
return false;
} catch (IOException e) {
throw new GHException("Failed to update post-commit hooks", e);
}
return false;
} catch (IOException e) {
throw new GHException("Failed to update post-commit hooks", e);
}
}
};
};
}
GHRepository wrap(GitHub root) {
this.root = root;
@@ -2944,17 +3028,57 @@ public class GHRepository extends GHObject {
final URL url = requireNonNull(getUrl(), "Missing instance URL!");
try {
// IMPORTANT: the url for repository records is does not reliably point to the API url.
// IMPORTANT: the url for repository records does not reliably point to the API url.
// There is bug in Push event payloads that returns the wrong url.
// All other occurrences of "url" take the form "https://api.github.com/...".
// For Push event repository records, they take the form "https://github.com/{fullName}".
root.createRequest().withPreview(BAPTISE).setRawUrlPath(url.toString()).fetchInto(this).wrap(root);
root.createRequest().withPreview(BAPTISTE).setRawUrlPath(url.toString()).fetchInto(this).wrap(root);
} catch (HttpException e) {
if (e.getCause() instanceof JsonParseException) {
root.createRequest().withPreview(BAPTISE).withUrlPath("/repos/" + full_name).fetchInto(this).wrap(root);
root.createRequest()
.withPreview(BAPTISTE)
.withUrlPath("/repos/" + full_name)
.fetchInto(this)
.wrap(root);
} else {
throw e;
}
}
}
/**
* A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request.
*
* Consumer must call {@link #done()} to commit changes.
*/
@BetaApi
@Deprecated
public static class Updater extends GHRepositoryBuilder<Updater> {
protected Updater(@Nonnull GHRepository repository) {
super(Updater.class, repository.root, null);
// even when we don't change the name, we need to send it in
// this requirement may be out-of-date, but we do not want to break it
requester.with("name", repository.name);
requester.method("PATCH").withUrlPath(repository.getApiTailUrl(""));
}
}
/**
* A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request.
*
* Consumer must call {@link #done()} to commit changes.
*/
@BetaApi
@Deprecated
public static class Setter extends GHRepositoryBuilder<GHRepository> {
protected Setter(@Nonnull GHRepository repository) {
super(GHRepository.class, repository.root, null);
// even when we don't change the name, we need to send it in
// this requirement may be out-of-date, but we do not want to break it
requester.with("name", repository.name);
requester.method("PATCH").withUrlPath(repository.getApiTailUrl(""));
}
}
}

View File

@@ -0,0 +1,235 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.BAPTISTE;
abstract class GHRepositoryBuilder<S> extends AbstractBuilder<GHRepository, S> {
protected GHRepositoryBuilder(Class<S> intermediateReturnType, GitHub root, GHRepository baseInstance) {
super(GHRepository.class, intermediateReturnType, root, baseInstance);
}
/**
* Allow or disallow squash-merging pull requests.
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S allowSquashMerge(boolean enabled) throws IOException {
return with("allow_squash_merge", enabled);
}
/**
* Allow or disallow merging pull requests with a merge commit.
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S allowMergeCommit(boolean enabled) throws IOException {
return with("allow_merge_commit", enabled);
}
/**
* Allow or disallow rebase-merging pull requests.
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S allowRebaseMerge(boolean enabled) throws IOException {
return with("allow_rebase_merge", enabled);
}
/**
* After pull requests are merged, you can have head branches deleted automatically.
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S deleteBranchOnMerge(boolean enabled) throws IOException {
return with("delete_branch_on_merge", enabled);
}
/**
* Default repository branch
*
* @param branch
* branch name
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S defaultBranch(String branch) throws IOException {
return with("default_branch", branch);
}
/**
* Description for repository
*
* @param description
* description of repository
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S description(String description) throws IOException {
return with("description", description);
}
/**
* Homepage for repository
*
* @param homepage
* homepage of repository
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S homepage(URL homepage) throws IOException {
return homepage(homepage.toExternalForm());
}
/**
* Homepage for repository
*
* @param homepage
* homepage of repository
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S homepage(String homepage) throws IOException {
return with("homepage", homepage);
}
/**
* Sets the repository to private
*
* @param enabled
* private if true
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S private_(boolean enabled) throws IOException {
return with("private", enabled);
}
/**
* Enables issue tracker
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S issues(boolean enabled) throws IOException {
return with("has_issues", enabled);
}
/**
* Enables projects
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S projects(boolean enabled) throws IOException {
return with("has_projects", enabled);
}
/**
* Enables wiki
*
* @param enabled
* true if enabled
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
*/
public S wiki(boolean enabled) throws IOException {
return with("has_wiki", enabled);
}
/**
* Enables downloads
*
* @param enabled
* true if enabled
*
* @return a builder to continue with building
*
* @throws IOException
* In case of any networking error or error from the server.
*/
public S downloads(boolean enabled) throws IOException {
return with("has_downloads", enabled);
}
/**
* Specifies whether the repository is a template.
*
* @param enabled
* true if enabled
* @return a builder to continue with building
* @throws IOException
* In case of any networking error or error from the server.
*/
@Preview(BAPTISTE)
@Deprecated
public S isTemplate(boolean enabled) throws IOException {
requester.withPreview(BAPTISTE);
return with("is_template", enabled);
}
@Override
public GHRepository done() throws IOException {
return super.done().wrap(this.root);
}
S archive() throws IOException {
return with("archived", true);
}
S name(String name) throws IOException {
return with("name", name);
}
}

View File

@@ -16,10 +16,9 @@ import java.util.NoSuchElementException;
*
* @author Martin van Zijl
*/
public class GHRepositoryStatistics {
public class GHRepositoryStatistics extends GitHubInteractiveObject {
private final GHRepository repo;
private final GitHub root;
private static final int MAX_WAIT_ITERATIONS = 3;
private static final int WAIT_SLEEP_INTERVAL = 5000;
@@ -60,7 +59,7 @@ public class GHRepositoryStatistics {
* @throws InterruptedException
* the interrupted exception
*/
@Preview
@BetaApi
@Deprecated
@SuppressWarnings("SleepWhileInLoop")
@SuppressFBWarnings(value = { "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" }, justification = "JSON API")
@@ -99,7 +98,6 @@ public class GHRepositoryStatistics {
"URF_UNREAD_FIELD" },
justification = "JSON API")
public static class ContributorStats extends GHObject {
/* package almost final */ private GitHub root;
private GHUser author;
private int total;
private List<Week> weeks;
@@ -255,7 +253,6 @@ public class GHRepositoryStatistics {
value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public static class CommitActivity extends GHObject {
/* package almost final */ private GitHub root;
private List<Integer> days;
private int total;
private long week;
@@ -398,7 +395,6 @@ public class GHRepositoryStatistics {
* The type Participation.
*/
public static class Participation extends GHObject {
/* package almost final */ private GitHub root;
private List<Integer> all;
private List<Integer> owner;

View File

@@ -8,7 +8,6 @@ import java.net.URL;
justification = "JSON API")
public class GHRequestedAction extends GHObject {
private GHRepository owner;
private GitHub root;
private String identifier;
private String label;
private String description;
@@ -46,4 +45,4 @@ public class GHRequestedAction extends GHObject {
return null;
}
}
}

View File

@@ -10,11 +10,10 @@ import java.util.Date;
* @see GHRepository#getSubscription() GHRepository#getSubscription()
* @see GHThread#getSubscription() GHThread#getSubscription()
*/
public class GHSubscription {
public class GHSubscription extends GitHubInteractiveObject {
private String created_at, url, repository_url, reason;
private boolean subscribed, ignored;
private GitHub root;
private GHRepository repo;
/**

View File

@@ -9,9 +9,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
*/
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public class GHTag {
public class GHTag extends GitHubInteractiveObject {
private GHRepository owner;
private GitHub root;
private String name;
private GHCommit commit;

View File

@@ -9,9 +9,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
*/
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public class GHTagObject {
public class GHTagObject extends GitHubInteractiveObject {
private GHRepository owner;
private GitHub root;
private String tag;
private String sha;

View File

@@ -24,8 +24,6 @@ public class GHTeam extends GHObject implements Refreshable {
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.
@@ -145,6 +143,22 @@ public class GHTeam extends GHObject implements Refreshable {
return GHDiscussion.readAll(this);
}
/**
* List members with specified role paged iterable.
*
* @param role
* the role
* @return the paged iterable
* @throws IOException
* the io exception
*/
public PagedIterable<GHUser> listMembers(String role) throws IOException {
return root.createRequest()
.withUrlPath(api("/members"))
.with("role", role)
.toIterable(GHUser[].class, item -> item.wrapUp(root));
}
/**
* Gets a single discussion by ID.
*
@@ -171,7 +185,7 @@ public class GHTeam extends GHObject implements Refreshable {
* the io exception
*/
public PagedIterable<GHUser> listMembers() throws IOException {
return root.createRequest().withUrlPath(api("/members")).toIterable(GHUser[].class, item -> item.wrapUp(root));
return listMembers("all");
}
/**

View File

@@ -7,9 +7,7 @@ import java.io.IOException;
*
* https://developer.github.com/v3/teams/#create-team
*/
public class GHTeamBuilder {
private final GitHub root;
public class GHTeamBuilder extends GitHubInteractiveObject {
protected final Requester builder;
private final String orgName;

View File

@@ -17,7 +17,6 @@ import java.util.Date;
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" },
justification = "JSON API")
public class GHThread extends GHObject {
private GitHub root;
private GHRepository repository;
private Subject subject;
private String reason;

View File

@@ -741,7 +741,7 @@ public class GitHub {
* @return the team
* @throws IOException
* the io exception
*
*
* @deprecated Use {@link GHOrganization#getTeam(long)}
* @see <a href= "https://developer.github.com/v3/teams/#get-team-legacy">deprecation notice</a>
*/
@@ -845,7 +845,7 @@ public class GitHub {
* @return the gh create repository builder
*/
public GHCreateRepositoryBuilder createRepository(String name) {
return new GHCreateRepositoryBuilder(this, "/user/repos", name);
return new GHCreateRepositoryBuilder(name, this, "/user/repos");
}
/**
@@ -1013,7 +1013,7 @@ public class GitHub {
* @see <a href="https://developer.github.com/v3/apps/#get-the-authenticated-github-app">Get the authenticated
* GitHub App</a>
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public GHApp getApp() throws IOException {
return createRequest().withPreview(MACHINE_MAN).withUrlPath("/app").fetch(GHApp.class).wrapUp(this);
@@ -1108,7 +1108,7 @@ public class GitHub {
*
* @return the gh commit search builder
*/
@Preview
@Preview(Previews.CLOAK)
@Deprecated
public GHCommitSearchBuilder searchCommits() {
return new GHCommitSearchBuilder(this);
@@ -1208,26 +1208,34 @@ public class GitHub {
}
/**
* Do not use this method. This method will be removed and should never have been needed in the first place.
* Gets an {@link ObjectWriter} that can be used to convert data objects in this library to JSON.
*
* If you must convert data object in this library to JSON, the {@link ObjectWriter} returned by this method is the
* only supported way of doing so. This {@link ObjectWriter} can be used to convert any library data object to JSON
* without throwing an exception.
*
* WARNING: While the JSON generated is generally expected to be stable, it is not part of the API of this library
* and may change without warning. Use with extreme caution.
*
* @return an {@link ObjectWriter} instance that can be further configured.
* @deprecated DO NOT USE THIS METHOD. Provided for backward compatibility with projects that did their own jackson
* mapping of this project's data objects, such as Jenkins Blue Ocean.
*/
@Deprecated
@Nonnull
public static ObjectWriter getMappingObjectWriter() {
return GitHubClient.getMappingObjectWriter();
}
/**
* Do not use this method. This method will be removed and should never have been needed in the first place.
* Gets an {@link ObjectReader} that can be used to convert JSON into library data objects.
*
* If you must manually create library data objects from JSON, the {@link ObjectReader} returned by this method is
* the only supported way of doing so.
*
* WARNING: Objects generated from this method have limited functionality. They will not throw when being crated
* from valid JSON matching the expected object, but they are not guaranteed to be usable beyond that. Use with
* extreme caution.
*
* @return an {@link ObjectReader} instance that can be further configured.
* @deprecated DO NOT USE THIS METHOD. Provided for backward compatibility with projects that did their own jackson
* mapping of this project's data objects, such as Jenkins Blue Ocean.
*/
@Deprecated
@Nonnull
public static ObjectReader getMappingObjectReader() {
return GitHubClient.getMappingObjectReader(GitHub.offline());

View File

@@ -0,0 +1,23 @@
package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JacksonInject;
/**
* Defines a base class that all classes in this library that interact with GitHub inherit from.
*
* Ensures that all data references to GitHub connection are transient.
*
* Classes that do not need to interact with GitHub after they are instantiated do not need to inherit from this class.
*/
abstract class GitHubInteractiveObject {
@JacksonInject
/* package almost final */ transient GitHub root;
GitHubInteractiveObject() {
root = null;
}
GitHubInteractiveObject(GitHub root) {
this.root = root;
}
}

View File

@@ -75,7 +75,7 @@ class GitHubRequest {
/**
* Create a new {@link Builder}.
*
*
* @return a new {@link Builder}.
*/
public static Builder<?> newBuilder() {
@@ -165,7 +165,7 @@ class GitHubRequest {
/**
* The base GitHub API URL for this request represented as a {@link String}
*
*
* @return the url string
*/
@Nonnull
@@ -176,7 +176,7 @@ class GitHubRequest {
/**
* The url path to be added to the {@link #apiUrl()} for this request. If this does not start with a "/", it instead
* represents the full url string for this request.
*
*
* @return a url path or full url string
*/
@Nonnull
@@ -186,7 +186,7 @@ class GitHubRequest {
/**
* The content type to to be sent by this request.
*
*
* @return the content type.
*/
@Nonnull
@@ -196,7 +196,7 @@ class GitHubRequest {
/**
* The {@link InputStream} to be sent as the body of this request.
*
*
* @return the {@link InputStream}.
*/
@CheckForNull
@@ -206,7 +206,7 @@ class GitHubRequest {
/**
* The {@link URL} for this request. This is the actual URL the {@link GitHubClient} will send this request to.
*
*
* @return the request {@link URL}
*/
@Nonnull
@@ -216,7 +216,7 @@ class GitHubRequest {
/**
* Whether arguments for this request should be included in the URL or in the body of the request.
*
*
* @return true if the arguements should be sent in the body of the request.
*/
public boolean inBody() {
@@ -226,7 +226,7 @@ class GitHubRequest {
/**
* Create a {@link Builder} from this request. Initial values of the builder will be the same as this
* {@link GitHubRequest}.
*
*
* @return a {@link Builder} based on this request.
*/
public Builder<?> toBuilder() {
@@ -346,7 +346,7 @@ class GitHubRequest {
/**
* Builds a {@link GitHubRequest} from this builder.
*
*
* @return a {@link GitHubRequest}
* @throws MalformedURLException
* if the GitHub API URL cannot be constructed
@@ -437,6 +437,25 @@ class GitHubRequest {
return withHeader("Accept", name);
}
public B withPreview(Previews preview) {
return withPreview(preview.mediaType());
}
/**
* With requester.
*
* @param Map
* map of key value pairs to add
* @return the request builder
*/
public B with(Map<String, Object> map) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
with(entry.getKey(), entry.getValue());
}
return (B) this;
}
/**
* With requester.
*

View File

@@ -42,8 +42,6 @@ public class GitUser {
*
* @return GitHub username
*/
@Preview
@Deprecated
@CheckForNull
public String getUsername() {
return username;
@@ -52,7 +50,7 @@ public class GitUser {
/**
* Gets date.
*
* @return This field doesn't appear to be consistently available in all the situations where this class is used.
* @return Commit Date.
*/
public Date getDate() {
return GitHubClient.parseDate(date);

View File

@@ -164,7 +164,7 @@ public abstract class PagedIterable<T> implements Iterable<T> {
/**
* Concatenates a list of arrays into a single array.
*
*
* @param type
* the type of array to be returned.
* @param pages

View File

@@ -35,14 +35,14 @@ public class PagedIterator<T> implements Iterator<T> {
* Current batch of items. Each time {@link #next()} is called the next item in this array will be returned. After
* the last item of the array is returned, when {@link #next()} is called again, a new page of items will be fetched
* and iterating will continue from the first item in the new page.
*
*
* @see #fetch() {@link #fetch()} for details on how this field is used.
*/
private T[] currentPage;
/**
* The index of the next item on the page, the item that will be returned when {@link #next()} is called.
*
*
* @see #fetch() {@link #fetch()} for details on how this field is used.
*/
private int nextItemIndex;

View File

@@ -18,7 +18,7 @@ import javax.annotation.Nonnull;
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" },
justification = "Constructed by JSON API")
public class PagedSearchIterable<T> extends PagedIterable<T> {
private final GitHub root;
private final transient GitHub root;
private final GitHubRequest request;

View File

@@ -8,11 +8,23 @@ import java.lang.annotation.RetentionPolicy;
* Indicates that the method/class/etc marked maps to GitHub API in the preview period.
* <p>
* These APIs are subject to change and not a part of the backward compatibility commitment. Always used in conjunction
* with 'deprecated' to raise awareness to clients.
* with 'deprecated' to raise awareness to clients. In addition, it's advised to update the targets documentation to
* signify that the deprecation is required until preview feature being used is promoted to stable.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Preview {
/**
* An optional field defining what API media types must be set inorder to support the usage of this annotations
* target.
* <p>
* This value must be set using the existing constants defined in {@link Previews}
*
* @return The API preview media type.
*/
public Previews[] value();
}

View File

@@ -7,13 +7,21 @@ package org.kohsuke.github;
*
* @author Kohsuke Kawaguchi
*/
class Previews {
enum Previews {
/**
* Check-runs and check-suites
*
* @see <a href="https://developer.github.com/v3/previews/#check-runs-and-check-suites-api">GitHub API Previews</a>
*/
static final String ANTIOPE = "application/vnd.github.antiope-preview+json";
ANTIOPE("application/vnd.github.antiope-preview+json"),
/**
* Enhanced Deployments
*
* @see <a href="https://developer.github.com/v3/previews/#enhanced-deployments">GitHub API Previews</a>
*/
ANT_MAN("application/vnd.github.ant-man-preview+json"),
/**
* Create repository from template repository
@@ -21,21 +29,28 @@ class Previews {
* @see <a href="https://developer.github.com/v3/previews/#create-and-use-repository-templates">GitHub API
* Previews</a>
*/
static final String BAPTISE = "application/vnd.github.baptiste-preview+json";
BAPTISTE("application/vnd.github.baptiste-preview+json"),
/**
* Commit Search
*
* @see <a href="https://developer.github.com/v3/previews/#commit-search">GitHub API Previews</a>
*/
static final String CLOAK = "application/vnd.github.cloak-preview+json";
CLOAK("application/vnd.github.cloak-preview+json"),
/**
* New deployment statuses and support for updating deployment status environment
*
* @see <a href="https://developer.github.com/v3/previews/#deployment-statuses">GitHub API Previews</a>
*/
FLASH("application/vnd.github.flash-preview+json"),
/**
* Owners of GitHub Apps can now uninstall an app using the Apps API
*
* @see <a href="https://developer.github.com/v3/previews/#uninstall-a-github-app">GitHub API Previews</a>
*/
static final String GAMBIT = "application/vnd.github.gambit-preview+json";
GAMBIT("application/vnd.github.gambit-preview+json"),
/**
* List branches or pull requests for a commit
@@ -43,21 +58,21 @@ class Previews {
* @see <a href="https://developer.github.com/v3/previews/#list-branches-or-pull-requests-for-a-commit">GitHub API
* Previews</a>
*/
static final String GROOT = "application/vnd.github.groot-preview+json";
GROOT("application/vnd.github.groot-preview+json"),
/**
* Manage projects
*
* @see <a href="https://developer.github.com/v3/previews/#projects">GitHub API Previews</a>
*/
static final String INERTIA = "application/vnd.github.inertia-preview+json";
INERTIA("application/vnd.github.inertia-preview+json"),
/**
* Update a pull request branch
*
* @see <a href="https://developer.github.com/v3/previews/#update-a-pull-request-branch">GitHub API Previews</a>
*/
static final String LYDIAN = "application/vnd.github.lydian-preview+json";
LYDIAN("application/vnd.github.lydian-preview+json"),
/**
* Require multiple approving reviews
@@ -65,21 +80,21 @@ class Previews {
* @see <a href="https://developer.github.com/v3/previews/#require-multiple-approving-reviews">GitHub API
* Previews</a>
*/
static final String LUKE_CAGE = "application/vnd.github.luke-cage-preview+json";
LUKE_CAGE("application/vnd.github.luke-cage-preview+json"),
/**
* Manage integrations through the API
*
* @see <a href="https://developer.github.com/v3/previews/#integrations">GitHub API Previews</a>
*/
static final String MACHINE_MAN = "application/vnd.github.machine-man-preview+json";
MACHINE_MAN("application/vnd.github.machine-man-preview+json"),
/**
* View a list of repository topics in calls that return repository results
*
* @see <a href="https://developer.github.com/v3/previews/#repository-topics">GitHub API Previews</a>
*/
static final String MERCY = "application/vnd.github.mercy-preview+json";
MERCY("application/vnd.github.mercy-preview+json"),
/**
* New visibility parameter for the Repositories API
@@ -87,27 +102,38 @@ class Previews {
* @see <a href="https://developer.github.com/v3/previews/#new-visibility-parameter-for-the-repositories-api">GitHub
* API Previews</a>
*/
static final String NEBULA = "application/vnd.github.nebula-preview+json";
NEBULA("application/vnd.github.nebula-preview+json"),
/**
* Draft pull requests
*
* @see <a href="https://developer.github.com/v3/previews/#draft-pull-requests">GitHub API Previews</a>
*/
static final String SHADOW_CAT = "application/vnd.github.shadow-cat-preview+json";
SHADOW_CAT("application/vnd.github.shadow-cat-preview+json"),
/**
* Reactions
*
* @see <a href="https://developer.github.com/v3/previews/#reactions">GitHub API Previews</a>
*/
static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview+json";
SQUIRREL_GIRL("application/vnd.github.squirrel-girl-preview+json"),
/**
* Require signed commits
*
* @see <a href="https://developer.github.com/v3/previews/#require-signed-commits">GitHub API Previews</a>
*/
static final String ZZZAX = "application/vnd.github.zzzax-preview+json";
ZZZAX("application/vnd.github.zzzax-preview+json")
;
private final String mediaType;
Previews(String mediaType) {
this.mediaType = mediaType;
}
public String mediaType() {
return mediaType;
}
}

View File

@@ -44,7 +44,7 @@ public abstract class RateLimitChecker {
* {@code true} at least once for a particular request, {@link GitHubRateLimitChecker} may choose to sleep for some
* small additional between calls and before letting the request continue.
* </p>
*
*
* @param rateLimitRecord
* the current {@link GHRateLimit.Record} to check against.
* @param count

View File

@@ -2,7 +2,7 @@ package org.kohsuke.github;
/**
* Specifies the rate limit record of an operation.
*
*
* @see GitHubBuilder#withRateLimitChecker(RateLimitChecker, RateLimitTarget)
*/
public enum RateLimitTarget {

View File

@@ -2,12 +2,14 @@ package org.kohsuke.github;
import java.io.IOException;
import static org.kohsuke.github.Previews.SQUIRREL_GIRL;
/**
* Those {@link GHObject}s that can have {@linkplain GHReaction reactions}.
*
* @author Kohsuke Kawaguchi
*/
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
public interface Reactable {
/**
@@ -15,7 +17,7 @@ public interface Reactable {
*
* @return the paged iterable
*/
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
PagedIterable<GHReaction> listReactions();
@@ -28,7 +30,7 @@ public interface Reactable {
* @throws IOException
* the io exception
*/
@Preview
@Preview(SQUIRREL_GIRL)
@Deprecated
GHReaction createReaction(ReactionContent content) throws IOException;
}

View File

@@ -40,7 +40,7 @@ import javax.annotation.Nonnull;
* @author Kohsuke Kawaguchi
*/
class Requester extends GitHubRequest.Builder<Requester> {
/* private */ final GitHubClient client;
/* private */ final transient GitHubClient client;
Requester(GitHubClient client) {
this.client = client;

View File

@@ -26,7 +26,11 @@ import javax.net.ssl.SSLSocketFactory;
*
* @author Roberto Tyley
* @author Kohsuke Kawaguchi
* @deprecated This class depends on an unsupported version of OkHttp. Switch to
* {@link org.kohsuke.github.extras.okhttp3.OkHttpConnector}.
* @see org.kohsuke.github.extras.okhttp3.OkHttpConnector
*/
@Deprecated
public class OkHttpConnector implements HttpConnector {
private static final String HEADER_NAME = "Cache-Control";
private final OkUrlFactory urlFactory;
@@ -45,7 +49,7 @@ public class OkHttpConnector implements HttpConnector {
/**
* package private for tests to be able to change max-age for cache.
*
*
* @param urlFactory
* @param cacheMaxAge
*/

View File

@@ -1,25 +1,5 @@
package org.kohsuke.github.extras.okhttp3;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.Handshake;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Pipe;
import okio.Timeout;
/*
* Copyright (C) 2014 Square, Inc.
*
@@ -35,6 +15,28 @@ import okio.Timeout;
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.Handshake;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Pipe;
import okio.Timeout;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -179,7 +181,7 @@ public final class ObsoleteUrlFactory implements URLStreamHandlerFactory, Clonea
* <p>
* This code configures OkHttp to handle all HTTP and HTTPS connections created with
* {@link java.net.URL#openConnection()}:
*
*
* <pre>
* {
* &#64;code
@@ -404,7 +406,7 @@ public final class ObsoleteUrlFactory implements URLStreamHandlerFactory, Clonea
try {
Response response = getResponse(true);
if (hasBody(response) && response.code() >= HTTP_BAD_REQUEST) {
return response.body().byteStream();
return new ResponseBodyInputStream(response.body());
}
return null;
} catch (IOException e) {
@@ -486,7 +488,7 @@ public final class ObsoleteUrlFactory implements URLStreamHandlerFactory, Clonea
Response response = getResponse(false);
if (response.code() >= HTTP_BAD_REQUEST)
throw new FileNotFoundException(url.toString());
return response.body().byteStream();
return new ResponseBodyInputStream(response.body());
}
@Override
@@ -957,6 +959,7 @@ public final class ObsoleteUrlFactory implements URLStreamHandlerFactory, Clonea
initOutputStream(Okio.buffer(pipe.sink()), expectedContentLength);
}
@Override
public boolean isOneShot() {
return true;
}
@@ -1367,4 +1370,69 @@ public final class ObsoleteUrlFactory implements URLStreamHandlerFactory, Clonea
super(cause);
}
}
/**
* Make sure both the ResponseBody and the InputStream are closed when the InputStream coming from the ResponseBody
* is closed.
*/
private static final class ResponseBodyInputStream extends InputStream {
private final ResponseBody responseBody;
private final InputStream inputStream;
private ResponseBodyInputStream(ResponseBody responseBody) {
this.responseBody = responseBody;
this.inputStream = responseBody.byteStream();
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public int read(byte b[]) throws IOException {
return inputStream.read(b);
}
@Override
public int read(byte b[], int off, int len) throws IOException {
return inputStream.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return inputStream.skip(n);
}
@Override
public int available() throws IOException {
return inputStream.available();
}
@Override
public synchronized void mark(int readlimit) {
inputStream.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
inputStream.reset();
}
@Override
public boolean markSupported() {
return inputStream.markSupported();
}
@Override
public void close() throws IOException {
try {
inputStream.close();
} finally {
responseBody.close();
}
}
}
}

View File

@@ -0,0 +1,77 @@
package org.kohsuke.github;
import io.jsonwebtoken.Jwts;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
public class AbstractGHAppInstallationTest extends AbstractGitHubWireMockTest {
private static String TEST_APP_ID_1 = "82994";
private static String TEST_APP_ID_2 = "83009";
private static String TEST_APP_ID_3 = "89368";
private static String PRIVATE_KEY_FILE_APP_1 = "/ghapi-test-app-1.private-key.pem";
private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem";
private static String PRIVATE_KEY_FILE_APP_3 = "/ghapi-test-app-3.private-key.pem";
private String createJwtToken(String keyFileResouceName, String appId) {
try {
String keyPEM = IOUtils.toString(this.getClass().getResource(keyFileResouceName), "US-ASCII")
.replaceAll("(?m)^--.*", "") // remove comments from PEM to allow decoding
.replaceAll("\\s", "");
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyPEM));
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpecPKCS8);
return Jwts.builder()
.setIssuedAt(Date.from(Instant.now()))
.setExpiration(Date.from(Instant.now().plus(5, ChronoUnit.MINUTES)))
.setIssuer(appId)
.signWith(privateKey)
.compact();
} catch (Exception e) {
throw new RuntimeException("Error creating JWT token.", e);
}
}
private GHAppInstallation getAppInstallationWithToken(String jwtToken) throws IOException {
GitHub gitHub = getGitHubBuilder().withJwtToken(jwtToken)
.withEndpoint(mockGitHub.apiServer().baseUrl())
.build();
GHAppInstallation appInstallation = gitHub.getApp()
.listInstallations()
.toList()
.stream()
.filter(it -> it.getAccount().login.equals("hub4j-test-org"))
.findFirst()
.get();
appInstallation
.setRoot(getGitHubBuilder().withAppInstallationToken(appInstallation.createToken().create().getToken())
.withEndpoint(mockGitHub.apiServer().baseUrl())
.build());
return appInstallation;
}
protected GHAppInstallation getAppInstallationWithTokenApp1() throws IOException {
return getAppInstallationWithToken(createJwtToken(PRIVATE_KEY_FILE_APP_1, TEST_APP_ID_1));
}
protected GHAppInstallation getAppInstallationWithTokenApp2() throws IOException {
return getAppInstallationWithToken(createJwtToken(PRIVATE_KEY_FILE_APP_2, TEST_APP_ID_2));
}
protected GHAppInstallation getAppInstallationWithTokenApp3() throws IOException {
return getAppInstallationWithToken(createJwtToken(PRIVATE_KEY_FILE_APP_3, TEST_APP_ID_3));
}
}

View File

@@ -174,14 +174,12 @@ public abstract class AbstractGitHubWireMockTest extends Assert {
* if repository could not be created or retrieved.
*/
protected GHRepository getTempRepository(String name) throws IOException {
String fullName = GITHUB_API_TEST_ORG + '/' + name;
if (mockGitHub.isUseProxy()) {
String fullName = getOrganization() + '/' + name;
if (mockGitHub.isUseProxy()) {
cleanupRepository(fullName);
GHRepository repository = getGitHubBeforeAfter().getOrganization(GITHUB_API_TEST_ORG)
.createRepository(name)
.description("A test repository for testing the github-api project: " + name)
getCreateBuilder(name).description("A test repository for testing the github-api project: " + name)
.homepage("http://github-api.kohsuke.org/")
.autoInit(true)
.wiki(true)
@@ -244,6 +242,20 @@ public abstract class AbstractGitHubWireMockTest extends Assert {
// assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2"));
}
private GHCreateRepositoryBuilder getCreateBuilder(String name) throws IOException {
GitHub github = getGitHubBeforeAfter();
if (mockGitHub.isTestWithOrg()) {
return github.getOrganization(GITHUB_API_TEST_ORG).createRepository(name);
}
return github.createRepository(name);
}
private String getOrganization() throws IOException {
return mockGitHub.isTestWithOrg() ? GITHUB_API_TEST_ORG : gitHub.getMyself().getLogin();
}
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
assertThat("", actual, matcher);
}

View File

@@ -69,10 +69,7 @@ public class AppTest extends AbstractGitHubWireMockTest {
assertThat(r.hasDownloads(), is(false));
assertThat(r.getName(), equalTo(targetName));
// ISSUE: #765
// From what I can tell this is a bug in GithHub.
// updating `has_projects` doesn't seem to do anything
assertThat(r.hasProjects(), is(true));
assertThat(r.hasProjects(), is(false));
r.delete();
}
@@ -180,6 +177,9 @@ public class AppTest extends AbstractGitHubWireMockTest {
assertFalse(Iterables.isEmpty(deployments));
GHDeployment unitTestDeployment = deployments.get(0);
assertEquals("unittest", unitTestDeployment.getEnvironment());
assertEquals("unittest", unitTestDeployment.getOriginalEnvironment());
assertEquals(false, unitTestDeployment.isProductionEnvironment());
assertEquals(true, unitTestDeployment.isTransientEnvironment());
assertEquals("master", unitTestDeployment.getRef());
}
@@ -191,14 +191,23 @@ public class AppTest extends AbstractGitHubWireMockTest {
.description("question")
.payload("{\"user\":\"atmos\",\"room_id\":123456}")
.create();
GHDeploymentStatus ghDeploymentStatus = deployment.createStatus(GHDeploymentState.SUCCESS)
GHDeploymentStatus ghDeploymentStatus = deployment.createStatus(GHDeploymentState.QUEUED)
.description("success")
.targetUrl("http://www.github.com")
.logUrl("http://www.github.com/logurl")
.environmentUrl("http://www.github.com/envurl")
.environment("new-ci-env")
.create();
Iterable<GHDeploymentStatus> deploymentStatuses = deployment.listStatuses();
assertNotNull(deploymentStatuses);
assertEquals(1, Iterables.size(deploymentStatuses));
assertEquals(ghDeploymentStatus.getId(), Iterables.get(deploymentStatuses, 0).getId());
GHDeploymentStatus actualStatus = Iterables.get(deploymentStatuses, 0);
assertEquals(ghDeploymentStatus.getId(), actualStatus.getId());
assertEquals(ghDeploymentStatus.getState(), actualStatus.getState());
assertEquals(ghDeploymentStatus.getLogUrl(), actualStatus.getLogUrl());
// Target url was deprecated and replaced with log url. The gh api will
// prefer the log url value and return it in place of target url.
assertEquals(ghDeploymentStatus.getTargetUrl(), actualStatus.getLogUrl());
}
@Test
@@ -208,6 +217,7 @@ public class AppTest extends AbstractGitHubWireMockTest {
.getIssues(GHIssueState.CLOSED);
// prior to using PagedIterable GHRepository.getIssues(GHIssueState) would only retrieve 30 issues
assertTrue(closedIssues.size() > 150);
String readRepoString = GitHub.getMappingObjectWriter().writeValueAsString(closedIssues.get(0));
}
private GHRepository getTestRepository() throws IOException {
@@ -662,6 +672,10 @@ public class AppTest extends AbstractGitHubWireMockTest {
assertEquals(commit.getCommitShortInfo().getMessage(), "doc");
assertFalse(commit.getCommitShortInfo().getVerification().isVerified());
assertEquals(commit.getCommitShortInfo().getVerification().getReason(), GHVerification.Reason.UNSIGNED);
assertThat(commit.getCommitShortInfo().getAuthor().getDate().toInstant().getEpochSecond(),
equalTo(1271650361L));
assertThat(commit.getCommitShortInfo().getCommitter().getDate().toInstant().getEpochSecond(),
equalTo(1271650361L));
}
@Ignore("Needs mocking check")

View File

@@ -0,0 +1,108 @@
package org.kohsuke.github;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaAnnotation;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.BeforeClass;
import org.junit.Test;
import static com.tngtech.archunit.lang.conditions.ArchConditions.beAnnotatedWith;
import static com.tngtech.archunit.lang.conditions.ArchConditions.not;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.methods;
import static org.junit.Assert.assertTrue;
public class ArchTests {
private static final JavaClasses classFiles = new ClassFileImporter()
.withImportOption(new ImportOption.DoNotIncludeTests())
.withImportOption(new ImportOption.DoNotIncludeJars())
.importPackages("org.kohsuke.github");
private static final DescribedPredicate<JavaAnnotation<?>> previewAnnotationWithNoMediaType = new DescribedPredicate<JavaAnnotation<?>>(
"preview has no required media types defined") {
@Override
public boolean apply(JavaAnnotation<?> javaAnnotation) {
boolean isPreview = javaAnnotation.getRawType().isEquivalentTo(Preview.class);
Object[] values = (Object[]) javaAnnotation.getProperties().get("value");
return isPreview && values != null && values.length < 1;
}
};
@BeforeClass
public static void beforeClass() {
assertTrue(classFiles.size() > 0);
}
@Test
public void testPreviewsAreFlaggedAsDeprecated() {
String reason = "all preview APIs must be annotated as @Deprecated until they are promoted to stable";
ArchRule classRule = classes().that()
.areAnnotatedWith(Preview.class)
.should()
.beAnnotatedWith(Deprecated.class)
.andShould(not(beAnnotatedWith(previewAnnotationWithNoMediaType)))
.because(reason);
ArchRule methodRule = methods().that()
.areAnnotatedWith(Preview.class)
.should()
.beAnnotatedWith(Deprecated.class)
.andShould(not(beAnnotatedWith(previewAnnotationWithNoMediaType)))
.because(reason);
ArchRule enumFieldsRule = fields().that()
.areDeclaredInClassesThat()
.areEnums()
.and()
.areAnnotatedWith(Preview.class)
.should()
.beAnnotatedWith(Deprecated.class)
.andShould(not(beAnnotatedWith(previewAnnotationWithNoMediaType)))
.because(reason);
classRule.check(classFiles);
enumFieldsRule.check(classFiles);
methodRule.check(classFiles);
}
@Test
public void testBetaApisAreFlaggedAsDeprecated() {
String reason = "all beta APIs must be annotated as @Deprecated until they are promoted to stable";
ArchRule classRule = classes().that()
.areAnnotatedWith(BetaApi.class)
.should()
.beAnnotatedWith(Deprecated.class)
.because(reason);
ArchRule methodRule = methods().that()
.areAnnotatedWith(BetaApi.class)
.should()
.beAnnotatedWith(Deprecated.class)
.because(reason);
ArchRule enumFieldsRule = fields().that()
.areDeclaredInClassesThat()
.areEnums()
.and()
.areAnnotatedWith(BetaApi.class)
.should()
.beAnnotatedWith(Deprecated.class)
.because(reason);
classRule.check(classFiles);
enumFieldsRule.check(classFiles);
methodRule.check(classFiles);
}
}

View File

@@ -7,6 +7,8 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
/**
* @author Kohsuke Kawaguchi
*/
@@ -120,4 +122,17 @@ public class CommitTest extends AbstractGitHubWireMockTest {
commit.getCommitShortInfo().getVerification().getPayload());
}
}
@Test // issue 883
public void commitDateNotNull() throws Exception {
GHRepository repo = gitHub.getRepository("hub4j/github-api");
GHCommit commit = repo.getCommit("865a49d2e86c24c5777985f0f103e975c4b765b9");
assertThat(commit.getCommitShortInfo().getAuthoredDate().toInstant().getEpochSecond(), equalTo(1609207093L));
assertThat(commit.getCommitShortInfo().getAuthoredDate(),
equalTo(commit.getCommitShortInfo().getAuthor().getDate()));
assertThat(commit.getCommitShortInfo().getCommitDate().toInstant().getEpochSecond(), equalTo(1609207652L));
assertThat(commit.getCommitShortInfo().getCommitDate(),
equalTo(commit.getCommitShortInfo().getCommitter().getDate()));
}
}

View File

@@ -0,0 +1,29 @@
package org.kohsuke.github;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class GHAppInstallationTest extends AbstractGHAppInstallationTest {
@Test
public void testListRepositoriesTwoRepos() throws IOException {
GHAppInstallation appInstallation = getAppInstallationWithTokenApp1();
List<GHRepository> repositories = appInstallation.listRepositories().toList();
assertEquals(2, repositories.size());
assertTrue(repositories.stream().anyMatch(it -> it.getName().equals("empty")));
assertTrue(repositories.stream().anyMatch(it -> it.getName().equals("test-readme")));
}
@Test
public void testListRepositoriesNoPermissions() throws IOException {
GHAppInstallation appInstallation = getAppInstallationWithTokenApp2();
assertTrue("App does not have permissions and should have 0 repositories",
appInstallation.listRepositories().toList().isEmpty());
}
}

Some files were not shown because too many files have changed in this diff Show More