LoginSignup
28
25

More than 5 years have passed since last update.

Capistrano3 で asset_sync をローカル環境で実行してからデプロイする

Last updated at Posted at 2015-04-15

rake assets:precompileで出力されるファイルを Amazon S3 などでホスティングしたい場合、asset_sync という gem が便利そうなので使ってみました。

asset_sync はrake assets:precompile実行時に Amazon S3 に出力ファイルをアップロードしてくれる優れものですが、デプロイ先のサーバーが複数台ある場合、複数台でそれぞれrake assets:precompileを実行してしまうのは冗長ですし、on primary(:web)とかすると manifest ファイル配るのはどうしよう。git に push するのもログが汚れてイヤだなーっと、これまた悩みそうです。

そこで、今回はデプロイ時にローカル環境でrake assets:precompileをしてから、manifest ファイルをデプロイ先サーバーに配る方式をとってみました。

今回の環境

  • capistrano と railsアプリケーション は別々のリポジトリで管理
  • asset_sync の設定は dotenv-rails で管理
  • デプロイ先のサーバーは複数台
  • 環境ごとに asset_sync したり、通常通り assets:precompile できるようにしたい

各種設定

Rails アプリケーション

asset_sync と、その設定内容の管理に dotenv-rails を利用しています。

Gemfile
gem 'asset_sync'
gem 'dotenv-rails'
config/asset_sync.yml
defaults: &defaults
  enabled:               <%= ENV['ASSET_SYNC_ENABLED'] %>
  fog_provider:          <%= ENV['ASSET_SYNC_PROVIDER'] %>
  fog_directory:         <%= ENV['ASSET_SYNC_FOG_DIRECTORY'] %>
  fog_region:            <%= ENV['ASSET_SYNC_FOG_REGION'] %>
  fog_endpoint:          <%= ENV['ASSET_SYNC_FOG_ENDPOINT'] %>
  aws_access_key_id:     <%= ENV['ASSET_SYNC_AWS_ACCESS_KEY_ID'] %>
  aws_secret_access_key: <%= ENV['ASSET_SYNC_AWS_SECRET_ACCESS_KEY'] %>
  existing_remote_files: 'keep'
  manifest:              true
  gzip_compression:      true

development:
  <<: *defaults

staging:
  <<: *defaults

production:
  <<: *defaults
.env
# asset_sync
ASSET_SYNC_ENABLED=false
ASSET_SYNC_PROVIDER=''
ASSET_SYNC_FOG_DIRECTORY=''
ASSET_SYNC_FOG_REGION=''
ASSET_SYNC_FOG_ENDPOINT=''
ASSET_SYNC_AWS_ACCESS_KEY_ID=''
ASSET_SYNC_AWS_SECRET_ACCESS_KEY=''

Capistrano

今回、capistrano と Rails アプリケーション は別々のリポジトリで管理していたため、ローカル環境に Rails アプリケーションをセットアップするタスクを追加します。
最新ソースを git から取得し、bundle install、環境変数を管理する .env ファイルを設置しています。

lib/capistrano/tasks/application.cap
namespace :application do

  desc 'Setup local application'
  task :setup do
    run_locally do
      # application のソースを取得
      if test "[ ! -d #{fetch(:application)} ]"
        execute :git, :clone, fetch(:repo_url), fetch(:application)
      end

      Dir.chdir(fetch(:application)) do
        # 最新ソースを取得
        execute :git, :checkout, fetch(:branch)
        execute :git, :fetch,    "origin"
        execute :git, :reset,    "--hard origin/#{fetch(:branch)}"
        # bundle install
        Bundler.with_clean_env do 
          execute "bundle install --path ./vendor/bundle"
        end

        # .env を設置
        execute :rm, "-rf .env"
        execute :ln, "-s ../config/deploy/env/env.#{fetch(:rails_env)} .env"
      end
    end
  end

end

環境ごとに asset_sync の有効/無効を切り替えるために設定を追加します。

config/deploy/production.rb
set :asset_sync_enabled, true

asset_sync のタスクを追加します。
asset_sync_enabled が true の場合は、asset_sync を実行し、false の場合は通常通りリモートサーバー上で assets:precompile を実行しています。

lib/capistrano/tasks/asset_sync.cap
namespace :deploy do
  namespace :asset_sync do

    desc 'Run asset_sync'
    task :run do
      if fetch(:asset_sync_enabled)
        invoke 'application:setup'
        invoke 'deploy:asset_sync:precompile'
        invoke 'deploy:asset_sync:upload_manifest'
        invoke 'deploy:asset_sync:cleanup'

        Rake::Task['deploy:compile_assets'].clear_actions
      end
    end

    desc 'Run assets:precompile'
    task :precompile do
      run_locally do
        Dir.chdir(fetch(:application)) do
          Bundler.with_clean_env do 
            execute "bundle exec rake assets:precompile RAILS_ENV=#{fetch(:rails_env)} ASSET_SYNC_ENABLED=#{fetch(:asset_sync_enabled)}"
          end
        end
      end
    end 

    desc 'Upload manifest'
    task :upload_manifest do
      Dir.chdir(fetch(:application)) do
        on roles(fetch(:assets_roles)) do
          if test "[ ! -d #{release_path}/public/assets ]"
            execute "mkdir -p #{release_path}/public/assets"
          end
          file_path = Dir::glob('public/assets/manifest*').first
          upload!(file_path, "#{release_path}/public/assets/")
        end
      end
    end

    desc 'Cleanup assets'
    task :cleanup do
      run_locally do
        Dir.chdir(fetch(:application)) do
          Bundler.with_clean_env do 
            execute "bundle exec rake assets:clobber"
          end
        end
      end
    end 

  end
end

デプロイ時にタスクが実行されるように設定を追加します。

config/deploy.rb
namespace :deploy do
  before :starting, 'asset_sync:run'
end

Deploy

あとは、

$ bundle exec cap production deploy

を実行するとデプロイ時に asset_sync が実行されます。

参考

今回、参考にさせていただいた記事はこちらです。
Capistrano3でasset_syncしてからデプロイする

28
25
1

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
28
25