Class: Raygun::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/raygun/raygun.rb

Constant Summary collapse

CARBONFIVE_REPO =
"carbonfive/raygun-rails"
C5_CONVENTIONS_REPO =
"carbonfive/c5-conventions"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target_dir, prototype_repo) ⇒ Runner

Returns a new instance of Runner.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/raygun/raygun.rb', line 22

def initialize(target_dir, prototype_repo)
  @target_dir     = target_dir
  @app_dir        = File.expand_path(target_dir.strip.to_s)
  @app_name       = File.basename(app_dir).gsub(/\s+/, "-")
  @dash_name      = app_name.tr("_", "-")
  @snake_name     = app_name.tr("-", "_")
  @camel_name     = camelize(snake_name)
  @title_name     = titleize(snake_name)
  @prototype_repo = prototype_repo

  @current_ruby_version     = RUBY_VERSION
  @current_ruby_patch_level = if RUBY_VERSION < "2.1.0" # Ruby adopted semver starting with 2.1.0.
                                "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
                              else
                                RUBY_VERSION.to_s
                              end
end

Instance Attribute Details

#app_dirObject

Returns the value of attribute app_dir.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def app_dir
  @app_dir
end

#app_nameObject

Returns the value of attribute app_name.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def app_name
  @app_name
end

#camel_nameObject

Returns the value of attribute camel_name.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def camel_name
  @camel_name
end

#current_ruby_patch_levelObject

Returns the value of attribute current_ruby_patch_level.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def current_ruby_patch_level
  @current_ruby_patch_level
end

#current_ruby_versionObject

Returns the value of attribute current_ruby_version.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def current_ruby_version
  @current_ruby_version
end

#dash_nameObject

Returns the value of attribute dash_name.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def dash_name
  @dash_name
end

#prototype_repoObject

Returns the value of attribute prototype_repo.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def prototype_repo
  @prototype_repo
end

#snake_nameObject

Returns the value of attribute snake_name.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def snake_name
  @snake_name
end

#target_dirObject

Returns the value of attribute target_dir.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def target_dir
  @target_dir
end

#title_nameObject

Returns the value of attribute title_name.



18
19
20
# File 'lib/raygun/raygun.rb', line 18

def title_name
  @title_name
end

Class Method Details

.parse(_args) ⇒ Object

rubocop:disable Metrics/MethodLength



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/raygun/raygun.rb', line 277

def parse(_args)
  raygun = nil

  options = OpenStruct.new
  options.target_dir     = nil
  options.prototype_repo = CARBONFIVE_REPO

  parser = OptionParser.new do |opts|
    opts.banner = "Usage: raygun [options] NEW_APP_DIRECTORY"

    opts.on("-h", "--help", "Show raygun usage") do
      usage_and_exit(opts)
    end
    opts.on(
      "-p",
      "--prototype [github_repo]",
      "Prototype github repo (e.g. carbonfive/raygun-rails)."
    ) do |prototype|
      options.prototype_repo = prototype
    end

    opts.on("-v", "--version", "Print the version number") do
      puts Raygun::VERSION
      exit 1
    end
  end

  begin
    parser.parse!
    options.target_dir = ARGV.first

    raise OptionParser::InvalidOption if options.target_dir.nil?

    raygun = Raygun::Runner.new(options.target_dir, options.prototype_repo)
  rescue OptionParser::InvalidOption
    usage_and_exit(parser)
  end

  raygun
end

.usage_and_exit(parser) ⇒ Object

rubocop:enable Metrics/MethodLength



319
320
321
322
# File 'lib/raygun/raygun.rb', line 319

def usage_and_exit(parser)
  puts parser
  exit 1
end

Instance Method Details

#check_raygun_versionObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/raygun/raygun.rb', line 77

