06 February 2017

Cloudbees Enterprise Jenkins Timezone When Machine is UTC

I did this on a Linux Red Hat Enterprise 7 machine. The problem I was having had to do with the default time zone on Linux was UTC. When I would do "time" from a command line, it would show UTC time. In my case, it was 6 hours later than the time on my phone.

Jenkins uses time in several ways and you have to make more than one change to make all of them use the correct time zone.
Note that there doesn't seem to be a way to have Jenkins figure out where the user sitting in front of a browser viewing a Jenkins screen may be located. If the server is in one time zone and the user is in another time zone, I'm hoping to have the time displayed equal the server's time zone.
Here are the places I found to check whether Jenkins is doing the time zone the way I want:
  1. Go into a build job and look in the lower left margin. The time of the builds is shown there. It should be the time zone you want.
  2. Go to a pipeline build job and look at the time displayed beside the flow diagrams for the builds. Again, this should be your desired time zone.
  3. Go to the CJOC > Manage Jenkins > System Logs > All Jenkins Logs and notice the time of the last logged event. It should be in the desired time zone. If your server has been idle for a while, it might not contain a recent log message. Take this into account.
  4. Repeat the same thing for the Client Masters. Each of them should display correct times in the log messages.
  5. Go to any build job that runs at a particular time of day. On the Configure screen, there is an item for build periodically > schedule that shows one or more "cron" type strings. The 2nd column is for the hour. The message below the schedule box should show the correct time zones for the times the job was and will be run.
    • A cron string "0 1 * * *" will run at 1 am every day. Check that's what it says below the schedule box.
    • A cron string "H H(9-17) * * *" will run every day once per hour between 9 AM and 6 PM. The H means Jenkins gets to pick the minute value randomly.
    • A cron string "@midnight" will run every night between midnight and 6 am.
  1. Similarly, the times the jobs run (after they run and the time of running is in the left margin at the bottom on the build job page) should be correct in the desired time zone. You may also be able to check the time of build by looking at the dates on built artifacts--stuff like build log files and jar files and such.

1st Change

Create a file, $JENKINS_HOME/init.groovy.d/my-timezone.groovy (which Jenkins will run upon startup). Do this on the CJOC (Operations Center) machine and on any Client Masters.
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'America/Chicago')
Note that you will use one of the Java timezone strings. I'm in the Central time zone of the United States. (See http://stackoverflow.com/questions/1694885/timezones-in-java)

This makes it so that Jenkins will use the defined time zone when it is formatting certain strings to contain the time of day of some event (like a log message or a build time). It sort of depends on which bit of code is doing the formatting.

2nd Change

