在 capistrano 3 任务中声明和使用 ruby 函数



我有这里描述的相同问题:

如何在另一个卡皮斯特拉诺的任务

中调用一个卡皮斯特拉诺的任务?

但是,回滚到 Capistrano v3.0.1 和 sshkit 1.0 的解决方法对我不起作用。

使用本教程,我在lib/capistrano/

tasks中声明了自定义任务,这些任务使用存储在lib/capistrano/的.rb文件中的函数。

帽文件:

# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
require 'capistrano/rails'
require 'capistrano/rvm'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
# Loads custom tasks from all folders below `lib/capistrano' if you have any defined.
Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }
# because the above didn't quite look right to me, and all the .rbs are in /lib/capistrano
Dir.glob('lib/capistrano/*.rb').each { |r| import r }

部署.rb

set :application, 'hello-rails'
set :app_shortname, 'hr'
set :repo_url, 'git@bitbutcket.org:me/myapp.git'  #<-substituted fake info here for this post
# Default value for :linked_files is []
set :linked_files, %w{config/database.yml config/application.yml}
# Default value for linked_dirs is []
 set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
# everything below this comment adapted from the talkingquickly tutorial
#which config files should be copied by deploy:setup_config
set(:config_files, %w(
  nginx.conf
  unicorn.rb
  unicorn_init.sh
))
# which config files should be made executable after copying
# by deploy:setup_config
set(:executable_config_files, %w(unicorn_init.sh))
# files which need to be symlinked
set(:symlinks, [
  {
    source: "nginx.conf",
    link: "/etc/nginx/sites-enabled/{{full_app_name}}"
  },
  {
    source: "unicorn_init.sh",
    link: "/etc/init.d/unicorn_{{full_app_name}}"
  }
])
#specify my ruby version
set :rvm_type, :system
#specify my gemset
set :rvm_ruby_version, '1.9.3-p385@hello-rails'
namespace :deploy do
  # make sure we're deploying what we think we're deploying
  before :deploy, "deploy:check_revision"
  # only allow a deploy with passing tests to deployed
  before :deploy, "deploy:run_tests"
  # compile assets locally then rsync
  after 'deploy:symlink:shared', 'deploy:compile_assets_locally'
  after :finishing, 'deploy:cleanup'
end

config/staging.rb

set :stage, :staging
set :branch, "cap-rails"
set :rails_env, :test
# used in case we're deploying multiple versions of the same
# app side by side. Also provides quick sanity checks when looking
# at filepaths
set :full_app_name, "#{fetch(:app_shortname)}_#{fetch(:stage)}"
set :deploy_to, "/srv/#{fetch(:app_shortname)}"
# number of unicorn workers
set :unicorn_worker_count, 5
# For building nginx config file
set :enable_ssl, false
# extended properties on the server.
server 'dev', user: 'deployer', roles: %w{web app}  #<-substituted fake info here for this post
# custom ssh options
 set :ssh_options, {
   user: 'deployer',  #<-substituted fake info here for this post
   keys: %w(path.to.key),  #<-substituted fake info here for this post
   forward_agent: true,
   auth_methods: %w(publickey)
 }

lib/capistrano/tasks/setup_config.cap

namespace :deploy do
  task :setup_config do
    on roles(:app) do
      # make the config dir
      execute :mkdir, "-p #{shared_path}/config"
      full_app_name = fetch(:full_app_name)
      # config files to be uploaded to shared/config, see the
      # definition of smart_template for details of operation.
      # Essentially looks for #{filename}.erb in deploy/#{full_app_name}/
      # and if it isn't there, falls back to deploy/#{shared}. Generally
      # everything should be in deploy/shared with params which differ
      # set in the stage files
      config_files = fetch(:config_files)
      config_files.each do |file|
        smart_template file
      end
      # which of the above files should be marked as executable
      executable_files = fetch(:executable_config_files)
      executable_files.each do |file|
        execute :chmod, "+x #{shared_path}/config/#{file}"
      end
      # symlink stuff which should be... symlinked
      symlinks = fetch(:symlinks)
      symlinks.each do |symlink|
        sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}"
      end
    end
  end
end

lib/capistrano/template.rb

def smart_template(from, to=nil)
  to ||= from
  full_to_path = "#{shared_path}/config/#{to}"
  if from_erb_path = template_file(from)
    from_erb = StringIO.new(ERB.new(File.read(from_erb_path)).result(binding))
    upload! from_erb, full_to_path
    info "copying: #{from_erb} to: #{full_to_path}"
  else
    error "error #{from} not found"
  end
end
def template_file(name)
  if File.exist?((file = "config/deploy/#{fetch(:full_app_name)}/#{name}.erb"))
    return file
  elsif File.exist?((file = "config/deploy/shared/#{name}.erb"))
    return file
  end
  return nil
