LoginSignup
46
44

More than 5 years have passed since last update.

Capistrano3 で deploy_via :copy する

Last updated at Posted at 2014-03-25

やりたかったこと

  • Capistrano3Capistrano2 までの deploy_via :copy なデプロイがしたい(タイトルそのまま)
  • Capistrano3 では deploy_via :copy の概念は導入されず

動作確認環境

  • クライアント
    • Mac OSX 10.9/Windows 7 (32bit)
    • Ruby 1.9.3-p484
  • リモート
    • CentOS 6.4/RedHat EL6.4

依存ライブラリ

  • Capistrano 3+
  • rubyzip

手順

インストール

Capistrano に加えて rubyzip をインストールして下さい。

Gemfile
group :deployment do
  gem 'capistrano', '~> 3.0', require: false
  gem 'rubyzip', require: false
end

セットアップ

cap install すると、以下のような構造になると思います。

config/
  deploy/
    production.rb
    staging.rb
  deploy.rb
lib/
  capistrano/
    tasks/
Capifile

で、 lib/capistrano/copy.rb を以下の内容で作成。

lib/capistrano/copy.rb
require 'zip'

Zip.setup do |c|
  c.unicode_names = true
  c.on_exists_proc = true
  c.continue_on_exists_proc = true
end

namespace :copy do
  task :check do
  end

  task create_release: 'release.zip' do |t|
    file = t.prerequisites.first
    on roles(:app) do
      execute :mkdir, '-p', fetch(:tmp_dir)
      upload! file, fetch(:tmp_dir)
      execute :unzip, '-o', "#{fetch(:tmp_dir)}/release.zip", '-d', release_path
    end
    File.delete file if File.exists?(file)
  end

  file 'release.zip' do |t|
    release_filename = File.join(Dir.pwd, t.name)

    Dir.chdir fetch(:copy_dir) do
      Zip::File.open(release_filename, Zip::File::CREATE) do |zipfile|
        files = FileList['**/*']
        files.exclude(*fetch(:copy_exclude)).each do |file|
          zipfile.add(file, file)
        end
      end
    end
  end
end

つまり、このように配置します。

config/
  deploy/
    production.rb
    staging.rb
  deploy.rb
lib/
  capistrano/
    tasks/
    copy.rb << Add to here!
Capifile

さらに Capifile の先頭に以下のように追記します。

Capifile
$:.unshift File.expand_path(File.dirname(__FILE__) + '/lib') # << 必ず先頭に追加

# Load DSL and Setup Up Stages
require 'capistrano/setup'

# Includes default deployment tasks
require 'capistrano/deploy'
#    :
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }

以上で準備が完了です。

使い方

deploy.rb とか deploy/production.rb とかで以下のように設定すれば OK。

config/deploy.rb
set :scm, 'copy'
set :copy_dir, '.'
set :tmp_dir, '/tmp'
set :copy_exclude, [ /\.log$/, %r!^files/.+! ]

これで cap production deploy とかすると、

  1. Capifile のあるディレクトリを基準に :copy_dir で指定したディレクトリ全体から、
  2. :copy_exclude除いた ファイル・ディレクトリが <Capifile のあるディレクトリ>/release.zip としてアーカイブされて、
  3. リモートの :tmp_dir に送信され、
  4. あとはいつも通り Capistrano さんが良きに計らってくださり、

デプロイ完了。

ちなみに、 :copy_dir:tmp_dir は必須です。

既知の問題

  • :copy_exclude の指定方法がわかりにくい
  • ファイル名に日本語が使われていると、名前によってはアーカイブで失敗する場合がある

以上です。

gem にしようかと思ってました(思ってます)が、いつになるか分からないので
まとめておくことにしました。参考になれば幸いです。

46
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
44