Then you need to add a startup string to the sysconfig file for jenkins. (How do you find it? Cloudbees has help but its very confusing. https://support.cloudbees.com/hc/en-us/articles/209715698-How-to-add-Java-arguments-to-Jenkins ) Mine was in /etc/sysconfig/jenkins (or jenkins-oc)
-Duser.timezone=America/Chicago
Note that this one has to be set when Java is first starting the JVM. As the Jenkins application come up, it reads the current time zone and stores it. If we were to use the Groovy method (as above) to set this Java system property, Jenkins would have already set the default time zone for all scheduled jobs and they would all use the default time zone NOT the time zone set in a Groovy init script.

3rd Change (optional)

Though I'm not sure if it matters, I also added this to Configure > Launch Method > JVM Options on my SSH slave. It depends on which kind of slaves you have if you want to find where to put that. And I don't know how to do it with a non-SSH slave or a Windows slave.

    -Duser.timezone=America/Chicago

Finally

Restart all the Jenkins and that's it.

More Stuff

The above will get jobs building on the correct hourly schedule(s). But perhaps you have one job that needs to run on a different schedule. Perhaps a long test run that needs to occur in the middle of the Indian night when the team in India is home sleeping.

You can put the following in for the schedule using two lines:
TZ=Asia/Kolkata
H H(0-1) * * *
Which will run the build job sometime between midnight an 1 AM using India's standard time zone.

Be careful that this long running build does not interfere with the work of people in other time zones. Midnight in India is 1:30 PM here (during the US Winder).

14 December 2016

Jenkins Pipeline Shared Groovy Script by Hand

There is currently a new version of the Pipeline Shared Groovy Libraries Plugin (2.5) that adds capabilities to put some Groovy scripts in Git, at least, and to make them available easily to call from Jenkinsfile (the Jenkins Pipeline script, also stored with the application code in Git)

I can't move to that version yet and so I set it up to load the script by hand:

def notify

stage "Load-Scripts"
node() {
    git branch: 'master', changelog: false, credentialsId: 'ID', poll: false, url: 'https://github.company.com/my-organization/my-repository.git'
    notify = load 'src/com/aa/jenkins/pipeline/notify.groovy'

    notify.notifySlack("START")
}
The above code goes in the Jenkinsfile at the top, before any other  stages. You will, of course have to put in your own  credentials and branch and so forth, the Pipeline Snippets tool might be handy in doing that line.

Some things ...

The variable into which we store the class created by loading the one groovy file has to be defined with the 'def' and without a type. This makes it into a global variable that can be used outside the scope in which we do the load.

The path to the groovy file is in the context of the root of the git workspace.

You may need a node name inside the parentheses.

07 November 2013

New to Git. Used to SVN.

Some random thoughts about moving to "git" from "SVN":

In git, when they talk about branches and draw those little diagrams with circles and lines to show branching, it is incredibly complex because git encourages branching.

When you do a commit on your local copy of the repo, it creates a new thing that is called a branch according to the way git thinks.

They draw pictures like this:

Each circle is what happens when there is a git commit and is called a branch. 

In SVN its just a sequence of commits and they tend to be called versions or revisions. In SVN they have numbers (in sequence) but the branches are named with their own sequence of numbers.

In git, they also talk about the contents of a branch which seems to mean all the changes that comprise the branch.

30 November 2012

Context in Javascript regex replace with anonymous function

I know. The title is a killer. I'm only putting this post here since I couldn't find this information anywhere.


First, lets talk about the 'replace' function on Javascript strings. Here's an example with a search for a string.


var name= "World";
var msg = "Hello name!";
var result = msg.replace("name", name);

This results in:

Hello World!


Now, you can use a regular expression (and, in fact, probably should) in place of the string. The yellow highlight shows what you change to make it a regular expression. (I'm not going to define regular expressions. I'm trying to get to my real concern in this particularly wordy way.)

var name= "World";
var msg = "Hello name!";
var result = msg.replace(/name/, name);

This results in the same thing:

Hello World!


Of course, we can use the regular expression to search for something more complicated. In this case, it will find one or more vowels between the 'n' and the 'm' in 'name' and match the whole word.

var name= "World";
var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/, name);

This results in the same thing three times even though the starting strings contained different vowels. Oh, no, it doesn't. It only replaces the first occurrence:

Hello World! Hello nime! Hello nouiame!


We get the result we want if we add the 'g' option to the regular expression.

var name= "World";
var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/g, name);

This results in the same thing three times even though the starting strings contained different vowels and it really works:

Hello World! >Hello World! Hello World!


Finally, getting close to what this blog entry is about. It concerns you when you have a block of Javascript like this. You are replacing multiple instances of some matched regular expression using a function to generate the replacement string. In this case we will reverse the original string and include that in the replacement.


var msg = "Hello name! Hello nime! Hello nouiame!";
var result = msg.replace(/n[aeiou]+me/g, function(matched) {
    return "World (" + matched.split("").reverse().join("") + ")";
});

This results in the same thing three times even though the starting strings contained different vowels. Oh, no, it doesn't. It only replaces the first occurrence:

Hello World (eman)! Hello World (emin)! Hello World (emaiuon)!


Finally, what I want to comment on. Again we will reverse the original string and include that in the replacement. But lets put it in a function and get the "World" from a variable that is in the same context.

{
    worldString : "World",
    myFunction: function() {
        var msg = "Hello name! Hello nime! Hello nouiame!";
        var result = msg.replace(/n[aeiou]+me/g, function(matched) {
            return this.worldString + " (" + matched.split("").reverse().join("") + ")";
        });
        return result;
    }
}

This should result in the same thing (You know, three times.) But it actually fails because the context of the function called by "replace" is the main 'window' object. Here is what Chrome (Version 23.0.1271.64 m), IE 9 and FireFox (16.0.2) shows:

Hello undefined (eman)! Hello undefined (emin)! Hello undefined (emaiuon)!

Here is a jsfiddle showing this fail and the success


So, what works? We do put it in a function still and we get the "World" from a variable that is in the same context. But we have to save the context in "myFunction" and use it in the anonymous function:

{
    worldString : "World",
    myFunction: function() {
        var self = this;
        var msg = "Hello name! Hello nime! Hello nouiame!";
        var result = msg.replace(/n[aeiou]+me/g, function(matched) {
            return self.worldString + " (" + matched.split("").reverse().join("") + ")";
        });
        return result;
    }
}