end

宝石文件

    source 'https://rubygems.org'
    # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
    gem 'rails', '4.0.4'
    # Use sqlite3 as the database for Active Record
    gem 'sqlite3'
    # Use SCSS for stylesheets
    gem 'sass-rails', '~> 4.0.2'
    # Use Uglifier as compressor for JavaScript assets
    gem 'uglifier', '>= 1.3.0'
    # Use CoffeeScript for .js.coffee assets and views
    gem 'coffee-rails', '~> 4.0.0'
    # Use jquery as the JavaScript library
    gem 'jquery-rails'
    # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
    gem 'turbolinks'
    # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
    gem 'jbuilder', '~> 1.2'
    #because sshkit 1.3 has this bug: https://stackoverflow.com/questions/21401665/how-to-call-a-capistranos-task-within-another-capistranos-task
    gem 'sshkit', '~> 1.0.0'
    gem 'capistrano',  '~> 3.0.1'
    gem 'capistrano-rails', '~> 1.1'
    gem 'capistrano-rvm'
    group :doc do
      # bundle exec rake doc:rails generates the API under doc/api.
      gem 'sdoc', require: false
    end

Gemfile.lock

GEM
  remote: https://rubygems.org/
  specs:
    actionmailer (4.0.4)
      actionpack (= 4.0.4)
      mail (~> 2.5.4)
    actionpack (4.0.4)
      activesupport (= 4.0.4)
      builder (~> 3.1.0)
      erubis (~> 2.7.0)
      rack (~> 1.5.2)
      rack-test (~> 0.6.2)
    activemodel (4.0.4)
      activesupport (= 4.0.4)
      builder (~> 3.1.0)
    activerecord (4.0.4)
      activemodel (= 4.0.4)
      activerecord-deprecated_finders (~> 1.0.2)
      activesupport (= 4.0.4)
      arel (~> 4.0.0)
    activerecord-deprecated_finders (1.0.3)
    activesupport (4.0.4)
      i18n (~> 0.6, >= 0.6.9)
      minitest (~> 4.2)
      multi_json (~> 1.3)
      thread_safe (~> 0.1)
      tzinfo (~> 0.3.37)
    arel (4.0.2)
    atomic (1.1.16)
    builder (3.1.4)
    capistrano (3.0.1)
      i18n
      rake (>= 10.0.0)
      sshkit (>= 0.0.23)
    capistrano-bundler (1.0.0)
      capistrano (>= 3.0.0.pre)
    capistrano-rails (1.1.0)
      capistrano (>= 3.0.0)
      capistrano-bundler (>= 1.0.0)
    capistrano-rvm (0.0.3)
      capistrano
    coffee-rails (4.0.1)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0, < 5.0)
    coffee-script (2.2.0)
      coffee-script-source
      execjs
    coffee-script-source (1.7.0)
    erubis (2.7.0)
    execjs (2.0.2)
    hike (1.2.3)
    i18n (0.6.9)
    jbuilder (1.5.3)
      activesupport (>= 3.0.0)
      multi_json (>= 1.2.0)
    jquery-rails (3.1.0)
      railties (>= 3.0, < 5.0)
      thor (>= 0.14, < 2.0)
    json (1.8.1)
    mail (2.5.4)
      mime-types (~> 1.16)
      treetop (~> 1.4.8)
    mime-types (1.25.1)
    minitest (4.7.5)
    multi_json (1.9.2)
    net-scp (1.1.2)
      net-ssh (>= 2.6.5)
    net-ssh (2.8.0)
    polyglot (0.3.4)
    rack (1.5.2)
    rack-test (0.6.2)
      rack (>= 1.0)
    rails (4.0.4)
      actionmailer (= 4.0.4)
      actionpack (= 4.0.4)
      activerecord (= 4.0.4)
      activesupport (= 4.0.4)
      bundler (>= 1.3.0, < 2.0)
      railties (= 4.0.4)
      sprockets-rails (~> 2.0.0)
    railties (4.0.4)
      actionpack (= 4.0.4)
      activesupport (= 4.0.4)
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rake (10.2.2)
    rdoc (4.1.1)
      json (~> 1.4)
    sass (3.2.18)
    sass-rails (4.0.2)
      railties (>= 4.0.0, < 5.0)
      sass (~> 3.2.0)
      sprockets (~> 2.8, <= 2.11.0)
      sprockets-rails (~> 2.0.0)
    sdoc (0.4.0)
      json (~> 1.8)
      rdoc (~> 4.0, < 5.0)
    sprockets (2.11.0)
      hike (~> 1.2)
      multi_json (~> 1.0)
      rack (~> 1.0)
      tilt (~> 1.1, != 1.3.0)
    sprockets-rails (2.0.1)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      sprockets (~> 2.8)
    sqlite3 (1.3.9)
    sshkit (1.0.0)
      net-scp
      net-ssh
      term-ansicolor
    term-ansicolor (1.3.0)
      tins (~> 1.0)
    thor (0.19.1)
    thread_safe (0.3.1)
      atomic (>= 1.1.7, < 2)
    tilt (1.4.1)
    tins (1.0.1)
    treetop (1.4.15)
      polyglot
      polyglot (>= 0.3.1)
    turbolinks (2.2.1)
      coffee-rails
    tzinfo (0.3.39)
    uglifier (2.5.0)
      execjs (>= 0.3.0)
      json (>= 1.8.0)
