diff --git a/src/main/java/org/kohsuke/github/GHApp.java b/src/main/java/org/kohsuke/github/GHApp.java index 91b24b275b..2da38b79fb 100644 --- a/src/main/java/org/kohsuke/github/GHApp.java +++ b/src/main/java/org/kohsuke/github/GHApp.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.net.URL; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -209,10 +210,26 @@ public void setPermissions(Map permissions) { */ @Preview(MACHINE_MAN) public PagedIterable listInstallations() { - return root().createRequest() - .withPreview(MACHINE_MAN) - .withUrlPath("/app/installations") - .toIterable(GHAppInstallation[].class, null); + return listInstallations(null); + } + + /** + * Obtains all the installations associated with this app since a given date. + *

+ * You must use a JWT to access this endpoint. + * + * @param since + * - Allows users to get installations that have been updated since a given date. + * @return a list of App installations since a given time. + * @see List installations + */ + @Preview(MACHINE_MAN) + public PagedIterable listInstallations(final Date since) { + Requester requester = root().createRequest().withPreview(MACHINE_MAN).withUrlPath("/app/installations"); + if (since != null) { + requester.with("since", GitHubClient.printDate(since)); + } + return requester.toIterable(GHAppInstallation[].class, null); } /** diff --git a/src/test/java/org/kohsuke/github/GHAppTest.java b/src/test/java/org/kohsuke/github/GHAppTest.java index 91c1bb9d17..2ceb479e4b 100644 --- a/src/test/java/org/kohsuke/github/GHAppTest.java +++ b/src/test/java/org/kohsuke/github/GHAppTest.java @@ -3,11 +3,15 @@ import org.junit.Test; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TimeZone; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThrows; @@ -85,6 +89,28 @@ public void listInstallations() throws IOException { testAppInstallation(appInstallation); } + /** + * List installations that have been updated since a given date. + * + * @throws IOException + * Signals that an I/O exception has occurred. + * + * @throws ParseException + * Issue parsing date string. + */ + @Test + public void listInstallationsSince() throws IOException, ParseException { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + Date localDate = simpleDateFormat.parse("2023-11-01"); + GHApp app = gitHub.getApp(); + List installations = app.listInstallations(localDate).toList(); + assertThat(installations.size(), is(1)); + + GHAppInstallation appInstallation = installations.get(0); + testAppInstallation(appInstallation); + } + /** * Gets the installation by id. * diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-app.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-app.json new file mode 100644 index 0000000000..d36be086d7 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-app.json @@ -0,0 +1,41 @@ +{ + "id": 11111, + "node_id": "MDM6QXBwMzI2MTY=", + "owner": { + "login": "bogus", + "id": 111111111, + "node_id": "asdfasdfasdf", + "avatar_url": "https://avatars2.githubusercontent.com/u/111111111?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/bogus", + "html_url": "https://github.com/bogus", + "followers_url": "https://api.github.com/users/bogus/followers", + "following_url": "https://api.github.com/users/bogus/following{/other_user}", + "gists_url": "https://api.github.com/users/bogus/gists{/gist_id}", + "starred_url": "https://api.github.com/users/bogus/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/bogus/subscriptions", + "organizations_url": "https://api.github.com/users/bogus/orgs", + "repos_url": "https://api.github.com/users/bogus/repos", + "events_url": "https://api.github.com/users/bogus/events{/privacy}", + "received_events_url": "https://api.github.com/users/bogus/received_events", + "type": "Organization", + "site_admin": false + }, + "name": "Bogus-Development", + "description": "", + "external_url": "https://bogus.domain.com", + "html_url": "https://github.com/apps/bogus-development", + "created_at": "2019-06-10T04:21:41Z", + "updated_at": "2019-06-10T04:21:41Z", + "permissions": { + "checks": "write", + "contents": "read", + "metadata": "read", + "pull_requests": "write" + }, + "events": [ + "pull_request", + "push" + ], + "installations_count": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-installations.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-installations.json new file mode 100644 index 0000000000..4ca1c46c81 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/__files/body-mapping-githubapp-installations.json @@ -0,0 +1,45 @@ +[ + { + "id": 11111111, + "account": { + "login": "bogus", + "id": 111111111, + "node_id": "asdfasdfasdf", + "avatar_url": "https://avatars2.githubusercontent.com/u/111111111?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/bogus", + "html_url": "https://github.com/bogus", + "followers_url": "https://api.github.com/users/bogus/followers", + "following_url": "https://api.github.com/users/bogus/following{/other_user}", + "gists_url": "https://api.github.com/users/bogus/gists{/gist_id}", + "starred_url": "https://api.github.com/users/bogus/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/bogus/subscriptions", + "organizations_url": "https://api.github.com/users/bogus/orgs", + "repos_url": "https://api.github.com/users/bogus/repos", + "events_url": "https://api.github.com/users/bogus/events{/privacy}", + "received_events_url": "https://api.github.com/users/bogus/received_events", + "type": "Organization", + "site_admin": false + }, + "repository_selection": "selected", + "access_tokens_url": "https://api.github.com/app/installations/11111111/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/organizations/bogus/settings/installations/11111111", + "app_id": 11111, + "target_id": 111111111, + "target_type": "Organization", + "permissions": { + "checks": "write", + "pull_requests": "write", + "contents": "read", + "metadata": "read" + }, + "events": [ + "pull_request", + "push" + ], + "created_at": "2019-07-04T01:19:36.000Z", + "updated_at": "2019-07-30T22:48:09.000Z", + "single_file_name": null + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-app.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-app.json new file mode 100644 index 0000000000..2e7a553f6d --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-app.json @@ -0,0 +1,37 @@ +{ + "request": { + "url": "/app", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.machine-man-preview+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "body-mapping-githubapp-app.json", + "headers": { + "Server": "GitHub.com", + "Date": "Fri, 09 Aug 2019 05:36:38 GMT", + "Content-Type": "application/json; charset=utf-8", + "Status": "200 OK", + "Cache-Control": "public, max-age=60, s-maxage=60", + "Vary": [ + "Accept", + "Accept-Encoding" + ], + "ETag": "W/\"01163b1a237898d328ed56cd0e9aefca\"", + "X-GitHub-Media-Type": "github.machine-man-preview; format=json", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", + "Access-Control-Allow-Origin": "*", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Content-Type-Options": "nosniff", + "X-Frame-Options": "deny", + "X-XSS-Protection": "1; mode=block", + "X-GitHub-Request-Id": "E0C4:3088:300C54:3ACB77:5D4D0666" + } + } +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-installations.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-installations.json new file mode 100644 index 0000000000..cb402b4a44 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationsSince/mappings/mapping-githubapp-installations.json @@ -0,0 +1,42 @@ +{ + "request": { + "urlPathPattern": "/app/installations", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.machine-man-preview+json" + } + }, + "queryParameters": { + "since": { + "equalTo": "2023-11-01T00:00:00Z" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "body-mapping-githubapp-installations.json", + "headers": { + "Server": "GitHub.com", + "Date": "Fri, 09 Aug 2019 05:36:38 GMT", + "Content-Type": "application/json; charset=utf-8", + "Status": "200 OK", + "Cache-Control": "public, max-age=60, s-maxage=60", + "Vary": [ + "Accept", + "Accept-Encoding" + ], + "ETag": "W/\"01163b1a237898d328ed56cd0e9aefca\"", + "X-GitHub-Media-Type": "github.machine-man-preview; format=json", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", + "Access-Control-Allow-Origin": "*", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Content-Type-Options": "nosniff", + "X-Frame-Options": "deny", + "X-XSS-Protection": "1; mode=block", + "X-GitHub-Request-Id": "E0C4:3088:300C54:3ACB77:5D4D0666" + } + } +} \ No newline at end of file