This does result in the three times we expected last time:

Hello World (eman)! Hello World (emin)! Hello World (emaiuon)!

Here is the same jsfiddle showing the fail and this success




25 March 2011

Maven Checkstyle Reports Shortcut

I'm using Maven 2.2.1 today. MyEclipse version is 8.5.

When you want a Checkstyle report from Maven 2 you need to put these two bits of xml in your pom.xml. Then you need to create the Checkstyle.xml and license.txt files.

Be sure to check what the right version is of the plugin. Its shown at the bottom of the page: maven-checkstyle-plugin You might have to back off one version.

<build>
    <pluginManagement>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>2.6</version>
            </plugin>
            ...
         </plugins>
    </pluginManagement>
</build>

and then put the report request in. (Be sure to put it after the JXR report if you are using that one. There is some report that needs to be after JXR and it might be Checkstyle. I can't remember for sure but we all have our little superstitions.)

<reporting>
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <configuration>
                <enableRulesSummary>false</enableRulesSummary>
                <configLocation>${basedir}/Checkstyle.xml</configLocation>
                <headerLocation>${basedir}/license.txt</headerLocation>
                <excludes>**/generated-sources/**/*.java</excludes>
            </configuration>
        </plugin>
        ...
     </plugins>
</reporting>

You may (or may not) want the "enableRulesSummary" option off. I find it obnoxious to have all that page space taken up by the long explanations.

The "license.txt" file is the easiest. You only need it if you are going to have a rule that checks for a certain header at the top of each .java file. You can change the name but be sure to use the real name when setting up the Checkstyle rules that you want to use.

Now, for the rules file -- Checkstyle.xml. There is an easy way to create this file. Much easier than typing a bunch of cryptic XML into an editor. We just let the Eclipse do it.

You have to have the Eclipse Checkstyle plugin installed. I've done it multiple times with multiple versions of Eclipse and multiple versions of the Checkstyle plugin. Once you have that plugin installed, use the Eclipse preferences menu item to bring up the preferences box. Find the Checkstyle entry in the left section of the box and click it.

This will bring up the Checkstyle preference. Create a Checkstyle configuration of your own. Or you can use the built-in Sun configuration as a start and fool around until it tells you enough but not too much. That's always the problem with code analysis tools. When you first run them on some code, they complain about all sorts of things that you just don't care about.

Maybe your code has curly-braces in the "wrong" place and you don't really care. Change the rule settings to ignore placement of the curly-braces. So, click about 1000 times and get all the Checkstyle rules set up as you like.
On a side note: I have found that using the Checkstyle Eclipse plugin together with the Eclipse Code Formatter you can sort of play the tools off against each other for code format issues.
Most groups of developers have some sort of code-format conventions. Whatever it is, most everyone dislikes some aspect of it. But if you supply them all with a code formatting template created to be used in Eclipse and exported to a file, they can use it just before submitting code.
They can type however they want. They can even format it to their own preferences while working on it (for the fussy programmer). Just fix it before putting the code away. Then use Checkstyle to see if they are doing it. You can make a build fail if the format is wrong but I find that obnoxious. Just create a report somewhere that the managers or team leads can look at and complain now and again. In real life, most everyone just gets used to it unless they are working on multiple sets of code with different rules.
Anyway, put the formatting rules in your Eclipse and format a large body of code. Do that by right clicking on a source folder and finding "reformat" on one of the nested menus. Then let Checkstyle, also inside Eclipse, check it.and see what the errors are. You will probably end up changing both configurations until you get it right.
Whatever the rules, when you have them "right," you can just export the rules with the button on the Checkstyle preferences page. Store them, if you want to use my pom XML as shown above, in the same folder that the pom.xml file is in and name that export file "Checkstyle.xml" matching the letter case. (Windows doesn't care but you'll thank me for that suggestion if you ever build under Linux.)

The trick is that the "export" stores the file in exactly the format that Checkstyle's Maven 2 plugin wants (or even the same format that Checkstyle's ANT task wants). I keep Checkstyle.xml with the project code, store it in my version control and now and then make a few changes.

The thing is, as time goes by you either get tired of seeing some of Checkstyles complaints that you thought you cared about. Or you decided to ratchet it up a notch and add some more checks because the code is better than it used to be or because the team is getting into some bad habits that you'd like to nip in the bud.

