Skip to content

Commit

Permalink
[FIXED JENKINS-51264] Add a snapshotPluginVersionOverride configurati…
Browse files Browse the repository at this point in the history
…on option to hpi and hpl goals
  • Loading branch information
stephenc committed May 11, 2018
1 parent b868233 commit 8ee9605
Show file tree
Hide file tree
Showing 11 changed files with 436 additions and 29 deletions.
20 changes: 20 additions & 0 deletions src/it/snapshot-version-override/invoker.properties
@@ -0,0 +1,20 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

invoker.goals=clean verify
69 changes: 69 additions & 0 deletions src/it/snapshot-version-override/pom.xml
@@ -0,0 +1,69 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.424</version>
</parent>

<groupId>org.jenkins-ci.tools.hpi.its</groupId>
<artifactId>snapshot-version-override</artifactId>
<version>1.x-SNAPSHOT</version>

<packaging>hpi</packaging>

<name>MyNewPlugin</name>

<scm>
<connection>scm:git:git://github.com/jenkinsci/maven-hpi-plugin.git</connection>
<developerConnection>scm:git:ssh://git@github.com/jenkinsci/maven-hpi-plugin.git</developerConnection>
<url>https://github.com/jenkinsci/maven-hpi-plugin</url>
<tag>HEAD</tag>
</scm>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
</plugin>
<plugin>
<groupId>org.kohsuke</groupId>
<artifactId>access-modifier-checker</artifactId>
<version>1.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.github.stephenc.continuous</groupId>
<artifactId>git-timestamp-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>timestamp</goal>
</goals>
</execution>
</executions>
<configuration>
<versionProperty>actual-version</versionProperty>
<versionFile>target/version.txt</versionFile>
</configuration>
</plugin>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<configuration>
<snapshotPluginVersionOverride>${actual-version}</snapshotPluginVersionOverride>
</configuration>
</plugin>
</plugins>
</build>

</project>
@@ -0,0 +1,139 @@
package org.jenkinsci.tools.hpi.its;
import hudson.Launcher;
import hudson.Extension;
import hudson.util.FormValidation;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.AbstractProject;
import hudson.tasks.Builder;
import hudson.tasks.BuildStepDescriptor;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.QueryParameter;

import javax.servlet.ServletException;
import java.io.IOException;

/**
* Sample {@link Builder}.
*
* <p>
* When the user configures the project and enables this builder,
* {@link org.jenkins.HelloWorldBuilder.DescriptorImpl#newInstance(StaplerRequest)} is invoked
* and a new {@link org.jenkins.HelloWorldBuilder} is created. The created
* instance is persisted to the project configuration XML by using
* XStream, so this allows you to use instance fields (like {@link #name})
* to remember the configuration.
*
* <p>
* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} method
* will be invoked.
*
* @author Kohsuke Kawaguchi
*/
public class HelloWorldBuilder extends Builder {

private final String name;

// Fields in config.jelly must match the parameter names in the "DataBoundConstructor"
@DataBoundConstructor
public HelloWorldBuilder(String name) {
this.name = name;
}

/**
* We'll use this from the {@code config.jelly}.
*/
public String getName() {
return name;
}

@Override
public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
// this is where you 'build' the project
// since this is a dummy, we just say 'hello world' and call that a build

// this also shows how you can consult the global configuration of the builder
if(getDescriptor().useFrench())
listener.getLogger().println("Bonjour, "+name+"!");
else
listener.getLogger().println("Hello, "+name+"!");
return true;
}

// overrided for better type safety.
// if your plugin doesn't really define any property on Descriptor,
// you don't have to do this.
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}

/**
* Descriptor for {@link org.jenkins.HelloWorldBuilder}. Used as a singleton.
* The class is marked as public so that it can be accessed from views.
*
* <p>
* See {@code views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly}
* for the actual HTML fragment for the configuration screen.
*/
@Extension // this marker indicates Hudson that this is an implementation of an extension point.
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
/**
* To persist global configuration information,
* simply store it in a field and call save().
*
* <p>
* If you don't want fields to be persisted, use {@code transient}.
*/
private boolean useFrench;

/**
* Performs on-the-fly validation of the form field 'name'.
*
* @param value
* This parameter receives the value that the user has typed.
* @return
* Indicates the outcome of the validation. This is sent to the browser.
*/
public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException {
if(value.length()==0)
return FormValidation.error("Please set a name");
if(value.length()<4)
return FormValidation.warning("Isn't the name too short?");
return FormValidation.ok();
}

public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// indicates that this builder can be used with all kinds of project types
return true;
}

/**
* This human readable name is used in the configuration screen.
*/
public String getDisplayName() {
return "Say hello world";
}

