Skip to content

Commit

Permalink
Merge pull request #906 from daspilker/JENKINS-37422
Browse files Browse the repository at this point in the history
[JENKINS-37422] fixed compatibility with Ruby Runtime Plugin
  • Loading branch information
daspilker committed Aug 31, 2016
2 parents 496b7eb + 8dc6921 commit b7d9b80
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 44 deletions.
7 changes: 7 additions & 0 deletions docs/Home.md
Expand Up @@ -27,6 +27,13 @@ Browse the Jenkins issue tracker to see any [open issues](https://issues.jenkins

## Release Notes
* 1.51 (unreleased)
* Fixed compatibility issue with [Ruby Runtime Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Ruby+Runtime+Plugin)
([JENKINS-37422](https://issues.jenkins-ci.org/browse/JENKINS-37422))
* Support for the older versions of the [RVM Plugin](https://wiki.jenkins-ci.org/display/JENKINS/RVM+Plugin) is
deprecated, see [Migration](Migration#migrating-to-151)
* Support for the older versions of the
[Ruby Runtime Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Ruby+Runtime+Plugin) is deprecated, see
[Migration](Migration#migrating-to-151)
* 1.50 (August 17 2016)
* Fixed regression when updating views
([JENKINS-37450](https://issues.jenkins-ci.org/browse/JENKINS-37450))
Expand Down
13 changes: 13 additions & 0 deletions docs/Migration.md
@@ -1,3 +1,16 @@
## Migrating to 1.51

### RVM

Support for versions older than 0.6 of the [RVM Plugin](https://wiki.jenkins-ci.org/display/JENKINS/RVM+Plugin) is
[[deprecated|Deprecation-Policy]] and will be removed.

### Ruby Runtime

Support for versions older than 0.13 of the
[Ruby Runtime Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Ruby+Runtime+Plugin) is
[[deprecated|Deprecation-Policy]] and will be removed.

## Migrating to 1.49

### ScriptLocation
Expand Down
4 changes: 2 additions & 2 deletions job-dsl-api-viewer/src/assets/javascripts/App.js
Expand Up @@ -135,7 +135,7 @@ Marionette.Renderer.render = function(template, data) {

var matches = this.allItems.filter(function(item) {
return item.name.toLowerCase().indexOf(val.toLowerCase()) !== -1 &&
(!item.method.plugin || !this.settings.isPluginExcluded(item.method.plugin.name));
!this.settings.isPluginsExcluded(item.method.plugins);
}, this);
var html = Handlebars.templates['searchResults']({results: matches});
$searchResults.html(html);
Expand Down Expand Up @@ -221,7 +221,7 @@ Marionette.Renderer.render = function(template, data) {
var signatures = this.dsl.getContextSignatures(parentSignature.contextClass, path);

signatures = _.filter(signatures, function(sig) {
return !sig.methodPlugin || !this.settings.isPluginExcluded(sig.methodPlugin.name);
return !this.settings.isPluginsExcluded(sig.methodPlugins);
}, this);

var contextView = new App.ContextView({signatures: signatures});
Expand Down
52 changes: 35 additions & 17 deletions job-dsl-api-viewer/src/assets/javascripts/Dsl.js
Expand Up @@ -12,6 +12,15 @@ _.extend(App.Dsl.prototype, {
context.simpleClassName = tokens[tokens.length - 1];

context.methods.forEach(function(method) {
method.signatures.forEach(function (signature) {
// maintain compatibility with older data
if (signature.plugin) {
signature.plugins = [signature.plugin];
} else {
signature.plugins = signature.plugins || [];
}
});

if (method.signatures.every(function(sig) { return sig.deprecated; })) {
method.deprecated = true;
}
Expand All @@ -25,10 +34,11 @@ _.extend(App.Dsl.prototype, {
method.contextClass = signatureWithContext.contextClass;
}

var signatureWithPlugin = _.find(method.signatures, function(signature) { return signature.plugin; });
if (signatureWithPlugin) {
method.plugin = window.updateCenter.data.plugins[signatureWithPlugin.plugin.id];
}
method.plugins = _.chain(method.signatures)
.pluck('plugins')
.flatten()
.map(function(plugin) { return window.updateCenter.data.plugins[plugin.id] })
.value();
});
},

Expand All @@ -48,8 +58,9 @@ _.extend(App.Dsl.prototype, {
return _.chain(this.data.contexts)
.pluck('methods')
.flatten()
.pluck('plugin')
.pluck('plugins')
.filter()
.flatten()
.unique()
.sortBy(function (item) {
return item.title.toLowerCase();
Expand Down Expand Up @@ -77,9 +88,11 @@ _.extend(App.Dsl.prototype, {
var usages = [];
_.forEach(this.data.contexts, function(context) {
context.methods.forEach(function(method) {
if (method.plugin === plugin) {
usages.push({method: method, context: context});
}
method.plugins.forEach(function(methodPlugin) {
if (methodPlugin === plugin) {
usages.push({method: method, context: context});
}
});
});
});
return usages;
Expand Down Expand Up @@ -202,15 +215,20 @@ _.extend(App.Dsl.prototype, {
data.enums = enums;
}

data.methodPlugin = method.plugin;
if (signature.plugin) {
data.plugin = signature.plugin;
var pluginData = window.updateCenter.data.plugins[signature.plugin.id];
if (pluginData) {
data.plugin.title = pluginData.title;
} else {
console.log('plugin not found', signature.plugin.id);
}
data.methodPlugins = method.plugins;
if (signature.plugins) {
data.plugins = signature.plugins;
data.plugins.forEach(function (plugin) {
plugin.name = plugin.id;

var pluginData = window.updateCenter.data.plugins[plugin.id];
if (pluginData) {
plugin.title = pluginData.title;
plugin.wiki = pluginData.wiki;
} else {
console.log('plugin not found', plugin.id);
}
});
}

return data;
Expand Down
4 changes: 4 additions & 0 deletions job-dsl-api-viewer/src/assets/javascripts/Settings.js
Expand Up @@ -16,6 +16,10 @@ App.Settings = Marionette.Object.extend({
return _.contains(this.excludedPlugins, name);
},

isPluginsExcluded: function(plugins) {
return plugins.length > 0 && _.pluck(plugins, 'name').some(this.isPluginExcluded.bind(this));
},

setPluginExcluded: function(name, isExcluded) {
if (isExcluded && !this.isPluginExcluded(name)) {
this.excludedPlugins.push(name);
Expand Down
Expand Up @@ -10,11 +10,12 @@
<div class="method-detail">
<h2>
{{name}}
{{#if methodNode.plugin}}<a href="{{methodNode.plugin.wiki}}"><span class="glyphicon glyphicon-new-window"></span> {{methodNode.plugin.title}}</a>{{/if}}
</h2>
<div class="signatures">
{{#each signatures}}
{{#if plugin.minimumVersion}}<span class="label label-min-version">Requires {{plugin.title}} v{{plugin.minimumVersion}}+</span>{{/if}}
{{#each plugins}}
<a href="{{wiki}}"><span class="label label-plugin">Requires {{title}}{{#if minimumVersion}} v{{minimumVersion}}+{{/if}}</span></a>
{{/each}}
{{#if availableSince}}
<span class="label label-since">Since {{availableSince}}</span>
{{/if}}
Expand Down
Expand Up @@ -18,7 +18,7 @@ App.HomeView = Marionette.LayoutView.extend({
var methodNode = pathInfo.methodNode;
var signatures = this.dsl.getContextSignatures(methodNode.contextClass);
signatures = _.filter(signatures, function(sig) {
return !sig.plugin || !this.settings.isPluginExcluded(sig.plugin.id);
return !this.settings.isPluginsExcluded(sig.plugins);
}, this);
var contextView = new App.ContextView({signatures: signatures});
this.contextRegion.show(contextView);
Expand Down
Expand Up @@ -48,7 +48,7 @@ App.TreeView = Marionette.ItemView.extend({
var contextClass = node.id === '#' ? this.dsl.getRootContextClass() : node.original.methodNode.contextClass;
var methods = _.chain(this.dsl.getContext(contextClass).methods)
.filter(function (method) {
return !method.plugin || !this.settings.isPluginExcluded(method.plugin.name);
return !this.settings.isPluginsExcluded(method.plugins);
}.bind(this))
.sortBy(function (method) {
return method.name.toLowerCase();
Expand Down
2 changes: 1 addition & 1 deletion job-dsl-api-viewer/src/assets/stylesheets/main.less
Expand Up @@ -246,7 +246,7 @@ body {
display: inline-block;
font-size: 12px;
padding: 4px 5px 5px;
&.label-min-version {
&.label-plugin {
background-color: @color2;
}
&.label-since {
Expand Down
Expand Up @@ -2,12 +2,12 @@ package javaposse.jobdsl.dsl.transform

import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.ast.expr.ArgumentListExpression
import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.ast.expr.Expression
import org.codehaus.groovy.ast.expr.ListExpression
import org.codehaus.groovy.ast.expr.MethodCallExpression
import org.codehaus.groovy.ast.expr.VariableExpression
import org.codehaus.groovy.ast.stmt.BlockStatement
Expand All @@ -18,6 +18,8 @@ import org.codehaus.groovy.syntax.Token
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation

import static org.codehaus.groovy.ast.ClassHelper.make

/**
* Global AST transformation for checking plugin requirements.
*
Expand All @@ -27,21 +29,14 @@ import org.codehaus.groovy.transform.GroovyASTTransformation
*/
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class PluginASTTransformation implements ASTTransformation {
private static final ClassNode REQUIRES_PLUGIN_ANNOTATION = ClassHelper.make('javaposse.jobdsl.dsl.RequiresPlugin')
private static final ClassNode REQUIRES_PLUGIN_ANNOTATION = make('javaposse.jobdsl.dsl.RequiresPlugin')
private static final ClassNode REQUIRES_PLUGINS_ANNOTATION = make('javaposse.jobdsl.dsl.RequiresPlugins')

@Override
void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
List<ClassNode> classes = sourceUnit.AST.classes.findAll { !it.interface }
classes.methods.flatten().each { MethodNode method ->
List<AnnotationNode> annotations = method.getAnnotations(REQUIRES_PLUGIN_ANNOTATION)
method.declaringClass.allInterfaces.each { ClassNode iface ->
MethodNode interfaceMethod = iface.getMethod(method.name, method.parameters)
if (interfaceMethod) {
annotations.addAll(interfaceMethod.getAnnotations(REQUIRES_PLUGIN_ANNOTATION))
}
}

annotations.each { AnnotationNode annotationNode ->
findAnnotations(method).each { AnnotationNode annotationNode ->
VariableExpression jobManagementVariable = ASTTransformationHelper.getJobManagementVariable(
sourceUnit,
method.declaringClass,
Expand Down Expand Up @@ -70,4 +65,32 @@ class PluginASTTransformation implements ASTTransformation {
}
}
}

private static List<AnnotationNode> findAnnotations(MethodNode method) {
List<AnnotationNode> annotations = method.getAnnotations(REQUIRES_PLUGIN_ANNOTATION)
List<AnnotationNode> containerAnnotations = method.getAnnotations(REQUIRES_PLUGINS_ANNOTATION)
method.declaringClass.allInterfaces.each { ClassNode iface ->
MethodNode interfaceMethod = iface.getMethod(method.name, method.parameters)
if (interfaceMethod) {
annotations.addAll(interfaceMethod.getAnnotations(REQUIRES_PLUGIN_ANNOTATION))
containerAnnotations.addAll(interfaceMethod.getAnnotations(REQUIRES_PLUGINS_ANNOTATION))
}
}

containerAnnotations.each { AnnotationNode annotationNode ->
if (annotationNode.members.value instanceof ListExpression) {
ListExpression value = annotationNode.members.value as ListExpression
value.expressions.each { Expression expression ->
if (expression instanceof ConstantExpression) {
Object constantValue = expression.value
if (constantValue instanceof AnnotationNode) {
annotations << constantValue
}
}
}
}
}

annotations
}
}
@@ -0,0 +1,25 @@
package javaposse.jobdsl.dsl;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// this has to be written in Java because of https://jira.codehaus.org/browse/GROOVY-6019

/**
* Container annotation for declaring multiple {@link RequiresPlugin} annotations.
*
* @since 1.51
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequiresPlugins {
/**
* A list of {@link RequiresPlugin} annotations to indicate that more than one plugin must be installed to use the
* features provided by the annotated DSL method.
*/
RequiresPlugin[] value();
}
Expand Up @@ -4,6 +4,7 @@ import groovy.json.JsonBuilder
import javaposse.jobdsl.dsl.DslFactory
import javaposse.jobdsl.dsl.NoDoc
import javaposse.jobdsl.dsl.RequiresPlugin
import javaposse.jobdsl.dsl.RequiresPlugins
import org.codehaus.groovy.groovydoc.GroovyAnnotationRef
import org.codehaus.groovy.groovydoc.GroovyClassDoc
import org.codehaus.groovy.groovydoc.GroovyMethodDoc
Expand Down Expand Up @@ -177,12 +178,17 @@ class ApiDocGenerator {
map.availableSince = availableSince.trim()
}

List plugins = []
RequiresPlugin requiresPluginAnnotation = method.getAnnotation(RequiresPlugin)
if (requiresPluginAnnotation) {
map.plugin = [id: requiresPluginAnnotation.id()]
if (requiresPluginAnnotation.minimumVersion()) {
map.plugin.minimumVersion = requiresPluginAnnotation.minimumVersion()
}
plugins << createPlugin(requiresPluginAnnotation)
}
RequiresPlugins requiresPluginsAnnotation = method.getAnnotation(RequiresPlugins)
if (requiresPluginsAnnotation) {
requiresPluginsAnnotation.value().each { plugins << createPlugin(it) }
}
if (plugins) {
map.plugins = plugins
}

GroovyMethodDoc methodDocWithComment = getMethodHierarchy(method, methodDoc).find {
Expand Down Expand Up @@ -276,4 +282,12 @@ class ApiDocGenerator {
}
name
}

private static Map createPlugin(RequiresPlugin requiresPluginAnnotation) {
Map plugin = [id: requiresPluginAnnotation.id()]
if (requiresPluginAnnotation.minimumVersion()) {
plugin.minimumVersion = requiresPluginAnnotation.minimumVersion()
}
plugin
}
}

0 comments on commit b7d9b80

Please sign in to comment.