For example, I worked with a team once and a couple of guys couldn't find it in themselves to put a debug logging statement in the code they were working on. They had to put a "System.out.println()" call in there and, of course, they would forget to remove them all. We added a custom regex rule to Checkstyle that said "System.out" and "printStackTrace(" were illegal to use in the code. We had to live with a few complaints here and there where we really wanted to output to the console. One was a little utility that just lived in the code but ran from the command line. The other was where everything went horribly wrong during startup and we needed a message but the logger wasn't set up yet. So we found all the funky debug lines and had the offenders (who we identified from the checkin records) remove them or change them to use the logger.

Once you save the export file, you run "mvn clean site" to generate the report.

If you have a site deployment location set up in the pom.xml you can then do "mvn site:deploy". Note that I have found you shouldn't do these three targets all together. Do the clean-site first and then do the site:deploy. It just works better that way.

04 November 2010

GWT StockWatcher and MyEclipse

I did the Google Web Toolkit tutorial creating the StockWatcher application. I don't know if there are more tutorials that build on this but the one at THIS PLACE creates an application in Eclipse and shows you how to compile it to a bunch of html, css, js and such files. The logic in this example all ends up in the javascript that is generated from the java the tutorial helps you create (or lets you copy and paste). [Note that you can do the tutorial without Eclipse but this article has "MyEclipse" in the title.]

I used MyEclipse version 8.6. I downloaded their Pulse tool sometime back and used it to build myself a new profile that included MyEclipse 8.6 (based on Eclipse 3.5 - Helios). Subclipse, Checkstyle and the Google Plugin for Eclipse. If you already have one of the 8.x series MyEclipses installed, you can probably use the included Pulse-like facility to create the new "profile". (For those unfamiliar with MyEclipse, a "profile" in Pulse is a collection including one version of Eclipse or MyEclipse and zero or more plugins. When you get it loaded on your computer, its simple another instance of Eclipse that can be run alongside any other Eclipse versions you have on your machine.) Also, you don't need Subclipse or Checkstyle installed to do the tutorial or what I describe below. I just always include them in my profiles.

You could probably do all this with a pure Eclipse version with the Google Plugin for Eclipse installed. But you would have to run Tomcat separately and build and deploy the war as described below. The feature of running Tomcat inside Eclipse and doing easy deployments is a MyEclipse feature. (But there may be other plugins that can do this independently but similarly.)

Sidebar: Note that to add the Google plugin to my Pulse profile, I could not simply select the Google plugin like I did with all the other plugins. I found a note on the web somewhere that explained how to do it. Find the information on the plugin by Googling for GWT. This will tell you the Eclipse update location that matches the version of Eclipse you are using. I found it at http://code.google.com/eclipse/docs/getting_started.html where it shows that the update location for Galileo is http://dl.google.com/eclipse/plugin/3.5 and chose, within Pulse, to "add an update site" which is a tiny link just to the right of a title near the top of the page. Enter the update location and save. A new entry appears allowing you to select the "Google Plugin for Eclipse" under that new entry. And there you go.

So, using my brand new MyEclipse 8.6 installation, I proceeded to open it up and select a location for the workspace.

Next I went through the whole tutorial to create the StockWatcher "application" and compile it.

When it compiles, it goes into a folder off the root of your Eclipse project that is named "war." That folder gets filled with all the results of the compilation and can be run, if you have deployed it in development mode you can run the compiled version by removing the query part of the URL used to access the app for debugging and development. In my case that URL was http://127.0.0.1:8888/Stockwatcher.html?gwt.codesvr=127.0.0.1:9997 and, removing the query part is http://127.0.0.1:8888/Stockwatcher.html.

But I wanted to run it in the Tomcat that is supplied with MyEclipse. Here's how to do that:

1) Since I had a whole new MyEclipse installation, I had to configure the Tomcat. You do this by going to the MyEclipse property page at Window > Preferences > MyEclipse > Servers > Integrated Sandbox > Tomcat. I only changed the port it runs on to 8090 so it wouldn't interfere with Google's development "server" (really an instance of Jetty included somewhere). Save all that.

2) Configure the project to deploy correctly. First, right click on the project itself and choose MyEclipse > Add Web Project Capabilities. Set the web root to the "war" folder that holds all the compiled artifacts for StockWatcher. Save this setting. When you do, it will complain about the folder to which Eclipse is set to store the compiled java class files. Click "Yes" you would like to change that folder to be inside the "war" folder you just selected.

