tetuyoko/capistrano-deploylock

View on GitHub
lib/capistrano/deploylock.rb

Summary

Maintainability
B
6 hrs
Test Coverage
require "capistrano/deploylock/version"
require 'capistrano'

module Capistrano::Deploylock

  def self.load_into(configuration)
    configuration.load do
      _cset :deploy_lock_basename, "deploy_lock"
      _cset(:deploy_lock_dirname) { "#{shared_path}/system" }
      _cset(:deploy_lock_template_path) { File.join(File.dirname(__FILE__), "templates", "deploy_lock.yml") }
      _cset(:deploy_lock_remote_path) { "#{deploy_lock_dirname}/#{deploy_lock_basename}.yml" }
      _cset(:deploy_lock_remote_log_path) {"#{deploy_lock_dirname}/#{deploy_lock_basename}.log" }
      _cset(:deploy_lock_file_local_path) {"./public/system/#{deploy_lock_basename}.yml" }

      def remote_file_exists?(full_path)
        'true' ==  capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip
      end

      def lock_force_end(with_log=false)
        if remote_file_exists?(deploy_lock_remote_path)
          puts '[SKIP] ロックファイルを削除します'
          lock_end_log if with_log
          run "rm -f #{deploy_lock_remote_path}"
        end
      end

      def lock_start_log
        run "echo [started], #{Time.now}, #{git_config_user_name} >> #{deploy_lock_remote_log_path}"
      end

      def lock_end_log
        run "echo [ended], #{Time.now}, #{git_config_user_name} >> #{deploy_lock_remote_log_path}"
      end

      def git_config_user_name
        `git config --get user.name`
      end

      def remove_local_file
        FileUtils.rm deploy_lock_file_local_path, force: true
      end

      namespace :deploy do
        namespace :lock do
          desc 'デプロイロックを確認する'
          task :start, roles: :web do
            on_rollback { run "rm -f #{deploy_lock_remote_path}" }
            require 'erb'
            puts "\n**** [DEPLOY LOCK] ****"
            puts "24時間後まであなたの名前を元に他人のデプロイをロックします。"
            puts "この操作は下記のコマンドで取り消しできます。"
            puts "bundle exedc cap $STAGENAME deploy:lock:end"

            #      対話用
            #      print "\n今日から何日間ロックしますか? [1-10/n]: "
            #      STDOUT.flush
            #      ans= STDIN.gets.chomp
            #      if ["", 'n'].include? ans
            #        puts "[SKIPPED] デプロイロックをスキップしました。"
            #        exit
            #      end
            #  
            #      day = ans.to_i
            #      unless (1..10).include?(day)
            #        puts "[FAILED] days must set [1-10/n]"
            #        exit
            #      end

            day = 1
            expired_at = Time.now + (day * (60 * 60 * 24))

            user = git_config_user_name
            puts "\n**** [LOCKED] #{rails_env}はロックされ、有効期限内が設定されました. **** "
            puts "\n  locked_user  : #{user}"
            puts "  expired_at   : #{expired_at}\n\n"

            erb = ERB.new(File.read("#{deploy_lock_template_path}.erb")).result(binding)
            put erb, "#{deploy_lock_remote_path}", mode: 0644
            lock_start_log
          end

          desc 'デプロイロックを解除する'
          task :end, roles: :web do
            lock_force_end(true)
          end

          desc 'デプロイロックを設定する'
          task :check, roles: :web do
            unless remote_file_exists?(deploy_lock_remote_path)
              puts '[SKIP] ロックファイルがありません.'
              next
            end

            FileUtils.rm deploy_lock_file_local_path, force: true
            FileUtils.mkdir_p './public/system'

            get deploy_lock_remote_path, deploy_lock_file_local_path
            lock = YAML.load_file deploy_lock_file_local_path

            if Time.now > lock["expired_at"]
              puts '[SKIP] ロックファイルの設定期限が過ぎています.'
              remove_local_file
              lock_force_end(false)
              next
            end

            current_user = git_config_user_name.chomp
            if lock["user"] == current_user
              puts '[SKIP] あなたのロックファイルです.'
              remove_local_file
              next
            end

            puts "\n**** [LOCKED] #{rails_env}はロックされ、有効期限内です. **** "
            puts "\n  locked_user  : #{lock["user"]}"
            puts "  expired_at   : #{lock["expired_at"]}\n\n"

            puts "ロックは下記のコマンドで取り消しできます。"
            puts "bundle exedc cap $STAGENAME deploy:lock:end"

            remove_local_file
            run "hostname; exit 1"
          end
        end
      end
    end
  end
end

if Capistrano::Configuration.instance
  Capistrano::Deploylock.load_into(Capistrano::Configuration.instance)
end