Назад | Перейти на главную страницу

Автоматическое развертывание BitBucket Server с помощью PHP WebHook

Я провел небольшое исследование и пытаюсь воспроизвести что-то похожее на сообщение в блоге JONATHAN NICOL ".Автоматическое развертывание git из Bitbucket".

ОБНОВЛЕНИЕ К ВЫПУСКУ

Я включил ведение журнала вывода из exec() функция с добавлением 2>&1 в конце моей команды.

Когда я печатаю содержимое того, что возвращается в deploy.log, я получаю следующее:

//ИЗ exec('cd /home/apache/www.websitename.org.git && git fetch 2>&1');

(
    [0] => fatal: Not a git repository (or any parent up to mount point /home)
    [1] => Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
)

// ВЫХОД ИЗ exec('cd /home/apache/www.websitename.org.git && GIT_WORK_TREE=/var/www/html/www.websitename.org /usr/bin/git checkout -f');

Array
(
    [0] => fatal: Not a git repository (or any parent up to mount point /home)
    [1] => Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
)

Описание проблемы:

Если я скопирую вывод, команды, выполненные в exec() функция, содержащаяся в указанном сценарии PHP Web Hook, изменения, внесенные в файлы, когда мой feature branch сливается с dev реплицируются в соответствующий каталог. Моя проблема в том, что я хотел бы убедиться, что команды, выполняемые в exec() функция фактически выполняется.

Сначала я подумал, что это из-за проблемы с разрешениями, но я запускаю те же команды из оболочки, что и тот же пользователь, который выдает команды через PHP exec() функция.

Кажется, я не могу понять, почему команды, сгенерированные сценарием Web Hook, работают из оболочки пользователя apache, но они не работают при выполнении PHP, который запускается как apache и генерирует их.

Описание окружающей среды:

У меня есть сервер BitBucket v4.7.1, работающий на машине RedHat 7.2. На этом сервере также находится среда разработки, в которой я хотел бы автоматически развертывать файлы при объединении определенных веток.

Мой веб-корень / var / www / html, к которому имеет доступ apache. Когда я выполняю <?php echo exec('whoami'); ?> выход apache.

Я использую PHP 5.6.23 и могу выполнять команды оболочки из сценариев php.

Мой пользователь php - это apache, у apache также есть оболочка, подключенная к пользователю.

Моя ветка по умолчанию в GIT - master, и у меня также есть dev и staging ветви. Типичный рабочий процесс - создать ответвление от master и зафиксируйте изменения в ветке функций. Затем объедините эту ветку функции с dev, затем staging и в конечном итоге вернуться в master.

Используя структуру сообщения в блоге Николая и измененный репозиторий BitBucket для использования с bitbucket.org, я смог воспроизвести следующее:

Репозиторий GIT клонируется как зеркало с помощью следующей команды:

Как пользователь apache:

cd /home/apache/
git clone --mirror ssh://git@path.to.bitbucket.local:7999/wn/www.websitename.org.git

Затем:

cd /home/apache/www.websitename.org.git
GIT_WORK_TREE=/var/www/html/www.websitename.org git checkout -f dev

Apache имеет соответствующие разрешения для репозитория .git, apache имеет доступ к git в его $PATH, а apache имеет право собственности и разрешения /var/www/html/www.websitename.org

Я выписываюсь dev в этом сценарии, потому что мой веб-перехватчик в BitBucket настроен для ответа, когда функциональные ветки объединяются в dev и перенесен в BitBucket.

Скрипт PHP, вызываемый подключаемым модулем Bitbucket Server Web Post Hooks, выглядит следующим образом:

ОБНОВЛЕННЫЙ ОБРАЗЕЦ КОДА

    <?php

//$repo_name = $_GET['repoName'];
//$client = $_GET['client'];


//for debug
//file_put_contents('deploy.log', serialize($_POST['payload']), FILE_APPEND);
//file_put_contents('deploy.log', $_GET['client'], FILE_APPEND);
//file_put_contents('deploy.log', $_GET['repoName'], FILE_APPEND);

//file_put_contents('deploy.log', print_r($_POST), FILE_APPEND);

// Full path to git binary is required if git is not in your PHP user's path. Otherwise just use 'git'.
$git_bin_path = '/usr/bin/git';


echo getcwd() . "\n";


$update = false;


// Parse data from Bitbucket hook payload
//$payload = json_decode($_POST['payload']);

