Интерпретировать задание Hudson как успешное, даже если одна из вызванных программ не работает - PullRequest
1 голос
/ 24 мая 2011

У меня есть задание Hudson, которое периодически объединяет изменения из репозитория верхнего базарного уровня.

В настоящее время, когда нет никаких изменений вверх по течению, Хадсон сообщает об этом задании как об ошибке, потому что команда bzr commit возвращается с ошибкой.Мой сценарий выглядит примерно так:

bzr branch lp:~lorinh/project/my-local-branch
cd my-local-branch
REV_UPSTREAM=`bzr version-info lp:project --custom --template="{revno}"`
bzr merge lp:project
bzr commit -m "merged upstream version ${REV_UPSTREAM}" 
./run_tests.sh 
bzr push lp:~lorinh/project/my-local-branch

Если нет изменений для слияния, вывод консоли Hudson выглядит примерно так:

+ bzr branch lp:~lorinh/project/my-local-branch
Branched 807 revision(s).    
+ bzr merge lp:project
Nothing to do.
+ bzr commit -m merged upstream version 733
Committing to: /var/lib/hudson/jobs/merge-upstream/workspace/myproject/
aborting commit write group: PointlessCommit(No changes to commit)
bzr: ERROR: No changes to commit. Use --unchanged to commit anyhow.
Sending e-mails to: me@example.com
Finished: FAILURE

Проблема в том, что я нехочу, чтобы Хадсон сообщил об этом как о неудаче.Как мне изменить мои команды, чтобы скрипт завершился неудачной фиксацией, но Хадсон не воспринял это как ошибку?Я попытался изменить команду коммита на:

bzr commit -m "merged upstream version ${REV_UPSTREAM}" || exit 

Но это не сработало.

(Примечание: я понимаю, что мог бы использовать «опрос SCM» Хадсона вместо «периодически строить». Однако на базаре, если кто-то делает толчок с локальными коммитами, которые были сделаны до самых последних модификаций, тогда Хадсонне обнаружит изменения в хранилище.)

Ответы [ 2 ]

4 голосов
/ 25 мая 2011

Вы были очень близки! Вот исправленная версия того, что вы пытались:

bzr commit -m "merged upstream version ${REV_UPSTREAM}" || exit 0

Это теперь делает то, что вы просили, но не идеально. Я вернусь к этому позже.

Обратите внимание на крошечное важное изменение в вашей версии - мы сейчас явно заявляем, что должны выйти с кодом 0 (успех), если команда bzr не делает этого. В вашей версии exit (без аргумента) прервет ваш скрипт, но вернет код завершения последней выполненной команды - в этом случае bzr commit.

Подробнее о выходе

Как мы узнаем об этом поведении выхода? Команда exit является встроенной в оболочку - для поиска документации по ней мы используем команду справки:

help exit

Что на моей машине говорит мне:

exit: exit [n]
Exit the shell.

Exits the shell with a status of N.  If N is omitted, the exit status
is that of the last command executed.

Вот достойное руководство по кодам выхода и выхода в оболочке bash

Hudson и коды выхода

Хадсон следует этому общему правилу интерпретации кода выхода 0 как успеха, а любого другого кода как сбоя. Он будет помечать вашу сборку как неудачную, если выполняемый скрипт сборки завершит работу с ненулевым кодом.

Почему ваш скрипт останавливается после коммита bzr

Если, как вы говорите, у вас есть следующее, и ваш скрипт останавливается после коммита bzr ...

bzr commit -m "merged upstream version ${REV_UPSTREAM}" 
./run_tests.sh 

... Я подозреваю, что в вашем скрипте есть инструкция типа set -e или он вызывается с чем-то вроде bash -e build_script.sh

Любой из этих параметров заставляет оболочку немедленно выйти, если команда завершается с ненулевым статусом, и передавать тот же самый код завершения «сбой». (Есть тонкости - см. Сноску 1).

