Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit f4b105b

Browse files
author
Chris Hut
committed
Enable creation and retrieval of org webhooks
made GHHook abstract and created two concrete subclasses for org and repo hooks. Created utility class GHHooks to manage creation and retrieval of org/repo hooks with minimal code duplication. These are invoked by GHOrganization and GHRepository respectively.
1 parent b976e0e commit f4b105b

7 files changed

Lines changed: 251 additions & 54 deletions

File tree

src/main/java/org/kohsuke/github/GHEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public enum GHEvent {
2828
PULL_REQUEST_REVIEW_COMMENT,
2929
PUSH,
3030
RELEASE,
31+
REPOSITORY, // only valid for org hooks
3132
STATUS,
3233
TEAM_ADD,
3334
WATCH

src/main/java/org/kohsuke/github/GHHook.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,12 @@
1111
/**
1212
* @author Kohsuke Kawaguchi
1313
*/
14-
public class GHHook extends GHObject {
15-
/**
16-
* Repository that the hook belongs to.
17-
*/
18-
/*package*/ transient GHRepository repository;
19-
14+
public abstract class GHHook extends GHObject {
2015
String name;
2116
List<String> events;
2217
boolean active;
2318
Map<String,String> config;
2419

25-
/*package*/ GHHook wrap(GHRepository owner) {
26-
this.repository = owner;
27-
return this;
28-
}
29-
3020
public String getName() {
3121
return name;
3222
}
@@ -50,7 +40,7 @@ public Map<String, String> getConfig() {
5040
* Deletes this hook.
5141
*/
5242
public void delete() throws IOException {
53-
new Requester(repository.root).method("DELETE").to(String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id));
43+
new Requester(root()).method("DELETE").to(path());
5444
}
5545

5646
/**
@@ -60,4 +50,8 @@ public void delete() throws IOException {
6050
public URL getHtmlUrl() {
6151
return null;
6252
}
53+
54+
abstract GitHub root();
55+
56+
abstract String path();
6357
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package org.kohsuke.github;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
6+
import java.util.Collection;
7+
import java.util.List;
8+
import java.util.Locale;
9+
import java.util.Map;
10+
11+
/**
12+
* Utility class for creating and retrieving webhooks; removes duplication between GHOrganization and GHRepository
13+
* functionality
14+
*/
15+
class GHHooks {
16+
static abstract class Context {
17+
private final GitHub root;
18+
19+
private Context(GitHub root) {
20+
this.root = root;
21+
}
22+
23+
public List<GHHook> getHooks() throws IOException {
24+
List<GHHook> list = new ArrayList<GHHook>(Arrays.asList(
25+
root.retrieve().to(collection(), collectionClass())));
26+
for (GHHook h : list)
27+
wrap(h);
28+
return list;
29+
}
30+
31+
public GHHook getHook(int id) throws IOException {
32+
GHHook hook = root.retrieve().to(collection() + "/" + id, clazz());
33+
return wrap(hook);
34+
}
35+
36+
public GHHook createHook(String name, Map<String, String> config, Collection<GHEvent> events, boolean active) throws IOException {
37+
List<String> ea = null;
38+
if (events!=null) {
39+
ea = new ArrayList<String>();
40+
for (GHEvent e : events)
41+
ea.add(e.name().toLowerCase(Locale.ENGLISH));
42+
}
43+
44+
GHHook hook = new Requester(root)
45+
.with("name", name)
46+
.with("active", active)
47+
._with("config", config)
48+
._with("events", ea)
49+
.to(collection(), clazz());
50+
51+
return wrap(hook);
52+
}
53+
54+
abstract String collection();
55+
56+
abstract Class<? extends GHHook[]> collectionClass();
57+
58+
abstract Class<? extends GHHook> clazz();
59+
60+
abstract GHHook wrap(GHHook hook);
61+
}
62+
63+
private static class RepoContext extends Context {
64+
private final GHRepository repository;
65+
private final GHUser owner;
66+
67+
private RepoContext(GHRepository repository, GHUser owner) {
68+
super(repository.root);
69+
this.repository = repository;
70+
this.owner = owner;
71+
}
72+
73+
@Override
74+
String collection() {
75+
return String.format("/repos/%s/%s/hooks", owner.getLogin(), repository.getName());
76+
}
77+
78+
@Override
79+
Class<? extends GHHook[]> collectionClass() {
80+
return GHRepoHook[].class;
81+
}
82+
83+
@Override
84+
Class<? extends GHHook> clazz() {
85+
return GHRepoHook.class;
86+
}
87+
88+
@Override
89+
GHHook wrap(GHHook hook) {
90+
return ((GHRepoHook)hook).wrap(repository);
91+
}
92+
}
93+
94+
private static class OrgContext extends Context {
95+
private final GHOrganization organization;
96+
97+
private OrgContext(GHOrganization organization) {
98+
super(organization.root);
99+
this.organization = organization;
100+
}
101+
102+
@Override
103+
String collection() {
104+
return String.format("/orgs/%s/hooks", organization.getLogin());
105+
}
106+
107+
@Override
108+
Class<? extends GHHook[]> collectionClass() {
109+
return GHOrgHook[].class;
110+
}
111+
112+
@Override
113+
Class<? extends GHHook> clazz() {
114+
return GHOrgHook.class;
115+
}
116+
117+
@Override
118+
GHHook wrap(GHHook hook) {
119+
return ((GHOrgHook)hook).wrap(organization);
120+
}
121+
}
122+
123+
static Context repoContext(GHRepository repository, GHUser owner) {
124+
return new RepoContext(repository, owner);
125+
}
126+
127+
static Context orgContext(GHOrganization organization) {
128+
return new OrgContext(organization);
129+
}
130+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* © Copyright 2015 - SourceClear Inc
3+
*/
4+
5+
package org.kohsuke.github;
6+
7+
class GHOrgHook extends GHHook {
8+
/**
9+
* Organization that the hook belongs to.
10+
*/
11+
/*package*/ transient GHOrganization organization;
12+
13+
/*package*/ GHOrgHook wrap(GHOrganization owner) {
14+
this.organization = owner;
15+
return this;
16+
}
17+
18+
@Override
19+
GitHub root() {
20+
return organization.root;
21+
}
22+
23+
@Override
24+
String path() {
25+
return String.format("/orgs/%s/hooks/%d", organization.getLogin(), id);
26+
}
27+
}

src/main/java/org/kohsuke/github/GHOrganization.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package org.kohsuke.github;
22

33
import java.io.IOException;
4+
import java.net.URL;
45
import java.util.ArrayList;
56
import java.util.Arrays;
67
import java.util.Collection;
8+
import java.util.Collections;
79
import java.util.List;
10+
import java.util.Locale;
811
import java.util.Map;
912
import java.util.TreeMap;
1013

@@ -26,7 +29,7 @@ public GHRepository createRepository(String name, String description, String hom
2629
GHTeam t = getTeams().get(team);
2730
if (t==null)
2831
throw new IllegalArgumentException("No such team: "+team);
29-
return createRepository(name,description,homepage,t,isPublic);
32+
return createRepository(name, description, homepage, t, isPublic);
3033
}
3134

3235
public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException {
@@ -252,4 +255,39 @@ protected void wrapUp(GHRepository[] page) {
252255
}
253256
};
254257
}
258+
259+
/**
260+
* Retrieves the currently configured hooks.
261+
*/
262+
public List<GHHook> getHooks() throws IOException {
263+
return GHHooks.orgContext(this).getHooks();
264+
}
265+
266+
public GHHook getHook(int id) throws IOException {
267+
return GHHooks.orgContext(this).getHook(id);
268+
}
269+
270+
/**
271+
*
272+
* See https://api.github.com/hooks for possible names and their configuration scheme.
273+
* TODO: produce type-safe binding
274+
*
275+
* @param name
276+
* Type of the hook to be created. See https://api.github.com/hooks for possible names.
277+
* @param config
278+
* The configuration hash.
279+
* @param events
280+
* Can be null. Types of events to hook into.
281+
*/
282+
public GHHook createHook(String name, Map<String,String> config, Collection<GHEvent> events, boolean active) throws IOException {
283+
return GHHooks.orgContext(this).createHook(name, config, events, active);
284+
}
285+
286+
public GHHook createWebHook(URL url, Collection<GHEvent> events) throws IOException {
287+
return createHook("web", Collections.singletonMap("url", url.toExternalForm()),events,true);
288+
}
289+
290+
public GHHook createWebHook(URL url) throws IOException {
291+
return createWebHook(url, null);
292+
}
255293
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.kohsuke.github;
2+
3+
class GHRepoHook extends GHHook {
4+
/**
5+
* Repository that the hook belongs to.
6+
*/
7+
/*package*/ transient GHRepository repository;
8+
9+
/*package*/ GHRepoHook wrap(GHRepository owner) {
10+
this.repository = owner;
11+
return this;
12+
}
13+
14+
@Override
15+
GitHub root() {
16+
return repository.root;
17+
}
18+
19+
@Override
20+
String path() {
21+
return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id);
22+
}
23+
}

0 commit comments

Comments
 (0)