if ( isset($_POST['payload']) ) { // old method
    $payload = $_POST['payload'];
} else { // new method
    $payload = json_decode(file_get_contents('php://input'),false);
}

/*if(function_exists('exec')) {
file_put_contents('deploy.log', print_r("exec enabled",true), FILE_APPEND);
}else{
    file_put_contents('deploy.log', print_r("exec NOT enabled",true), FILE_APPEND);
}

if(function_exists('chdir')) {
file_put_contents('deploy.log', print_r("chdir enabled",true), FILE_APPEND);
}else{
    file_put_contents('deploy.log', print_r("chdir NOT enabled",true), FILE_APPEND);
}

file_put_contents('deploy.log', print_r($payload,true), FILE_APPEND);*/

//set repo name
$repo_name = $payload->repository->slug;

file_put_contents('/var/www/html/deploy/deploy.log', print_r($repo_name.":",true), FILE_APPEND);

$web_root_dir = '/var/www/html/lt/'.$repo_name;
$repo_dir = '/home/apache/'.$repo_name.'.git';


$dir = getcwd();
file_put_contents('/var/www/html/deploy/deploy.log',print_r("BEFORECHDIR:".$dir."CHDIRBEFORE\r\n"), FILE_APPEND);
file_put_contents('/var/www/html/deploy/deploy.log', print_r("repo".$repo_dir."repo\r\n",true), FILE_APPEND);

chdir($repo_dir);

file_put_contents('/var/www/html/deploy/deploy.log', print_r("DIR:repo".getcwd()."repo:DIR \r\n",true), FILE_APPEND);

$test = chdir($repo_dir);

file_put_contents('/var/www/html/deploy/deploy.log', print_r($test,true), FILE_APPEND);

if(count($payload->refChanges) == '0'){
    $update = false;
}elseif($payload->refChanges[0]->refId == 'refs/heads/dev' ){
    $update = true;
}

file_put_contents('/var/www/html/deploy/deploy.log', print_r("This is the update:".$update.": this ends update \r\n",true), FILE_APPEND);

if ($update) {
    file_put_contents('/var/www/html/deploy/deploy.log', print_r("It's an update",true), FILE_APPEND);
    // Do a git checkout to the web root

    $cmd1 = $git_bin_path  . ' fetch';
    $cmd2 = 'GIT_WORK_TREE=' . $web_root_dir . ' ' . $git_bin_path  . ' checkout -f ';

file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd1,true), FILE_APPEND);
file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd2,true), FILE_APPEND);

    $test = chdir($repo_dir);
    file_put_contents('/var/www/html/deploy/deploy.log', print_r($test,true), FILE_APPEND);


    exec("cd ".$repo_dir." && ". $cmd1 ." 2>&1",$out1,$outtest);
    if($outtest !==0 ){
        file_put_contents('/var/www/html/deploy/deploy.log', print_r($out1,true), FILE_APPEND);
    }

    exec("cd ".$repo_dir." && ". $cmd2 ." 2>&1",$out2,$outtest1);
    if($outtest1 !==0 ){
        file_put_contents('/var/www/html/deploy/deploy.log', print_r($out2,true), FILE_APPEND);
    }

    file_put_contents('/var/www/html/deploy/deploy.log', print_r("made it past exec",true), FILE_APPEND);
    //$test = shell_exec($cmd1);
    //$test2 = shell_exec($cmd2);

    file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd1,true), FILE_APPEND);
    file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd2,true), FILE_APPEND);



    // Log the deployment
    $commit_hash = exec('cd ' . $repo_dir . ' && ' .$git_bin_path  . ' rev-parse --short HEAD');
    file_put_contents('/var/www/html/deploy/deploy.log', date('m/d/Y h:i:s a') . " Deployed branch: " .  $branch . " Commit: " . $commit_hash . "\n", FILE_APPEND);

}
?>

Что я, возможно, упускаю из виду, что могло бы вызвать PHP exec() функция, выполняемая с недостаточными привилегиями при использовании exec() в отличие от выполнения непосредственно из оболочки пользователя php?

Оказалось, что это проблема с разрешением SELinux для пользователя apache в RedHat 7.2.

Я создал другого пользователя и добавил сценарий bash для выполнения git fetch и checkout.

Я также изменил свой файл sudoers, чтобы позволить apache запускать сценарий bash от имени вновь созданного пользователя.