Отключение выхода при ошибке

Хотя такое поведение при выходе из ошибки чрезвычайно полезно, иногда мы хотели бы временно отключить его. Вы нашли один способ, в

bzr commit whatever || true

Мы также можем отключить проверку ошибок с помощью set + e.

Вот шаблон, который вы можете найти полезным. В нем мы будем:

  1. Отключить выход при ошибке (с set +e)
  2. запустить команду, которая может вызвать ошибку bzr commit whatever
  3. захватить код выхода ($?) Для позже проверка
  4. Снова включить выход при ошибке (с set -e)
  5. Тестировать и действовать по коду выхода любых команд

Давайте реализуем это. Снова мы выйдем 0 (успех), если команда bzr не удалась.

set +e
bzr commit whatever
commit_status=$?
set -e
if [[ "$commit_status" != "0" ]]; then
  echo "bzr commit finds nothing to do.  Build will stop, with success"
  exit 0
fi
echo "On we go with the rest of the build script..."

Обратите внимание, что мы заключаем в скобки как можно меньше с помощью set + e / set -e. Если в этом разделе в нашем скрипте есть опечатки, они не остановят скрипт, и будет хаос. Прочтите раздел «Как избежать set -e» в посте « Недостаточно известные функции оболочки POSIX » для получения дополнительных идей.

Что не так с foo || exit 0?

Как я упоминал ранее, есть проблема с нашим первым предложенным решением. Мы сказали, что когда bzr commit не равен нулю (т.е. он не фиксируется нормально), мы всегда останавливаемся и указываем success . Это произойдет, даже если bzr commit не получится по какой-то другой причине (и с некоторым другим ненулевым кодом выхода): возможно, вы сделали опечатку в вызове команды, или bzr не может подключиться к репо.

По крайней мере, в некоторых из этих случаев вы, возможно, захотите пометить сборку как сбой, чтобы вы могли что-то с этим сделать.

На пути к лучшему решению

Мы хотим конкретно указать, какие ненулевые коды выхода мы ожидаем от bzr, и что мы будем делать с каждым.

Если вы оглянетесь назад на шаблон set + e / set -e, приведенный выше, не составит труда расширить приведенную выше условную логику (если) в нечто, что может иметь дело с рядом конкретных кодов выхода из bzr, и с универсальным кодом для непредвиденных кодов выхода, который (я полагаю) завершается неудачно при сборке и сообщает о нарушающем коде и команде.

Чтобы узнать коды выхода для любой команды, прочитайте документы или выполните команду, а затем введите echo $? в качестве следующей команды . $? содержит код завершения предыдущей команды.

Сноска 1. В поведении выхода при ошибке, переключенном с помощью set -e, есть некоторые тонкости, с которыми вам нужно ознакомиться, касающиеся поведения, когда команды находятся в конвейерах, условных выражениях и других конструкциях.

1 голос
/ 25 мая 2011

, учитывая, что bzr, похоже, не выдает правильный код выхода (на примере вас bzr ... || exit), одно из решений - захватить выходные данные bzr и затем выполнить сканирование на наличие ОШИБКИ или другого.

 bzr commit -m "merged upstream version ${REV_UPSTREAM}" 2>&1 | tee /tmp/bzr_tmp.$$

 case $( < /tmp/bzr_tmp.$$ ) in
   *ERROR* ) 
     printf "error running bzr, found error msg = $(< /tmp/bzr_tmp.$$)\n"
     exit 1
   ;;
   * )
     : # everything_OK this case target
       # just to document the default action of 'nothing' ;-)
   ;;
 esac

Несколько более простое регулярное выражение для случая, основанное на результатах выборки, будет *FAILURE ) ....

$( < file ) - это более новая функция оболочки, о которой вы можете думать как $(cat file), но она более эффективна в использовании ресурсов процесса, поскольку не требует запуска нового процесса (cat) , чтобы выгрузить файл.

Надеюсь, это поможет.

...