-
Notifications
You must be signed in to change notification settings - Fork 0
/
deploy.php
154 lines (133 loc) · 4.61 KB
/
deploy.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
/**
* Класс Deploy
*
* Класс реализует функционал автоматического обновления файлов при пуше в ветку репозитория с Bitbucket.
*
* Для обновления файлов используются команды:
* 1. git reset --hard HEAD
* 2. git pull
*/
class Deploy
{
/**
* @const string секретный ключ
*/
const SECRET = '';
/**
* @const string имя репозитория
*/
const REPOSITORY = '';
/**
* @const string имя ветки
*/
const BRANCH = 'master';
/**
* @const string имя удалённого репозитория (по умолчанию)
*/
const REMOTE = 'origin';
/**
* @const путь к файлу с репозиторием
*/
const REPOSITORY_ROOT_PATH = '';
/**
* @const string путь к файлу с логами
*/
const LOG_ROOT_PATH = '';
/**
* @const string имя файла с логами
*/
const LOG_FILENAME = '';
/**
* @const string формат записи даты
*/
const LOG_DATE_FORMAT = 'd.m.Y H:i:s';
/**
* @var array массив данных с Bitbucket
*/
public $payload;
/**
* Создаёт объект класса
*
* @param string $secret секретный ключ из GET запроса
* @param array $payload массив данных с Bitbucket
*/
public function __construct($secret, $payload)
{
$this->payload = json_decode($payload, true);
$this->checkSecretOrDie($secret);
$this->checkDataOrDie($this->payload);
}
/**
* Выполняет обновление файлов на сервере.
*/
public function execute()
{
$this->log('Началось обновление файлов на сервере...');
try {
$command = 'cd ' . self::REPOSITORY_ROOT_PATH;
$command .= ' && git reset --hard HEAD';
$command .= ' && git pull ' . self::REMOTE . ' ' . self::BRANCH;
$result = shell_exec($command);
} catch (Exception $ex) {
$this->log('Ошибка: "Выполнение команды обновления файлов произошло с ошибкой".');
}
$this->log('Обновление файлов завершено с результатом: ' . $result);
}
/**
* Логирует сообщение в файл.
*
* @param string $message сообщение
*/
private function log($message)
{
$filePath = realpath(self::LOG_ROOT_PATH) . DIRECTORY_SEPARATOR . self::LOG_FILENAME;
if (!file_exists($filePath)) {
file_put_contents($filePath, '');
chmod($filePath, 0666);
}
file_put_contents($filePath, date(self::LOG_DATE_FORMAT) . ' ' . $message . PHP_EOL, FILE_APPEND);
}
/**
* Проверяет соответствие ключа из GET запроса с ключом константы SECRET.
* В случае неудачи логирует ошибку и приостанавливает выполнение скрипта.
*
* @param string $secret секретный ключ
*/
private function checkSecretOrDie($secret)
{
if (self::SECRET !== $secret) {
$this->log('Ошибка: "Не совпадает секретный ключ".');
die();
}
}
/**
* Проверяет корректность данных с Bitbucket.
*
* @param array $payload массив данных с Bitbucket
*/
private function checkPayloadOrDie($payload)
{
$dieFlag = false;
if (empty($payload)) {
$dieFlag = true;
$this->log('Ошибка: "Массив данных с Bitbucket пуст".');
}
if (self::REPOSITORY !== $payload['repository']['name']) {
$dieFlag = true;
$this->log('Ошибка: "Не совпадает название репозитория".');
}
if (self::BRANCH !== $payload['push']['changes']['new']['name']) {
$dieFlag = true;
$this->log('Ошибка: "Не совпадает название ветки".');
}
if ($dieFlag == true) {
die();
}
}
}
date_default_timezone_set('Europe/Moscow');
$secret = $_GET['secret'];
$payload = file_get_contents('php://input');
$deploy = new Deploy($secret, $payload);
$deploy->execute();