def check_raygun_version
  required_raygun_version =
    `tar xfz #{@prototype} --include "*.raygun-version" -O 2> /dev/null`.chomp ||
    ::Raygun::VERSION
  return unless Gem::Version.new(required_raygun_version) > Gem::Version.new(::Raygun::VERSION)

  puts  ""
  print "Hold up!".colorize(:red)
  print " This version of the raygun gem (".colorize(:light_red)
  print "#{::Raygun::VERSION})".colorize(:white)
  print " is too old to generate this application (needs ".colorize(:light_red)
  print required_raygun_version.to_s.colorize(:white)
  puts  " or newer).".colorize(:light_red)
  puts  ""
  print "Please update the gem by running ".colorize(:light_red)
  print "gem update raygun".colorize(:white)
  puts  ", and try again. Thanks!".colorize(:light_red)
  puts  ""
  exit 1
end

#check_targetObject



40
41
42
43
44
45
# File 'lib/raygun/raygun.rb', line 40

def check_target
  return if Dir["#{@app_dir}/*"].empty?

  puts "Misfire! The target directory isn't empty... aim elsewhere.".colorize(:light_red)
  exit 1
end

#clean_up_unwanted_filesObject



140
141
142
# File 'lib/raygun/raygun.rb', line 140

def clean_up_unwanted_files
  FileUtils.rm "#{app_dir}/.raygun-version", force: true
end

#configure_new_appObject



132
133
134
135
136
137
138
# File 'lib/raygun/raygun.rb', line 132

def configure_new_app
  clean_up_unwanted_files

  update_ruby_version

  initialize_git
end

#copy_prototypeObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/raygun/raygun.rb', line 98

def copy_prototype
  FileUtils.mkdir_p(app_dir)

  shell "tar xfz #{@prototype} -C \"#{app_dir}\""

  # Github includes an extra directory layer in the tag tarball.
  extraneous_dir = Dir.glob("#{app_dir}/*").first
  dirs_to_move   = Dir.glob("#{extraneous_dir}/*", File::FNM_DOTMATCH)
    .reject { |d| %w[. ..].include?(File.basename(d)) }

  FileUtils.mv         dirs_to_move, app_dir
  FileUtils.remove_dir extraneous_dir

  fetch_rubocop_file if @prototype_repo == CARBONFIVE_REPO
end

#fetch_prototypeObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/raygun/raygun.rb', line 47

def fetch_prototype
  print "Checking for the latest application prototype...".colorize(:yellow)
  $stdout.flush

  # Check if we can connect, or fail gracefully and use the latest cached version.
  repo        = TemplateRepo.new(prototype_repo)
  name        = repo.name
  tarball_url = repo.tarball
  sha         = repo.sha

  print " #{name}.".colorize(:white)
  $stdout.flush

  cached_prototypes_dir = File.join(Dir.home, ".raygun")
  @prototype = "#{cached_prototypes_dir}/#{name.gsub("/", "--")}-#{sha}.tar.gz"

  # Do we already have the tarball cached under ~/.raygun?
  if File.exist?(@prototype)
    puts " Using cached version.".colorize(:yellow)
  else
    print " Downloading...".colorize(:yellow)
    $stdout.flush

    # Download the tarball and install in the cache.
    Dir.mkdir(cached_prototypes_dir, 0o755) unless Dir.exist?(cached_prototypes_dir)
    shell "curl -s -L #{tarball_url} -o #{@prototype}"
    puts " done!".colorize(:yellow)
  end
end

#initialize_gitObject



154
155
156
157
158
159
160
161
# File 'lib/raygun/raygun.rb', line 154

def initialize_git
  Dir.chdir(app_dir) do
    shell "git init"
    shell "git checkout -q -b main"
    shell "git add -A ."
    shell "git commit -m 'Raygun-zapped skeleton.'"
  end
end

rubocop:enable Metrics/AbcSize



185
186
187
188
189
190
191
# File 'lib/raygun/raygun.rb', line 185

def print_next_steps
  if @prototype_repo == CARBONFIVE_REPO
    print_next_steps_carbon_five
  else
    print_next_steps_for_custom_repo
  end
end

rubocop:disable Metrics/AbcSize



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/raygun/raygun.rb', line 194

