Skip to content

Instantly share code, notes, and snippets.

@hackimov
Created March 11, 2020 05:43
Show Gist options
  • Save hackimov/9b0dbaabdb99cd720e4bc40fb0826c62 to your computer and use it in GitHub Desktop.
Save hackimov/9b0dbaabdb99cd720e4bc40fb0826c62 to your computer and use it in GitHub Desktop.
AutoDeploy и приём информации серверами , путем вызова вебхуков сервером GitHub
<?php /** @noinspection PhpUndefinedMethodInspection PhpUnused */
/**
* НЕ ИЗМЕНЯТЬ!!!!! (жене мужу и т.д., а контроллер можно но в исключительных случаях)
* Автор класса Александр Хакимов https://github.com/hackimov
* Контроллер который занимается автодеплоем на стэйджинг и продакшин.
* Это функционал ядра который восприимчив к изменению!
* Если затронуть код то автодеплой сломается, исключением является если он уже сломался по причине если сервера были перенесены или недоступны из вне!
*/
namespace App\Http\Controllers\API\autodeploy;
use App\Http\Controllers\Controller;
use App\Services\ErgResponseService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Config;
use Illuminate\Http\Request;
class AutoDeployController extends Controller
{
protected static $path = '/home/bitrix/ext_www/';
protected static $url_path = '@github.com/MicrosDevGroup/';
protected static $reset = 'git reset --hard 2>&1';
protected static $git_push = 'git push --force';
protected static $build = '/home/bitrix/bin/Sencha/Cmd/sencha app build -des ./ 2>&1';
protected static $cd = 'cd ';
protected static $and = ' && ';
protected static $quot = '"';
protected static $protocol = 'https://';
protected static $git_pull = 'git pull ';
protected static $git_ext = '.git';
protected static $master_branch = ' master 2>&1';
protected static $dev_branch = ' dev 2>&1';
public static function back_production(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'master' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.production.backend');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.backend');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin master
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$master_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('backend production git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get backend push response production but is not needed branch', $return_data);
}
public static function back_staging(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'dev' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.staging.backend');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.backend');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin dev
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$dev_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('backend staging git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get backend push response staging but is not needed branch', $return_data);
}
public static function front_production(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'master' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.production.frontend');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.frontend');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin master
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$master_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// sencha app build -des ./
$build_output = [];
$build_command = self::$cd . self::$path . $repo . self::$and . self::$build;
exec($build_command, $build_output);
$data['build_output']['command'] = $build_command;
$data['build_output']['data'] = $build_output;
// ищем ошибки билда
$build_errors = [];
foreach ($build_output as $build_string) {
if(false !== stripos($build_string, '[ERR]')) {
$build_errors[] = $build_string;
}
}
$data['build_output']['data']['errors'] = $build_errors;
if(empty($build_errors)){
// сообщение об успешном принятии данных с гитхаба и билд прошёл без ошибок
return ErgResponseService::success('frontend production git pull and build executed successfully without errors', $data);
}
// обработка проблемного реквеста с ошибками в билде (откат последнего пул реквеста на основной ветке)
// git reset --hard
$reset_output_force = [];
$reset_command_force = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command_force, $reset_output_force);
$data['reset_output_force']['command'] = $reset_command_force;
$data['reset_output_force']['data'] = $reset_output_force;
// git push origin master --force
$push_output_force = [];
$push_force = self::$git_push . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$master_branch;
$push_command_force = self::$cd . self::$path . $repo . self::$and . $push_force;
exec($push_command_force, $push_output_force);
$data['push_output_force']['command'] = $push_command_force;
$data['push_output_force']['data'] = $push_output_force;
// sencha app build -des ./
$build_output_force = [];
$build_command_force = self::$cd . self::$path . $repo . self::$and . self::$build;
exec($build_command_force, $build_output_force);
$data['build_output_force']['command'] = $build_command_force;
$data['build_output_force']['data'] = $build_output_force;
// сообщение о проблемном пулл реквесте, и откат на предыдущий, с выводом ошибок проблемного билда в ответе
return ErgResponseService::success('frontend production git pull and build executed successfully but with errors. last commit build', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get frontend push response production but is not needed branch', $return_data);
}
public static function front_staging(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'dev' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.staging.frontend');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.frontend');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin dev
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$dev_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// sencha app build -des ./
$build_output = [];
$build_command = self::$cd . self::$path . $repo . self::$and . self::$build;
exec($build_command, $build_output);
$data['build_output']['command'] = $build_command;
$data['build_output']['data'] = $build_output;
// ищем ошибки билда
$build_errors = [];
foreach ($build_output as $build_string) {
if(false !== stripos($build_string, '[ERR]')) {
$build_errors[] = $build_string;
}
}
$data['build_output']['data']['errors'] = $build_errors;
if(empty($build_errors)){
// сообщение об успешном принятии данных с гитхаба и билд прошёл без ошибок
return ErgResponseService::success('frontend staging git pull and build executed successfully without errors', $data);
}
// обработка проблемного реквеста с ошибками в билде (откат последнего пул реквеста на основной ветке)
// git reset --hard
$reset_output_force = [];
$reset_command_force = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command_force, $reset_output_force);
$data['reset_output_force']['command'] = $reset_command_force;
$data['reset_output_force']['data'] = $reset_output_force;
// git push origin dev --force
$push_output_force = [];
$push_force = self::$git_push . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$dev_branch;
$push_command_force = self::$cd . self::$path . $repo . self::$and . $push_force;
exec($push_command_force, $push_output_force);
$data['push_output_force']['command'] = $push_command_force;
$data['push_output_force']['data'] = $push_output_force;
// sencha app build -des ./
$build_output_force = [];
$build_command_force = self::$cd . self::$path . $repo . self::$and . self::$build;
exec($build_command_force, $build_output_force);
$data['build_output_force']['command'] = $build_command_force;
$data['build_output_force']['data'] = $build_output_force;
// сообщение о проблемном пулл реквесте, и откат на предыдущий, с выводом ошибок проблемного билда в ответе
return ErgResponseService::success('frontend staging git pull and build executed successfully but with errors. last commit build', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get frontend push response staging but is not needed branch', $return_data);
}
public static function admin_production(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'master' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.production.admin');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.admin');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin master
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$master_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('admin production git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get admin panel push response production but is not needed branch', $return_data);
}
public static function admin_staging(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'dev' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.staging.admin');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.admin');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin dev
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$dev_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('admin staging git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get admin panel push response staging but is not needed branch', $return_data);
}
public static function auth_production(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'master' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.production.auth');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.auth');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin master
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$master_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('auth production git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get auth repo push response production but is not needed branch', $return_data);
}
public static function auth_staging(Request $request): JsonResponse
{
// получаем параметр payload с входными данными пул реквеста
$payload = $request->get('payload');
if(empty($payload)){
$payload = $request->getContent();
}
// форматируем данные
$pull_response = self::github_pull_request_formatter($payload);
$return_data['request_content'] = $payload;
$return_data['request_response'] = $pull_response;
// проверяем на нужную ли ветку пришёл пул реквест
if(isset($pull_response['branch']) && $pull_response['branch'] === 'dev' && $pull_response['branch'] !== false) {
$repo = Config::get('application.github.staging.auth');
$token = Config::get('application.github.token');
$git_repo = Config::get('application.github.github_repo.auth');
// git reset --hard
$reset_output = [];
$reset_command = self::$cd . self::$path . $repo . self::$and . self::$reset;
exec($reset_command, $reset_output);
$data['reset_output']['command'] = $reset_command;
$data['reset_output']['data'] = $reset_output;
// git pull origin dev
$pull_output = [];
$pull = self::$git_pull . self::$quot . self::$protocol . $token . self::$url_path . $git_repo . self::$git_ext . self::$quot . self::$dev_branch;
$pull_command = self::$cd . self::$path . $repo . self::$and . $pull;
exec($pull_command, $pull_output);
$data['pull_output']['command'] = $pull_command;
$data['pull_output']['data'] = $pull_output;
// сообщение об успешном принятии данных с гитхаба
return ErgResponseService::success('auth staging git pull executed successfully', $data);
}
// сообщение о том, что это не нужный нам пулл реквест (был прислан на другую ветку или вообще не является пулл реквестом)
return ErgResponseService::success('get auth repo push response staging but is not needed branch', $return_data);
}
/**
* @param $json
* @return array|bool
* функция возвращает результат форматирования входящих данных пулл реквеста и выдаёт необходимые данные
*/
public static function github_pull_request_formatter($json)
{
// декодируем тело реквеста
$request = json_decode($json, true);
$pull_response = [];
// если нам прислали подмассив с полным путем, обрабатываем и получаем название ветки
if(isset($request['ref'])){
$branch_data = explode('/', $request['ref']);
$branch = end($branch_data);
$pull_response['branch'] = $branch;
}
// смотрим кто был инициатором пулл реквеста
if(isset($request['head_commit']['committer']['username'])){
$pull_response['pushed_from'] = $request['head_commit']['committer']['username'];
}
// регулярное выражение которое проверяет является ли это пулл реквестом
$merge_pattern = '/Merge pull request/m';
if(isset($request['head_commit']['message']) && preg_match($merge_pattern, $request['head_commit']['message'])){
$pull_response['github_merge'] = true;
} else {
$pull_response['github_merge'] = false;
}
// если это не пул реквест возвращает пустой результат
if(empty($pull_response)){
return false;
}
// возвращаем результат форматированны пул реквест
return $pull_response;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment