diff --git a/tfs/src/main/java/hudson/plugins/tfs/JenkinsEventNotifier.java b/tfs/src/main/java/hudson/plugins/tfs/JenkinsEventNotifier.java index e718c223b..e5ee69441 100644 --- a/tfs/src/main/java/hudson/plugins/tfs/JenkinsEventNotifier.java +++ b/tfs/src/main/java/hudson/plugins/tfs/JenkinsEventNotifier.java @@ -60,7 +60,7 @@ public static void sendJobCompletionEvent(final JSONObject payload) { final JobCompletionEventArgs args = new JobCompletionEventArgs( connectionParameters.getConnectionKey(), jsonPayload, - getPayloadSignature(connectionParameters, jsonPayload)); + getPayloadSignature(connectionParameters.getConnectionSignature(), jsonPayload)); client.sendJobCompletionEvent(args); } catch (final Exception e) { log.warning("ERROR: sendJobCompletionEvent: (collection=" + c.getCollectionUrl() + ") " + e.getMessage()); @@ -154,6 +154,23 @@ public static String getApiJson(final String url) { } } + /** + * Calculates the payload hash. + * @param secret + * @param payload + * @return + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws UnsupportedEncodingException + */ + public static String getPayloadSignature(final String secret, final String payload) + throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { + final SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(ENCODING), "HmacSHA1"); + final Mac mac = Mac.getInstance("HmacSHA1"); + mac.init(signingKey); + return toHexString(mac.doFinal(payload.getBytes(ENCODING))); + } + private static String urlCombine(final String url, final String... parts) { final StringBuilder sb = new StringBuilder(); if (url != null) { @@ -170,15 +187,6 @@ private static String urlCombine(final String url, final String... parts) { return sb.toString(); } - private static String getPayloadSignature(final ConnectionParameters connectionParameters, final String payload) - throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { - final String key = connectionParameters.getConnectionSignature(); - final SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(ENCODING), "HmacSHA1"); - final Mac mac = Mac.getInstance("HmacSHA1"); - mac.init(signingKey); - return toHexString(mac.doFinal(payload.getBytes(ENCODING))); - } - private static String toHexString(final byte[] bytes) { final Formatter formatter = new Formatter(); for (final byte b : bytes) { diff --git a/tfs/src/main/java/hudson/plugins/tfs/TeamEventsEndpoint.java b/tfs/src/main/java/hudson/plugins/tfs/TeamEventsEndpoint.java index 3912c53f3..e73ca0a74 100644 --- a/tfs/src/main/java/hudson/plugins/tfs/TeamEventsEndpoint.java +++ b/tfs/src/main/java/hudson/plugins/tfs/TeamEventsEndpoint.java @@ -12,6 +12,7 @@ import hudson.plugins.tfs.model.GitPushEvent; import hudson.plugins.tfs.model.PingHookEvent; import hudson.plugins.tfs.model.servicehooks.Event; +import hudson.plugins.tfs.rm.ConnectReleaseWebHookEvent; import hudson.plugins.tfs.telemetry.TelemetryHelper; import hudson.plugins.tfs.util.EndpointHelper; import hudson.plugins.tfs.util.MediaType; @@ -62,6 +63,7 @@ public class TeamEventsEndpoint implements UnprotectedRootAction { eventMap.put("gitPullRequestMerged", new GitPullRequestMergedEvent.Factory()); eventMap.put("gitPush", new GitPushEvent.Factory()); eventMap.put("connect", new ConnectHookEvent.Factory()); + eventMap.put("rmWebhook", new ConnectReleaseWebHookEvent.Factory()); HOOK_EVENT_FACTORIES_BY_NAME = Collections.unmodifiableMap(eventMap); } @@ -225,6 +227,16 @@ public void doConnect( dispatch(request, response, body); } + @RequirePOST + public void doRmwebhook( + final StaplerRequest request, + final StaplerResponse response, + @StringBodyParameter @Nonnull final String body) { + // Send telemetry + TelemetryHelper.sendEvent("team-events-rmwebhook", new TelemetryHelper.PropertyMapBuilder().build()); + dispatch(request, response, body); + } + public static T findTrigger(final Job job, final Class tClass) { if (job instanceof ParameterizedJobMixIn.ParameterizedJob) { final ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) job; diff --git a/tfs/src/main/java/hudson/plugins/tfs/TeamPluginGlobalConfig.java b/tfs/src/main/java/hudson/plugins/tfs/TeamPluginGlobalConfig.java index a35323d1c..1248dc396 100644 --- a/tfs/src/main/java/hudson/plugins/tfs/TeamPluginGlobalConfig.java +++ b/tfs/src/main/java/hudson/plugins/tfs/TeamPluginGlobalConfig.java @@ -6,6 +6,7 @@ import hudson.plugins.tfs.model.DomainUserAccountMapper; import hudson.plugins.tfs.model.UserAccountMapper; import hudson.plugins.tfs.model.UserAccountMapperDescriptor; +import hudson.plugins.tfs.rm.ReleaseWebHook; import jenkins.model.GlobalConfiguration; import jenkins.model.Jenkins; import net.sf.json.JSONObject; @@ -27,7 +28,8 @@ public class TeamPluginGlobalConfig extends GlobalConfiguration { public static final TeamPluginGlobalConfig DEFAULT_CONFIG = new TeamPluginGlobalConfig(false); private List collectionConfigurations = new ArrayList(); - + private List releaseWebHookConfigurations = new ArrayList(); + private boolean configFolderPerNode; private boolean enableTeamPushTriggerForAllJobs; private boolean enableTeamStatusForAllJobs; @@ -64,6 +66,14 @@ public List getCollectionConfigurations() { public void setCollectionConfigurations(final List collectionConfigurations) { this.collectionConfigurations = collectionConfigurations; } + + public List getReleaseWebHookConfigurations() { + return this.releaseWebHookConfigurations; + } + + public void setReleaseWebHookConfigurations(final List releaseWebHookConfigurations) { + this.releaseWebHookConfigurations = releaseWebHookConfigurations; + } public boolean isConfigFolderPerNode() { return configFolderPerNode; @@ -108,6 +118,9 @@ public List getUserAccountMapperDescriptors() { public boolean configure(StaplerRequest req, JSONObject json) throws FormException { try { req.bindJSON(this, json); + + // stapler oddity, empty lists are not set on bean by "req.bindJSON(this, json)" + this.releaseWebHookConfigurations = req.bindJSONToList(ReleaseWebHook.class, json.get("releaseWebHookConfigurations")); } catch (final Exception e) { final String message = "Configuration error: " + e.getMessage(); diff --git a/tfs/src/main/java/hudson/plugins/tfs/rm/ReleaseWebHookHelper.java b/tfs/src/main/java/hudson/plugins/tfs/rm/ReleaseWebHookHelper.java index 2897a39f9..085c25b42 100644 --- a/tfs/src/main/java/hudson/plugins/tfs/rm/ReleaseWebHookHelper.java +++ b/tfs/src/main/java/hudson/plugins/tfs/rm/ReleaseWebHookHelper.java @@ -1,7 +1,10 @@ package hudson.plugins.tfs.rm; +import hudson.plugins.tfs.JenkinsEventNotifier; import hudson.plugins.tfs.TeamPluginGlobalConfig; -import java.util.ArrayList; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.List; /** @@ -22,8 +25,7 @@ public static List getReleaseWebHookConfigurations() { throw new InternalError("Cannot load TFS global configuration"); } - //return config.getReleaseWebHookConfigurations(); - return new ArrayList(); + return config.getReleaseWebHookConfigurations(); } /** @@ -36,7 +38,7 @@ public static void saveReleaseWebHookConfigurations(final List r throw new InternalError("Cannot load TFS global configuration"); } - //config.setReleaseWebHookConfigurations(releaseWebHooks); + config.setReleaseWebHookConfigurations(releaseWebHooks); config.save(); } @@ -46,8 +48,7 @@ public static void saveReleaseWebHookConfigurations(final List r * @param payload * @return */ - public static String getPayloadSignature(final String secret, final String payload) { - //JenkinsEventNotifier.getPayloadSignature(secret payload); - return null; + public static String getPayloadSignature(final String secret, final String payload) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { + return JenkinsEventNotifier.getPayloadSignature(secret, payload); } } diff --git a/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/config.groovy b/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/config.groovy index 3a1f4bbda..48a82bfcb 100644 --- a/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/config.groovy +++ b/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/config.groovy @@ -33,4 +33,9 @@ f.section(title: descriptor.displayName) { f.checkbox (default: false) } } + f.entry(title: _("Release WebHooks"), + field: "releaseWebHookConfigurations") { + + f.repeatableProperty(field: "releaseWebHookConfigurations") + } } diff --git a/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/help-releaseWebhookConfigurations.html b/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/help-releaseWebhookConfigurations.html new file mode 100644 index 000000000..7b61f53e3 --- /dev/null +++ b/tfs/src/main/resources/hudson/plugins/tfs/TeamPluginGlobalConfig/help-releaseWebhookConfigurations.html @@ -0,0 +1,3 @@ +
+ Adds a Release Webhook. Project can refer to this Webhook in its post build action. When a build completes it will send the event payload to the payload url mentioned. +