Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable creation and retrieval of org webhooks #192

Merged
merged 1 commit into from
Jul 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/org/kohsuke/github/GHEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public enum GHEvent {
PULL_REQUEST_REVIEW_COMMENT,
PUSH,
RELEASE,
REPOSITORY, // only valid for org hooks
STATUS,
TEAM_ADD,
WATCH
Expand Down
18 changes: 6 additions & 12 deletions src/main/java/org/kohsuke/github/GHHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,12 @@
/**
* @author Kohsuke Kawaguchi
*/
public class GHHook extends GHObject {
/**
* Repository that the hook belongs to.
*/
/*package*/ transient GHRepository repository;

public abstract class GHHook extends GHObject {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No way. It breaks the binary compatibility of the code

String name;
List<String> events;
boolean active;
Map<String,String> config;

/*package*/ GHHook wrap(GHRepository owner) {
this.repository = owner;
return this;
}

public String getName() {
return name;
}
Expand All @@ -50,7 +40,7 @@ public Map<String, String> getConfig() {
* Deletes this hook.
*/
public void delete() throws IOException {
new Requester(repository.root).method("DELETE").to(String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id));
new Requester(root()).method("DELETE").to(path());
}

/**
Expand All @@ -60,4 +50,8 @@ public void delete() throws IOException {
public URL getHtmlUrl() {
return null;
}

abstract GitHub root();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Implement methods with a default behavior instead.
  • Oracle Java codestyle requires getRoot() and getPath()
  • Javadocs are required as well. Also add @since TODO to document the API changes properly


abstract String path();
}
130 changes: 130 additions & 0 deletions src/main/java/org/kohsuke/github/GHHooks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.kohsuke.github;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
* Utility class for creating and retrieving webhooks; removes duplication between GHOrganization and GHRepository
* functionality
*/
class GHHooks {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GHHooksHelper?

static abstract class Context {
private final GitHub root;

private Context(GitHub root) {
this.root = root;
}

public List<GHHook> getHooks() throws IOException {
List<GHHook> list = new ArrayList<GHHook>(Arrays.asList(
root.retrieve().to(collection(), collectionClass())));
for (GHHook h : list)
wrap(h);
return list;
}

public GHHook getHook(int id) throws IOException {
GHHook hook = root.retrieve().to(collection() + "/" + id, clazz());
return wrap(hook);
}

public GHHook createHook(String name, Map<String, String> config, Collection<GHEvent> events, boolean active) throws IOException {
List<String> ea = null;
if (events!=null) {
ea = new ArrayList<String>();
for (GHEvent e : events)
ea.add(e.name().toLowerCase(Locale.ENGLISH));
}

GHHook hook = new Requester(root)
.with("name", name)
.with("active", active)
._with("config", config)
._with("events", ea)
.to(collection(), clazz());

return wrap(hook);
}

abstract String collection();

abstract Class<? extends GHHook[]> collectionClass();

abstract Class<? extends GHHook> clazz();

abstract GHHook wrap(GHHook hook);
}

private static class RepoContext extends Context {
private final GHRepository repository;
private final GHUser owner;

private RepoContext(GHRepository repository, GHUser owner) {
super(repository.root);
this.repository = repository;
this.owner = owner;
}

@Override
String collection() {
return String.format("/repos/%s/%s/hooks", owner.getLogin(), repository.getName());
}

@Override
Class<? extends GHHook[]> collectionClass() {
return GHRepoHook[].class;
}

@Override
Class<? extends GHHook> clazz() {
return GHRepoHook.class;
}

@Override
GHHook wrap(GHHook hook) {
return ((GHRepoHook)hook).wrap(repository);
}
}

private static class OrgContext extends Context {
private final GHOrganization organization;

private OrgContext(GHOrganization organization) {
super(organization.root);
this.organization = organization;
}

@Override
String collection() {
return String.format("/orgs/%s/hooks", organization.getLogin());
}

@Override
Class<? extends GHHook[]> collectionClass() {
return GHOrgHook[].class;
}

@Override
Class<? extends GHHook> clazz() {
return GHOrgHook.class;
}

@Override
GHHook wrap(GHHook hook) {
return ((GHOrgHook)hook).wrap(organization);
}
}

static Context repoContext(GHRepository repository, GHUser owner) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to create new objects every operation?
I would also rename the method

return new RepoContext(repository, owner);
}

static Context orgContext(GHOrganization organization) {
return new OrgContext(organization);
}
}
27 changes: 27 additions & 0 deletions src/main/java/org/kohsuke/github/GHOrgHook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* © Copyright 2015 - SourceClear Inc
*/

package org.kohsuke.github;

class GHOrgHook extends GHHook {
/**
* Organization that the hook belongs to.
*/
/*package*/ transient GHOrganization organization;

/*package*/ GHOrgHook wrap(GHOrganization owner) {
this.organization = owner;
return this;
}

@Override
GitHub root() {
return organization.root;
}

@Override
String path() {
return String.format("/orgs/%s/hooks/%d", organization.getLogin(), id);
}
}
40 changes: 39 additions & 1 deletion src/main/java/org/kohsuke/github/GHOrganization.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.kohsuke.github;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

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

public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException {
Expand Down Expand Up @@ -252,4 +255,39 @@ protected void wrapUp(GHRepository[] page) {
}
};
}

/**
* Retrieves the currently configured hooks.
*/
public List<GHHook> getHooks() throws IOException {
return GHHooks.orgContext(this).getHooks();
}

public GHHook getHook(int id) throws IOException {
return GHHooks.orgContext(this).getHook(id);
}

/**
*
* See https://api.github.com/hooks for possible names and their configuration scheme.
* TODO: produce type-safe binding
*
* @param name
* Type of the hook to be created. See https://api.github.com/hooks for possible names.
* @param config
* The configuration hash.
* @param events
* Can be null. Types of events to hook into.
*/
public GHHook createHook(String name, Map<String,String> config, Collection<GHEvent> events, boolean active) throws IOException {
return GHHooks.orgContext(this).createHook(name, config, events, active);
}

public GHHook createWebHook(URL url, Collection<GHEvent> events) throws IOException {
return createHook("web", Collections.singletonMap("url", url.toExternalForm()),events,true);
}

public GHHook createWebHook(URL url) throws IOException {
return createWebHook(url, null);
}
}
23 changes: 23 additions & 0 deletions src/main/java/org/kohsuke/github/GHRepoHook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.kohsuke.github;

class GHRepoHook extends GHHook {
/**
* Repository that the hook belongs to.
*/
/*package*/ transient GHRepository repository;

/*package*/ GHRepoHook wrap(GHRepository owner) {
this.repository = owner;
return this;
}

@Override
GitHub root() {
return repository.root;
}

@Override
String path() {
return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id);
}
}
Loading