вторник, 18 октября 2011 г.
Создание pull request-а для GitHub из командной стркоки
curl -i -u "your-name:your-passwd" https://api.github.com/repos/his-name/his-repo/pulls -d '{"title": "Title of pull request", "body": "Body of pull request", "head":"your-repo:your-branch", "base":"his-branch"}'
пятница, 30 сентября 2011 г.
Установка и настройка сервера непрерывной интеграции phpUnderControl
Описание
Сервер непрерывной интеграции (CI - Continuous Integration) предназначен для автоматической периодической сборки проектов, запуска модульных тестов, проверки кода на наличие распространенных ошибок и формирования ряда других отчетов. В качестве CI-сервера будет использоваться CruiseСontrol (CC) с дополнением phpUnderControl. CС запускается в качестве демона, периодически опрашивает SVN-репозиторий и, в случае наличия изменений, создает локальную копию, над которой в дальнейшем производится ряд определенных действий. Для выполнения этих действий в нужной последовательности используется утилита Ant (также поддерживается работа с его php-клоном phing), которая поставляется в комплекте с CC.
Дополнение phpUnderControl предоставляет консольную утилиту phpuc которая дополняет CC рядом шаблонов, а также позволяет быстро добавлять/удалять проекты в CC. В phpUnderControl встроена поддержка проверки синтаксиса php-кода, а также следующих утилит:
- phpunit
- автоматизированное тестирование приложения
- phpdoc
- PhpDocumentor - автоматическая генерация документации
- phpcb
- PHP_CodeBrowser - просмотр кода онлайн (включая подсветку и описание проблемных мест, таких как: нарушение стандартов кодирования, дублирование кода, высокая сложность кода)
- phpcs
- PHP_CodeSniffer - обнаружение нарушений стандартов кодирования
- ezcGraph
- простроение графиков изменения контролируемых параметров с течением времени
Кроме того есть возможность добавить поддержку других утилит, таких как:
- phpmd
- анализ сложности исходного кода
- phpcpd
- поиск дублирующегося кода
Скриншоты
Главная страница: список проектов, ручной запуск сборок:

Страница с результатами выполнения тестов phpunit:

Страница метрик, изменение контролируемых параметров от сборки к сборке:

Страница, отображающая покрытие кода тестами:

Онлайн-просмотр кода с подсветкой и описанием проблемных участков (оформление, сложность, дублирование и пр.):

Онлайн документация:

Страница отчета о нарушениях стандартов кодирования:

Страница отчета сложности кода, дублирования кода и других проблем:

Просмотр продублированного кода:

