Compare commits

...

145 Commits

Author SHA1 Message Date
Liam Newman
d033355e84 [maven-release-plugin] prepare release github-api-1.121 2021-01-14 13:19:31 -08:00
Liam Newman
59d7a117d0 [maven-release-plugin] prepare for next development iteration 2021-01-14 10:51:52 -08:00
Liam Newman
dfbb38c5f1 [maven-release-plugin] prepare release github-api-1.120 2021-01-14 10:51:41 -08:00
Liam Newman
3f9954144a Merge pull request #945 from MarcosCela/feat/credential-provider-refresh
Feat/credential provider refresh
2021-01-14 10:37:30 -08:00
Liam Newman
1b84efdbfa Add GitHub.DependentAuthorizationProvider
Rather than exposing an unsafe wrapper for GitHub instances, I added a base class
that can be extended by anyone wanting to implement an authorization provider
that needs a GitHub instance to generate it's authorization string.
2021-01-14 10:32:25 -08:00
Liam Newman
c33e78a7dc Create authorization package 2021-01-14 09:23:17 -08:00
Marcos.Cela
747c759bbb fix code violations again 2021-01-08 10:10:44 +01:00
Marcos.Cela
e0a709676e fix format violations 2021-01-08 09:56:05 +01:00
Marcos.Cela
a96275c286 tests for JWTTokenProvider, verifying the "Authentication" header
This test basically ensures that the requests made with a
JWTTokenProvider follow a valid Authentication pattern,
verifying that the header "conforms" to a valid JWT token
More information on JWT tokens can be found at:

- https://jwt.io/introduction/
2021-01-08 09:52:50 +01:00
Marcos.Cela
ca7c809feb remove unused field MINUTES_10 from JWTTokenProvider 2021-01-08 08:21:35 +01:00
Marcos Cela López
a8a0bcb7db Merge branch 'master' into feat/credential-provider-refresh 2021-01-07 12:03:27 +01:00
Marcos.Cela
0e2bf23830 add CODE_SCANNING_ALERT to GHEvent enum 2021-01-07 11:32:33 +01:00
Marcos.Cela
44a8b797fb fix: JWTTokenProvider has an incorrect value for the returned authorization header
more info:
https://docs.github.com/en/free-pro-team@latest/developers/apps/authenticating-with-github-apps#authenticating-as-a-github-app
2021-01-07 11:23:22 +01:00
Marcos.Cela
cdede298a9 rename OrgInstallationAuthorizationProvider to OrgAppInstallationAuthorizationProvider 2021-01-07 09:53:19 +01:00
Marcos.Cela
f6ac4d3559 rename: credential provider -> authorization provider
This includes renames in comments, related methods,
javadocs and fields/variables.
2021-01-07 09:46:30 +01:00
Liam Newman
7e1531dbca [maven-release-plugin] prepare for next development iteration 2021-01-05 17:27:23 -08:00
Liam Newman
9aeb422157 [maven-release-plugin] prepare release github-api-1.119 2021-01-05 17:27:08 -08:00
Liam Newman
fba0f8cf8e Merge pull request #1015 from seregamorph/feature/mock-previews
Fix mocking Previews
2021-01-05 17:23:55 -08:00
seregamorph
0f4a5227e1 internal package 2021-01-05 23:03:49 +03:00
seregamorph
d16a752b43 Fix mocking Previews 2021-01-05 18:50:24 +03:00
Liam Newman
4bec27fd49 [maven-release-plugin] prepare for next development iteration 2021-01-04 01:48:27 -08:00
Liam Newman
be3bd74bb7 [maven-release-plugin] prepare release github-api-1.118 2021-01-04 01:48:16 -08:00
Liam Newman
0b14cee817 Merge pull request #1011 from hub4j/dependabot/maven/org.kohsuke.stapler-stapler-1.262
Chore(deps-dev): Bump stapler from 1.260 to 1.262
2021-01-03 23:43:02 -08:00
dependabot[bot]
252ca04084 Chore(deps-dev): Bump stapler from 1.260 to 1.262
Bumps [stapler](https://github.com/stapler/stapler) from 1.260 to 1.262.
- [Release notes](https://github.com/stapler/stapler/releases)
- [Changelog](https://github.com/stapler/stapler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stapler/stapler/compare/stapler-parent-1.260...stapler-parent-1.262)

Signed-off-by: dependabot[bot] <support@github.com>
2021-01-01 02:00:35 +00:00
Liam Newman
6670446037 Reenable GitHubBuilder tests 2020-12-31 09:49:51 -08:00
Liam Newman
bd39b07bb5 Fix javadoc issues 2020-12-30 14:07:37 -08:00
Liam Newman
a9438b6121 Move tests to use JWTTokenProvider 2020-12-30 10:46:45 -08:00
Liam Newman
f546cf4521 Use only credential providers internally to track credentials
Removes extra fields from GitHubClient.
2020-12-30 09:52:30 -08:00
Liam Newman
43efa78750 Post-merge fixes 2020-12-29 09:29:30 -08:00
Liam Newman
9e3de43802 Merge remote-tracking branch 'upstream/master' into feat/credential-provider-refresh 2020-12-29 09:19:09 -08:00
Liam Newman
dc615e432e Merge pull request #985 from lower-case/bugfix-883
Fixes null commit date
2020-12-28 22:06:47 -08:00
Liam Newman
cf9caa6af5 Update test to check values 2020-12-28 22:00:44 -08:00
Liam Newman
15f748358d Merge remote-tracking branch 'upstream/master' into bugfix-883 2020-12-28 20:02:24 -08:00
Liam Newman
b30d648623 Merge pull request #939 from jgangemi/jae/bulk-update
- bulk update of repository options
2020-12-28 19:54:44 -08:00
Liam Newman
33d70560b8 Deprecate templateRepository() for isTemplate() 2020-12-28 18:44:30 -08:00
Liam Newman
865a49d2e8 Update GHRepository method to use Setter
It appears that the correct way to pass these booleans is as booleans not as strings.

Fixes #765
2020-12-28 18:07:32 -08:00
Liam Newman
4fca68c25c Add GHRepository.Setter 2020-12-28 17:03:36 -08:00
Liam Newman
f131a0c1c2 Formatting fixes 2020-12-28 16:26:23 -08:00
Liam Newman
cd4368fa79 Merge remote-tracking branch 'upstream/master' into jae/bulk-update 2020-12-28 16:25:31 -08:00
Liam Newman
4ec4b160b0 Update contributing.md for more clarity 2020-12-28 16:18:04 -08:00
Liam Newman
a585b4957f Merge pull request #1004 from bitwiseman/object-base
Make root field transient in all classes
2020-12-28 16:05:48 -08:00
Liam Newman
e6b02b3bed Merge branch 'master' into object-base 2020-12-28 15:48:41 -08:00
Liam Newman
1ef0ec0432 Update src/main/java/org/kohsuke/github/GitHub.java
Co-authored-by: Tim Jacomb <21194782+timja@users.noreply.github.com>
2020-12-28 15:47:28 -08:00
Liam Newman
2e87bd86a1 Merge pull request #1006 from hub4j/dependabot/maven/org.eclipse.jgit-org.eclipse.jgit-5.10.0.202012080955-r
Chore(deps-dev): Bump org.eclipse.jgit from 5.9.0.202009080501-r to 5.10.0.202012080955-r
2020-12-28 15:46:53 -08:00
Liam Newman
0228a0d023 Merge pull request #1010 from hub4j/dependabot/maven/org.slf4j-slf4j-simple-1.7.30
Chore(deps-dev): Bump slf4j-simple from 1.7.2 to 1.7.30
2020-12-28 15:46:33 -08:00
dependabot[bot]
6365f3749d Chore(deps-dev): Bump slf4j-simple from 1.7.2 to 1.7.30
Bumps [slf4j-simple](https://github.com/qos-ch/slf4j) from 1.7.2 to 1.7.30.
- [Release notes](https://github.com/qos-ch/slf4j/releases)
- [Commits](https://github.com/qos-ch/slf4j/compare/v_1.7.2...v_1.7.30)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-28 23:45:31 +00:00
dependabot[bot]
25c18130f9 Chore(deps-dev): Bump org.eclipse.jgit
Bumps org.eclipse.jgit from 5.9.0.202009080501-r to 5.10.0.202012080955-r.

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-28 23:45:30 +00:00
Liam Newman
436c19634d Merge pull request #1009 from hub4j/dependabot/maven/com.github.spotbugs-spotbugs-maven-plugin-4.1.4
Chore(deps): Bump spotbugs-maven-plugin from 4.0.4 to 4.1.4
2020-12-28 15:45:13 -08:00
Liam Newman
1a6facc685 Merge pull request #1008 from hub4j/dependabot/maven/com.tngtech.archunit-archunit-0.15.0
Chore(deps-dev): Bump archunit from 0.14.1 to 0.15.0
2020-12-28 15:44:45 -08:00
Liam Newman
bd0093c8ea Change reader and writer to no longer deprecated
While still no recommended, these methods are more recommended than
users creating their own.  These will continue to work even when
internals change, whereas user configured readers or writers may not.
2020-12-28 12:39:21 -08:00
Liam Newman
e150280010 Merge remote-tracking branch 'upstream/master' into object-base 2020-12-28 10:52:16 -08:00
dependabot[bot]
827fd5e472 Chore(deps): Bump spotbugs-maven-plugin from 4.0.4 to 4.1.4
Bumps [spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.0.4 to 4.1.4.
- [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases)
- [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.0.4...spotbugs-maven-plugin-4.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-28 18:51:35 +00:00
dependabot[bot]
f89fbc67b9 Chore(deps-dev): Bump archunit from 0.14.1 to 0.15.0
Bumps [archunit](https://github.com/TNG/ArchUnit) from 0.14.1 to 0.15.0.
- [Release notes](https://github.com/TNG/ArchUnit/releases)
- [Commits](https://github.com/TNG/ArchUnit/compare/v0.14.1...v0.15.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-28 18:51:35 +00:00
Liam Newman
c567a88892 Merge pull request #1005 from bitwiseman/task/spotless
Switch to using spotless plugin for formatting
2020-12-28 10:51:06 -08:00
Liam Newman
6a39d7fca5 Trim whitespace and end with newline 2020-12-23 17:13:27 -08:00
Liam Newman
a15e67f065 Switch formatting to spotless
This is change includes minimal changes required to make the switch
2020-12-23 17:13:27 -08:00
Liam Newman
7a1bce9578 Merge branch 'master' into object-base 2020-12-22 09:17:52 -08:00
Liam Newman
f2b4de7943 Merge branch 'master' into jae/bulk-update 2020-12-22 08:32:12 -08:00
Liam Newman
b3ff4ac6d9 Merge pull request #984 from gsmet/okhttp-close-responsebody
Close Okhttp ResponseBody instances when closing the InputStream
2020-12-21 10:20:50 -08:00
Liam Newman
1c56e7fab5 Add missing argument 2020-12-21 09:28:44 -08:00
Liam Newman
70ba4df385 Make root field transient in all classes 2020-12-18 14:58:12 -08:00
Liam Newman
8062c705e8 Merge branch 'master' into jae/bulk-update 2020-12-17 15:12:19 -08:00
Liam Newman
fafb23c1a6 Merge pull request #1002 from marcoferrer/add-sdk-beta-annotation
Implement BetaApi annotation for hub4j sdk
2020-12-17 12:57:01 -08:00
Marco Ferrer
4e7ac7030c Add beta api annotation to project 2020-12-16 16:39:48 -05:00
Liam Newman
4803daca5a Merge branch 'master' into okhttp-close-responsebody 2020-12-15 16:21:08 -08:00
Liam Newman
facfc61316 Merge branch 'master' into jae/bulk-update 2020-12-15 16:08:41 -08:00
Liam Newman
e3e495bfb1 Merge pull request #1001 from marcoferrer/preview-enum-and-cleanup
Implement static typing for previews and clean up usage declarations
2020-12-15 15:39:06 -08:00
Liam Newman
e007284d2f Merge branch 'master' into preview-enum-and-cleanup 2020-12-15 15:20:30 -08:00
Liam Newman
1da8416ebd Merge pull request #983 from marcoferrer/add-preview-arch-rules
Add arch test for preview API usage
2020-12-15 15:20:05 -08:00
Marco Ferrer
79b49a469c Clean up preview declarations 2020-12-15 14:39:00 -05:00
Marco Ferrer
5888efcaef Merge branch 'master' into add-preview-arch-rules 2020-12-15 12:41:51 -05:00
Marco Ferrer
459d1b4f56 update arch tests to add enum checks 2020-12-15 12:41:02 -05:00
Liam Newman
9151102bda Merge pull request #998 from bitwiseman/obsolete-okhttp
Deprecate OkHttp 2.x connector
2020-12-12 16:49:13 -08:00
Liam Newman
3819984add Merge pull request #999 from tginiotis-at-work/targeturl-for-status
"target_url" for the payload of the status event
2020-12-12 16:48:16 -08:00
Tadas Giniotis
3b58fbc186 test "target_url" 2020-12-12 23:53:40 +02:00
Tadas Giniotis
55e589b3d9 add the "target_url" field for "status" events 2020-12-12 23:46:03 +02:00
Liam Newman
e64d64d8d8 Deprecate OkHttp 2.x connector
OkHttp 2.x is unsupported.  OkHttpUrlFactory contains bugs and limiations which will not
be fixed and also cannot be mitigated by this library.  Users should move to OkHttp3.

Closes #997
2020-12-11 17:17:08 -08:00
Jae Gangemi
37c2d9135b - bulk update of repository options 2020-12-11 16:56:26 -07:00
Liam Newman
30c96221bd Make wiremock less noisy with slf4j simple logger during tests 2020-12-11 13:54:47 -08:00
Liam Newman
bf7305e3f8 Merge pull request #990 from hub4j/dependabot/maven/org.apache.maven.plugins-maven-project-info-reports-plugin-3.1.1
Chore(deps): Bump maven-project-info-reports-plugin from 3.1.0 to 3.1.1
2020-12-09 08:54:55 -08:00
Liam Newman
3b12a229c3 Merge branch 'master' into dependabot/maven/org.apache.maven.plugins-maven-project-info-reports-plugin-3.1.1 2020-12-04 14:41:12 -08:00
Liam Newman
5726ceb8dc Merge branch 'master' into okhttp-close-responsebody 2020-12-03 16:55:48 -08:00
Liam Newman
c06c06624d Merge pull request #981 from eSentire/AffiliationFilter
Add affiliation filter for collaborators
2020-12-03 16:54:02 -08:00
Rob Rodrigues
ad40d7071e Streamline per feedback 2020-12-02 11:41:13 -08:00
Rob Rodrigues
f55a39eb90 Merge branch 'master' into AffiliationFilter 2020-12-01 20:08:54 -08:00
Rob Rodrigues
c3869bee31 Reverted changes which added filter unnecessarily, cleanup, add test cache, enable test 2020-12-01 19:50:24 -08:00
dependabot[bot]
6eac15df0f Chore(deps): Bump maven-project-info-reports-plugin from 3.1.0 to 3.1.1
Bumps [maven-project-info-reports-plugin](https://github.com/apache/maven-project-info-reports-plugin) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/apache/maven-project-info-reports-plugin/releases)
- [Commits](https://github.com/apache/maven-project-info-reports-plugin/compare/maven-project-info-reports-plugin-3.1.0...maven-project-info-reports-plugin-3.1.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-01 18:21:10 +00:00
Liam Newman
6f5d3c32c3 Spotbugs 4.1.3 2020-12-01 10:07:46 -08:00
Liam Newman
68ef40e4d0 Merge branch 'master' into bugfix-883 2020-12-01 09:11:23 -08:00
Liam Newman
4046bc4f72 Merge pull request #991 from hub4j/dependabot/maven/org.mockito-mockito-core-3.6.28
Chore(deps-dev): Bump mockito-core from 3.6.0 to 3.6.28
2020-12-01 08:49:54 -08:00
dependabot[bot]
1b8d131915 Chore(deps-dev): Bump mockito-core from 3.6.0 to 3.6.28
Bumps [mockito-core](https://github.com/mockito/mockito) from 3.6.0 to 3.6.28.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v3.6.0...v3.6.28)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-01 02:00:23 +00:00
Guillaume Smet
f5ad332d28 Properly close ResponseBody when closing the InputStream
ResponseBody objects from Okhttp needs to be closed and, right now, we
just close the InputStream which is not sufficient.

I noticed that because I saw some warnings about leaked ResponseBody
instances in my logs.
2020-11-29 21:56:11 +01:00
Lovekesh Garg
938603ff60 Fixes null commit date 2020-11-28 17:20:28 +05:30
Rob Rodrigues
17af78f2bb Merge branch 'master' into AffiliationFilter 2020-11-25 13:10:09 -08:00
Marco Ferrer
7588267743 Add arch test for preview API usage 2020-11-25 13:16:04 -05:00
Liam Newman
ed4f9c8176 Merge pull request #960 from marcoferrer/update-deployments-api
Implement deployment API support for ant-man and flash previews
2020-11-25 06:37:36 -08:00
Liam Newman
bbb46e88b0 Merge branch 'master' into update-deployments-api 2020-11-25 06:18:07 -08:00
Rob Rodrigues
3db7aac0d8 Merge branch 'master' into AffiliationFilter 2020-11-24 12:52:48 -08:00
Liam Newman
fdbbd2e563 [maven-release-plugin] prepare for next development iteration 2020-11-24 11:13:29 -08:00
Marco Ferrer
da2aaff9e5 Merge branch 'master' into update-deployments-api 2020-11-24 11:37:36 -05:00
Marco Ferrer
4bba692170 Merge branch 'master' into update-deployments-api 2020-11-23 17:20:40 -05:00
Marco Ferrer
59b61cd8be add deprecated to logUrl field 2020-11-23 17:19:57 -05:00
Marco Ferrer
247b013e16 add deprecated annotations to preview usage 2020-11-23 15:51:57 -05:00
Rob Rodrigues
3c56f1f076 Merge branch 'master' into AffiliationFilter 2020-11-19 15:57:36 -08:00
Rob Rodrigues
7fee1fcc74 Add affiliation filter for collaborators 2020-11-18 17:58:51 -08:00
Marcos.Cela
610b02968e exlude org.kohsuke.github.extras.auth.* from code coverage
This is a package for examples/extra implementations
2020-10-05 13:57:52 +02:00
Marcos.Cela
a7112c42df linting: JWTTokenProvider.java 2020-10-05 13:48:37 +02:00
Marcos.Cela
8a474a3b00 add: example for Org Installation token on extras package 2020-10-05 13:39:30 +02:00
Marcos.Cela
59e18d155e add dependencies for jwt token generation
These dependencies are marked as "provided" because they are only
used in the extras package
2020-10-05 13:39:01 +02:00
Marco Ferrer
12ca5d8063 update deployment wiremocks 2020-10-02 17:40:47 -04:00
Marco Ferrer
c959e0a928 update accept header in wiremocks 2020-10-02 17:37:21 -04:00
Marco Ferrer
89a08b021d formatting 2020-10-02 17:14:28 -04:00
Marco Ferrer
04b553cdec update deployment status checks 2020-10-02 17:12:10 -04:00
Marco Ferrer
15e9ee30ee formatting 2020-10-02 16:52:23 -04:00
Marco Ferrer
a0d650a86c update deployment tests to read new fields 2020-10-02 16:47:01 -04:00
Marco Ferrer
1a6ad48e08 formatting 2020-10-02 16:35:46 -04:00
Marco Ferrer
7c82eeb018 Support deployment api previews ant-man and flash 2020-10-02 15:57:52 -04:00
Marco Ferrer
b188e74ee0 Add new const for flash preview 2020-10-02 14:16:50 -04:00
Marcos.Cela
ff790eeefb formatting of OrgInstallationCredentialProvider.java 2020-09-30 16:48:54 +02:00
Marcos.Cela
97e918da03 remove unused JWTTokenProvider (we are now using a github client) 2020-09-30 16:39:41 +02:00
Marcos.Cela
4f30998873 OrgInstallationCredentialProvider now receives a pre-configured client
This is required to pass integration tests. In terms of functionality,
the user should be able to provide a client with the given token provider.
It additionally increases control (e.g: usage of proxies)

Add tests
2020-09-29 16:13:23 +02:00
Marcos.Cela
a0fc478a28 remove final modifier from credentialProvider (required for tests) 2020-09-29 16:12:06 +02:00
Marcos.Cela
bb03fd1968 use Date#after instead of compareTo 2020-09-28 16:11:16 +02:00
Marcos.Cela
0c65f74662 formatting 2020-09-28 14:45:00 +02:00
Marcos.Cela
29ac2bd4f5 return a correctly formatted token 2020-09-28 14:24:01 +02:00
Marcos.Cela
0d8b4f32e8 document oauthAccessToken 2020-09-28 13:48:56 +02:00
Marcos.Cela
83db7f24eb document CredentialProvider @throws 2020-09-28 13:48:26 +02:00
Marcos.Cela
5f9976a193 formatting for OrgInstallationCredentialProvider 2020-09-28 13:37:59 +02:00
Marcos.Cela
9480ef485b withCredentialProvider is now public 2020-09-28 13:34:14 +02:00
Marcos.Cela
a9b7432584 formatting 2020-09-28 13:28:13 +02:00
Marcos.Cela
6d7081910f add OrgInstallationCredentialProvider and JWTTokenProvider
The JWTTokenProvider implementation is left to the end user,
otherwise we would need to include specific libraries, at least
as far as I am aware.
The OrgInstallationCredentialProvider will give a token,
refreshing when necessary and using the JWTTokenProvider
that the user needs to provide to request new tokens
2020-09-28 13:17:46 +02:00
Marcos.Cela
aa96089ab4 remove @see to external docs 2020-09-28 13:01:55 +02:00
Marcos.Cela
58ae681417 reduce visibilitof GitHubBuilder#withCredentialProvider 2020-09-28 12:59:21 +02:00
Marcos.Cela
c038e0af5e typo it'ts -> it's 2020-09-28 12:51:54 +02:00
Marcos.Cela
4f9976c0cb add GitHubBuilder#withCredentialProvider
With this we also need to check for exceptions when calling
"/user", because now we don't know what kind of credentials
are coming from the provider, and we could be requesting
a "/user" when the type of credentials is not supported
2020-09-28 12:40:44 +02:00
Marcos.Cela
e308e5ed57 use static utility methods instead of building logic in the constructor 2020-09-28 12:26:56 +02:00
Marcos.Cela
7b1b1ca994 ensure that isAnonymous() correctly handles IOException 2020-09-28 12:18:22 +02:00
Marcos.Cela
551be49a1a utility methods on ImmutableCredentialProvider
These methods let us build the most-used cases
for static credentials that will never change:
- JWT credentials
- Token-based credentials
- Basic Auth credentials
2020-09-28 10:43:43 +02:00
Marcos.Cela
a3888e6902 add CredentialProvider#ANONYMOUS class and field
This is basically an implementation of a CredentialProvider
that will always authenticate anonymously
2020-09-28 10:09:54 +02:00
Marcos Cela López
43bb6a0dd8 Merge branch 'master' into feat/credential-provider-refresh 2020-09-28 10:02:16 +02:00
Marcos Cela López
05863acbcd Merge branch 'master' into feat/credential-provider-refresh 2020-09-25 12:05:31 +02:00
Marcos.Cela
0e4cd06137 GitHubClient uses CredentialProvider, instead of encodedAuthorization (string) 2020-09-25 12:02:14 +02:00
Marcos.Cela
85d2d974e7 add ImmutableCredentialProvider
This is basically a class that will hold an authorization
string, returning the same value all the time
2020-09-25 12:01:33 +02:00
Marcos.Cela
3f021f9552 lint CredentialProvider 2020-09-25 10:56:07 +02:00
Marcos.Cela
4688870984 add CredentialProvider interface 2020-09-24 09:01:52 +02:00
197 changed files with 5923 additions and 918 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.

91
pom.xml
View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
<version>1.117</version>
<version>1.121</version>
<name>GitHub API for Java</name>
<url>https://github-api.kohsuke.org/</url>
<description>GitHub API for Java</description>
@@ -11,7 +11,7 @@
<connection>scm:git:git@github.com/hub4j/${project.artifactId}.git</connection>
<developerConnection>scm:git:ssh://git@github.com/hub4j/${project.artifactId}.git</developerConnection>
<url>https://github.com/hub4j/github-api/</url>
<tag>github-api-1.117</tag>
<tag>github-api-1.121</tag>
</scm>
<distributionManagement>
@@ -33,19 +33,19 @@
<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>
<!-- For non-ci builds we'd like the build to still complete if jacoco metrics aren't met. -->
<jacoco.haltOnFailure>false</jacoco.haltOnFailure>
<jjwt.suite.version>0.11.2</jjwt.suite.version>
</properties>
<build>
@@ -154,7 +154,7 @@
<exclude>org.kohsuke.github.example.*</exclude>
<!-- No methods -->
<exclude>org.kohsuke.github.Previews</exclude>
<exclude>org.kohsuke.github.internal.Previews</exclude>
<!-- Deprecated -->
<exclude>org.kohsuke.github.extras.OkHttp3Connector</exclude>
@@ -261,7 +261,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 +343,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 +407,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>
@@ -469,7 +472,7 @@
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>stapler</artifactId>
<version>1.260</version>
<version>1.262</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -481,26 +484,26 @@
<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>
<version>${jjwt.suite.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>test</scope>
<version>${jjwt.suite.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>test</scope>
<version>${jjwt.suite.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
@@ -537,7 +540,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>
@@ -561,7 +564,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.2</version>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -589,8 +592,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>
@@ -615,8 +617,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

@@ -5,7 +5,7 @@ import java.net.URL;
import java.util.List;
import java.util.Map;
import static org.kohsuke.github.Previews.MACHINE_MAN;
import static org.kohsuke.github.internal.Previews.MACHINE_MAN;
/**
* A Github App.
@@ -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

@@ -5,7 +5,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.kohsuke.github.Previews.MACHINE_MAN;
import static org.kohsuke.github.internal.Previews.MACHINE_MAN;
/**
* Creates a access token for a GitHub App Installation
@@ -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

@@ -8,8 +8,8 @@ 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;
import static org.kohsuke.github.internal.Previews.GAMBIT;
import static org.kohsuke.github.internal.Previews.MACHINE_MAN;
/**
* A Github App Installation.
@@ -22,7 +22,6 @@ import static org.kohsuke.github.Previews.MACHINE_MAN;
* @see GHApp#getInstallationByUser(String) GHApp#getInstallationByUser(String)
*/
public class GHAppInstallation extends GHObject {
private GitHub root;
private GHUser account;
@JsonProperty("access_tokens_url")
@@ -124,7 +123,7 @@ public class GHAppInstallation extends GHObject {
*
* @return the paged iterable
*/
@Preview
@Preview(MACHINE_MAN)
@Deprecated
public PagedSearchIterable<GHRepository> listRepositories() {
GitHubRequest request;
@@ -322,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()
@@ -344,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,
@@ -361,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

@@ -3,6 +3,7 @@ package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.net.URL;
@@ -20,8 +21,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 +78,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 +89,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 +102,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 +137,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

@@ -6,7 +6,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.util.Collection;
import static org.kohsuke.github.Previews.ZZZAX;
import static org.kohsuke.github.internal.Previews.ZZZAX;
/**
* The type GHBranchProtection.
@@ -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

@@ -12,7 +12,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.LUKE_CAGE;
/**
* Builder to configure the branch protection settings.

View File

@@ -3,6 +3,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 org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.net.URL;
@@ -22,7 +23,6 @@ public class GHCheckRun extends GHObject {
@JsonProperty("repository")
GHRepository owner;
GitHub root;
private String status;
private String conclusion;
@@ -295,10 +295,10 @@ public class GHCheckRun extends GHObject {
/**
* Updates this check run.
*
*
* @return a builder which you should customize, then call {@link GHCheckRunBuilder#create}
*/
@Preview
@Preview(Previews.ANTIOPE)
@Deprecated
public @NonNull GHCheckRunBuilder update() {
return new GHCheckRunBuilder(owner, getId());

View File

@@ -28,6 +28,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.util.Collections;
@@ -46,7 +47,7 @@ import java.util.Locale;
* @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 {

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,7 +11,8 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import static org.kohsuke.github.Previews.GROOT;
import static org.kohsuke.github.internal.Previews.ANTIOPE;
import static org.kohsuke.github.internal.Previews.GROOT;
/**
* A commit in a repository.
@@ -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

@@ -5,7 +5,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.SQUIRREL_GIRL;
/**
* A comment attached to a commit (or a specific line in a specific file of a commit.)
@@ -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

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
@@ -10,7 +11,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.internal.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

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
@@ -14,7 +16,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 +25,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 +86,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 +115,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 +198,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

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.util.List;
@@ -19,7 +21,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 +45,7 @@ public class GHDeploymentBuilder {
*
* @param branch
* the branch
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder ref(String branch) {
@@ -52,6 +58,7 @@ public class GHDeploymentBuilder {
*
* @param task
* the task
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder task(String task) {
@@ -64,6 +71,7 @@ public class GHDeploymentBuilder {
*
* @param autoMerge
* the auto merge
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder autoMerge(boolean autoMerge) {
@@ -76,6 +84,7 @@ public class GHDeploymentBuilder {
*
* @param requiredContexts
* the required contexts
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder requiredContexts(List<String> requiredContexts) {
@@ -88,6 +97,7 @@ public class GHDeploymentBuilder {
*
* @param payload
* the payload
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder payload(String payload) {
@@ -100,6 +110,7 @@ public class GHDeploymentBuilder {
*
* @param environment
* the environment
*
* @return the gh deployment builder
*/
public GHDeploymentBuilder environment(String environment) {
@@ -107,11 +118,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 +170,7 @@ public class GHDeploymentBuilder {
* Create gh deployment.
*
* @return the gh deployment
*
* @throws IOException
* the io exception
*/

View File

@@ -1,8 +1,40 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
/**
* 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

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
import java.net.URL;
import java.util.Locale;
@@ -8,19 +10,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 +38,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 +71,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

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
/**
@@ -21,6 +23,7 @@ public class GHDeploymentStatusBuilder {
* the deployment id
* @param state
* the state
*
* @deprecated Use {@link GHDeployment#createStatus(GHDeploymentState)}
*/
@Deprecated
@@ -31,15 +34,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 +73,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 +146,7 @@ public class GHDeploymentStatusBuilder {
* Create gh deployment status.
*
* @return the gh deployment status
*
* @throws IOException
* the io exception
*/

View File

@@ -1,7 +1,7 @@
package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.kohsuke.github.internal.Previews;
import java.io.IOException;
import java.net.URL;
@@ -18,8 +18,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 +128,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 +139,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,6 +12,7 @@ import java.util.Locale;
public enum GHEvent {
CHECK_RUN,
CHECK_SUITE,
CODE_SCANNING_ALERT,
COMMIT_COMMENT,
CONTENT_REFERENCE,
CREATE,

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;

View File

@@ -17,9 +17,7 @@ import java.util.List;
*/
@SuppressWarnings("UnusedDeclaration")
@SuppressFBWarnings("UWF_UNWRITTEN_FIELD")
public class GHEventPayload {
protected GitHub root;
public class GHEventPayload extends GitHubInteractiveObject {
// https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#webhook-payload-object-common-properties
// Webhook payload object common properties: action, sender, repository, organization, installation
private String action;
@@ -1216,19 +1214,29 @@ public class GHEventPayload {
private String description;
private GHCommitState state;
private GHCommit commit;
private String targetUrl;
/**
* Gets the status content.
*
*
* @return status content
*/
public String getContext() {
return context;
}
/**
* The optional link added to the status.
*
* @return a url
*/
public String getTargetUrl() {
return targetUrl;
}
/**
* Gets the status description.
*
*
* @return status description
*/
public String getDescription() {
@@ -1237,7 +1245,7 @@ public class GHEventPayload {
/**
* Gets the status state.
*
*
* @return status state
*/
public GHCommitState getState() {
@@ -1246,7 +1254,7 @@ public class GHEventPayload {
/**
* Sets the status stage.
*
*
* @param state
* status state
*/
@@ -1256,7 +1264,7 @@ public class GHEventPayload {
/**
* Gets the commit associated with the status event.
*
*
* @return commit
*/
public GHCommit getCommit() {
@@ -1265,7 +1273,7 @@ public class GHEventPayload {
/**
* Sets the commit associated with the status event.
*
*
* @param commit
* commit
*/

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

@@ -39,7 +39,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;
import static org.kohsuke.github.Previews.SQUIRREL_GIRL;
import static org.kohsuke.github.internal.Previews.SQUIRREL_GIRL;
/**
* Represents an issue on GitHub.
@@ -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

@@ -26,7 +26,7 @@ package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.SQUIRREL_GIRL;
/**
* Comment to the issue
@@ -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

@@ -10,7 +10,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import static org.kohsuke.github.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.INERTIA;
/**
* The type GHOrganization.
@@ -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

@@ -28,7 +28,7 @@ import java.io.IOException;
import java.net.URL;
import java.util.Locale;
import static org.kohsuke.github.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.INERTIA;
/**
* A GitHub project.
@@ -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

@@ -6,7 +6,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.INERTIA;
/**
* The type GHProjectCard.
@@ -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

@@ -4,7 +4,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.INERTIA;
/**
* The type GHProjectColumn.
@@ -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

@@ -36,8 +36,8 @@ import java.util.Objects;
import javax.annotation.CheckForNull;
import static org.kohsuke.github.Previews.LYDIAN;
import static org.kohsuke.github.Previews.SHADOW_CAT;
import static org.kohsuke.github.internal.Previews.LYDIAN;
import static org.kohsuke.github.internal.Previews.SHADOW_CAT;
/**
* A pull request.
@@ -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

@@ -1,6 +1,6 @@
package org.kohsuke.github;
import static org.kohsuke.github.Previews.SHADOW_CAT;
import static org.kohsuke.github.internal.Previews.SHADOW_CAT;
/**
* Lists up pull requests with some filtering and sorting.

View File

@@ -28,7 +28,7 @@ import java.net.URL;
import javax.annotation.CheckForNull;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.SQUIRREL_GIRL;
/**
* Review comment to the pull request
@@ -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

@@ -3,7 +3,7 @@ package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.SQUIRREL_GIRL;
/**
* Reaction to issue, comment, PR, and so on.
@@ -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

@@ -19,7 +19,6 @@ import static java.lang.String.*;
* @see GHRepository#createRelease(String) GHRepository#createRelease(String)
*/
public class GHRelease extends GHObject {
GitHub root;
GHRepository owner;
private String html_url;
@@ -260,7 +259,6 @@ public class GHRelease extends GHObject {
* existing logic in place for backwards compatibility.
*/
@Deprecated
@Preview
public List<GHAsset> assets() {
return assets;
}

View File

@@ -54,8 +54,16 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.WeakHashMap;
import javax.annotation.Nonnull;
import static java.util.Arrays.*;
import static org.kohsuke.github.Previews.*;
import static org.kohsuke.github.internal.Previews.ANTIOPE;
import static org.kohsuke.github.internal.Previews.ANT_MAN;
import static org.kohsuke.github.internal.Previews.BAPTISTE;
import static org.kohsuke.github.internal.Previews.FLASH;
import static org.kohsuke.github.internal.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.MERCY;
import static org.kohsuke.github.internal.Previews.SHADOW_CAT;
/**
* A repository on GitHub.
@@ -66,7 +74,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;
@@ -163,6 +170,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));
}
@@ -178,6 +187,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);
}
@@ -704,7 +715,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) {
@@ -814,6 +825,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.
*
@@ -837,6 +855,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
@@ -884,6 +915,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.
*
@@ -1039,14 +1093,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.
*
@@ -1056,7 +1102,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);
}
/**
@@ -1068,7 +1114,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);
}
/**
@@ -1080,7 +1126,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);
}
/**
@@ -1092,7 +1138,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);
}
/**
@@ -1104,7 +1150,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void renameTo(String name) throws IOException {
edit("name", name);
set().name(name);
}
/**
@@ -1116,7 +1162,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setDescription(String value) throws IOException {
edit("description", value);
set().description(value);
}
/**
@@ -1128,7 +1174,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setHomepage(String value) throws IOException {
edit("homepage", value);
set().homepage(value);
}
/**
@@ -1140,7 +1186,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setDefaultBranch(String value) throws IOException {
edit("default_branch", value);
set().defaultBranch(value);
}
/**
@@ -1152,7 +1198,7 @@ public class GHRepository extends GHObject {
* the io exception
*/
public void setPrivate(boolean value) throws IOException {
edit("private", Boolean.toString(value));
set().private_(value);
}
/**
@@ -1164,7 +1210,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);
}
/**
@@ -1176,7 +1222,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);
}
/**
@@ -1188,7 +1234,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);
}
/**
@@ -1200,7 +1246,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);
}
/**
@@ -1237,12 +1283,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
*/
@@ -1878,7 +1942,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()
@@ -1952,7 +2016,7 @@ 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);
@@ -1965,7 +2029,7 @@ public class GHRepository extends GHObject {
* the existing checkId
* @return a builder which you should customize, then call {@link GHCheckRunBuilder#create}
*/
@Preview
@Preview(BAPTISTE)
@Deprecated
public @NonNull GHCheckRunBuilder updateCheckRun(long checkId) {
return new GHCheckRunBuilder(this, checkId);
@@ -2088,9 +2152,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));
}
/**
@@ -2153,7 +2219,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;
}
}
/**
@@ -2162,57 +2233,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;
@@ -2906,17 +2983,57 @@ public class GHRepository extends GHObject {
final URL url = Objects.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.internal.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.

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

@@ -26,6 +26,8 @@ package org.kohsuke.github;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import org.kohsuke.github.authorization.AuthorizationProvider;
import org.kohsuke.github.internal.Previews;
import java.io.*;
import java.util.*;
@@ -37,8 +39,8 @@ import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import static org.kohsuke.github.Previews.INERTIA;
import static org.kohsuke.github.Previews.MACHINE_MAN;
import static org.kohsuke.github.internal.Previews.INERTIA;
import static org.kohsuke.github.internal.Previews.MACHINE_MAN;
/**
* Root of the GitHub API.
@@ -93,39 +95,112 @@ public class GitHub {
* "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has <code>/api/v3</code> in the URL. For
* historical reasons, this parameter still accepts the bare domain name, but that's considered
* deprecated. Password is also considered deprecated as it is no longer required for api usage.
* @param login
* The user ID on GitHub that you are logging in as. Can be omitted if the OAuth token is provided or if
* logging in anonymously. Specifying this would save one API call.
* @param oauthAccessToken
* Secret OAuth token.
* @param password
* User's password. Always used in conjunction with the {@code login} parameter
* @param connector
* HttpConnector to use. Pass null to use default connector.
* a connector
* @param rateLimitHandler
* rateLimitHandler
* @param abuseLimitHandler
* abuseLimitHandler
* @param rateLimitChecker
* rateLimitChecker
* @param authorizationProvider
* a authorization provider
*/
GitHub(String apiUrl,
String login,
String oauthAccessToken,
String jwtToken,
String password,
HttpConnector connector,
RateLimitHandler rateLimitHandler,
AbuseLimitHandler abuseLimitHandler,
GitHubRateLimitChecker rateLimitChecker) throws IOException {
GitHubRateLimitChecker rateLimitChecker,
AuthorizationProvider authorizationProvider) throws IOException {
if (authorizationProvider instanceof DependentAuthorizationProvider) {
((DependentAuthorizationProvider) authorizationProvider).bind(this);
}
this.client = new GitHubHttpUrlConnectionClient(apiUrl,
login,
oauthAccessToken,
jwtToken,
password,
connector,
rateLimitHandler,
abuseLimitHandler,
rateLimitChecker,
(myself) -> setMyself(myself));
(myself) -> setMyself(myself),
authorizationProvider);
users = new ConcurrentHashMap<>();
orgs = new ConcurrentHashMap<>();
}
private GitHub(GitHubClient client) {
this.client = client;
users = new ConcurrentHashMap<>();
orgs = new ConcurrentHashMap<>();
}
public static abstract class DependentAuthorizationProvider implements AuthorizationProvider {
private GitHub baseGitHub;
private GitHub gitHub;
private final AuthorizationProvider authorizationProvider;
/**
* An AuthorizationProvider that requires an authenticated GitHub instance to provide its authorization.
*
* @param authorizationProvider
* A authorization provider to be used when refreshing this authorization provider.
*/
@BetaApi
@Deprecated
protected DependentAuthorizationProvider(AuthorizationProvider authorizationProvider) {
this.authorizationProvider = authorizationProvider;
}
/**
* Binds this authorization provider to a github instance.
*
* Only needs to be implemented by dynamic credentials providers that use a github instance in order to refresh.
*
* @param github
* The github instance to be used for refreshing dynamic credentials
*/
synchronized void bind(GitHub github) {
if (baseGitHub != null) {
throw new IllegalStateException("Already bound to another GitHub instance.");
}
this.baseGitHub = github;
}
protected synchronized final GitHub gitHub() {
if (gitHub == null) {
gitHub = new GitHub.AuthorizationRefreshGitHubWrapper(this.baseGitHub, authorizationProvider);
}
return gitHub;
}
}
private static class AuthorizationRefreshGitHubWrapper extends GitHub {
private final AuthorizationProvider authorizationProvider;
AuthorizationRefreshGitHubWrapper(GitHub github, AuthorizationProvider authorizationProvider) {
super(github.client);
this.authorizationProvider = authorizationProvider;
// no dependent authorization providers nest like this currently, but they might in future
if (authorizationProvider instanceof DependentAuthorizationProvider) {
((DependentAuthorizationProvider) authorizationProvider).bind(this);
}
}
@Nonnull
@Override
Requester createRequest() {
try {
// Override
return super.createRequest().setHeader("Authorization", authorizationProvider.getEncodedAuthorization())
.rateLimit(RateLimitTarget.NONE);
} catch (IOException e) {
throw new GHException("Failed to create requester to refresh credentials", e);
}
}
}
/**
* Obtains the credential from "~/.github" or from the System Environment Properties.
*
@@ -741,7 +816,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 +920,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 +1088,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 +1183,7 @@ public class GitHub {
*
* @return the gh commit search builder
*/
@Preview
@Preview(Previews.CLOAK)
@Deprecated
public GHCommitSearchBuilder searchCommits() {
return new GHCommitSearchBuilder(this);
@@ -1208,26 +1283,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

@@ -1,6 +1,8 @@
package org.kohsuke.github;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.authorization.AuthorizationProvider;
import org.kohsuke.github.authorization.ImmutableAuthorizationProvider;
import org.kohsuke.github.extras.ImpatientHttpConnector;
import java.io.File;
@@ -24,16 +26,13 @@ public class GitHubBuilder implements Cloneable {
// default scoped so unit tests can read them.
/* private */ String endpoint = GitHubClient.GITHUB_URL;
/* private */ String user;
/* private */ String password;
/* private */ String oauthToken;
/* private */ String jwtToken;
private HttpConnector connector;
private RateLimitHandler rateLimitHandler = RateLimitHandler.WAIT;
private AbuseLimitHandler abuseLimitHandler = AbuseLimitHandler.WAIT;
private GitHubRateLimitChecker rateLimitChecker = new GitHubRateLimitChecker();
/* private */ AuthorizationProvider authorizationProvider = AuthorizationProvider.ANONYMOUS;
/**
* Instantiates a new Git hub builder.
@@ -61,13 +60,13 @@ public class GitHubBuilder implements Cloneable {
builder = fromEnvironment();
if (builder.oauthToken != null || builder.user != null || builder.jwtToken != null)
if (builder.authorizationProvider != null)
return builder;
try {
builder = fromPropertyFile();
if (builder.oauthToken != null || builder.user != null || builder.jwtToken != null)
if (builder.authorizationProvider != null)
return builder;
} catch (FileNotFoundException e) {
// fall through
@@ -215,9 +214,20 @@ public class GitHubBuilder implements Cloneable {
*/
public static GitHubBuilder fromProperties(Properties props) {
GitHubBuilder self = new GitHubBuilder();
self.withOAuthToken(props.getProperty("oauth"), props.getProperty("login"));
self.withJwtToken(props.getProperty("jwt"));
self.withPassword(props.getProperty("login"), props.getProperty("password"));
String oauth = props.getProperty("oauth");
String jwt = props.getProperty("jwt");
String login = props.getProperty("login");
String password = props.getProperty("password");
if (oauth != null) {
self.withOAuthToken(oauth, login);
}
if (jwt != null) {
self.withJwtToken(jwt);
}
if (password != null) {
self.withPassword(login, password);
}
self.withEndpoint(props.getProperty("endpoint", GitHubClient.GITHUB_URL));
return self;
}
@@ -247,9 +257,7 @@ public class GitHubBuilder implements Cloneable {
* @return the git hub builder
*/
public GitHubBuilder withPassword(String user, String password) {
this.user = user;
this.password = password;
return this;
return withAuthorizationProvider(ImmutableAuthorizationProvider.fromLoginAndPassword(user, password));
}
/**
@@ -260,7 +268,7 @@ public class GitHubBuilder implements Cloneable {
* @return the git hub builder
*/
public GitHubBuilder withOAuthToken(String oauthToken) {
return withOAuthToken(oauthToken, null);
return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken));
}
/**
@@ -273,8 +281,21 @@ public class GitHubBuilder implements Cloneable {
* @return the git hub builder
*/
public GitHubBuilder withOAuthToken(String oauthToken, String user) {
this.oauthToken = oauthToken;
this.user = user;
return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken, user));
}
/**
* Configures a {@link AuthorizationProvider} for this builder
*
* There can be only one authorization provider per client instance.
*
* @param authorizationProvider
* the authorization provider
* @return the git hub builder
*
*/
public GitHubBuilder withAuthorizationProvider(final AuthorizationProvider authorizationProvider) {
this.authorizationProvider = authorizationProvider;
return this;
}
@@ -287,7 +308,7 @@ public class GitHubBuilder implements Cloneable {
* @see GHAppInstallation#createToken(java.util.Map) GHAppInstallation#createToken(java.util.Map)
*/
public GitHubBuilder withAppInstallationToken(String appInstallationToken) {
return withOAuthToken(appInstallationToken, "");
return withAuthorizationProvider(ImmutableAuthorizationProvider.fromAppInstallationToken(appInstallationToken));
}
/**
@@ -298,8 +319,7 @@ public class GitHubBuilder implements Cloneable {
* @return the git hub builder
*/
public GitHubBuilder withJwtToken(String jwtToken) {
this.jwtToken = jwtToken;
return this;
return withAuthorizationProvider(ImmutableAuthorizationProvider.fromJwtToken(jwtToken));
}
/**
@@ -421,14 +441,11 @@ public class GitHubBuilder implements Cloneable {
*/
public GitHub build() throws IOException {
return new GitHub(endpoint,
user,
oauthToken,
jwtToken,
password,
connector,
rateLimitHandler,
abuseLimitHandler,
rateLimitChecker);
rateLimitChecker,
authorizationProvider);
}
@Override

View File

@@ -1,33 +1,19 @@
package org.kohsuke.github;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.authorization.AuthorizationProvider;
import org.kohsuke.github.authorization.UserAuthorizationProvider;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.net.*;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.function.Consumer;
import java.util.logging.Logger;
@@ -56,17 +42,13 @@ abstract class GitHubClient {
static final int retryTimeoutMillis = 100;
/* private */ final String login;
/**
* Value of the authorization header to be sent with the request.
*/
/* private */ final String encodedAuthorization;
// Cache of myself object.
private final String apiUrl;
protected final RateLimitHandler rateLimitHandler;
protected final AbuseLimitHandler abuseLimitHandler;
private final GitHubRateLimitChecker rateLimitChecker;
private final AuthorizationProvider authorizationProvider;
private HttpConnector connector;
@@ -91,15 +73,12 @@ abstract class GitHubClient {
}
GitHubClient(String apiUrl,
String login,
String oauthAccessToken,
String jwtToken,
String password,
HttpConnector connector,
RateLimitHandler rateLimitHandler,
AbuseLimitHandler abuseLimitHandler,
GitHubRateLimitChecker rateLimitChecker,
Consumer<GHMyself> myselfConsumer) throws IOException {
Consumer<GHMyself> myselfConsumer,
AuthorizationProvider authorizationProvider) throws IOException {
if (apiUrl.endsWith("/")) {
apiUrl = apiUrl.substring(0, apiUrl.length() - 1); // normalize
@@ -111,33 +90,38 @@ abstract class GitHubClient {
this.apiUrl = apiUrl;
this.connector = connector;
if (oauthAccessToken != null) {
encodedAuthorization = "token " + oauthAccessToken;
} else {
if (jwtToken != null) {
encodedAuthorization = "Bearer " + jwtToken;
} else if (password != null) {
String authorization = (login + ':' + password);
String charsetName = StandardCharsets.UTF_8.name();
encodedAuthorization = "Basic "
+ Base64.getEncoder().encodeToString(authorization.getBytes(charsetName));
} else {// anonymous access
encodedAuthorization = null;
}
}
// Prefer credential configuration via provider
this.authorizationProvider = authorizationProvider;
this.rateLimitHandler = rateLimitHandler;
this.abuseLimitHandler = abuseLimitHandler;
this.rateLimitChecker = rateLimitChecker;
if (login == null && encodedAuthorization != null && jwtToken == null) {
GHMyself myself = fetch(GHMyself.class, "/user");
login = myself.getLogin();
if (myselfConsumer != null) {
myselfConsumer.accept(myself);
this.login = getCurrentUser(myselfConsumer);
}
private String getCurrentUser(Consumer<GHMyself> myselfConsumer) throws IOException {
String login = null;
if (this.authorizationProvider instanceof UserAuthorizationProvider
&& this.authorizationProvider.getEncodedAuthorization() != null) {
UserAuthorizationProvider userAuthorizationProvider = (UserAuthorizationProvider) this.authorizationProvider;
login = userAuthorizationProvider.getLogin();
if (login == null) {
try {
GHMyself myself = fetch(GHMyself.class, "/user");
if (myselfConsumer != null) {
myselfConsumer.accept(myself);
}
login = myself.getLogin();
} catch (IOException e) {
return null;
}
}
}
this.login = login;
return login;
}
private <T> T fetch(Class<T> type, String urlPath) throws IOException {
@@ -202,7 +186,13 @@ abstract class GitHubClient {
* @return {@code true} if operations that require authentication will fail.
*/
public boolean isAnonymous() {
return login == null && encodedAuthorization == null;
try {
return login == null && this.authorizationProvider.getEncodedAuthorization() == null;
} catch (IOException e) {
// An exception here means that the provider failed to provide authorization parameters,
// basically meaning the same as "no auth"
return false;
}
}
/**
@@ -224,6 +214,11 @@ abstract class GitHubClient {
return getRateLimit(RateLimitTarget.NONE);
}
@CheckForNull
protected String getEncodedAuthorization() throws IOException {
return authorizationProvider.getEncodedAuthorization();
}
@Nonnull
GHRateLimit getRateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOException {
GHRateLimit result;
@@ -394,7 +389,6 @@ abstract class GitHubClient {
"GitHub API request [" + (login == null ? "anonymous" : login) + "]: "
+ request.method() + " " + request.url().toString());
}
rateLimitChecker.checkRateLimit(this, request);
responseInfo = getResponseInfo(request);

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import org.apache.commons.io.IOUtils;
import org.kohsuke.github.authorization.AuthorizationProvider;
import java.io.IOException;
import java.io.InputStream;
@@ -33,25 +34,19 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
class GitHubHttpUrlConnectionClient extends GitHubClient {
GitHubHttpUrlConnectionClient(String apiUrl,
String login,
String oauthAccessToken,
String jwtToken,
String password,
HttpConnector connector,
RateLimitHandler rateLimitHandler,
AbuseLimitHandler abuseLimitHandler,
GitHubRateLimitChecker rateLimitChecker,
Consumer<GHMyself> myselfConsumer) throws IOException {
Consumer<GHMyself> myselfConsumer,
AuthorizationProvider authorizationProvider) throws IOException {
super(apiUrl,
login,
oauthAccessToken,
jwtToken,
password,
connector,
rateLimitHandler,
abuseLimitHandler,
rateLimitChecker,
myselfConsumer);
myselfConsumer,
authorizationProvider);
}
@Nonnull
@@ -114,8 +109,12 @@ class GitHubHttpUrlConnectionClient extends GitHubClient {
// if the authentication is needed but no credential is given, try it anyway (so that some calls
// that do work with anonymous access in the reduced form should still work.)
if (client.encodedAuthorization != null)
connection.setRequestProperty("Authorization", client.encodedAuthorization);
if (!request.headers().containsKey("Authorization")) {
String authorization = client.getEncodedAuthorization();
if (authorization != null) {
connection.setRequestProperty("Authorization", client.getEncodedAuthorization());
}
}
setRequestMethod(request.method(), connection);
buildRequest(request, connection);

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

@@ -2,6 +2,7 @@ package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.github.internal.Previews;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -75,7 +76,7 @@ class GitHubRequest {
/**
* Create a new {@link Builder}.
*
*
* @return a new {@link Builder}.
*/
public static Builder<?> newBuilder() {
@@ -165,7 +166,7 @@ class GitHubRequest {
/**
* The base GitHub API URL for this request represented as a {@link String}
*
*
* @return the url string
*/
@Nonnull
@@ -176,7 +177,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 +187,7 @@ class GitHubRequest {
/**
* The content type to to be sent by this request.
*
*
* @return the content type.
*/
@Nonnull
@@ -196,7 +197,7 @@ class GitHubRequest {
/**
* The {@link InputStream} to be sent as the body of this request.
*
*
* @return the {@link InputStream}.
*/
@CheckForNull
@@ -206,7 +207,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 +217,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 +227,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 +347,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 +438,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

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import org.kohsuke.github.internal.Previews;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -8,11 +10,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

@@ -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.internal.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

@@ -0,0 +1,43 @@
package org.kohsuke.github.authorization;
import java.io.IOException;
/**
* Provides a functional interface that returns a valid encodedAuthorization. This strategy allows for a provider that
* dynamically changes the credentials. Each request will request the credentials from the provider.
*/
public interface AuthorizationProvider {
/**
* An static instance for an ANONYMOUS authorization provider
*/
AuthorizationProvider ANONYMOUS = new AnonymousAuthorizationProvider();
/**
* Returns the credentials to be used with a given request. As an example, a authorization provider for a bearer
* token will return something like:
*
* <pre>
* {@code
* &#64;Override
* public String getEncodedAuthorization() {
* return "Bearer myBearerToken";
* }
* }
* </pre>
*
* @return encoded authorization string, can be null
* @throws IOException
* on any error that prevents the provider from getting a valid authorization
*/
String getEncodedAuthorization() throws IOException;
/**
* A {@link AuthorizationProvider} that ensures that no credentials are returned
*/
class AnonymousAuthorizationProvider implements AuthorizationProvider {
@Override
public String getEncodedAuthorization() throws IOException {
return null;
}
}
}

View File

@@ -0,0 +1,123 @@
package org.kohsuke.github.authorization;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.annotation.CheckForNull;
/**
* A {@link AuthorizationProvider} that always returns the same credentials
*/
public class ImmutableAuthorizationProvider implements AuthorizationProvider {
private final String authorization;
public ImmutableAuthorizationProvider(String authorization) {
this.authorization = authorization;
}
/**
* Builds and returns a {@link AuthorizationProvider} from a given oauthAccessToken
*
* @param oauthAccessToken
* The token
* @return a correctly configured {@link AuthorizationProvider} that will always return the same provided
* oauthAccessToken
*/
public static AuthorizationProvider fromOauthToken(String oauthAccessToken) {
return new UserProvider(String.format("token %s", oauthAccessToken));
}
/**
* Builds and returns a {@link AuthorizationProvider} from a given oauthAccessToken
*
* @param oauthAccessToken
* The token
* @param login
* The login for this token
*
* @return a correctly configured {@link AuthorizationProvider} that will always return the same provided
* oauthAccessToken
*/
public static AuthorizationProvider fromOauthToken(String oauthAccessToken, String login) {
return new UserProvider(String.format("token %s", oauthAccessToken), login);
}
/**
* Builds and returns a {@link AuthorizationProvider} from a given App Installation Token
*
* @param appInstallationToken
* A string containing the GitHub App installation token
* @return the configured Builder from given GitHub App installation token.
*/
public static AuthorizationProvider fromAppInstallationToken(String appInstallationToken) {
return fromOauthToken(appInstallationToken, "");
}
/**
* Builds and returns a {@link AuthorizationProvider} from a given jwtToken
*
* @param jwtToken
* The JWT token
* @return a correctly configured {@link AuthorizationProvider} that will always return the same provided jwtToken
*/
public static AuthorizationProvider fromJwtToken(String jwtToken) {
return new ImmutableAuthorizationProvider(String.format("Bearer %s", jwtToken));
}
/**
* Builds and returns a {@link AuthorizationProvider} from the given user/password pair
*
* @param login
* The login for the user, usually the same as the username
* @param password
* The password for the associated user
* @return a correctly configured {@link AuthorizationProvider} that will always return the credentials for the same
* user and password combo
* @deprecated Login with password credentials are no longer supported by GitHub
*/
@Deprecated
public static AuthorizationProvider fromLoginAndPassword(String login, String password) {
try {
String authorization = (String.format("%s:%s", login, password));
String charsetName = StandardCharsets.UTF_8.name();
String b64encoded = Base64.getEncoder().encodeToString(authorization.getBytes(charsetName));
String encodedAuthorization = String.format("Basic %s", b64encoded);
return new UserProvider(encodedAuthorization, login);
} catch (UnsupportedEncodingException e) {
// If UTF-8 isn't supported, there are bigger problems
throw new IllegalStateException("Could not generate encoded authorization", e);
}
}
@Override
public String getEncodedAuthorization() {
return this.authorization;
}
/**
* An internal class representing all user-related credentials, which are credentials that have a login or should
* query the user endpoint for the login matching this credential.
*/
private static class UserProvider extends ImmutableAuthorizationProvider implements UserAuthorizationProvider {
private final String login;
UserProvider(String authorization) {
this(authorization, null);
}
UserProvider(String authorization, String login) {
super(authorization);
this.login = login;
}
@CheckForNull
@Override
public String getLogin() {
return login;
}
}
}

View File

@@ -0,0 +1,63 @@
package org.kohsuke.github.authorization;
import org.kohsuke.github.BetaApi;
import org.kohsuke.github.GHAppInstallation;
import org.kohsuke.github.GHAppInstallationToken;
import org.kohsuke.github.GitHub;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import javax.annotation.Nonnull;
/**
* Provides an AuthorizationProvider that performs automatic token refresh.
*/
public class OrgAppInstallationAuthorizationProvider extends GitHub.DependentAuthorizationProvider {
private final String organizationName;
private String latestToken;
@Nonnull
private Instant validUntil = Instant.MIN;
/**
* Provides an AuthorizationProvider that performs automatic token refresh, based on an previously authenticated
* github client.
*
* @param organizationName
* The name of the organization where the application is installed
* @param authorizationProvider
* A authorization provider that returns a JWT token that can be used to refresh the App Installation
* token from GitHub.
*/
@BetaApi
@Deprecated
public OrgAppInstallationAuthorizationProvider(String organizationName,
AuthorizationProvider authorizationProvider) {
super(authorizationProvider);
this.organizationName = organizationName;
}
@Override
public String getEncodedAuthorization() throws IOException {
synchronized (this) {
if (latestToken == null || Instant.now().isAfter(this.validUntil)) {
refreshToken();
}
return String.format("token %s", latestToken);
}
}
private void refreshToken() throws IOException {
GitHub gitHub = this.gitHub();
GHAppInstallation installationByOrganization = gitHub.getApp()
.getInstallationByOrganization(this.organizationName);
GHAppInstallationToken ghAppInstallationToken = installationByOrganization.createToken().create();
this.validUntil = ghAppInstallationToken.getExpiresAt().toInstant().minus(Duration.ofMinutes(5));
this.latestToken = Objects.requireNonNull(ghAppInstallationToken.getToken());
}
}

View File

@@ -0,0 +1,22 @@
package org.kohsuke.github.authorization;
import javax.annotation.CheckForNull;
/**
* Interface for all user-related authorization providers.
*
* {@link AuthorizationProvider}s can apply to a number of different account types. This interface applies to providers
* for user accounts, ones that have a login or should query the "/user" endpoint for the login matching this
* credential.
*/
public interface UserAuthorizationProvider extends AuthorizationProvider {
/**
* Gets the user login name.
*
* @return the user login for this provider, or {@code null} if the login value should be queried from the "/user"
* endpoint.
*/
@CheckForNull
String getLogin();
}

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