XWiki's Continuous Build
General
XWiki has a Continuous Integration setup to ensure XWiki's code is built at all times (i.e at every code check in). This also allows developers to only build the module they want and they'll have the other XWiki module dependencies downloaded from the XWiki remote repository.
We use the following tools:
- GitHub is used as our SCM
- Maven is used for building XWiki
- Jenkins is used as our Continuous Integration (CI) tool (set up at http://ci.xwiki.org/)
We use a technique called binary dependency build which allows to check out only the module a developer wishes to work on and he'll automatically get the latest fresh binary dependencies built by our CI tool.
Maintainer's guide
Prerequisites
- You need to have an account on maven.xwiki.org (this is the machine hosting XWiki's remote repository) and you'll need a key setup on your account there so that you can ssh to it without having to enter username or password (See the XWPLT project in JIRA).
- You need to have an administrator account on ci.xwiki.org.
Functional tests
General
- If your project includes functional tests don't check "Run Xvnc during build" in the project configuration, we have a XVNC server always running on the machine and jenkins is aware of it (DISPLAY :1.0).
Debugging
Connect to the XVNC server
- Establish a SSH tunnel between your computer and the server on port 5901 (ssh -L 5901:localhost:5901 [email protected])
- Use your favorite VNC client to connect to the XVNC server
- Host : localhost
- Display : 1
- Password : same password as for XWiki SAS wifi access points
- See the functional tests live.
Wysiwyg functional tests
GWT seems to have an unusual way to manage input events, our WYSIWYG editor needs its container window to have a _real_ focus (Windowing System level) to catch them (at least on Linux and OSX). Wysiwyg functional tests execute a small C program, the compiled program must be available at /home/maven/xwindowfocus on the continuous build server.
Source : main.c
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int XWindowFocus(Display *display, char *window_name)
{
Window root;
Window query_root, query_parent;
Window *children_windows;
char *win_name;
unsigned int children_nb;
int match, i;
root = DefaultRootWindow(display);
// Retrieve all windows
XQueryTree(display, root, &query_root, &query_parent, &children_windows, &children_nb);
// Loop over windows
for (i = 0, match = 1; i < children_nb; i++)
{
XFetchName(display, children_windows[i], &win_name);
// Match window name
if (!strcmp(win_name, window_name))
{
// Set X focus on the matching window
XSetInputFocus(display, children_windows[i], RevertToNone, CurrentTime);
printf("Focus set on window \"%s\"\n", win_name);
match = 0;
}
XFree(win_name);
}
XFree(children_windows);
return match;
}
int main(int ac, char **av)
{
Display *display = XOpenDisplay(NULL);
int ret;
// Check arguments
if (ac < 2)
{
fprintf(stderr, "Usage : xwindowfocus <window_name>\n");
exit(1);
}
// Verify DISPLAY
if (display == NULL)
{
fprintf(stderr, "Error : failed to open DISPLAY\n");
exit(1);
}
ret = XWindowFocus(display, av[1]);
if (ret == 1)
{
fprintf(stderr, "Error : failed to find window\n");
}
exit(ret);
}
Jenkins jamming up
Occasionally (especially under high load) Jenkins will have an SCM polling thread jam up due to JENKINS-5413. This will prevent any further builds but it can be remedied by running the following script on the master's script console.
Thread.getAllStackTraces().keySet().each(){ item ->
if( item.getName().contains("SCM polling") &&
item.getName().contains("waiting for hudson.remoting")){
println("THREAD: " + item);
item.interrupt();
i++
}
}
println("count = " + i);