def print_next_steps_carbon_five
  puts ""
  puts "Zap! Your application is ready. Next steps...".colorize(:yellow)
  puts ""
  puts "# Install updated dependencies and prepare the database".colorize(:light_green)
  puts "$".colorize(:blue) + " cd #{target_dir}".colorize(:light_blue)
  puts "$".colorize(:blue) + " bin/setup".colorize(:light_blue)
  puts ""
  puts "# Run the specs (they should all pass)".colorize(:light_green)
  puts "$".colorize(:blue) + " bin/rake".colorize(:light_blue)
  puts ""
  puts "# Run the app and check things out".colorize(:light_green)
  puts "$".colorize(:blue) + " yarn start".colorize(:light_blue)
  puts "$".colorize(:blue) + " open http://localhost:3000".colorize(:light_blue)
  puts ""
  puts "# For next steps like adding Bootstrap or React, check out the raygun README".colorize(:light_green)
  puts "$".colorize(:blue) + " open https://github.com/carbonfive/raygun/#next-steps".colorize(:light_blue)
  puts ""
  puts "Enjoy your Carbon Five flavored Rails application!".colorize(:yellow)
end

rubocop:enable Metrics/AbcSize



216
217
218
219
220
221
# File 'lib/raygun/raygun.rb', line 216

def print_next_steps_for_custom_repo
  puts ""
  puts "Zap! Your application is ready.".colorize(:yellow)
  puts ""
  puts "Enjoy your raygun generated application!".colorize(:yellow)
end

rubocop:disable Metrics/AbcSize



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/raygun/raygun.rb', line 164

def print_plan
  puts "     ____ ".colorize(:light_yellow)
  puts '    / __ \____ ___  ______ ___  ______ '.colorize(:light_yellow)
  puts '   / /_/ / __ `/ / / / __ `/ / / / __ \ '.colorize(:light_yellow)
  puts "  / _, _/ /_/ / /_/ / /_/ / /_/ / / / / ".colorize(:light_yellow)
  puts ' /_/ |_|\__,_/\__, /\__, /\__,_/_/ /_/ '.colorize(:light_yellow)
  puts "             /____//____/ ".colorize(:light_yellow)
  puts
  puts "Raygun will create new app in directory:".colorize(:yellow) +
       " #{target_dir}".colorize(:yellow) + "...".colorize(:yellow)
  puts
  puts "-".colorize(:blue) + " Application Name:".colorize(:light_blue) +
       " #{title_name}".colorize(:light_reen)
  puts "-".colorize(:blue) + " Project Template:".colorize(:light_blue) +
       " #{prototype_repo}".colorize(:light_reen)
  puts "-".colorize(:blue) + " Ruby Version:    ".colorize(:light_blue) +
       " #{@current_ruby_patch_level}".colorize(:light_reen)
  puts
end

#rename_new_appObject



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/raygun/raygun.rb', line 114

def rename_new_app
  Dir.chdir(app_dir) do
    {
      "AppPrototype"  => camel_name,
      "app-prototype" => dash_name,
      "app_prototype" => snake_name,
      "App Prototype" => title_name
    }.each do |proto_name, new_name|
      shell "find . -type f -print | xargs #{sed_i} 's/#{proto_name}/#{new_name}/g'"
    end

    %w[d f].each do |find_type|
      shell "find . -depth -type #{find_type} -name '*app_prototype*' " \
            "-exec bash -c 'mv $0 ${0/app_prototype/#{snake_name}}' {} \\;"
    end
  end
end

#update_ruby_versionObject



144
145
146
147
148
149
150
151
152
# File 'lib/raygun/raygun.rb', line 144

def update_ruby_version
  prototype_ruby_patch_level = File.read(File.expand_path("#{app_dir}/.ruby-version", __FILE__)).strip
  prototype_ruby_version     = prototype_ruby_patch_level.match(/(\d\.\d\.\d).*/)[1]

  Dir.chdir(app_dir) do
    shell "#{sed_i} 's/#{prototype_ruby_patch_level}/#{@current_ruby_patch_level}/g' .ruby-version README.md"
    shell "#{sed_i} 's/#{prototype_ruby_version}/#{@current_ruby_version}/g' Gemfile"
  end
end