Как организовать деплой с Bitbacket
(Взято из комментария на хабре Q&A по причине удаления этого вопроса с ответами. Автор ответа Андрей Хохлов @andrhohlov )
VPS с Ubuntu, на нем установлен соответственно git и созданы 2 папки под сайты
test.example.com (тестовая версия сайта)
и example.com (боевая версия)
Создать на сервере директорию для репозиториев, например:
1 |
sudo mkdir /var/www/git |
Далее я дал права на папку с сайтами и репозиториями пользователю www-data (собственно с правами и была основная морока при реализации)
1 |
sudo chown -R www-data:www-data /var/www |
И все делал от имени этого пользователя (под ним работает apache или nginx).
Сгенерировал ему ключи
1 |
sudo -u www-data ssh-keygen -t rsa |
Создал конфиг файл
1 |
sudo -u www-data nano /var/www/.ssh/config |
и добавил в него
1 2 |
Host bitbucket.org IdentityFile ~/.ssh/id_rsa |
Сгенерированый ключ нужно добавить в битбакет (Settings -> Deployment keys).
Если далее будет проблема с ключами, проверить права доступа к ним, если что выставить:
1 2 3 4 |
sudo chmod 0755 /var/www/.ssh sudo chmod 0600 /var/www/.ssh/id_rsa sudo chmod 0600 /var/www/.ssh/id_rsa.pub sudo chmod 0644 /var/www/.ssh/known_hosts |
Далее, клонируем репозиторий от имени пользователя www-data с ключем —mirror. Это в общем пустой репозиторий, без файлов. В гайде описывалось почему именно —mirror.
1 2 |
cd /var/www/git sudo -u www-data git clone --mirror git@bitbucket.org:username/example.git |
Копируем непосредственно файлы репозитория
1 2 |
cd example.git sudo -u www-data GIT_WORK_TREE=/var/www/example.com/public_html git checkout -f master |
Обратите внимание на путь GIT_WORK_TREE. Суть в том, что у нас файлы сайта будут храниться отдельно от папки .git.
В примере выше я копирую ветку master.
Далее, создаем скрипт деплоя
1 2 3 4 5 |
cd /var/www/example.com/public_html sudo -u www-data mkdir deploy cd deploy sudo -u www-data touch deploy.log sudo -u www-data nano deploy.php |
Рекомендуется обозвать папку и сам файл deploy.php каким-нибудь неадекватным набором символов вроде deploy-fseuo77w7rwegfe.php.
Собственно сам скрипт deploy.php, рассчитанный на 2 ветки, master (можно переименовать её в dev например и production.
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 |
<?php // Examine the Bitbucket payload that’s being sent to deployment script file_put_contents('deploy.log', serialize($_POST['payload']) . "\n", FILE_APPEND); $repo_dir = '/var/git-repos/example.git'; $master_dir = '/var/www/dev.example.com/public_html'; $production_dir = '/var/www/example.com/public_html'; // Full path to git binary is required if git is not in your PHP user's path. Otherwise just use 'git'. $git_bin_path = 'git'; $update = false; // Parse data from Bitbucket hook payload $payload = json_decode($_POST['payload']); if (empty($payload->commits)){ // When merging and pushing to bitbucket, the commits array will be empty. // In this case there is no way to know what branch was pushed to, so we will do an update. $update = true; } else { foreach ($payload->commits as $commit) { $branch = $commit->branch; if ($branch === 'master' || isset($commit->branches) && in_array('master', $commit->branches)) { $update = true; break; } elseif ($branch === 'production' || isset($commit->branches) && in_array('production', $commit->branches)) { $update = true; break; } } } if ($update) { // Do a git checkout to the web root exec('cd ' . $repo_dir . ' && ' . $git_bin_path . ' fetch'); exec('cd ' . $repo_dir . ' && GIT_WORK_TREE=' . $master_dir . ' ' . $git_bin_path . ' checkout -f master'); exec('cd ' . $repo_dir . ' && GIT_WORK_TREE=' . $production_dir . ' ' . $git_bin_path . ' checkout -f production'); // Log the deployment $commit_hash = shell_exec('cd ' . $repo_dir . ' && ' . $git_bin_path . ' rev-parse --short HEAD'); file_put_contents('deploy.log', date('m/d/Y h:i:s a') . " Deployed branch: " . $branch . " Commit: " . $commit_hash . "\n", FILE_APPEND); } ?> |
Остается только добавить post hook с ссылкой на deploy.php (Settings -> Hooks).
Получается что каждый раз когда мы пушим изменения в репозиторий (не важно в какую ветку) обновляются файлы на сервере в обоих ветках.