# Capistrano

---
## Introduction
- remote server automation tool
- To script arbitrary workflows over SSH
- Support multi-environments
官網:https://capistranorb.com/documentation/overview/what-is-capistrano/
---
### 資料結構
```
├── Capfile
└── config
├── deploy
│ ├── production.rb
│ └── staging.rb
├── unicorn
│ ├── production.rb
│ └── staging.rb
└── deploy.rb
```
---

---
# 設定檔案
---
### Capfile
- 腳本: 部署就是要完成這個腳本裡面的事情
- 在做每個步驟的時候,會去讀取 `config/deploy.rb` 或者 `config/deploy/<環境>.rb` 檔案裡面的資訊,像是 env var 或者額外的 rake
---
### Capfile
```ruby
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
# require "capistrano/rvm"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
require 'whenever/capistrano'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
```
---
### Deploy config files
- 提供 Capfile 在執行的時候,所需要的資訊
- 分成所有環境共用的跟個別環境使用
- 所有環境共用的資訊會放在 `config/deply.rb`
- 個別環境使用的會放在 `config/deploy/<環境>.rb` 檔案中
---
其中比較重要的設定:
```ruby
# 設定 application 的名字跟 Github 上位置
set :application, '<repo name>'
set :repo_url, '<repo_url on Github>'
# linked files 跟 linked_dirs 是讓沒有在版控內的檔案可以透過 symlink 被抓到
# 可以選擇手動上機器寫檔案,或者參考後面的補充上傳
append :linked_files, '.env', 'config/aws/cf-ishin-dev-tw.pem'
append :linked_dirs, 'tmp/pids', 'tmp/sockets'
# capistrano 透過 ssh 去機台操作,這裡在設定 ssh
server 'server-name', user: 'deployer', roles: %w[app db web]
# 也可以這樣設定
# server 需要有 deploy 使用者
# 同時 deploy 的 ~/.ssh/authorized_key 要有我本地的 ssh 公鑰
role :web, %w{deploy@178.128.xxx.xxx}
role :db, %w{deploy@178.128.xxx.xxx}
# 環境設定
set :rails_env, :staging
# 在 server 上 repo 會部署在哪裡
set :deploy_to, '/path/to/repo'
# 可以設定 capistrano 這個 session 使用的環境變數
set :default_env, 'PATH' => 'path/i/want:$PATH'
```
---
這邊的環境變數,可以在 capistrano 部署偵錯的時候看到,例如
```
Command: cd/home/user1/rails/releases/20150507175646
&& ( RAILS_ENV=production/usr/bin/env /usr/bin/env bundle install )
```
可以看到 capistrano 都會先到當下的 release 資料夾,然後把我們設定的環境變數設定上去之後跑每一個步驟
---
另外可以自訂 rake 接在 capistrano 的 rake 之後
```ruby
task :restart_sidekiq do
on roles(:worker) do
execute :service, "sidekiq restart"
end
end
after "deploy:published", "restart_sidekiq"
```
---
這次部署的額外發現: 每次執行指令時不是同一個 ssh 連線
```ruby
namespace :deploy do
desc 'Run rake yarn:install'
task :yarn_install do
on roles(:web) do
within release_path do
execute("source <source_file>")
execute("yarn install --check-files;")
end
end
end
end
# Nodejs vesrion is too old!
namespace :deploy do
desc 'Run rake yarn:install'
task :yarn_install do
on roles(:web) do
within release_path do
execute("source <source_file>;yarn install --check-files;")
end
end
end
end
# ok
```
---
### 常見指令
```bash
# 可以使用的 capistrano 指令
bundle exec cap -T
# 把遠端伺服器中的 linked_files 檔案抓下來 需要裝 'capistrano-upload-config' gem
bundle exec cap production config:pull
# 把遠端伺服器中的 linked_files 檔案抓下來
bundle exec cap production config:push
# 幫忙檢查要部署的專案目錄( deploy_to設定的那個 )
# 、 linkeddirs 、 linkedfiles 這些是否存在,如果不存在它會幫我們把目錄的部分做出來
bundle exec cap production deploy:check
# 部署
bundle exec cap production deploy
# 保留到省下 keep_releases 數量的 releases
bundle exec cap deploy:cleanup
```
---
參考資料:
https://5xruby.tw/posts/rails-deploy/
http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html
https://qiita.com/pyru89kwmr/items/4b91ec22e6c0d8c524ac
https://medium.com/@kirill_shevch/using-chef-and-capistrano-to-deploy-rails-application-on-ubuntu-16-04-fae1dfe0dd12
完整的變數種類參考:https://capistranorb.com/documentation/getting-started/configuration/
{"metaMigratedAt":"2023-06-15T05:16:24.124Z","metaMigratedFrom":"Content","title":"Capistrano","breaks":true,"contributors":"[{\"id\":\"585db56d-e46e-4ead-8838-90ccbfa7118c\",\"add\":2578,\"del\":4635}]"}