diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java
index 9413418af1..0f65498678 100644
--- a/src/main/java/org/kohsuke/github/GHEventPayload.java
+++ b/src/main/java/org/kohsuke/github/GHEventPayload.java
@@ -1,10 +1,12 @@
package org.kohsuke.github;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.io.Reader;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -265,16 +267,47 @@ void lateBind() {
* @see GitHub App Installation
*/
public static class Installation extends GHEventPayload {
- private List repositories;
+
+ private List repositories;
+ private List ghRepositories = null;
/**
- * Gets repositories.
+ * Gets repositories. For the "deleted" action please rather call {@link #getRawRepositories()}
*
* @return the repositories
*/
public List getRepositories() {
+ if ("deleted".equalsIgnoreCase(getAction())) {
+ throw new IllegalStateException("Can't call #getRepositories() on Installation event "
+ + "with 'deleted' action. Call #getRawRepositories() instead.");
+ }
+
+ if (ghRepositories == null) {
+ ghRepositories = new ArrayList<>(repositories.size());
+ try {
+ for (Repository singleRepo : repositories) {
+ // populate each repository
+ // the repository information provided here is so limited
+ // as to be unusable without populating, so we do it eagerly
+ ghRepositories.add(this.root().getRepositoryById(singleRepo.getId()));
+ }
+ } catch (IOException e) {
+ throw new GHException("Failed to refresh repositories", e);
+ }
+ }
+
+ return Collections.unmodifiableList(ghRepositories);
+ }
+
+ /**
+ * Returns a list of raw, unpopulated repositories. Useful when calling from within Installation event with
+ * action "deleted". You can't fetch the info for repositories of an already deleted installation.
+ *
+ * @return the list of raw Repository records
+ */
+ public List getRawRepositories() {
return Collections.unmodifiableList(repositories);
- };
+ }
/**
* Late bind.
@@ -286,17 +319,64 @@ void lateBind() {
"Expected installation payload, but got something else. Maybe we've got another type of event?");
}
super.lateBind();
- if (repositories != null && !repositories.isEmpty()) {
- try {
- for (GHRepository singleRepo : repositories) {
- // populate each repository
- // the repository information provided here is so limited
- // as to be unusable without populating, so we do it eagerly
- singleRepo.populate();
- }
- } catch (IOException e) {
- throw new GHException("Failed to refresh repositories", e);
- }
+ }
+
+ /**
+ * A special minimal implementation of a {@link GHRepository} which contains only fields from "Properties of
+ * repositories" from here
+ */
+ public static class Repository {
+ private long id;
+ private String fullName;
+ private String name;
+ private String nodeId;
+ @JsonProperty(value = "private")
+ private boolean isPrivate;
+
+ /**
+ * Get the id.
+ *
+ * @return the id
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * Gets the full name.
+ *
+ * @return the full name
+ */
+ public String getFullName() {
+ return fullName;
+ }
+
+ /**
+ * Gets the name.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the node id.
+ *
+ * @return the node id
+ */
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ /**
+ * Gets the repository private flag.
+ *
+ * @return whether the repository is private
+ */
+ public boolean isPrivate() {
+ return isPrivate;
}
}
}
diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java
index 783fa06a6f..91560170c7 100644
--- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java
+++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java
@@ -990,8 +990,33 @@ public void InstallationRepositoriesEvent() throws Exception {
* the exception
*/
@Test
- @Payload("installation")
- public void InstallationEvent() throws Exception {
+ @Payload("installation_created")
+ public void InstallationCreatedEvent() throws Exception {
+ final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
+ .build()
+ .parseEventPayload(payload.asReader(), GHEventPayload.Installation.class);
+
+ assertThat(event.getAction(), is("created"));
+ assertThat(event.getInstallation().getId(), is(43898337L));
+ assertThat(event.getInstallation().getAccount().getLogin(), is("CronFire"));
+
+ assertThat(event.getRepositories().isEmpty(), is(false));
+ assertThat(event.getRepositories().get(0).getId(), is(1296269L));
+ assertThat(event.getRawRepositories().isEmpty(), is(false));
+ assertThat(event.getRawRepositories().get(0).getId(), is(1296269L));
+
+ assertThat(event.getSender().getLogin(), is("Haarolean"));
+ }
+
+ /**
+ * Installation event.
+ *
+ * @throws Exception
+ * the exception
+ */
+ @Test
+ @Payload("installation_deleted")
+ public void InstallationDeletedEvent() throws Exception {
final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl())
.build()
.parseEventPayload(payload.asReader(), GHEventPayload.Installation.class);
@@ -1000,12 +1025,13 @@ public void InstallationEvent() throws Exception {
assertThat(event.getInstallation().getId(), is(2L));
assertThat(event.getInstallation().getAccount().getLogin(), is("octocat"));
- assertThat(event.getRepositories().get(0).getId(), is(1296269L));
- assertThat(event.getRepositories().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxMjk2MjY5"));
- assertThat(event.getRepositories().get(0).getName(), is("Hello-World"));
- assertThat(event.getRepositories().get(0).getFullName(), is("octocat/Hello-World"));
- assertThat(event.getRepositories().get(0).isPrivate(), is(false));
- assertThat(event.getRepositories().get(0).getOwner().getLogin(), is("octocat"));
+ assertThrows(IllegalStateException.class, () -> event.getRepositories().isEmpty());
+ assertThat(event.getRawRepositories().isEmpty(), is(false));
+ assertThat(event.getRawRepositories().get(0).getId(), is(1296269L));
+ assertThat(event.getRawRepositories().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxMjk2MjY5"));
+ assertThat(event.getRawRepositories().get(0).getName(), is("Hello-World"));
+ assertThat(event.getRawRepositories().get(0).getFullName(), is("octocat/Hello-World"));
+ assertThat(event.getRawRepositories().get(0).isPrivate(), is(false));
assertThat(event.getSender().getLogin(), is("octocat"));
}
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation_created.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation_created.json
new file mode 100644
index 0000000000..d9923841e1
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation_created.json
@@ -0,0 +1,98 @@
+{
+ "action": "created",
+ "installation": {
+ "id": 43898337,
+ "account": {
+ "login": "CronFire",
+ "id": 68755481,
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4NzU1NDgx",
+ "avatar_url": "https://avatars.githubusercontent.com/u/68755481?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/CronFire",
+ "html_url": "https://github.com/CronFire",
+ "followers_url": "https://api.github.com/users/CronFire/followers",
+ "following_url": "https://api.github.com/users/CronFire/following{/other_user}",
+ "gists_url": "https://api.github.com/users/CronFire/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/CronFire/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/CronFire/subscriptions",
+ "organizations_url": "https://api.github.com/users/CronFire/orgs",
+ "repos_url": "https://api.github.com/users/CronFire/repos",
+ "events_url": "https://api.github.com/users/CronFire/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/CronFire/received_events",
+ "type": "Organization",
+ "site_admin": false
+ },
+ "repository_selection": "selected",
+ "access_tokens_url": "https://api.github.com/app/installations/43898337/access_tokens",
+ "repositories_url": "https://api.github.com/installation/repositories",
+ "html_url": "https://github.com/organizations/CronFire/settings/installations/43898337",
+ "app_id": 421464,
+ "app_slug": "kapybro-dev",
+ "target_id": 68755481,
+ "target_type": "Organization",
+ "permissions": {
+ "checks": "write",
+ "issues": "write",
+ "actions": "read",
+ "members": "read",
+ "contents": "write",
+ "metadata": "read",
+ "statuses": "write",
+ "single_file": "read",
+ "pull_requests": "write",
+ "administration": "read"
+ },
+ "events": [
+ "issues",
+ "issue_comment",
+ "organization",
+ "public",
+ "pull_request",
+ "pull_request_review",
+ "pull_request_review_comment",
+ "push",
+ "repository",
+ "status"
+ ],
+ "created_at": "2023-11-11T10:55:06.000+08:00",
+ "updated_at": "2023-11-11T10:55:06.000+08:00",
+ "single_file_name": ".github/kapybro/config.yml",
+ "has_multiple_single_files": true,
+ "single_file_paths": [
+ ".github/kapybro/config.yml",
+ ".github/kapybro/rules.yml"
+ ],
+ "suspended_by": null,
+ "suspended_at": null
+ },
+ "repositories": [
+ {
+ "id": 1296269,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "private": false
+ }
+ ],
+ "requester": null,
+ "sender": {
+ "login": "Haarolean",
+ "id": 1494347,
+ "node_id": "MDQ6VXNlcjE0OTQzNDc=",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1494347?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Haarolean",
+ "html_url": "https://github.com/Haarolean",
+ "followers_url": "https://api.github.com/users/Haarolean/followers",
+ "following_url": "https://api.github.com/users/Haarolean/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Haarolean/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Haarolean/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Haarolean/subscriptions",
+ "organizations_url": "https://api.github.com/users/Haarolean/orgs",
+ "repos_url": "https://api.github.com/users/Haarolean/repos",
+ "events_url": "https://api.github.com/users/Haarolean/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Haarolean/received_events",
+ "type": "User",
+ "site_admin": false
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation_deleted.json
similarity index 100%
rename from src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation.json
rename to src/test/resources/org/kohsuke/github/GHEventPayloadTest/installation_deleted.json
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/1-r_o_hello-world.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/1-r_o_hello-world.json
new file mode 100644
index 0000000000..fd3c1ce7ca
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/1-r_o_hello-world.json
@@ -0,0 +1,108 @@
+{
+ "id": 1296269,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "private": false,
+ "owner": {
+ "login": "octocat",
+ "id": 583231,
+ "node_id": "MDQ6VXNlcjU4MzIzMQ==",
+ "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/octocat",
+ "html_url": "https://github.com/octocat",
+ "followers_url": "https://api.github.com/users/octocat/followers",
+ "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+ "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+ "organizations_url": "https://api.github.com/users/octocat/orgs",
+ "repos_url": "https://api.github.com/users/octocat/repos",
+ "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/octocat/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/octocat/Hello-World",
+ "description": "My first repository on GitHub!",
+ "fork": false,
+ "url": "https://api.github.com/repos/octocat/Hello-World",
+ "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
+ "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
+ "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
+ "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/octocat/Hello-World/events",
+ "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
+ "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
+ "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
+ "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
+ "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
+ "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
+ "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
+ "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
+ "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
+ "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
+ "created_at": "2011-01-26T19:01:12Z",
+ "updated_at": "2022-02-03T00:06:57Z",
+ "pushed_at": "2022-01-30T18:13:40Z",
+ "git_url": "git://github.com/octocat/Hello-World.git",
+ "ssh_url": "git@github.com:octocat/Hello-World.git",
+ "clone_url": "https://github.com/octocat/Hello-World.git",
+ "svn_url": "https://github.com/octocat/Hello-World",
+ "homepage": "",
+ "size": 1,
+ "stargazers_count": 1764,
+ "watchers_count": 1764,
+ "language": null,
+ "has_issues": true,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": true,
+ "has_pages": false,
+ "forks_count": 1682,
+ "mirror_url": null,
+ "archived": false,
+ "disabled": false,
+ "open_issues_count": 802,
+ "license": null,
+ "allow_forking": true,
+ "is_template": false,
+ "topics": [],
+ "visibility": "public",
+ "forks": 1682,
+ "open_issues": 802,
+ "watchers": 1764,
+ "default_branch": "master",
+ "permissions": {
+ "admin": false,
+ "maintain": false,
+ "push": false,
+ "triage": false,
+ "pull": true
+ },
+ "temp_clone_token": "",
+ "network_count": 1682,
+ "subscribers_count": 1731
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/2-repositories_1296269.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/2-repositories_1296269.json
new file mode 100644
index 0000000000..8b2db1e11c
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/__files/2-repositories_1296269.json
@@ -0,0 +1,103 @@
+{
+ "id": 1296269,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "private": false,
+ "owner": {
+ "login": "octocat",
+ "id": 583231,
+ "node_id": "MDQ6VXNlcjU4MzIzMQ==",
+ "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/octocat",
+ "html_url": "https://github.com/octocat",
+ "followers_url": "https://api.github.com/users/octocat/followers",
+ "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+ "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+ "organizations_url": "https://api.github.com/users/octocat/orgs",
+ "repos_url": "https://api.github.com/users/octocat/repos",
+ "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/octocat/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/octocat/Hello-World",
+ "description": "My first repository on GitHub!",
+ "fork": false,
+ "url": "https://api.github.com/repos/octocat/Hello-World",
+ "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
+ "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
+ "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
+ "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/octocat/Hello-World/events",
+ "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
+ "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
+ "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
+ "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
+ "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
+ "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
+ "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
+ "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
+ "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
+ "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
+ "created_at": "2011-01-26T19:01:12Z",
+ "updated_at": "2024-03-13T21:25:44Z",
+ "pushed_at": "2024-03-09T06:28:31Z",
+ "git_url": "git://github.com/octocat/Hello-World.git",
+ "ssh_url": "git@github.com:octocat/Hello-World.git",
+ "clone_url": "https://github.com/octocat/Hello-World.git",
+ "svn_url": "https://github.com/octocat/Hello-World",
+ "homepage": "",
+ "size": 1,
+ "stargazers_count": 2486,
+ "watchers_count": 2486,
+ "language": null,
+ "has_issues": true,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": true,
+ "has_pages": false,
+ "has_discussions": false,
+ "forks_count": 2168,
+ "mirror_url": null,
+ "archived": false,
+ "disabled": false,
+ "open_issues_count": 1291,
+ "license": null,
+ "allow_forking": true,
+ "is_template": false,
+ "web_commit_signoff_required": false,
+ "topics": [],
+ "visibility": "public",
+ "forks": 2168,
+ "open_issues": 1291,
+ "watchers": 2486,
+ "default_branch": "master",
+ "temp_clone_token": null,
+ "network_count": 2168,
+ "subscribers_count": 1731
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/1-r_o_hello-world.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/1-r_o_hello-world.json
new file mode 100644
index 0000000000..885e76133f
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/1-r_o_hello-world.json
@@ -0,0 +1,47 @@
+{
+ "id": "825b1b2a-1bcf-4273-9204-54f989479669",
+ "name": "repos_octocat_hello-world",
+ "request": {
+ "url": "/repos/octocat/Hello-World",
+ "method": "GET",
+ "headers": {
+ "Accept": {
+ "equalTo": "application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "bodyFileName": "1-r_o_hello-world.json",
+ "headers": {
+ "Server": "GitHub.com",
+ "Date": "Thu, 03 Feb 2022 14:07:49 GMT",
+ "Content-Type": "application/json; charset=utf-8",
+ "Cache-Control": "private, max-age=60, s-maxage=60",
+ "Vary": [
+ "Accept, Authorization, Cookie, X-GitHub-OTP",
+ "Accept-Encoding, Accept, X-Requested-With"
+ ],
+ "ETag": "W/\"54ebfbf708e274f11202ea42a54ccb98955c89b119059c79c8f1bf7e76126198\"",
+ "Last-Modified": "Thu, 03 Feb 2022 00:06:57 GMT",
+ "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, gist, notifications, repo, user, workflow, write:discussion",
+ "X-Accepted-OAuth-Scopes": "repo",
+ "X-GitHub-Media-Type": "github.v3; param=baptiste-preview.nebula-preview; format=json",
+ "X-RateLimit-Limit": "5000",
+ "X-RateLimit-Remaining": "4999",
+ "X-RateLimit-Reset": "1643900869",
+ "X-RateLimit-Used": "1",
+ "X-RateLimit-Resource": "core",
+ "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
+ "X-Frame-Options": "deny",
+ "X-Content-Type-Options": "nosniff",
+ "X-XSS-Protection": "0",
+ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
+ "Content-Security-Policy": "default-src 'none'",
+ "X-GitHub-Request-Id": "AD00:CEBF:18E9BF0:19A3623:61FBE1B5"
+ }
+ },
+ "uuid": "825b1b2a-1bcf-4273-9204-54f989479669",
+ "persistent": true,
+ "insertionIndex": 1
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/2-repositories_1296269.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/2-repositories_1296269.json
new file mode 100644
index 0000000000..bc21ed64a4
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationCreatedEvent/mappings/2-repositories_1296269.json
@@ -0,0 +1,46 @@
+{
+ "id": "71720657-76be-4371-932d-edc25c1e1972",
+ "name": "repositories_1296269",
+ "request": {
+ "url": "/repositories/1296269",
+ "method": "GET",
+ "headers": {
+ "Accept": {
+ "equalTo": "application/vnd.github.v3+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "bodyFileName": "2-repositories_1296269.json",
+ "headers": {
+ "Server": "GitHub.com",
+ "Date": "Thu, 14 Mar 2024 00:05:07 GMT",
+ "Content-Type": "application/json; charset=utf-8",
+ "Cache-Control": "public, max-age=60, s-maxage=60",
+ "Vary": "Accept, Accept-Encoding, Accept, X-Requested-With",
+ "ETag": "W/\"463b3a1acb093fa3ed0bb1f11b4182aa6b7f54a6f613cb6293b24c6150c757f9\"",
+ "Last-Modified": "Wed, 13 Mar 2024 21:25:44 GMT",
+ "X-GitHub-Media-Type": "github.v3; format=json",
+ "x-github-api-version-selected": "2022-11-28",
+ "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset",
+ "Access-Control-Allow-Origin": "*",
+ "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
+ "X-Frame-Options": "deny",
+ "X-Content-Type-Options": "nosniff",
+ "X-XSS-Protection": "0",
+ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
+ "Content-Security-Policy": "default-src 'none'",
+ "X-RateLimit-Limit": "60",
+ "X-RateLimit-Remaining": "59",
+ "X-RateLimit-Reset": "1710378307",
+ "X-RateLimit-Resource": "core",
+ "X-RateLimit-Used": "1",
+ "Accept-Ranges": "bytes",
+ "X-GitHub-Request-Id": "D434:1950C9:DD1F3:134998:65F23F32"
+ }
+ },
+ "uuid": "71720657-76be-4371-932d-edc25c1e1972",
+ "persistent": true,
+ "insertionIndex": 2
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/repos_octocat_hello-world-1.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/repos_octocat_hello-world-1.json
new file mode 100644
index 0000000000..fd3c1ce7ca
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/repos_octocat_hello-world-1.json
@@ -0,0 +1,108 @@
+{
+ "id": 1296269,
+ "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
+ "name": "Hello-World",
+ "full_name": "octocat/Hello-World",
+ "private": false,
+ "owner": {
+ "login": "octocat",
+ "id": 583231,
+ "node_id": "MDQ6VXNlcjU4MzIzMQ==",
+ "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/octocat",
+ "html_url": "https://github.com/octocat",
+ "followers_url": "https://api.github.com/users/octocat/followers",
+ "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+ "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+ "organizations_url": "https://api.github.com/users/octocat/orgs",
+ "repos_url": "https://api.github.com/users/octocat/repos",
+ "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/octocat/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/octocat/Hello-World",
+ "description": "My first repository on GitHub!",
+ "fork": false,
+ "url": "https://api.github.com/repos/octocat/Hello-World",
+ "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks",
+ "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams",
+ "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks",
+ "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/octocat/Hello-World/events",
+ "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags",
+ "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages",
+ "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers",
+ "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors",
+ "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers",
+ "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription",
+ "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges",
+ "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads",
+ "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}",
+ "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments",
+ "created_at": "2011-01-26T19:01:12Z",
+ "updated_at": "2022-02-03T00:06:57Z",
+ "pushed_at": "2022-01-30T18:13:40Z",
+ "git_url": "git://github.com/octocat/Hello-World.git",
+ "ssh_url": "git@github.com:octocat/Hello-World.git",
+ "clone_url": "https://github.com/octocat/Hello-World.git",
+ "svn_url": "https://github.com/octocat/Hello-World",
+ "homepage": "",
+ "size": 1,
+ "stargazers_count": 1764,
+ "watchers_count": 1764,
+ "language": null,
+ "has_issues": true,
+ "has_projects": true,
+ "has_downloads": true,
+ "has_wiki": true,
+ "has_pages": false,
+ "forks_count": 1682,
+ "mirror_url": null,
+ "archived": false,
+ "disabled": false,
+ "open_issues_count": 802,
+ "license": null,
+ "allow_forking": true,
+ "is_template": false,
+ "topics": [],
+ "visibility": "public",
+ "forks": 1682,
+ "open_issues": 802,
+ "watchers": 1764,
+ "default_branch": "master",
+ "permissions": {
+ "admin": false,
+ "maintain": false,
+ "push": false,
+ "triage": false,
+ "pull": true
+ },
+ "temp_clone_token": "",
+ "network_count": 1682,
+ "subscribers_count": 1731
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/users_octocat-2.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/users_octocat-2.json
new file mode 100644
index 0000000000..2652766fa8
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/__files/users_octocat-2.json
@@ -0,0 +1,34 @@
+{
+ "login": "octocat",
+ "id": 583231,
+ "node_id": "MDQ6VXNlcjU4MzIzMQ==",
+ "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/octocat",
+ "html_url": "https://github.com/octocat",
+ "followers_url": "https://api.github.com/users/octocat/followers",
+ "following_url": "https://api.github.com/users/octocat/following{/other_user}",
+ "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
+ "organizations_url": "https://api.github.com/users/octocat/orgs",
+ "repos_url": "https://api.github.com/users/octocat/repos",
+ "events_url": "https://api.github.com/users/octocat/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/octocat/received_events",
+ "type": "User",
+ "site_admin": false,
+ "name": "The Octocat",
+ "company": "@github",
+ "blog": "https://github.blog",
+ "location": "San Francisco",
+ "email": "octocat@github.com",
+ "hireable": null,
+ "bio": null,
+ "twitter_username": null,
+ "public_repos": 8,
+ "public_gists": 8,
+ "followers": 4752,
+ "following": 9,
+ "created_at": "2011-01-25T18:44:36Z",
+ "updated_at": "2022-01-24T15:08:43Z"
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/repos_octocat_hello-world-1.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/repos_octocat_hello-world-1.json
new file mode 100644
index 0000000000..942435fa56
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/repos_octocat_hello-world-1.json
@@ -0,0 +1,47 @@
+{
+ "id": "825b1b2a-1bcf-4273-9204-54f989479669",
+ "name": "repos_octocat_hello-world",
+ "request": {
+ "url": "/repos/octocat/Hello-World",
+ "method": "GET",
+ "headers": {
+ "Accept": {
+ "equalTo": "application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "bodyFileName": "repos_octocat_hello-world-1.json",
+ "headers": {
+ "Server": "GitHub.com",
+ "Date": "Thu, 03 Feb 2022 14:07:49 GMT",
+ "Content-Type": "application/json; charset=utf-8",
+ "Cache-Control": "private, max-age=60, s-maxage=60",
+ "Vary": [
+ "Accept, Authorization, Cookie, X-GitHub-OTP",
+ "Accept-Encoding, Accept, X-Requested-With"
+ ],
+ "ETag": "W/\"54ebfbf708e274f11202ea42a54ccb98955c89b119059c79c8f1bf7e76126198\"",
+ "Last-Modified": "Thu, 03 Feb 2022 00:06:57 GMT",
+ "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, gist, notifications, repo, user, workflow, write:discussion",
+ "X-Accepted-OAuth-Scopes": "repo",
+ "X-GitHub-Media-Type": "github.v3; param=baptiste-preview.nebula-preview; format=json",
+ "X-RateLimit-Limit": "5000",
+ "X-RateLimit-Remaining": "4999",
+ "X-RateLimit-Reset": "1643900869",
+ "X-RateLimit-Used": "1",
+ "X-RateLimit-Resource": "core",
+ "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
+ "X-Frame-Options": "deny",
+ "X-Content-Type-Options": "nosniff",
+ "X-XSS-Protection": "0",
+ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
+ "Content-Security-Policy": "default-src 'none'",
+ "X-GitHub-Request-Id": "AD00:CEBF:18E9BF0:19A3623:61FBE1B5"
+ }
+ },
+ "uuid": "825b1b2a-1bcf-4273-9204-54f989479669",
+ "persistent": true,
+ "insertionIndex": 1
+}
\ No newline at end of file
diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/users_octocat-2.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/users_octocat-2.json
new file mode 100644
index 0000000000..3a64fa2112
--- /dev/null
+++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/wiremock/InstallationDeletedEvent/mappings/users_octocat-2.json
@@ -0,0 +1,47 @@
+{
+ "id": "a801936f-7ec1-4f5a-8e1a-999cff08aec8",
+ "name": "users_octocat",
+ "request": {
+ "url": "/users/octocat",
+ "method": "GET",
+ "headers": {
+ "Accept": {
+ "equalTo": "application/vnd.github.v3+json"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "bodyFileName": "users_octocat-2.json",
+ "headers": {
+ "Server": "GitHub.com",
+ "Date": "Thu, 03 Feb 2022 14:09:13 GMT",
+ "Content-Type": "application/json; charset=utf-8",
+ "Cache-Control": "private, max-age=60, s-maxage=60",
+ "Vary": [
+ "Accept, Authorization, Cookie, X-GitHub-OTP",
+ "Accept-Encoding, Accept, X-Requested-With"
+ ],
+ "ETag": "W/\"6b9192ff77357b29af6623ef400f86c862e7b184905220e1f1d09cfd0a545d37\"",
+ "Last-Modified": "Mon, 24 Jan 2022 15:08:43 GMT",
+ "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, gist, notifications, repo, user, workflow, write:discussion",
+ "X-Accepted-OAuth-Scopes": "",
+ "X-GitHub-Media-Type": "github.v3; format=json",
+ "X-RateLimit-Limit": "5000",
+ "X-RateLimit-Remaining": "4998",
+ "X-RateLimit-Reset": "1643900869",
+ "X-RateLimit-Used": "2",
+ "X-RateLimit-Resource": "core",
+ "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
+ "X-Frame-Options": "deny",
+ "X-Content-Type-Options": "nosniff",
+ "X-XSS-Protection": "0",
+ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
+ "Content-Security-Policy": "default-src 'none'",
+ "X-GitHub-Request-Id": "AD02:CC9B:2A1ACBB:2AF0199:61FBE209"
+ }
+ },
+ "uuid": "a801936f-7ec1-4f5a-8e1a-999cff08aec8",
+ "persistent": true,
+ "insertionIndex": 2
+}
\ No newline at end of file