3) You need to change the "deployment" options for the web application. So, reopen a similar dialog box to the one in step 2 above, by going to the project properties for your project and opening the web entry under MyEclipse. (Select the project. From the menu bar do Project > Properties > MyEclipse > Web)

4) Open the "deployment" tab (the rightmost one) and DON'T use the default settings for Web Project Deployment Policies. Instead, click the "ignore" option to "do it yourself", which means you will do nothing. Also, DON'T use the Library Deployment Policies default setting. Instead, unclick everything there. (Note that you may need to select some of those options judiciously if you are deploying a different web app that uses back-end, server based code requiring some 3rd party jars. Remember that StockWatcher, at this point, only has JavaScript and no back-end code at all.) Save all that.

5) There are two ways to add a deployment for Tomcat and your StockWatcher project. You can approach it from either the project deployments direction or the Tomcat deployments direction. I like the latter. So click the tiny arrow beside the icon for "run/start/remove MyEclipse deployments" that looks like a little desktop/tower computer box. (Funny how people have taken to calling those the "hard disk.") The options drop down and you click "Manage Deployments". When the box opens, select "Tomcat" in the top drop-down box labeled "Server" and then click the "add" button at the right. Select your project from the drop down list. You may want to choose exploded war or not. Then save it. (The other way starts by right-clicking on the server itself in the "Server" view ...)

6) You might see some lines from the Tomcat console display.

7) Go to your browser and open up "http://localhost:8090/stockwatcher/StockWatcher.html" or similar URL depending on what, exactly, you named things. If you don't know what to use for the html file name, look in the "war" folder in your project. It will be there. If you don't know the application context (which is the 1st part of the url after the port number), you approved it and maybe entered it on the project properties myeclipse web page on the left tab where it says "context root."

There you go. Now you have the StockWatcher application running on the Tomcat inside MyEclipse.

If you want to create a .war file that can be deployed on an independent Tomcat (or other JEE server) you can right click on the project name, select Export, choose the project again, browse to a folder and supply a .war file name and, finally, click "Finish". The .war file will get put where you choose and can be deployed however your server deploys apps. (For Tomcat, drop the war file into the "webapps" folder and that usually does it.)

Addendum: I followed through with the additional tutorial at http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html and found that these same steps work to deploy the StockWatch example with RPC back-end code included.

25 February 2010

Auto-Install Maven into Hudson

It turns out to be easy to have Hudson download a version of Maven for you to use in your builds.I Googled for instructions and found none but then any Google for anything about Hudson is likely to find the river, the explorer or Jennifer.

I'm using Hudson 1.336 as I write.

You may need to figure out how to set up a proxy if your Hudson server is inside your companies network boundaries. The following instructions assume you have already got that working. I find the whole proxy issue confusing as there is a way documented to enter a proxy when deploying to a repository and a way to enter a proxy that is sort of hidden when updating plugins. I haven't seen one related to downloading tools.

1) Click on the "Manage Hudson" link on the top page.
2) Click on the "Configure System" link at the top of the list in the main part of the page.
3) Scroll Down to the "Maven" section and click the "add Maven button" as in the red circle below
4) Select "Add Installer"
5) The drop down list of install from options has an option "tar.gz" you should select.
6) "Label" field is blank. I don't know quite what this does.
7) Enter a link to one of the apache mirrors like: "http://mirror.uoregon.edu/apache/maven/binaries/apache-maven-2.2.1-bin.tar.gz" but you can pick your own mirror by opening another browser tab and going to "http://maven.apache.org/download.html" and clicking on the link for the tar.gz file in the "mirrors" column. I picked the one at the top of the top section on that page but you may want a not-latest version. That takes you to the page where it allows picking a mirror. Copy one of the mirror links for the site close to you. The link above is the one I picked.
8) The subdirectory will be like "apache-maven-2.2.1" with the main folder name from the tar.gz file you pointed to. Note that older versions of Maven (for example 2.0.7) are like "maven-2.0.7" and newer ones add the word "apache" to the front. This subdirectory is added to the root folder of where-ever Hudson puts tools that it downloads to produce the MAVEN_HOME value Hudson passes to Maven for builds using this Maven version.
9) Save the configuration changes with the button at the very bottom of the page (or just hit 'enter').

At this point in the process, I was left wondering when it would get downloaded and installed.

10) Create or edit an M2 build to use the new Maven version you just added. When it first runs, the tool will be added to a "tools/maven" folder inside your hudson folder structure AND THEN the build will kick off. (This might work with some other type of build but I haven't tried it.)