Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Webアプリのデプロイ今昔物語

 Webアプリのデプロイ今昔物語

PHP Conference Japan 2014
https://joind.in/12041

Kenji Akiyama

October 11, 2014
Tweet

More Decks by Kenji Akiyama

Other Decks in Programming

Transcript

  1. EFQMPZUBTL ‣ EFQMPZTUBSUJOH ‣ EFQMPZDIFDL ‣ HJUDIFDL ‣ EFQMPZDIFDLEJSFDUPSJFT ‣

    EFQMPZDIFDLMJOLFE@EJST ‣ EFQMPZDIFDLNBLF@MJOLFE@EJST ‣ EFQMPZDIFDLMJOLFE@pMFT ‣ EFQMPZTUBSUFE ‣ EFQMPZVQEBUJOH ‣ HJUDSFBUF@SFMFBTF ‣ EFQMPZTZNMJOLTIBSFE ‣ EFQMPZTZNMJOLMJOLFE@pMFT ‣ EFQMPZTZNMJOLMJOLFE@EJST ‣ EFQMPZVQEBUFE ‣ EFQMPZQVCMJTIJOH ‣ EFQMPZTZNMJOLSFMFBTF ‣ EFQMPZQVCMJTIFE ‣ EFQMPZpOJTIJOH ‣ EFQMPZDMFBOVQ ‣ EFQMPZpOJTIFE $BQJTUSBOPͷσϓϩΠϑϨʔϜϫʔΫͷ࢖͍ํ աڈܗͰه͞Ε͍ͯΔλεΫ͸ۭͷλεΫ ͳͷͰ͜ΕΒΛඞཁʹԠ্ͯ͡ॻ͖͢Δ
  2. ͔ͭͯͷσϓϩΠखॱ (JUͷ։ൃϒϥϯν͔ΒANBTUFSAϒϥϯν΁Ϛʔδ͢Δ ࡞ۀͷ։࢝Λ4MBDLͰશһʹ௨஌͢Δ લճͷσϓϩΠ͔Βมߋͷ͋ͬͨϑΝΠϧ͚ͩΛαʔόʔʹίϐʔ͢Δ ݱߦόʔδϣϯͷσΟϨΫτϦΛ৽ͨͳόʔδϣϯ໊Λ෇͚ͯίϐʔ͢ Δ

    αʔόʔʹίϐʔͨ͠ϑΝΠϧͰ৽όʔδϣϯσΟϨΫτϦͷϑΝΠϧ Λ্ॻ͖͢Δ ݱߦόʔδϣϯͷσΟϨΫτϦΛࢦ͢4ZNMJOLΛɺ৽όʔδϣϯσΟϨ ΫτϦΛࢦ͢Α͏ʹ࡞੒͠௚͢ $BDIFϑΝΠϧΛ࡟আ͢Δ QIQGQNΛ࠶ىಈ͢Δ ࡞ۀͷऴྃΛ4MBDLͰશһʹ௨஌͢Δ
  3. ͔ͭͯͷσϓϩΠखॱ # local ! $ git checkout master $ git

    pull $ git merge DEV_BRANCH $ PAGER=cat git diff --name-status LAST_TAG CRRT_TAG \ > > file_diff.txt $ grep '^D' file_diff.txt > file_del.txt $ grep -v '^D' file_diff.txt > file_mod.txt $ grep '\w\s*wordpress' file_diff.txt > file_wdp.txt $ perl -i -ple '/\.scss$/ \ > && s/(sass|scss$)/css/g’ file_mod.txt $ bundle exec compass compile $ mkdir -p DEST_DIR $ perl -ple 's/^\w\s+//' file_mod.txt \ > | xargs -I% rsync -R % DEST_DIR $ cp file_del.txt DEST_DIR $ scp -r DEST_DIR REMOTE_HOST:~/DEST_DIR ! # remote ! $ cd DEPLOY_TO $ sudo -u DEPLOY_USER cp -apr LAST_TAG CRRT_TAG $ sudo -u DEPLOY_USER rsync -av DEST_DIR DEPLOY_TO/ \ > CRRT_TAG $ cd DEPLOY_TO/CRRT_TAG $ perl -ple 's/^D\s+//' file_del.txt | xargs rm $ sudo -u DEPLOY_USER ln -snf DEPLOY_TO/CRRT_TAG WEB_ROOT $ sudo find CAKE1_APP_CACHE -type f -exec rm {} \; $ sudo find CAKE2_APP_CACHE -type f -name 'empty' -prune \ > -o -type f -exec rm {} \; $ sudo service php5-fpm restart
  4. ࣗಈԽͷԸܙ # local ! $ git checkout master $ git

    pull $ git merge DEV_BRANCH $ PAGER=cat git diff --name-status LAST_TAG CRRT_TAG \ > > file_diff.txt $ grep '^D' file_diff.txt > file_del.txt $ grep -v '^D' file_diff.txt > file_mod.txt $ grep '\w\s*wordpress' file_diff.txt > file_wdp.txt $ perl -i -ple '/\.scss$/ \ > && s/(sass|scss$)/css/g’ file_mod.txt $ bundle exec compass compile $ mkdir -p DEST_DIR $ perl -ple 's/^\w\s+//' file_mod.txt \ > | xargs -I% rsync -R % DEST_DIR $ cp file_del.txt DEST_DIR $ scp -r DEST_DIR REMOTE_HOST:~/DEST_DIR ! # remote ! $ cd DEPLOY_TO $ sudo -u DEPLOY_USER cp -apr LAST_TAG CRRT_TAG $ sudo -u DEPLOY_USER rsync -av DEST_DIR DEPLOY_TO/ \ > CRRT_TAG $ cd DEPLOY_TO/CRRT_TAG $ perl -ple 's/^D\s+//' file_del.txt | xargs rm $ sudo -u DEPLOY_USER ln -snf DEPLOY_TO/CRRT_TAG WEB_ROOT $ sudo find CAKE1_APP_CACHE -type f -exec rm {} \; $ sudo find CAKE2_APP_CACHE -type f -name 'empty' -prune \ > -o -type f -exec rm {} \; $ sudo service php5-fpm restart
  5. ࣗಈԽͷԸܙ # local ! $ git checkout master $ git

    pull $ git merge DEV_BRANCH $ PAGER=cat git diff --name-status LAST_TAG CRRT_TAG \ > > file_diff.txt $ grep '^D' file_diff.txt > file_del.txt $ grep -v '^D' file_diff.txt > file_mod.txt $ grep '\w\s*wordpress' file_diff.txt > file_wdp.txt $ perl -i -ple '/\.scss$/ \ > && s/(sass|scss$)/css/g’ file_mod.txt $ bundle exec compass compile $ mkdir -p DEST_DIR $ perl -ple 's/^\w\s+//' file_mod.txt \ > | xargs -I% rsync -R % DEST_DIR $ cp file_del.txt DEST_DIR $ scp -r DEST_DIR REMOTE_HOST:~/DEST_DIR ! # remote ! $ cd DEPLOY_TO $ sudo -u DEPLOY_USER cp -apr LAST_TAG CRRT_TAG $ sudo -u DEPLOY_USER rsync -av DEST_DIR DEPLOY_TO/ \ > CRRT_TAG $ cd DEPLOY_TO/CRRT_TAG $ perl -ple 's/^D\s+//' file_del.txt | xargs rm $ sudo -u DEPLOY_USER ln -snf DEPLOY_TO/CRRT_TAG WEB_ROOT $ sudo find CAKE1_APP_CACHE -type f -exec rm {} \; $ sudo find CAKE2_APP_CACHE -type f -name 'empty' -prune \ > -o -type f -exec rm {} \; $ sudo service php5-fpm restart # local ! $ cap production deploy
  6. ࣗಈԽͷԸܙ # local ! $ git checkout master $ git

    pull $ git merge DEV_BRANCH $ PAGER=cat git diff --name-status LAST_TAG CRRT_TAG \ > > file_diff.txt $ grep '^D' file_diff.txt > file_del.txt $ grep -v '^D' file_diff.txt > file_mod.txt $ grep '\w\s*wordpress' file_diff.txt > file_wdp.txt $ perl -i -ple '/\.scss$/ \ > && s/(sass|scss$)/css/g’ file_mod.txt $ bundle exec compass compile $ mkdir -p DEST_DIR $ perl -ple 's/^\w\s+//' file_mod.txt \ > | xargs -I% rsync -R % DEST_DIR $ cp file_del.txt DEST_DIR $ scp -r DEST_DIR REMOTE_HOST:~/DEST_DIR ! # remote ! $ cd DEPLOY_TO $ sudo -u DEPLOY_USER cp -apr LAST_TAG CRRT_TAG $ sudo -u DEPLOY_USER rsync -av DEST_DIR DEPLOY_TO/ \ > CRRT_TAG $ cd DEPLOY_TO/CRRT_TAG $ perl -ple 's/^D\s+//' file_del.txt | xargs rm $ sudo -u DEPLOY_USER ln -snf DEPLOY_TO/CRRT_TAG WEB_ROOT $ sudo find CAKE1_APP_CACHE -type f -exec rm {} \; $ sudo find CAKE2_APP_CACHE -type f -name 'empty' -prune \ > -o -type f -exec rm {} \; $ sudo service php5-fpm restart # local ! $ cap production deploy UBLFOCZXJFENBJFS
  7. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end
  8. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end $BLF1)1ϥΠϒϥϦ΁ ϦϯΫΛுΔ
  9. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end $BLF1)1ϥΠϒϥϦ΁ ϦϯΫΛுΔ DPNQPTFSͰϓϥάΠϯ ΛΠϯετʔϧ͢Δ
  10. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end $BLF1)1ϥΠϒϥϦ΁ ϦϯΫΛுΔ DPNQPTFSͰϓϥάΠϯ ΛΠϯετʔϧ͢Δ σʔλϕʔεϚΠάϨʔ γϣϯΛ࣮ߦ͢Δ
  11. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end $BLF1)1ϥΠϒϥϦ΁ ϦϯΫΛுΔ DPNQPTFSͰϓϥάΠϯ ΛΠϯετʔϧ͢Δ DPNQBTTͰTBTTϑΝΠϧ ΛίϯύΠϧ͢Δ σʔλϕʔεϚΠάϨʔ γϣϯΛ࣮ߦ͢Δ
  12. ͲΜͳίʔυʁ task :updated do on roles(:app) do ["cakephp1","cakephp2"].each do |cake_dir|

    ["cake", "lib", "index.php", "plugins", "vendors"].each do |part_dir| part_path = fetch(:deploy_to) + '/' + cake_dir + '/' + part_dir if test "[ -e #{part_path} ]" then execute :ln, '-snf', part_path, "#{fetch(:release_path)}/#{cake_dir}/#{part_dir}" end end end ! within "#{fetch(:release_path)}/cakephp2/app" do composer_path = "#{fetch(:release_path)}/cakephp2/app/composer.phar" if test "[ -f #{composer_path} ]" then execute "./composer.phar", 'install' end ! if fetch(:run_migration) then execute '../lib/Cake/Console/cake', 'Migrations.migration', 'run', 'all' end end ! if fetch(:sass_compile_path) then within "#{fetch(:release_path)}/#{fetch(:sass_compile_path)}" do execute :compass, 'compile', '--boring' end end ! end end $BLF1)1ϥΠϒϥϦ΁ ϦϯΫΛுΔ DPNQPTFSͰϓϥάΠϯ ΛΠϯετʔϧ͢Δ DPNQBTTͰTBTTϑΝΠϧ ΛίϯύΠϧ͢Δ σʔλϕʔεϚΠάϨʔ γϣϯΛ࣮ߦ͢Δ ΞϓϦέʔγϣϯಛҟతͳλεΫΛ௥ ه͍ͯ͘͠
  13. ͲΜͳίʔυʁ task :restart do on roles(:app, :wp) do execute :sudo,

    :service, 'php5-fpm', 'restart' end end ! after :publishing, :restart ! before :restart, :clear_cache do on roles(:app) do if fetch(:app_cache1_path) then execute :sudo, :find, fetch(:app_cache1_path), '-type f -exec rm {} \;' end if fetch(:app_cache2_path) then execute :sudo, :find, fetch(:app_cache2_path), '-type f -name "empty" -prune -o -type f -exec rm {} \;' end end end
  14. ͲΜͳίʔυʁ task :restart do on roles(:app, :wp) do execute :sudo,

    :service, 'php5-fpm', 'restart' end end ! after :publishing, :restart ! before :restart, :clear_cache do on roles(:app) do if fetch(:app_cache1_path) then execute :sudo, :find, fetch(:app_cache1_path), '-type f -exec rm {} \;' end if fetch(:app_cache2_path) then execute :sudo, :find, fetch(:app_cache2_path), '-type f -name "empty" -prune -o -type f -exec rm {} \;' end end end QIQGQNΛϦελʔτ͢Δ
  15. ͲΜͳίʔυʁ task :restart do on roles(:app, :wp) do execute :sudo,

    :service, 'php5-fpm', 'restart' end end ! after :publishing, :restart ! before :restart, :clear_cache do on roles(:app) do if fetch(:app_cache1_path) then execute :sudo, :find, fetch(:app_cache1_path), '-type f -exec rm {} \;' end if fetch(:app_cache2_path) then execute :sudo, :find, fetch(:app_cache2_path), '-type f -name "empty" -prune -o -type f -exec rm {} \;' end end end QIQGQNΛϦελʔτ͢Δ QVCMJTIJOHλεΫͷޙ ʹ࣮ߦͯ͠Ͷὑ
  16. ͲΜͳίʔυʁ task :restart do on roles(:app, :wp) do execute :sudo,

    :service, 'php5-fpm', 'restart' end end ! after :publishing, :restart ! before :restart, :clear_cache do on roles(:app) do if fetch(:app_cache1_path) then execute :sudo, :find, fetch(:app_cache1_path), '-type f -exec rm {} \;' end if fetch(:app_cache2_path) then execute :sudo, :find, fetch(:app_cache2_path), '-type f -name "empty" -prune -o -type f -exec rm {} \;' end end end QIQGQNΛϦελʔτ͢Δ QVCMJTIJOHλεΫͷޙ ʹ࣮ߦͯ͠Ͷὑ Ϧελʔτ͢ΔલʹΩϟο γϡΛফ͠ͱ͍ͯͶὑ
  17. ͲΜͳίʔυʁ task :restart do on roles(:app, :wp) do execute :sudo,

    :service, 'php5-fpm', 'restart' end end ! after :publishing, :restart ! before :restart, :clear_cache do on roles(:app) do if fetch(:app_cache1_path) then execute :sudo, :find, fetch(:app_cache1_path), '-type f -exec rm {} \;' end if fetch(:app_cache2_path) then execute :sudo, :find, fetch(:app_cache2_path), '-type f -name "empty" -prune -o -type f -exec rm {} \;' end end end QIQGQNΛϦελʔτ͢Δ QVCMJTIJOHλεΫͷޙ ʹ࣮ߦͯ͠Ͷὑ Ϧελʔτ͢ΔલʹΩϟο γϡΛফ͠ͱ͍ͯͶὑ طଘͷλεΫͷલޙʹ೚ҙͷλεΫΛ )PPL͢Δ
  18. ͲΜͳίʔυʁ namespace :notify do namespace :update do task :start do

    _send_message("[\`#{fetch(:application)}\`] Deployment has started.") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Deployment has finished. :ok_woman:\n> #{fetch(:commit_message)}") end end ! namespace :rollback do task :start do _send_message("[\`#{fetch(:application)}\`] Rollback has started.\nCurrent Revision is \`#{fetch(:latest_revision)}\`") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Rollback has finished. :ok_woman:\nCurrent revision is \`#{fetch(:current_revision)}\`") end end end ! before 'deploy:starting', 'notify:update:start' after 'deploy:finishing', 'notify:update:finish' before 'deploy:reverting', 'notify:rollback:start' after 'deploy:finishing_rollback', 'notify:rollback:finish' $BQJTUSBOPʹΑΔσϓϩΠͷ࣮ߦ࣌ʹ4MBDL௨஌͢Δํ๏
  19. ͲΜͳίʔυʁ namespace :notify do namespace :update do task :start do

    _send_message("[\`#{fetch(:application)}\`] Deployment has started.") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Deployment has finished. :ok_woman:\n> #{fetch(:commit_message)}") end end ! namespace :rollback do task :start do _send_message("[\`#{fetch(:application)}\`] Rollback has started.\nCurrent Revision is \`#{fetch(:latest_revision)}\`") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Rollback has finished. :ok_woman:\nCurrent revision is \`#{fetch(:current_revision)}\`") end end end ! before 'deploy:starting', 'notify:update:start' after 'deploy:finishing', 'notify:update:finish' before 'deploy:reverting', 'notify:rollback:start' after 'deploy:finishing_rollback', 'notify:rollback:finish' σϓϩΠ΍ϩʔϧόοΫͷ։࢝ऴྃ ͷલޙʹ௨஌ΛૹΔ $BQJTUSBOPʹΑΔσϓϩΠͷ࣮ߦ࣌ʹ4MBDL௨஌͢Δํ๏
  20. ͲΜͳίʔυʁ namespace :notify do namespace :update do task :start do

    _send_message("[\`#{fetch(:application)}\`] Deployment has started.") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Deployment has finished. :ok_woman:\n> #{fetch(:commit_message)}") end end ! namespace :rollback do task :start do _send_message("[\`#{fetch(:application)}\`] Rollback has started.\nCurrent Revision is \`#{fetch(:latest_revision)}\`") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Rollback has finished. :ok_woman:\nCurrent revision is \`#{fetch(:current_revision)}\`") end end end ! before 'deploy:starting', 'notify:update:start' after 'deploy:finishing', 'notify:update:finish' before 'deploy:reverting', 'notify:rollback:start' after 'deploy:finishing_rollback', 'notify:rollback:finish' σϓϩΠ΍ϩʔϧόοΫͷ։࢝ऴྃ ͷલޙʹ௨஌ΛૹΔ $BQJTUSBOPʹΑΔσϓϩΠͷ࣮ߦ࣌ʹ4MBDL௨஌͢Δํ๏ ఆٛͨ͠3VCZͷؔ਺ Λݺͼग़͢
  21. ͲΜͳίʔυʁ namespace :notify do namespace :update do task :start do

    _send_message("[\`#{fetch(:application)}\`] Deployment has started.") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Deployment has finished. :ok_woman:\n> #{fetch(:commit_message)}") end end ! namespace :rollback do task :start do _send_message("[\`#{fetch(:application)}\`] Rollback has started.\nCurrent Revision is \`#{fetch(:latest_revision)}\`") end ! task :finish do _send_message("[\`#{fetch(:application)}\`] Rollback has finished. :ok_woman:\nCurrent revision is \`#{fetch(:current_revision)}\`") end end end ! before 'deploy:starting', 'notify:update:start' after 'deploy:finishing', 'notify:update:finish' before 'deploy:reverting', 'notify:rollback:start' after 'deploy:finishing_rollback', 'notify:rollback:finish' σϓϩΠ΍ϩʔϧόοΫͷ։࢝ऴྃ ͷલޙʹ௨஌ΛૹΔ $BQJTUSBOPʹΑΔσϓϩΠͷ࣮ߦ࣌ʹ4MBDL௨஌͢Δํ๏ ఆٛͨ͠3VCZͷؔ਺ Λݺͼग़͢ 3VCZͰ֦ு͢Δ