Skip to content
This repository was archived by the owner on Aug 18, 2021. It is now read-only.
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ You may want to disable debug options to get faster page load time:
## Acknowledgements

This project is started and based on the [gitlab-plugin][3], thanks for the great project.
The coding-api module follows [github-api][6], and coding-auth module follows [github-oauth-plugin][7], thanks for them.

[1]: https://coding.net
[2]: https://open.coding.net/webhooks
[3]: https://github.com/jenkinsci/gitlab-plugin
[4]: https://plugins.jenkins.io
[5]: https://jenkins.io/doc/book/managing/plugins
[6]: https://github.com/kohsuke/github-api
[7]: https://github.com/jenkinsci/github-oauth-plugin
51 changes: 45 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
plugins {
id 'org.jenkins-ci.jpi' version '0.18.1'
id 'me.tatarka.retrolambda' version '3.6.0'
id 'org.jenkins-ci.jpi' version '0.25.0'
id "com.github.hierynomus.license" version "0.14.0"
id 'idea'
}
Expand All @@ -12,8 +11,8 @@ repositories {
url "http://repo.jenkins-ci.org/public/"
}
}

dependencies {

jenkinsPlugins 'org.jenkins-ci.plugins:git:2.4.1@jar'
jenkinsPlugins 'org.jenkins-ci.plugins:git-client:1.19.0@jar'

Expand All @@ -22,23 +21,63 @@ dependencies {
compile 'org.eclipse.jgit:org.eclipse.jgit:3.5.2.201411120430-r'
compile 'org.apache.httpcomponents:httpclient:4.5'
compile 'commons-codec:commons-codec:1.10'

// below are for coding oauth
jenkinsPlugins 'org.jenkins-ci.plugins:mailer:1.18@jar'
jenkinsPlugins 'org.jenkins-ci.plugins:matrix-project:1.7@jar'
jenkinsPlugins 'org.jenkins-ci.plugins:github-branch-source:1.9@jar'

compile 'org.jenkins-ci.plugins.workflow:workflow-multibranch:2.9@jar'
compile 'org.jenkins-ci.plugins:branch-api:1.11@jar'
compile 'org.jenkins-ci.plugins:scm-api:1.3@jar'
compile 'org.jenkins-ci.plugins:cloudbees-folder:5.12@jar'
compile 'org.jenkins-ci.plugins.workflow:workflow-api:2.3@jar'
compile 'org.jenkins-ci.plugins.workflow:workflow-job:2.6@jar'

compile 'com.fasterxml.jackson.core:jackson-databind:2.2.3'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0'

compile group: 'com.google.code.gson', name: 'gson', version:'2.8.4'
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.7'
testCompile group: 'org.powermock', name: 'powermock-api-mockito', version:'1.6.5'
testCompile group: 'org.powermock', name: 'powermock-module-junit4', version:'1.6.5'
testCompile group: 'junit', name: 'junit', version:'4.12'
testCompile group: 'org.jenkins-ci.plugins', name: 'external-monitor-job', version:'1.6'
testCompile group: 'javax.servlet', name: 'javax.servlet-api', version:'3.1.0'
testCompile group: 'org.jenkins-ci.main', name: 'jenkins-war', version:'2.7.1', classifier:'war-for-test'
testCompile group: 'org.jenkins-ci.main', name: 'jenkins-war', version:'2.7.1'
testCompile(group: 'org.jenkins-ci.main', name: 'jenkins-test-harness', version:'2.15') {
exclude(module: 'junit-dep')
}
testCompile group: 'org.jenkins-ci', name: 'test-annotations', version:'1.2'
testCompile group: 'org.slf4j', name: 'log4j-over-slf4j', version:'1.7.7'
testCompile group: 'org.slf4j', name: 'jcl-over-slf4j', version:'1.7.7'
testCompile group: 'org.slf4j', name: 'slf4j-jdk14', version:'1.7.7'
compileOnly group: 'com.google.code.findbugs', name: 'annotations', version:'3.0.0'
compileOnly group: 'net.jcip', name: 'jcip-annotations', version:'1.0'
compileOnly group: 'org.codehaus.mojo', name: 'animal-sniffer-annotations', version:'1.14'
compileOnly group: 'javax.servlet', name: 'servlet-api', version:'2.4'
compileOnly group: 'org.jenkins-ci.main', name: 'jenkins-core', version:'2.7.1'
}

group = 'org.jenkins-ci.plugins'
description = 'Webhook trigger for Coding (https://coding.net)'
version = '1.2.2'
version = '1.3.0-alpha.1'

sourceCompatibility = 1.7
targetCompatibility = 1.7

task wrapper(type: Wrapper) {
gradleVersion = '2.14'
}

license {
header project.file('LICENSE_HEADER')
excludes (["**/webhook/filter/*.java", "**/Messages.java"])
excludes (["**/webhook/filter/*.java", "**/Messages.java", "**/net/coding/jenkins/plugin/oauth/**", "**/net/coding/api/**"])
}

jenkinsPlugin {
coreVersion = '1.625.3'
coreVersion = '2.7.3'
shortName = 'coding-webhook'
displayName = 'Coding Webhook Plugin'
url = 'https://wiki.jenkins.io/display/JENKINS/Coding+Webhook+Plugin'
Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Thu Feb 15 20:12:54 CST 2018
#Tue May 15 15:33:00 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip
230 changes: 230 additions & 0 deletions src/main/java/net/coding/api/Coding.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/**
* Copyright (c) 2011- Kohsuke Kawaguchi and other contributors
* Copyright (c) 2016-present, Coding, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package net.coding.api;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import org.apache.commons.codec.Charsets;
import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;

public class Coding {
/*package*/ final String login;

private final Map<String, CodingUser> users = new Hashtable<String, CodingUser>();
private final Map<String, CodingOrganization> orgs = new Hashtable<String, CodingOrganization>();

private final String apiUrl;
private HttpConnector connector = HttpConnector.DEFAULT;
/*package*/ final String encodedAuthorization;

Coding(String apiUrl, String login, String oauthAccessToken, String password, HttpConnector connector) throws IOException {
if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length() - 1); // normalize
this.apiUrl = apiUrl;
if (null != connector) this.connector = connector;

if (oauthAccessToken != null) {
encodedAuthorization = oauthAccessToken;
} else {
if (password != null) {
String authorization = (login + ':' + password);
String charsetName = Charsets.UTF_8.name();
encodedAuthorization = "Basic " + new String(Base64.encodeBase64(authorization.getBytes(charsetName)), charsetName);
} else {// anonymous access
encodedAuthorization = null;
}
}

if (login == null && encodedAuthorization != null)
login = getMyself().getLogin();
this.login = login;
}

/**
* This method returns a shallowly populated organizations.
*
* To retrieve full organization details, you need to call {@link #getOrganization(String)}
* TODO: make this automatic.
*/
public Map<String, CodingOrganization> getMyOrganizations() throws IOException {
if ("https://coding.net".equals(apiUrl)) {
return Collections.singletonMap("coding_dot_net", null);
}
return Collections.singletonMap("coding_dot_net", null);
// CodingOrganization[] orgs = retrieve().to("/user/orgs", CodingOrganization[].class);
// Map<String, CodingOrganization> r = new HashMap<String, CodingOrganization>();
// for (CodingOrganization o : orgs) {
// // don't put 'o' into orgs because they are shallow
// r.put(o.getLogin(),o.wrapUp(this));
// }
// return r;
}

public CodingOrganization getOrganization(String name) throws IOException {
CodingOrganization o = new CodingOrganization();
o.global_key = "coding_dot_net";
return o;
// CodingOrganization o = orgs.get(name);
// if (o==null) {
// o = retrieve().to("/orgs/" + name, CodingOrganization.class).wrapUp(this);
// orgs.put(name,o);
// }
// return o;
}

/**
* Gets the repository object from 'user/reponame' string that GitHub calls as "repository name"
*
* @see CodingRepository#getName()
*/
public CodingRepository getRepository(String name) throws IOException {
String[] tokens = name.split("/");
return retrieve().to("/repos/" + tokens[0] + '/' + tokens[1], CodingRepository.class).wrap(this);
}

/**
* Gets complete map of organizations/teams that current user belongs to.
*
* Leverages the new GitHub API /user/teams made available recently to
* get in a single call the complete set of organizations, teams and permissions
* in a single call.
*/
public Map<String, Set<CodingTeam>> getMyTeams() throws IOException {
Map<String, Set<CodingTeam>> allMyTeams = new HashMap<>();
for (CodingTeam team : retrieve().to("/api/team/joined", CodingTeam[].class)) {
team.wrapUp(this);
String orgLogin = team.getOrganization().getLogin();
Set<CodingTeam> teamsPerOrg = allMyTeams.get(orgLogin);
if (teamsPerOrg == null) {
teamsPerOrg = new HashSet<>();
}
teamsPerOrg.add(team);
allMyTeams.put(orgLogin, teamsPerOrg);
}
return allMyTeams;
}

/**
* Obtains the object that represents the named user.
*/
public CodingUser getUser(String login) throws IOException {
if ("MANAGE_DOMAINS".equals(login)) {
LOGGER.log(Level.INFO, "ignore fetch user info for MANAGE_DOMAINS");
return null;
}
CodingUser u = users.get(login);
if (u == null) {
u = retrieve().to("/api/user/key/" + login, CodingUser.class);
if (u == null) {
return null;
}
u.root = this;
users.put(u.getLogin(), u);
}
return u;
}


/**
* Gets the {@link CodingUser} that represents yourself.
*/
@WithBridgeMethods(CodingUser.class)
public CodingMyself getMyself() throws IOException {
requireCredential();

CodingMyself u = retrieve().to("/api/current_user", CodingMyself.class);
LOGGER.log(Level.FINE, "fetch current_user " + u);

u.root = this;
users.put(u.getLogin(), u);

return u;
}

/*package*/ void requireCredential() {
if (isAnonymous())
throw new IllegalStateException("This operation requires a credential but none is given to the GitHub constructor");
}

/**
* Is this an anonymous connection
* @return {@code true} if operations that require authentication will fail.
*/
public boolean isAnonymous() {
return login == null && encodedAuthorization == null;
}

Requester retrieve() {
return new Requester(this).method("GET");
}

public HttpConnector getConnector() {
return connector;
}

/*package*/ URL getApiURL(String tailApiUrl) throws IOException {
if (tailApiUrl.startsWith("/")) {
return new URL(apiUrl + tailApiUrl);
} else {
return new URL(tailApiUrl);
}
}

/*package*/
static String printDate(Date dt) {
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(dt);
}

/*package*/ static final ObjectMapper MAPPER = new ObjectMapper();

private static final String[] TIME_FORMATS = {"yyyy/MM/dd HH:mm:ss ZZZZ", "yyyy-MM-dd'T'HH:mm:ss'Z'"};

static {
MAPPER.setVisibilityChecker(new VisibilityChecker.Std(NONE, NONE, NONE, NONE, ANY));
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}

/* package */ static final String CODING_URL = "https://coding.net";

private static final Logger LOGGER = Logger.getLogger(Coding.class.getName());
}
Loading