PLATFORMS
  ruby
DEPENDENCIES
  capistrano (~> 3.0.1)
  capistrano-rails (~> 1.1)
  capistrano-rvm
  coffee-rails (~> 4.0.0)
  jbuilder (~> 1.2)
  jquery-rails
  rails (= 4.0.4)
  sass-rails (~> 4.0.2)
  sdoc
  sqlite3
  sshkit (~> 1.0.0)
  turbolinks
  uglifier (>= 1.3.0)

当我执行时 捆绑执行上限暂存部署:setup_config

我得到这个输出:

INFO [9e71d728] Running mkdir -p /srv/hr/shared/config on ruby-dev
DEBUG [9e71d728] Command: mkdir -p /srv/hr/shared/config
 INFO [9e71d728] Finished in 0.738 seconds command successful.
cap aborted!
NoMethodError: undefined method `smart_template' for #<SSHKit::Backend::Netssh:0x007f8a4dc04980>
/Users/nico/DevOps/repo/hello-rails/lib/capistrano/tasks/setup_config.cap:16:in `block (4 levels) in <top (required)>'
/Users/nico/DevOps/repo/hello-rails/lib/capistrano/tasks/setup_config.cap:15:in `each'
/Users/nico/DevOps/repo/hello-rails/lib/capistrano/tasks/setup_config.cap:15:in `block (3 levels) in <top (required)>'
/Users/nico/.rvm/gems/ruby-1.9.3-p385@hello-rails-cap-v3-sshkit-v1/gems/sshkit-1.0.0/lib/sshkit/backends/netssh.rb:42:in `instance_exec'
/Users/nico/.rvm/gems/ruby-1.9.3-p385@hello-rails-cap-v3-sshkit-v1/gems/sshkit-1.0.0/lib/sshkit/backends/netssh.rb:42:in `run'

看来使用 capistrano v3.0.1 和 sshkit v1.0 并不能解决我的问题。 deploy:setup_config 任务正在尝试调用 lib/capistrano/template.rb 中定义的函数smart_template,并且输出指示找不到该函数。 我不知道如何让它正常工作。 欢迎就解决该问题提出任何建议。另外,如果存在为nginx和unicorn创建配置和可执行文件的更好方法,我很想听听。

编辑

在怀疑来自红宝石的 sshkit 宝石仍然含有该错误后,我添加了

gem 'sshkit', :git => 'https://github.com/capistrano/sshkit.git' 

到我的 Capfile 并重建了我当地的宝石集。 然而,这并没有解决这个问题,并指示我寻找其他地方。 从那里,我能够诊断出与导入由我的 Capfile 中的这些行定义的 ruby 文件有关的问题:

Dir.glob('lib/capistrano/*.rb').each { |r| import r }
Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }

我注释掉了这些行并将它们替换为:

require_relative 'lib/capistrano/template.rb'
require_relative 'lib/capistrano/substitute_strings.rb'

现在,我的 deploy:setup_config 任务正确调用了这些函数。 我导出了工作宝石组,并使用红宝石宝石的 sshkit 创建了一个新的宝石组。 使用上面列出的require_relative行,来自红宝石的 sshkit 宝石工作正常。 因此,无论我使用哪个来源(git 或 rubygems),问题都不在于 sshkit 中的错误,而在于导入包含我的 cap 任务正在调用的函数的 ruby 文件。

您的示例有两个问题,正确的行是:

Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }                                                                                                                                      
Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }    

您可以在此处查看完整示例

根据我在原始问题中的编辑,sshkit gem 的来源不是我的问题。相反,问题出在进口声明上。

更改线路:

# Loads custom tasks from all folders below `lib/capistrano' if you have any defined.
Dir.glob('lib/capistrano/*.rb').each { |r| import r }
Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }

自:

require_relative 'lib/capistrano/template.rb'
require_relative 'lib/capistrano/substitute_strings.rb'

为我解决了这个问题。

我不确定为什么 Dir.glob 方法对我不起作用,我假设操作员错误,期望弄清楚我做错了什么将有助于在未来的上限部署中推广导入。

相关内容

  • 没有找到相关文章

最新更新