Установка CruiseСontrol
Для работы сервера CC нужна java-машина, устанавливаем, если еще не установлена:
sudo apt-get install sun-java6-bin
Затем следует скачать архив с последней версией CC с сайта http://cruisecontrol.sourceforge.net/download.html (на момент написания последней была версия 2.8.4) и распаковать в локальный каталог (в данном примере /opt):
sudo unzip cruisecontrol-bin-2.8.4.zip -d /opt
Для удобства обновлений программы можно создать символическую ссылку cruisecontrol, которая будет указывать на используемую версию данного ПО:
cd /opt
sudo ln -s cruisecontrol-bin-2.8.4 cruisecontrol
Теперь, когда CC-сервер установлен, можно настроить его автоматический запуск при старте системы. Для этого следует добавить нового пользователя, от имени которого будет запускаться процесс CC, разместить стартовый скрипт cruisecontrol (приложение А) в каталоге /etc/init.d/ (для debian-подобных систем), установить необходимые для его запуска права и, собственно, настроить автозапуск:
sudo adduser --system --group --home /opt/cruisecontrol cruisecontrol
sudo chown -R cruisecontrol:cruisecontrol /opt/cruisecontrol-bin-2.8.4 /opt/cruisecontrol
sudo cp cruisecontrol /etc/init.d/cruisecontrol
sudo chmod 755 /etc/init.d/cruisecontrol
sudo update-rc.d cruisecontrol defaults
Теперь вручную сервер CC можно запустить командой
sudo /etc/init.d/cruisecontrol start
Остановить:
sudo /etc/init.d/cruisecontrol stop
Для отладочных целей запуск сервера CC можно выполнить командой (из каталога /opt/cruisecontrol/):
sudo ./cruisecontrol.sh -configfile /opt/cruisecontrol/config.xml -webport 8080 -jmxport 8082 -rmiport
После успешного запуска CC-сервера должен быть доступен адрес http://localhost:8080.
Возможна проблема при запуске CC сервера, когда в файл /opt/cruisecontrol/cruisecontrol.sh из стартового скрипта не передается переменная окружения JAVA_HOME. Одним из вариантов решения данной проблемы может быть запись строки JAVA_HOME=/usr/lib/jvm/java-6-sun в общесистемный файл /etc/environment. Также, в качестве временного решения, можно указать значение этой переменной непосредственно в файле /opt/cruisecontrol/cruisecontrol.sh. Однако при использовании в стартовом скрипте команды su cruisecontrol -p -c ... этой проблемы возникать не должно.
Установка phpUnderControl и необходимых модулей
Прежде чем переходить к установке phpuc следует проверить наличие требуемых модулей, и установить/обновить недостающие (может потребоваться обновление xdebug и pear installer):
sudo apt-get install php5-xdebug
sudo pear install PhpDocumentor
sudo pear install PHP_CodeSniffer
sudo pecl install pecl/xdebug
pear channel-discover pear.phpunit.de
pear install phpunit/PHPUnit
sudo pear install phpunit/phpcpd
sudo pear upgrade pear
sudo pear install phpunit/PHP_CodeBrowser
Далее можно перейти к установке phpuc (на момент написания использовалась версия 0.6.1beta1):
sudo pear channel-discover components.ez.no
sudo pear channel-discover pear.phpundercontrol.org
sudo pear install --alldeps phpuc/phpUnderControl-beta
А также установить дополнительные модули, поддержка которых в phpUnderControl на данный момент реализована лишь частично (требуется ручная правка конфигов):
sudo pear channel-discover pear.phpmd.org
sudo pear channel-discover pear.pdepend.org
sudo pear install --alldeps phpmd/PHP_PMD
sudo pear install --alldeps phpunit/PHPCPD
phpuc представляет собой консольную утилиту для взаимодействия с установленной версией CC. Следующая команда скопирует набор дополнительных файлов и шаблонов для веб-интерфейса в каталоги с установленной копией CC:
sudo phpuc install /opt/cruisecontrol
Добавление проектов
Утилита phpuc также предоставляет команды для быстрого добавления проектов под управление ci-сервера (следующая команда - это одна строка, отформатированная для удобства чтения):
sudo phpuc project
--ant-script /opt/cruisecontrol/apache-ant-1.7.0/bin/ant
--version-control svn
--version-control-url file://localhost/home/user/svn/myProjectName/trunk
--coding-guideline Zend
--source-dir application
--test-dir tests
--project-name myProjectName
/opt/cruisecontrol
В результате работы данной команды
- в каталоге projects CC-сервера будут созданы подкаталоги для указанного проекта
- в конфигурационный файл СС будет добавлена новая секция <project/> (см. приложение Б). Стоит отметить что нода <shedule/> отвечает за выполнение запланированных для проекта действий (в данном примере каждые 300 сек. будет запускаться указанный ant-скрипт)
- в каталоге проекта будет создан файл build.xml (см. приложение В), содержащий ряд заданий для последующих регулярных сборок проекта
- выполнена команда svn checkout
Для удаления проекта следует использовать команду
sudo phpuc delete myProjectName
Настройка проектов
На данном этапе мы должны получить готовую автоматическую систему сборки и тестирования проектов, однако она может нуждаться в дополнительных доработках. В частности для цели lint (файл build.xml проекта) можно исключить из списка проверяемых путей некоторые каталоги (например каталог с дистрибутивом Zend) - это уменьшит время сборки:
<target name="lint">
<apply executable="php" dir="${basedir}/source" failonerror="on" logerror="on">
<arg line="-l"/>
<fileset dir="${basedir}/source">
<include name="**/*.php"/>
<exclude name="library/Zend/**/*.php"/>
</fileset>
</apply>
</target>
Для публикации отчетов о проблемах кода (phpmd) следует добавить новую цель:
...
<target name="phpmd">
<exec executable="phpmd" dir="${basedir}/source">
<arg line="application
xml
codesize,unusedcode,naming
--reportfile ${basedir}/build/logs/phpmd.xml"/>
</exec>
</target>
...
А также не забыть указать её в зависимостях цели сборки по умолчанию:
<target name="build" depends="checkout,lint,php-documentor,php-codesniffer,phpunit,phpcpd,phpmd,pdepend"/>
Для публикации отчетов о дублировании кода (phpcpd) нужно также добавить вручную новую цель в файл build.xml:
...
<target name="phpcpd" >
<exec executable="phpcpd" failonerror="false">
<arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml
${basedir}/source/application" />
</exec>
</target>
...
А также не забыть указать её в зависимостях цели сборки по умолчанию:
<target name="build" depends="checkout,lint,php-documentor,php-codesniffer,phpunit,phpcpd,phpmd,pdepend"/>
Для построении графиков внутренних зависимостей кода (pdepend) нужно добавить следующую цель в build.xml:
...
<target name="pdepend" depends="lint">
<exec executable="pdepend" dir="${basedir}/source" logerror="on">
<arg line="--summary-xml=${basedir}/build/logs/pdepend.xml
--jdepend-chart=${basedir}/build/graph/jdepend.svg
--overview-pyramid=${basedir}/build/graph/overview-pyramid.svg
--coderank-mode=inheritance,property,method
application" />
</exec>
</target>
...
А также не забыть указать её в зависимостях цели сборки по умолчанию:
<target name="build" depends="checkout,lint,php-documentor,php-codesniffer,phpunit,phpcpd,phpmd,pdepend"/>
Кроме того, для публикации этих графиков на странице метрик, следует добавить в ноду <publishers/> соответствующего проекта в файле config.xml следующую строку:
<publishers>
...
<artifactspublisher subdirectory="graph" dest="artifacts/${project.name}" dir="projects/${project.name}/build/graph"/>
...
</publishers>
Можно добавить и другие цели, которые могут потребоваться для сборки проекта, например создание необходимых каталогов, установка прав на файлы и каталоги, подготовка БД, выполнение других скриптов, минимизация css, js и др.
Наконец, есть возможность рассылать уведомления об удачных и неудачных сборках на email, jabber и др. Ниже пример для рассылки e-mail уведомлений:
<publishers>
...
<email mailhost="localhost"
returnaddress="cruisecontrol@my.marketgid.net"
buildresultsurl="http://localhost:8080/cruisecontrol/buildresults/mgtest"
skipusers="true" spamwhilebroken="true">
<map alias="management" address="root@localhost" />
<map alias="qa" address="user@localhost" />
<map alias="developer" address="user@my.marketgid.net" />
<always address="management" />
<success address="qa" />
<failure address="developer" reportWhenFixed="true" />
</email>
...
</publishers>
В данном случае определены 3 группы получателей; первая группа management получает уведомления о всех сборках, вторая группа qa только об удачных сборках, и третья группа developer о неудачных.
Примеры окончательного варианта файлов настроек config.xml и build.xml в приложении Г и приложении Д.
Ссылки
- http://habrahabr.ru/blogs/php/68571/
- на русском, есть неточности
- http://nohn.net/blog/view/id/cruisecontrol_ant_and_phpunit
- настройка phpunit+ant, рассылка email-ов
- http://www.phpunit.de/manual/3.2/en/continuous-integration.html
- пример cli для phpuc (создание проекта в сс)
- http://recursive-design.com/blog/2011/05/13/continuous-integration-for-php-with-php-under-control/
- подробное руководство
- http://techportal.ibuildings.com/2009/03/03/getting-started-with-phpundercontrol/
- неполный мануал и пример выполнения sql-кода в ant
- http://topecoders.blogspot.com/2010/05/how-to-configure-phpundercontrol.html
- пример cli phpuc для zend, добавление нового таба
- http://criticallog.thornet.net/2010/03/02/integrate-php_depend-with-phpundercontrol/
- настройка pdepend (+см. комментарии)
- http://zendframework.ru/articles/continuous-integration-and-cruisecontrol
- CC с учетом специфики zf
Приложение А - скрипт для автоматического запуска CC при загрузке ОС
Скрипт отличается от источника установленными значениями переменных, а также опцией команды su -p, что решает проблему передачи переменной окружения JAVA_HOME серверу CC. Стоить отметить что инициализацию переменных можно вынести в отдельный файл /etc/default/cruisecontrol. Значения, указанные в этом файле, будут иметь приоритет (имеет смысл воспользоваться этой возможностью, если принято решение собрать deb-пакет для установки сервера CC).
#!/bin/sh
#content of /opt/cruisecontrol/init script
# chkconfig: 345 99 05
# description: CruiseControl build loop (see /home/tools)
# CruiseControl Unix Startup Script Version 2.1
#
# based on http://confluence.public.thoughtworks.org/display/CC/UnixStartupScriptVersion1.x
# adapted for multiple projects
# also based on the file attached to the above page created by Jerome Lacoste
#
# CruiseControl startup: Startup and kill script for Cruise Control
#
###################################################################################################
# USER CONFIGURATION
#
# Fill in these values for your Cruise Control setup
# What user will Cruise Control run as? The user will need permission to write and modify files
# in the next entries.
CC_USER=cruisecontrol
# Where is the CC startup script located?
CC_INSTALL_DIR=/opt/cruisecontrol
# In what directory is the config.xml file located for CC?
# default: CC_WORK_DIR=$CC_INSTALL_DIR
CC_WORK_DIR=$CC_INSTALL_DIR
# Where will the cruisecontrol.log file be located?
# default: CC_LOGFILE_DIR=$CC_INSTALL_DIR
CC_LOGFILE_DIR=$CC_INSTALL_DIR
#######################
# ENVIRONMENT ADDITIONS
# Add environement variables here that are needed by your build.
# example:
# export JAVA_HOME=/usr/local/java
#
# or like this for local variables ONLY used in this file:
# JAVA_HOME=/usr/local/java
JAVA_HOME=/usr/lib/jvm/java-6-sun
export JAVA_HOME
# Add path to additional executables needed for project build. See PATH entry below for base config.
# No additional action taken when blank.
PATH_ADDITIONS=
##############################
# CRUISE CONTROL PORT SETTINGS
# Port for Jetty reporting application. You can access it by going to http://localhost:8080
# default CC_WEBPORT=8080
CC_WEBPORT=8080
# JMX port for webapp and Java Management eXtensions (JMX). You can access it by going to http://localhost:8080
# Change only if this port is in use as the webapp will also need modification.
# default CC_JMXPORT=8082
CC_JMXPORT=8082
# RMI port for control via Java's Remote Management Interface (RMI)
# Leave blank to disable.
CC_RMIPORT=
###################################################################################################
# DO NOT MODIFY ENTRIES BELOW THIS LINE
NAME=cruisecontrol
DESC="CruiseControl - continuous integration build loop"
PATH=/sbin:/usr/sbin:/usr/bin:/bin
# add additions if variable has text defined
if [ -n "$PATH_ADDITIONS" ]; then
PATH=$PATH_ADDITIONS:$PATH
fi
export PATH
CC_DAEMON=$CC_INSTALL_DIR/cruisecontrol.sh
CC_CONFIG_FILE=$CC_WORK_DIR/config.xml
CC_LOG_FILE=$CC_LOGFILE_DIR/cruisecontrol.log
CC_COMMAND="$CC_DAEMON -configfile $CC_CONFIG_FILE -webport $CC_WEBPORT -jmxport $CC_JMXPORT -rmiport $CC_RMIPORT"
# overwrite settings from default file
if [ -f /etc/default/cruisecontrol ]; then
. /etc/default/cruisecontrol
fi
# does the executable exist?
test -f $CC_DAEMON || (echo "The executable $CC_DAEMON does not exist!" && exit 0)
if [ `id -u` -ne 0 ]; then
echo "Not starting/stopping $DESC, you are not root."
exit 4
fi
# Get the PID output from the startup script
if [ -f $CC_INSTALL_DIR/cc.pid ]; then
CC_PID=`cat $CC_INSTALL_DIR/cc.pid`
else
echo "No cc.pid file found. CC process may not be controllable from this script!"
fi
case "$1" in
'start')
cd $CC_INSTALL_DIR
# echo "CC environtment at startup" > cc.startup.env
# env >> cc.startup.env
su $CC_USER -p -c "/bin/sh -c \"$CC_COMMAND >> $CC_LOG_FILE 2>&1\"" & RETVAL=$?
echo "$NAME started with jmx on port ${CC_JMXPORT}"
;;
'stop')
if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
kill -9 ${CC_PID}
$0 status
RETVAL=$?
else
echo "$NAME is not running"
RETVAL=1
fi
;;
'status')
if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
echo $NAME \(pids $CC_PID\) is running
RETVAL=0
else
echo "$NAME is stopped"
RETVAL=1
fi
;;
'restart')
$0 stop && $0 start
RETVAL=$?
;;
*)
echo "Usage: $0 { start | stop | status | restart }"
exit 1
;;
esac
#echo ending $0 $$....
exit 0;
Приложение Б - project-секция config.xml для проекта myProjectName
<cruisecontrol>
...
<project name="myProjectName" buildafterfailed="false">
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<modificationset>
<svn localWorkingCopy="/opt/cruisecontrol/projects/myProjectName/source"/>
</modificationset>
<bootstrappers>
<svnbootstrapper localWorkingCopy="/opt/cruisecontrol/projects/myProjectName/source"/>
</bootstrappers>
<schedule interval="300">
<ant buildfile="projects/${project.name}/build.xml" antscript="/opt/cruisecontrol/apache-ant-1.7.0/bin/ant"/>
</schedule>
<log dir="logs/${project.name}">
<merge dir="projects/${project.name}/build/logs/"/>
</log>
<publishers>
<artifactspublisher dir="projects/${project.name}/build/api" dest="artifacts/${project.name}" subdirectory="api"/>
<artifactspublisher dir="projects/${project.name}/build/coverage" dest="artifacts/${project.name}" subdirectory="coverage"/>
<execute command="phpcb --log projects/${project.name}/build/logs --source projects/${project.name}/source/application --output projects/${project.name}/build/php-code-browser"/>
<artifactspublisher dir="projects/${project.name}/build/php-code-browser" dest="artifacts/${project.name}" subdirectory="php-code-browser"/>
<execute command="/usr/bin/phpuc graph logs/${project.name} artifacts/${project.name}"/>
</publishers>
</project>
...
</cruisecontrol>
Приложение В - сгенерированный конфигурационный файл build.xml для проекта myProjectName
<?xml version="1.0" encoding="UTF-8"?>
<project name="myProjectName" default="build" basedir=".">
<target name="build" depends="checkout,lint,php-documentor,php-codesniffer,phpunit"/>
<target name="checkout">
<exec executable="svn" dir="${basedir}/source" failonerror="on">
<arg line="up"/>
</exec>
</target>
<target name="lint">
<apply executable="php" dir="${basedir}/source" failonerror="on" logerror="on">
<arg line="-l"/>
<fileset dir="${basedir}/source">
<include name="**/*.php"/>
</fileset>
</apply>
</target>
<target name="php-documentor" depends="lint">
<exec executable="phpdoc" dir="${basedir}/source" logerror="on">
<arg line="--title '${ant.project.name}' -ue on -t ${basedir}/build/api -d application -tb '/usr/share/php/data/phpUnderControl/data/phpdoc' -o HTML:Phpuc:phpuc"/>
</exec>
</target>
<target name="php-codesniffer" depends="lint">
<exec executable="phpcs" dir="${basedir}/source" output="${basedir}/build/logs/checkstyle.xml" error="/tmp/checkstyle.error.log">
<arg line="--report=checkstyle --standard=Zend application"/>
</exec>
</target>
<target name="phpunit" depends="lint">
<exec executable="phpunit" dir="${basedir}/source" failonerror="on">
<arg line=" --log-junit ${basedir}/build/logs/phpunit.xml --coverage-clover ${basedir}/build/logs/phpunit.coverage.xml --coverage-html ${basedir}/build/coverage tests"/>
</exec>
</target>
</project>
Приложение Г - пример окончательного варианта файла настройки проекта в config.xml
<?xml version="1.0"?>
<cruisecontrol>
...
<project name="myProjectName" buildafterfailed="false">
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
<modificationset>
<svn localWorkingCopy="/opt/cruisecontrol/projects/myProjectName/source"/>
</modificationset>
<bootstrappers>
<svnbootstrapper localWorkingCopy="/opt/cruisecontrol/projects/myProjectName/source"/>
</bootstrappers>
<schedule interval="300">
<ant buildfile="projects/${project.name}/build.xml" antscript="/opt/cruisecontrol/apache-ant-1.7.0/bin/ant"/>
</schedule>
<log dir="logs/${project.name}">
<merge dir="projects/${project.name}/build/logs/"/>
</log>
<publishers>
<artifactspublisher dir="projects/${project.name}/build/api" dest="artifacts/${project.name}" subdirectory="api"/>
<artifactspublisher dir="projects/${project.name}/build/coverage" dest="artifacts/${project.name}" subdirectory="coverage"/>
<execute command="phpcb --log projects/${project.name}/build/logs --source projects/${project.name}/source --output projects/${project.name}/build/php-code-browser"/>
<artifactspublisher dir="projects/${project.name}/build/php-code-browser" dest="artifacts/${project.name}" subdirectory="php-code-browser"/>
<execute command="/usr/bin/phpuc graph logs/${project.name} artifacts/${project.name}"/>
<artifactspublisher subdirectory="graph" dest="artifacts/${project.name}" dir="projects/${project.name}/build/graph"/>
<email mailhost="localhost"
returnaddress="cruisecontrol@my.marketgid.net"
buildresultsurl="http://localhost:8080/cruisecontrol/buildresults/myProjectName"
skipusers="true" spamwhilebroken="true">
<map alias="management" address="root@localhost" />
<map alias="qa" address="user@localhost" />
<map alias="developer" address="user@my.marketgid.net" />
<always address="management" />
<success address="qa" />
<failure address="developer" reportWhenFixed="true" />
</email>
</publishers>
</project>
...
</cruisecontrol>
Приложение Д - пример окончательного варианта файла build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="mgtest" default="build" basedir=".">
<target name="build" depends="checkout,mkdirs,lint,php-documentor,php-codesniffer,phpunit,phpcpd,phpmd,pdepend"/>
<target name="checkout">
<exec executable="svn" dir="${basedir}/source" failonerror="on">
<arg line="up"/>
</exec>
</target>
<target name="lint">
<apply executable="php" dir="${basedir}/source" failonerror="on" logerror="on">
<arg line="-l"/>
<fileset dir="${basedir}/source">
<include name="**/*.php"/>
<exclude name="library/Zend/**/*.php"/>
</fileset>
</apply>
</target>
<target name="mkdirs">
<mkdir dir="${basedir}/source/cache/models"/>
</target>
<target name="php-documentor" depends="lint">
<exec executable="phpdoc" dir="${basedir}/source" logerror="on">
<arg line="--title '${ant.project.name}'
-ue on
-t ${basedir}/build/api
-d application
-tb '/usr/share/php/data/phpUnderControl/data/phpdoc'
-o HTML:Phpuc:phpuc"/>
</exec>
</target>
<target name="php-codesniffer" depends="lint">
<exec executable="phpcs" dir="${basedir}/source" output="${basedir}/build/logs/checkstyle.xml" error="/tmp/checkstyle.error.log">
<arg line="--report=checkstyle
--standard=Zend
application"/>
</exec>
</target>
<target name="phpmd">
<exec executable="phpmd" dir="${basedir}/source">
<arg line="application
xml
codesize,unusedcode,naming
--reportfile ${basedir}/build/logs/phpmd.xml"/>
</exec>
</target>
<target name="phpunit" depends="lint">
<exec executable="phpunit" dir="${basedir}/source/tests" failonerror="false">
<arg line="--bootstrap ${basedir}/source/tests/bootstrap.php
--log-junit ${basedir}/build/logs/phpunit.xml
--coverage-clover ${basedir}/build/logs/phpunit.coverage.xml
--coverage-html ${basedir}/build/coverage
."/>
</exec>
</target>
<target name="phpcpd" >
<exec executable="phpcpd" failonerror="false">
<arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml
${basedir}/source/application" />
</exec>
</target>
<target name="pdepend" depends="lint">
<exec executable="pdepend" dir="${basedir}/source" logerror="on">
<arg line="--summary-xml=${basedir}/build/logs/pdepend.xml
--jdepend-chart=${basedir}/build/graph/jdepend.svg
--overview-pyramid=${basedir}/build/graph/overview-pyramid.svg
--coderank-mode=inheritance,property,method
application" />
</exec>
</target>
</project>
вторник, 18 января 2011 г.
Отправка e-mail сообщений на несколько smtp-серверов с помощью masqmail и msmtp
sudo cat > /etc/masqmail/route.utel-unlim
# mail_host="relay.ukrpost.ua"
protocol="pipe"
pipe="/usr/bin/msmtp -f ${return_path} -- ${rcpt}"
^C
Так как будет использоваться общесистемный конфиг msmtp, то потребуется создать (или скопировать из домашнего каталога) файл /etc/msmtprc с нужными настройками.
см. также
понедельник, 17 января 2011 г.
Автоматическая отправка почты на комьютере без постоянного подключения к интернет (masqmail, procmail)
За прием и обработку очереди сообщений отвечает почтовый сервер masqmail, который был создан именно для таких случаев. В debian начальная настройка производится при установке этого пакета (в дальнейшем его можно повторно перенастроить выполнив команду dpkg-reconfigure masqmail). Часть опций, отвечающих за интеграцию в систему debian записывается в файл /etc/default/masqmail:
$ cat /etc/default/masqmail
#
# better use 'dpkg-reconfigure masqmail'
# instead of editing by hand
#
INIT_SMTP_DAEMON="false"
INIT_QUEUE_DAEMON="false"
INIT_FETCH_DAEMON="false"
#
QUEUE_DAEMON_IVAL="-q10m"
FETCH_DAEMON_IVAL="-go5m"
#
IPUP_RUNQUEUE="true"
IPUP_FETCH="false"
IFUP_IFACES="all"
В моем случае при старте системы smtp-демон не запускается (стартует из inetd при запросе), получение почты с других серверов также отключено (для этих целей используется fetchmail). Обработка очереди производится при поднятии любого интерфейса (отрабатывают скрипты, установленные в /etc/network/if-up.d/ и /etc/ppp/ip-up.d/).
Главный конфиг masqmail выглядит так:
$ cat /etc/masqmail/masqmail.conf
### BEGIN DEBCONF SECTION
# Do not edit within this region if you want your changes to be preserved by
# debconf. Instead, make changes after the "### END DEBCONF SECTION" line.
host_name="kirill-u100"
local_hosts="localhost;kirill-u100;localhost.localdomain"
local_nets=""
listen_addresses="localhost:25"
spool_dir="/var/spool/masqmail"
mail_dir="/var/mail"
log_dir="/var/log/masqmail"
do_queue=false
use_syslog=false
online_detect=file
online_file="/var/run/masqmail-route"
mbox_default=mda
mda="/usr/bin/procmail -Y -d ${rcpt_local}"
alias_file=/etc/aliases
alias_local_caseless="false"
### END DEBCONF SECTION
#
# include the locations of your route and get configurations here.
# Examples:
# online_routes.default = "/etc/masqmail/default.route"
# online_gets.default = "/etc/masqmail/default.get"
# You can have more of those, with '.default' replaced with other
# names. See man 8 masqmail.conf.
#
online_routes.kyivstar-xl = "/etc/masqmail/route.kyivstar-xl"
online_routes.utel-unlim = "/etc/masqmail/route.utel-unlim"
Файлы настроек для передачи почты разным провайдерам перечислены в конце файла (строки вида online_routes.<provider_name> = <config_file>). Где <provider_name> устанавливается опцией ipparam при запуске ppp (в соответствующем файле из /etc/ppp/peers/).
Простейший пример одного из таких файлов:
$ sudo cat /etc/masqmail/route.kyivstar-xl
mail_host="relay.kyivstar.net"
Запуск masqmail из inetd производится следующим образом:
$ cat /etc/inetd.conf | grep masqmail
127.0.0.1:25 stream tcp nowait mail /usr/sbin/masqmail masqmail -bd -q -bs
см. также:
четверг, 13 января 2011 г.
Автоматическое получение почты на компьютере без постоянного подключения к интернет (debian, fetchmail, procmail)
- Доставка и чтение почты: fetchmail, procmail, kmail
- Автоматическая отправка почты на комьютере без постоянного подключения к интернет (masqmail)
Часть 2 - общесистемное получение почты
Для автоматического получения почты с помощью fetchmail необходимо изменить несколько конфигурационных файлов.
$ vi /etc/default/fetchmail
указать START_DAEMON=yes
Создать общесистемный конфигурационный файл для fetchmail (его можно скопировать из каталога с примерами):
$ sudo cp /usr/share/doc/fetchmail/examples/fetchmailrc.example /etc/fetchmailrc
Установить владельца и разумные права доступа к конфигурационному файлу с паролями:
$ sudo chown fetchmail:root /etc/fetchmailrc
$ sudo chmod 0600 /etc/fetchmailrc
Добавить в этот конфиг правила приема почты из всех почтовых ящиков для всех пользователей (пример полного конфига выглядит так):
$ sudo cat /etc/fetchmailrc
# /etc/fetchmailrc for system-wide daemon mode
# This file must be chmod 0600, owner fetchmail
set daemon 600
set no bouncemail
defaults:
antispam -1
batchlimit 100
poll freemail.ukr.net with proto POP3
user 'r*******@ukr.net' there with password '********' is 'reel' here options keep
mda 'procmail -d %T'
user 'm*********@ukr.net' there with password '********' is 'reel' here options keep
mda 'procmail -d %T'
poll imap.gmail.com with proto IMAP
user 'kirill.zabarniuk@gmail.com' there with password '********' is 'reel' here options keep ssl
mda 'procmail -d %T'
Основное отличие от правил, находящихся в ~/.fetchmailrc - это команда запуска mda 'procmail -d %T'. Ключ -d переключает procmail в режим доставки с правами получателя и с использьзованием конфига из его домашнего каталога (имя получателя будет подставлено вместо переменной %T).
На данный момент fetchmail будет запускаться при старте системы в режиме демона и периодически проверять доступность почтовых серверов. Можно перенастроить его так, чтобы демон запускался при поднятии сетевого интерфейса и завершал свою работу при пропадании сети. Инструкции можно найти в /usr/share/doc/fetchmail/README.Debian.gz (описаны шаги только для отслеживания состояния интерфейсов ppp, без учета возможности подключения через eth; возможно поэтому там же говорится что такой режим работы fetchmail особых преимуществ не имеет :)).
среда, 12 января 2011 г.
Доставка и чтение почты: fetchmail, procmail, kmail
Среди найденного списка программ ($ apt-cache search fetch mail) наиболее подходящими оказались getmail4 и fetchmail. В итоге установил старый добрый fetchmail, несмотря на то что питоновский getmail4 позиционируется как более простой, и даже поддерживает Maildir из коробки.
Итак почту я храню в ящике формата maildir:
~/Mail/
drafts/
inbox/
cur/
new/
tmp/
outbox/
sent-mail/
templates/
trash/
За обработку полученной корреспонденции (распихивание её по ящикам) будет отвечать procmail (в качестве альтернативы можно выбрать maildrop, как рекомендуется в man fetchmail или другой mda).
Часть 1 - получение почты вручную от имени пользователя
Создаем простейший конфигурационный файл для procmail (слэш в конце имени ящика указывает на то, что это ящик maildir):
$ cat > ~/.procmailrc
MAILDIR=$HOME/Mail/
:0
inbox/
^C
В результате вся обрабатываемая почта будет складываться в каталог inbox/.
Конфиг для fetchmail можно создать при помощи утилиты fetchmailconf; вот итог её работы, подходящий под мои требования:
$ cat > ~/.fetchmailrc
# Configuration created Wed Jan 12 11:10:56 2011 by fetchmailconf 1.57
set postmaster "reel"
set bouncemail
set no spambounce
set softbounce
set properties ""
set invisible
poll freemail.ukr.net with proto POP3
user 'r*******@ukr.net' there with password '**********' is 'reel' here options keep stripcr
mda 'procmail'
user 'm*******@ukr.net' there with password '**********' is 'reel' here options keep
mda 'procmail'
poll imap.gmail.com with proto IMAP
user 'kirill.zabarniuk@gmail.com' there with password '**********' is 'reel' here options keep ssl
mda 'procmail'
^C
При запуске, fetchmail будет получать почту из двух почтовых ящиков на сервере ukr.net (по протоколу pop3), и из одного ящика на gmail (по протоколу imap). Копии всех сообщений будут оставаться на сервере, а сами сообщения будут передаваться для дальнейшей обработки procmail-у.
Имеет смысл написать пару сообщений самому себе и проверить как это работает:
$ fetchmail
1 сообщение (1 просмотрено) для r*******@ukr.net на freemail.ukr.net (1974 октетов).
пропускается сообщение r*******@ukr.net@new.ukr.net:1 не очищено
1 сообщение (1 просмотрено) для m*********@ukr.net на freemail.ukr.net (1144 октетов).
пропускается сообщение m*********@ukr.net@new.ukr.net:1 не очищено
1 сообщение для kirill.zabarniuk@gmail.com на imap.gmail.com.
считывается сообщение kirill.zabarniuk@gmail.com@wy-in-f109.1e100.net:1 из 1 (1443 октетов в заголовке) (513 октетов в теле) не очищено
Почту я читаю с матом (mutt), но иногда пользуюсь kmail. Обычно kmail сам находит каталоги с почтой пользователя при первом запуске. Но если этого не произошло, и он решил заныкать сообщения у себя (в каталоге по умолчанию ~/.kde/share/apps/kmail/Mail/), то можно попросить его изменить путь к этому каталогу (http://kmail.kde.org/manual/faq.html#id2792815, http://forum.kde.org/viewtopic.php?f=20&t=84335#p140087):
$ kwriteconfig --file kmailrc --group General --key folders $HOME/Mail
см также Автоматическое получение почты на компьютере без постоянного подключения к интернет
вторник, 11 января 2011 г.
Настройка msmtp для отправки сообщений через несколько серверов (ukr.net, gmail.com)
$ cat ~/.msmtprc
defaults
syslog on
account r*******_at_ukr.net
from r*******@ukr.net
host smtp.ukr.net
protocol smtp
auth on
tls on
tls_starttls off
tls_certcheck off
port 465
user r*******@ukr.net
password **********
account m*********_at_ukr.net
from m*********@ukr.net
host smtp.ukr.net
protocol smtp
auth on
tls on
tls_starttls off
tls_certcheck off
port 465
user m*********@ukr.net
password **********
account kirill.zabarniuk_at_gmail.com
from kirill.zabarniuk@gmail.com
host smtp.gmail.com
protocol smtp
auth on
tls on
tls_starttls on
tls_certcheck off
port 587
user kirill.zabarniuk@gmail.com
password ***********
account default
host localhost
port 25
auto_from on
maildomain localhost
Подружить msmtp с ukr.net оказалось просто, ключевое слово: tls_starttls off.
понедельник, 10 января 2011 г.
Просмотр html-содержимого в mutt и правильная кодировка


Так вот, в debian-е, если этот пакет установлен, mutt будет использовать его при отображении html-содержимого в e-mail сообщениях. Однако, сообщения приходят в различных кодировках, а в mutt все отображается лишь в одной (utf8 по умолчанию), в результате часть сообщений оказываются нечитаемыми. Чтобы это исправить, надо добавить следующую строку в свой .mailcap:
cat >> ~/.mailcap
text/html; /usr/bin/w3m -dump -I %{charset} -T text/html '%s'; copiousoutput; description=HTML Text; nametemplate=%s.html
"Магической" является опция -I %{charset}. Результат - на картинках:

