Thursday, 21 April 2011

Supporting both Hudson & Jenkins - Part 5: Improving the situation

I have a number of Hudson/Jenkins issues in order to make improve the dual support situation. I have listed them below for those who wish to follow track them.

Hudson
hudson-plugin-info macro assumes subversion when it can't find github
hudson-plugin-info assumes issues being managed in hudson jira (created this one before seeing the duplicate)
Allow specifying an alternative issue tracking URL in plugin information  (this one already existed)
Update centre json should take information from pom not wiki


Jenkins
jenkins-plugin-info macro assumes subversion when it can't find github
Allow specifying an alternative issue tracking URL in plugin information (this one already existed)
Update centre json should take information from pom not wiki

There is properly going to be more later, but these are the things that are most visible to the end users.

Monday, 18 April 2011

Supporting both Hudson & Jenkins - Part 4: Post release work

After you have done the release there is a couple of tasks left in order for everything to work cleanly.

Create a stub page on the Hudson wiki.
Go here and create a child page
- Make sure to add the hudson-plugin-info and excerpt macro.
- Add labels to the page for correct groupin
- Add a reference to where the plugin is hosted.

You can take a look at Project Health Report Plugin as an example

Create a stub page on the Jenkins wiki
Go here and create a child page. You should follow the same convention as on the Hudson wiki, except that the project info macro is now called jenkins-plugin-info. An example is here.

Announce the plug-in
Announce the plug-in on the hudson and jenkins developer list. Be sure to mention it is hosted elsewhere because both projects need to adjust their update centre script.

This is because their scripts try to match the wiki url from the pom with their respective wikis in order to provide a link and description in the update centre. When it can't find the wiki page, the information will be blank.


Supporting both Hudson & Jenkins - Part 3: The Release process

The release process is actually fairly simple even though it is not a one click process. I normally does the Hudson release first because then I can validate things in the nexus staging repository.

My development environment is set up so that I have my SCM (bitbucket) credentials, and the repository credentials, such that I do not need to provide them in the process.

Step Zero: Prerequisites
Make sure that everything you have is committed and you have performed a "mvn clean release:clean"

Step One: Running release prepare
Simply run "mvn release:prepare". I usually run it in interactive mode and answers the version questions, but you can add parameters to run it in batch mode.

Step Two: Save the release.properties file
Now you actually need to run release:perform twice once per profile, but Maven cleans up the directory after the first release perform. Therefore you must provide extra parameters to the second release:perform.

You will need to look at the documentation on which parameters to specify, maybe you can get lucky and only specify "tag". I however use another short cut, the release.properties that release:prepare generated contains all the needed information, so I save this by making a copy outside the project directory

Step Tree: Do the Hudson release
Now that you have taken note of the needed properties or simply saved the release.properties file, run "mvn release:perform -Phudson-publish"
Now the plug-in should be in the nexus OSS staging repository. Verify and release it as described here

Step Four: Do the Jenkins release
Now copy the release.properties back into the project directory and run "mvn release:perform -Pjenkins-publish"

Sunday, 10 April 2011

Supporting both Hudson & Jenkins - Part 2: Settings.xml and the pom.xml

Overview:
The main strategy for supporting both Hudson and Jenkins is to make the main pom structure neutral and then use two profiles to handle the version specifics. These profile which I have called hudson-publish and jenkins-publish is both represented in the settings.xml and the pom.xml.

pom.xml:
In order to create a pom that works for both sides, I have done the following things.
  • Specified the parent version as 1.392. This is the latest pre-fork parent which do not suffer from the bug which prevents publishing of "requiresCoreVersion". Full specification is org.jvnet.hudson.plugins:plugin:1.392
  • The groupId of the plug-in must be org.jvnet.hudson.plugins otherwise the publishing to maven central wont work.
  • The basic items like name, description and url must be set. The Hudson update centre uses the URL and description.
  • Remember to add license and developer information.
  • Remember to override scm and issueManagment section.
  • Don't specify distributionManagment outside the profiles.
  • Configure the release plugin to only make deploy not site-deploy and use forked-path which is needed by the gpg plug-in.
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.1</version>
  <configuration>
    <mavenExecutorId>forked-path</mavenExecutorId>
    <goals>deploy</goals>
  </configuration>
</plugin>

settings.xml:
There are some things that need to go into the settings.xml which are not profile specific. This is the list of server definitions, which you must add in order to provide username/passwords. I have server definitions for the following list
  • sonatype-nexus-snapshots
  • sonatype-nexus-staging
  • maven.jenkins-ci.org

jenkins-publish profile:
In the settings.xml you need to specify the Jenkins maven repository
<repository>
  <id>maven.jenkins-ci.org</id>
  <name>Jenkins Repository</name>
  <layout>default</layout>
  <url>http://maven.jenkins-ci.org:8081/content/repositories/releases/</url>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>

In the pom.xml specify the distributionManagment as:
<distributionManagement>
  <repository>
    <id>maven.jenkins-ci.org</id>
    <url>http://maven.jenkins-ci.org:8081/content/repositories/releases/</url>
  </repository>
</distributionManagement>

hudson-publish profile:
In the settings.xml you need to specify the Hudson maven repositories and your gpg passphrase.
<repositories>
  <repository>
    <id>sonatype-nexus-staging</id>
    <name>Nexus Release Repository</name>
    <layout>default</layout>
    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
  <repository>
    <id>sonatype-nexus-snapshots</id>
    <name>Sonatype Nexus Snapshots</name>
    <layout>default</layout>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <releases>
      <enabled>false</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
    </snapshots>
  </repository>
</repositories>
<properties>
  <gpg.passphrase>REPLACE_WITH_YOUR_OWNPASSPHRASE</gpg.passphrase>
</properties>

In the pom file, you need to specify both distributionManagment and configure the gpg plugin
<distributionManagement>
  <snapshotRepository>
    <id>sonatype-nexus-snapshots</id>
    <name>Sonatype Nexus Snapshots</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
  </snapshotRepository>
  <repository>
    <id>sonatype-nexus-staging</id>
    <name>Nexus Release Repository</name>
    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
  </repository>
</distributionManagement> 
<build>
  <plugins>             
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-gpg-plugin</artifactId>
      <executions>
        <execution>
          <id>sign-artifacts</id>
          <phase>verify</phase>
          <goals>
            <goal>sign</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Full pom examle
You can look here for an example of a complete pom file

Sunday, 3 April 2011

Supporting both Hudson & Jenkins - Part 1: Getting access

When I write Hudson and Jenkins plug-ins , I want to support both of them and remain as neutral to the fork as possible.  In order to do this I have chosen to host my plug-ins in a neutral place (bitbucket), but I still want my plug-in to show up in both update centres. This series of blog entries is my attempt at documenting how that it done, and this part is about which accounts you need.

My plugin:
My plugin is hosted at bitbucket.org, I use it both for source code, wiki and issues. In effect I am not relying on Hudson or Jenkins infrastructure except for publishing to their update centres.

Jenkins:
In order to publish to Jenkins you only need one account. This account is used to access the jenkins Wiki, Jira, Fisheye and publish to their Maven repository. You create it here: https://jenkins-ci.org/account

Hudson:
Hudson is a bit more complicated as they use Maven Central repository for hosting their plug-ins,  so you will need both access to Hudson and to push to maven push to Maven central.
- First you need access to the Hudson wiki.
- Secondly you will need to have PGP key in order to sign your plug-in. I used Gnomes built in feature but the hudson pages have a guide as well.
- You need an account  with Nexus OSS in order to use their staging facility and publish to Maven central repository. Create the account according to this page, and make sure to create the Jira ticket. YOu need the later part in order to get the hudson-deployer role.

References:
Jenkins Account page
Jenkins Releasing
Hudson Wiki
Releasing Hudson Plugin
Sonatype OSS Maven Repository Usage Guide
How To Generate PGP Signatures With Maven