@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
// To persist global configuration information,
// set that to properties and call save().
useFrench = formData.getBoolean("useFrench");
// ^Can also use req.bindJSON(this, formData);
// (easier when there are many fields; need set* methods for this, like setUseFrench)
save();
return super.configure(req,formData);
}

/**
* This method returns true if the global configuration says we should speak French.
*/
public boolean useFrench() {
return useFrench;
}
}
}

@@ -0,0 +1,9 @@
<!--
This view is used to render the plugin list page.
Since we don't really have anything dynamic here, let's just use static HTML.
-->
<?jelly escape-by-default='true'?>
<div>
This plugin is a sample plugin to explain how to write a Jenkins plugin.
</div>
@@ -0,0 +1,16 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<!--
This jelly script is used for per-project configuration.
See global.jelly for a general discussion about jelly script.
-->

<!--
Creates a text field that shows the value of the "name" property.
When submitted, it will be passed to the corresponding constructor parameter.
-->
<f:entry title="Name" field="name">
<f:textbox />
</f:entry>
</j:jelly>
@@ -0,0 +1,33 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<!--
This Jelly script is used to produce the global configuration option.
Hudson uses a set of tag libraries to provide uniformity in forms.
To determine where this tag is defined, first check the namespace URI,
and then look under $HUDSON/views/. For example, <f:section> is defined
in $HUDSON/views/lib/form/section.jelly.
It's also often useful to just check other similar scripts to see what
tags they use. Views are always organized according to its owner class,
so it should be straightforward to find them.
-->
<f:section title="Hello World Builder">
<!--
optional @help points to the help document HTML. /plugin/compile-its
is mapped to our webapp/ directory, so this is a convenient way to serve
static resources.
-->
<f:entry title="French"
description="Check if we should say hello in French"
help="/plugin/compile-its/help-globalConfig.html">
<!--
we'll have on input field. In HTML, single "namespace" is shared between
all form components in one <form>, so we need to choose a name that doesn't
collide with other plugins. The 'descriptor' variable represents our descriptor
object, so we use that to determine the initial value for this form.
-->
<f:checkbox name="hello_world.useFrench" checked="${descriptor.useFrench()}" />
</f:entry>
</f:section>
</j:jelly>
@@ -0,0 +1,5 @@
<div>
Help file for fields are discovered through a file name convention. This file is an line help for
the "name" field. You can have <i>arbitrary</i> HTML here. You can write this file as a Jelly script
if you need a dynamic content (but if you do so, change the extension to .jelly)
</div>
@@ -0,0 +1,2 @@
it.msg=It rocks

@@ -0,0 +1,8 @@
<div>
<p>
This HTML fragment will be injected into the configuration screen
when the user clicks the 'help' icon. See global.jelly for how the
form decides which page to load.
You can have any HTML fragment here.
</p>
</div>
51 changes: 51 additions & 0 deletions src/it/snapshot-version-override/verify.groovy
@@ -0,0 +1,51 @@
import java.util.jar.JarFile

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

assert new File(basedir, 'target/version.txt').exists();
assert new File(basedir, 'target/classes').exists();
assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its').exists();
assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.class').exists();
assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder$DescriptorImpl.class').exists();
assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/HelloWorldBuilder.stapler').exists();
assert new File(basedir, 'target/classes/org/jenkinsci/tools/hpi/its/Messages.class').exists();
assert new File(basedir, 'target/snapshot-version-override.hpi').exists();
assert new File(basedir, 'target/snapshot-version-override.jar').exists();

assert new File(basedir, 'target/generated-sources/localizer/org/jenkinsci/tools/hpi/its/Messages.java').exists();

def content = new File(basedir, 'target/generated-sources/localizer/org/jenkinsci/tools/hpi/its/Messages.java').text;
assert content.contains(" holder.format(\"it.msg\");");

def expectVersion = new File(basedir, 'target/version.txt').text.trim();

assert !expectVersion.isEmpty() : "contents of target/version.txt, '${expectVersion}' is not empty string";
assert !"1.x-SNAPSHOT".equals(expectVersion) : "contents of target/version.txt, '${expectVersion}' is not 1.x-SNAPSHOT";

def actualVersion
JarFile jf = new JarFile(new File(basedir, 'target/snapshot-version-override.hpi'));
try {
actualVersion = jf.getManifest().getMainAttributes().getValue("Plugin-Version").replaceFirst(' [(].+[)]$', "");
} finally {
jf.close();
}
assert expectVersion.equals(actualVersion) : "Manifest Plugin-Version entry: '${actualVersion}' == '${expectVersion}'";

return true;

0 comments on commit 8ee9605

Please sign in to comment.