Данное
руководство содержит пошаговые инструкции
для установки системы непрерывной
разработки Jenkins. Развёртывание системы
происходило на виртуальной машине под
управлением Proxmox. Этапы
настройки Proxmox и создания
виртуальной машины опущены.
Установка
и настройка операционной системы.
1.2. По
умолчанию на свежей системе поднят
только loopback интерфейс, поэтому при
необходимости конфигурируем путём
изменения файла
/etc/sysconfig/network-scpipts/ifcfg-eth0 (установить
параметр ONBOOT=”yes”)
и запускаем скриптом ifup-eth0.
1.3. Устанавливаем
Midnight Commander, просто так, на всякий случай:
yum install mc,
При необходимости устанавливаем sshd:
yum install openssh-server
(вообще-то по дефолту ssh server уже должен
быть установлен).
1.4. Устанавливаем
hostname (в файле /etc/sysconfig/network),
меняем пароль рута, поскольку через
Java-апплет управления,
предоставляемый PROXMOX,
как-то было неудобно эти параметры
сразу нормально выставить.
Затем
смотрим ip-адрес ifconfig
и конннектимся через SSH: ssh
root@192.168.10.235
На
этом этапе я забекапил виртуалку:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_09-18_06_01.tar.gz
Установка
и настройка Mercurial.
2.1. Посмотрим,
что у нас есть в репозиториях:
[root@jenkins-edi
~]# yum search mercurial
...
mercurial.i686
: A fast, lightweight distributed source control management system
...
[root@jenkins-edi
~]# yum info mercurial.i686
...
Version
: 1.4
Release
: 3.el6
Size
: 1.5 M
[root@jenkins-edi
~]# rpm -Uvh
http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.i686.rpm
...
Далее
нам нужно включить репозиторий
rpmforge-extra. Это осуществляется правкой
конфигурационного файла
/etc/yum.repos.d/rpmforge.repo.
Нужная строка выделена жирным.
[rpmforge-extras]
...
enabled = 1
...
Проверяем
версию доступного для установки
Mercurial:
[root@jenkins-edi
yum.repos.d]# yum info mercurial.i686
...
Version
: 2.2.2
Release
: 1.el6.rfx
Size
: 2.8 M
Repo
: rpmforge-extras
...
Теперь версия
свежая. Вот её
и установим.
[root@jenkins-edi
yum.repos.d]# yum install mercurial.i686
Тут я решил создать ещё один бекап:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_10-12_14_44.tar.gz'
2.2. Теперь
необходимо настроить ssh-доступ к
репозиторию. Создаём нового пользователя и директорию для нашего будущего
репозитория:
[root@jenkins-edi
yum.repos.d]# adduser hg
[root@jenkins-edi
yum.repos.d]# passwd hg
[root@jenkins-edi
/]# su hg
[hg@jenkins-edi
/]$ mkdir /home/hg/repo
[hg@jenkins-edi
/]$ cd /home/hg
[hg@jenkins-edi
~]$ chmod 700 repo/
[hg@jenkins-edi
~]$ ll
итого
4
drwx------.
2 hg hg 4096 Окт 10 13:54 repo
Подготавливаем
клиента. У меня это будет виртуальная
машина с Windows XP. С официального сайта
http://mercurial.selenic.com/
скачан дистрибутив Mercurial и установлен
с указанием прописать в path путь до
исполняемых модулей приложения.
Помимо этого
установим Eclipse c JDK для создания тестового
проекта, который мы будем размещать на
наш сервер-репозитарий.
Для успешной
работы Mercurial необходимо указать имя
пользователя, которое будет фигурировать
в каждом коммите. В нашем случае оно
указывается в конфигурационном файле:
C:\Program
Files\Mercurial\Mercurial.ini
Там
мы в разделе [ui]
прописываем следующее:
username = Dmirty
Myasnikov <d****v@***.ru>
Также для
успешного доступа к удалённому репозиторию
через ssh нам необходимо указать
используемый ssh-клиент под Windows. Я для
этих целей установил TortoiseHG и в том же
разделе конфигурационного файла
Mercurial прописал (раскомментировал):
ssh =
"C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
Первый
тестовый проект разместим в каком-нибудь
каталоге. Запустим командную строку
Windows и перейдём в этот каталог. Затем
будем выполнять команды для работы с
репозиторием:
C:\Documents
and Settings\Admin>cd c:\java\projects
C:\java\projects>cd
HelloMercurials
C:\java\projects\HelloMercurial>hg
init
C:\java\projects\HelloMercurial>hg
add
adding
.classpath
adding
.project
adding
.settings\org.eclipse.jdt.core.prefs
adding
bin\ru\ediweb\ci\MyMain.class
adding
bin\test\TestMyMain.class
adding
src\ru\ediweb\ci\MyMain.java
adding
src\test\TestMyMain.java
C:\java\projects\HelloMercurial>hg
commit -m "First version of project"
А теперь
склонируем репозиторий на удалённый
сервер (параметр -v указываем для вывода
дополнительной информации):
C:\java\projects\HelloMercurial>hg
clone . ssh://hg@192.168.10.235/repo/HelloMercurial -v
running
"C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
hg@192.168.10.235 "hg init repo/HelloMercurial"
running
"C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
hg@192.168.10.235 "hg -R repo/HelloMercurial serve --stdio"
searching
for changes
1
changesets found
remote:
adding changesets
remote:
adding manifests
remote:
adding file changes
remote:
added 1 changesets with 7 changes to 7 files
Получилось!
Попробуем что-нибудь изменить в проекте.
К примеру я создал новый класс. Выполним
следующие команды, чтобы добавить новые
файлы, просмотреть изменения по сравнению
с исходным проектом и закоммитить эти
изменения:
C:\java\projects\HelloMercurial>hg
add
adding
bin\ru\ediweb\ci\SimpleClass.class
adding
src\ru\ediweb\ci\SimpleClass.java
C:\java\projects\HelloMercurial>hg
diff
diff
-r 8e52463bc091 bin/ru/ediweb/ci/SimpleClass.class
Binary
file bin/ru/ediweb/ci/SimpleClass.class has changed
diff
-r 8e52463bc091 src/ru/ediweb/ci/SimpleClass.java
---
/dev/null Thu Jan 01 00:00:00 1970 +0000
+++
b/src/ru/ediweb/ci/SimpleClass.java Wed Oct 10 16:38:29 2012 +0400
@@
-0,0 +1,14 @@
+package
ru.ediweb.ci;
+
+public
class SimpleClass {
+
private String name;
+
+
public String getName() {
+
return name;
+
}
+
+
public void setName(String name) {
+
this.name = name;
+
}
+
+}
C:\java\projects\HelloMercurial>hg
commit -m "Adding new class"
Проталкиваем
изменения на сервер:
C:\java\projects\HelloMercurial>hg
push ssh://hg@192.168.10.235/repo/HelloMercurial -v
pushing
to ssh://hg@192.168.10.235/repo/HelloMercurial
running
"C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
hg@192.168.10.235 "hg -R repo/HelloMercurial serve --stdio"
searching
for changes
1
changesets found
remote:
adding changesets
remote:
adding manifests
remote:
adding file changes
remote:
added 1 changesets with 2 changes to 2 files
Теперь
у нас есть свой Mercurial сервер с доступом
к репозиторию по SSH. По идее перед тем
как устанавливать Jenkins было бы неплохо
на этом сервере развернуть какую-нибудь
систему сборки проектов и автоматизированного
тестирования, которые брали бы проект
из репозитория Mercurial, собирали и
тестировали бы его. Мой тестовый проект
написан на Java, поэтому для экспериментов
я поставлю Ant и JUnit. Помимо них нам ещё
понадобится JDK для сборки.
В
случае работы с PHP-проектами нам нужно
будет дополнительно поднять веб сервер
с PHP-движком, систему сборки Phing и,
очевидно, какой-нибудь PHPUnit.
Вообще,
можно поступить хитрее и попробовать
настроить некоторые вещи через Jenkins.
Однако мы всё сделаем руками, чтобы
знать, что, где и зачем. Настройка Jenkins
в плане привязки установленного
программного обеспечения рассмотрена
в п. 4.2.
Перед
тем как идти дальше, забекапим-ка нашу
виртуальную машину:
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_10-16_57_06.tar.gz'
3.1. Cкачиваем
JDK c сайта
Oracle и копируем его на
наш хост:
На
сервере:
[root@jenkins-edi
~]# mkdir install
На
клиенте:
Z:\home\install\win\putty>pscp
"c:\Documents and Settings\Admin\Мои
документы\Downloads\jdk-7u7-linux-i586.rpm"
root@192.168.10.235:/root/install/
root@192.168.10.235's
password:
jdk-7u7-linux-i586.rpm
| 123515 kB | 4117.2 kB/s | ETA: 00:00:00 | 100%
На
сервере:
[root@jenkins-edi
~]# cd install
[root@jenkins-edi
install]# rpm -i jdk-7u7-linux-i586.rpm
Проверяем,
установилась ли Java:
[root@jenkins-edi
install]# java -version
java
version "1.7.0_07"
Java(TM)
SE Runtime Environment (build 1.7.0_07-b10)
Java
HotSpot(TM) Client VM (build 23.3-b01, mixed mode, sharing
3.2. Устанавливаем
Ant. Предварительно
устанавливаем wget.
[root@jenkins-edi
~]# yum install wget
…
[root@jenkins-edi
install]# wget
http://www.apache.org/dist/ant/binaries/apache-ant-1.8.4-bin.tar.bz2
/root/install
[root@jenkins-edi
install]# tar xvf apache-ant-1.8.4-bin.tar.bz2
…
[root@jenkins-edi
install]# mv apache-ant-1.8.4 /opt
[root@jenkins-edi
install]# export JAVA_HOME=/usr/java/jdk1.7.0_07/
[root@jenkins-edi
install]# export ANT_HOME=/opt/apache-ant-1.8.4/
[root@jenkins-edi
install]# export PATH=$PATH:$ANT_HOME/bin
Последние
три строки нужно бы добавить в
~/.bash_profile
соответствующего пользователя, чтобы
переменные окружения автоматически
инициализировались при перезагрузке.
Я работаю под рутом, поэтому в
/root/.bash_profile
добавил следующие строки:
JAVA_HOME=/usr/java/jdk1.7.0_07
export JAVA_HOME
ANT_HOME=/opt/apache-ant-1.8.4/
export
ANT_HOME
PATH=$PATH:$ANT_HOME/bin:$JAVA_HOME/bin
export PATH
Проверяем,
работает ли наш Ant.
[root@jenkins-edi
install]# ant
Buildfile:
build.xml does not exist!
Build
failed
Ant
работает. Теперь поколдуем над нашим
тестовым проектом.
3.3. Скачаем
JUnit на клиент, создадим
Ant-скрипт, проверим работу
всего этого на сервере.
На
клиенте скачанный JUnit
будет расположен в папке C:\Java
в виде файла junit-4.10.jar. Попробуем для
начала натравить JUnit на
наш проект:
C:\java\projects\HelloMercurial>java
-cp c:\java\junit-4.10.jar;.\bin\ junit.textui.TestRunner
test.TestMyMain
..
Time:
0,016
OK
(2 tests)
В
сам проект добавим каталог /lib,
куда поместим junit-4.10.jar
(хотя это неправильно, но мы оставим
так в тестовых целях, чтобы не править
потом build.xml
на сервере) и создадим buildfile
для Ant следующего содержания:
<?xml
version="1.0" encoding="UTF-8"?>
<project
name="HelloMercurial"
default="compile"
basedir=".">
<path
id="JUnit.classpath">
<pathelement
location="./lib/junit-4.10.jar"/>
</path>
<path
id="HelloMercurial.classpath">
<pathelement
location="bin"/>
</path>
<target
name
="compile"
description="Compile
project">
<javac
srcdir="src" destdir="bin"/>
</target>
<target
name
="test"
description="Test
project">
<junit
printsummary="yes">
<classpath
refid="JUnit.classpath"
/>
<classpath
refid="HelloMercurial.classpath"
/>
<test
name="test.TestMyMain"/>
</junit>
</target>
</project>
Весь
это проект протолкнём в наш репозиторий:
C:\java\projects\HelloMercurial>hg
add
adding
build.xml
adding
lib\junit-4.10.jar
C:\java\projects\HelloMercurial>hg
commit -m "Tests, Ant build"
C:\java\projects\HelloMercurial>hg
push ssh://hg@192.168.10.235/repo/HelloMercurial -v
pushing to
ssh://hg@192.168.10.235/repo/HelloMercurial
running
"C:\Progra~1\TortoiseHg\TortoisePlink.exe" -ssh -2
hg@192.168.10.235 "hg
-R
repo/HelloMercurial serve --stdio"
searching
for changes
1
changesets found
remote:
adding changesets
remote:
adding manifests
remote:
adding file changes
remote:
added 1 changesets with 5 changes to 5 files
теперь
на сервере сделаем следующее:
[root@jenkins-edi
/]# cd /home/hg/repo/
[root@jenkins-edi
repo]# hg clone HelloMercurial /root/HelloMercurial
обновляемся
на ветку default
11
файлов обновлено, 0 слито, 0 удалено, 0 c
конфликтами
[root@jenkins-edi
repo]# cd /root/HelloMercurial/
[root@jenkins-edi
HelloMercurial]# ant test
Buildfile:
/root/HelloMercurial/build.xml
test:
[junit] Running
test.TestMyMain
[junit] Tests run:
2, Failures: 0, Errors: 0, Time elapsed: 0,002 sec
BUILD
SUCCESSFUL
Total
time: 0 seconds
И
тут мы опять бекапимся!
/var/lib/vz/backups//dump/vzdump-qemu-501-2012_10_11-17_21_58.tar.gz
Отлично.
Теперь на сервере у нас работают и
Mercurial, и Ant
и JUnit. Не совсем канонично
настроенные, но вполне ок такие.
Приступаем к установке Jenkins.
4.1. Добавляем
нужные репозитории:
[root@jenkins-edi
HelloMercurial]# wget -O /etc/yum.repos.d/jenkins.repo
http://pkg.jenkins-ci.org/redhat/jenkins.repo
--2012-10-11
14:21:58-- http://pkg.jenkins-ci.org/redhat/jenkins.repo
Распознаётся
pkg.jenkins-ci.org... 63.246.20.93
Устанавливается
соединение с pkg.jenkins-ci.org|63.246.20.93|:80...
соединение установлено.
Запрос
HTTP послан, ожидается ответ... 200
OK
Длина:
75 [text/plain]
Saving
to: «/etc/yum.repos.d/jenkins.repo»
100%[======================================>]
75 --.-K/s в 0s
2012-10-11
14:21:59 (11,4 MB/s) - «/etc/yum.repos.d/jenkins.repo» saved
[75/75]
[root@jenkins-edi
HelloMercurial]# rpm --import
http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
Устанавливаем
Jenkins:
[root@jenkins-edi
HelloMercurial]# yum install jenkins
Открываем
порт 8080 в
IPTABLES
[root@jenkins-edi
~]# iptables -I INPUT 2 -p tcp -i eth0 --dport 8080 -j ACCEPT
[root@jenkins-edi
~]# iptables -A OUTPUT -p tcp --sport 8080 -j ACCEPT
[root@jenkins-edi
~]# /etc/init.d/iptables save
Запускаем
Jenkins
[root@jenkins-edi
~]# /etc/init.d/jenkins start
Starting
Jenkins [ OK ]
4.2. Теперь
мы можем обратиться к порту 8080 нашего
хоста по http. Там мы должны
увидеть веб-интерфейс Jenkins:
Рис.
1. Веб-интерфейс Jenkins.
Нажимаем на
кнопку Manage Jenkins.
На следующей странице нажимаем на Manage
Plugins. Воспользовавшись
поиском, поставим плагин Mercurial:
Рис.
2. Mercurial plugin.
Теперь
нажимаем Manage Jenkins –
Configure System. Указываем там параметры
установленного на сервере JDK:
Рис.
3. Параметры JDK.
Параметры
установленного Mercurial:
Рис.
4. Параметры Mercurial.
Параметры
установленного Ant:
Рис.
5. Параметры Ant.
Нажмём кнопку
Save, чтобы сохранить
сделанные изменения и приступим к
созданию нашего первого задания. Для
этого нажмём на кнопку New
Job и зададим имя заданию.
Рис. 6.
Создание нового задания.
Настроим
ежеминутную сборку нашего проекта,
чтобы не пришлось долго ждать результата:
Рис. 7.
Настройка проекта и планировщика сборки.
Далее на той
же странице в разделе Build
жмём кнопку Add build
step и выбираем пункт Invoke
Ant. Добавим два таких шага:
Рис. 8.
Настройка сборки.
Сборка должна
завершиться ошибкой. Ещё бы, ведь при
доступе к репозиторию по SSH
необходимо вводить пароль. Исправим
это. Настроим
SSH-авторизацию по RSA-ключу:
[root@jenkins-edi
/]# sudo -u jenkins ssh-keygen
Generating
public/private rsa key pair.
Enter file in which
to save the key (/var/lib/jenkins/.ssh/id_rsa):
Enter passphrase
(empty for no passphrase):
Enter same
passphrase again:
Your identification
has been saved in /var/lib/jenkins/.ssh/id_rsa.
Your public key has
been saved in /var/lib/jenkins/.ssh/id_rsa.pub.
The key fingerprint
is:
dd:78:a9:26:19:26:a8:ae:48:0f:04:29:80:9c:22:d1
jenkins@jenkins-edi
The key's randomart
image is:
+--[ RSA 2048]----+
|=o. |
|=+E |
|* |
|o . . o . |
| . . . S o + |
|. . o o o |
| o. o o |
|o.o o |
|o... |
+-----------------+
[root@jenkins-edi
/]# cat /var/lib/jenkins/.ssh/id_rsa.pub >>
/home/hg/.ssh/authorized_keys
Добавим
на хосте сами себя в список известных
хостов:
[root@jenkins-edi
bin]# sudo -u jenkins /usr/bin/ssh hg@192.168.10.235
The
authenticity of host '192.168.10.235 (192.168.10.235)' can't be
established.
RSA
key fingerprint is f1:ff:dc:32:fe:42:50:84:74:7c:78:85:14:2d:df:5b.
Are
you sure you want to continue connecting (yes/no)? yes
Warning:
Permanently added '192.168.10.235' (RSA) to the list of known hosts.
В некоторых
рекомендациях по конфигурированию
Jenkins говорится следующее:
По умолчанию
при выполнении задания у пользователя
jenkins не определена
переменная окружения HOME,
поэтому он не знает, где ему искать
параметры подключения к SSH-серверу.
Поэтому необходимо в свойствах задания
указать дополнительный параметр в
разделе This build
is parametrized.
У меня
всё работает и без указания дополнительных
параметров, однако на всякий случай я
приведу скриншоты этих настроек. Думаю,
они будут актуальны при хранении
ssh-ключей в месте, отличном
от JENKINS_HOME.
Рис. 9. Добавление
строкового параметра.
Рис. 10. Необходимый параметр
Переходим
на главную страницу и видим, что проект
успешно собран:
Рис. 11.
Первый успех.
Посмотрим,
что у нас в потоке вывода. Подведём
курсор мыши к нужному месту и выберем
Console Output:
Рис. 12.
Просмотр вывода сборщика проекта.
Вот
что там у нас:
Started
by timer
Building
in workspace /var/lib/jenkins/jobs/MyFirstJob/workspace
[workspace]
$ /usr/bin/hg showconfig paths.default
[workspace]
$ /usr/bin/hg pull --rev default
[workspace]
$ /usr/bin/hg update --clean --rev default
0
файлов обновлено, 0 слито, 0 удалено, 0 c
конфликтами
[workspace]
$ /usr/bin/hg log --rev . --template {node}
[workspace]
$ /usr/bin/hg log --rev . --template {rev}
[workspace]
$ /usr/bin/hg log --rev 67d89a607a40570bdd1a2b50c4cbd3eeac8fc9ac
[workspace]
$ /usr/bin/hg log --template "<changeset node='{node}'
author='{author|xmlescape}' rev='{rev}'
date='{date}'><msg>{desc|xmlescape}</msg><added>{file_adds|stringify|xmlescape}</added><deleted>{file_dels|stringify|xmlescape}</deleted><files>{files|stringify|xmlescape}</files><parents>{parents}</parents></changeset>\n"
--rev default:0 --follow --prune
67d89a607a40570bdd1a2b50c4cbd3eeac8fc9ac
[workspace]
$ /opt/apache-ant-1.8.4/bin/ant test
Buildfile:
/var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml
[junit] Running
test.TestMyMain
[junit] Tests run:
2, Failures: 0, Errors: 0, Time elapsed: 0,002 sec
BUILD
SUCCESSFUL
Total
time: 0 seconds
[workspace]
$ /opt/apache-ant-1.8.4/bin/ant
Buildfile:
/var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml
[javac]
/var/lib/jenkins/jobs/MyFirstJob/workspace/build.xml:13: warning:
'includeantruntime' was not set, defaulting to
build.sysclasspath=last; set to false for repeatable builds
BUILD
SUCCESSFUL
Total
time: 0 seconds
Finished:
SUCCESS
Тест
и компиляция, заданные в соответствующем
ant-скрипте проходят, как
этого и следовало ожидать. С первичной
настройкой сервера покончено.
Ссылки:
CentOS:
Официальный
сайт Mercurial:
Графический
клиент Mercurial под Windows:
Настройка
сервера для работы с Mercurial:
Ant:
JUnit:
Jenkins: