Class: Raygun::Runner

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

Constant Summary collapse

CARBONFIVE_REPO =
"carbonfive/raygun-rails"

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.



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

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.



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

def app_dir
  @app_dir
end

#app_nameObject

Returns the value of attribute app_name.



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

def app_name
  @app_name
end

#camel_nameObject

Returns the value of attribute camel_name.



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

def camel_name
  @camel_name
end

#current_ruby_patch_levelObject

Returns the value of attribute current_ruby_patch_level.



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

def current_ruby_patch_level
  @current_ruby_patch_level
end

#current_ruby_versionObject

Returns the value of attribute current_ruby_version.



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

def current_ruby_version
  @current_ruby_version
end

#dash_nameObject

Returns the value of attribute dash_name.



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

def dash_name
  @dash_name
end

#prototype_repoObject

Returns the value of attribute prototype_repo.



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

def prototype_repo
  @prototype_repo
end

#snake_nameObject

Returns the value of attribute snake_name.



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

def snake_name
  @snake_name
end

#target_dirObject

Returns the value of attribute target_dir.



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

def target_dir
  @target_dir
end

#title_nameObject

Returns the value of attribute title_name.



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

def title_name
  @title_name
end

Class Method Details

.parse(_args) ⇒ Object

rubocop:disable Metrics/MethodLength



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/raygun/raygun.rb', line 252

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



294
295
296
297
# File 'lib/raygun/raygun.rb', line 294

def usage_and_exit(parser)
  puts parser
  exit 1
end

Instance Method Details

#check_raygun_versionObject



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

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



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

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



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

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

#configure_new_appObject



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

def configure_new_app
  clean_up_unwanted_files

  update_ruby_version

  initialize_git
end

#copy_prototypeObject



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

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

  C5Conventions.install(target: app_dir) if @prototype_repo == CARBONFIVE_REPO
end

#fetch_prototypeObject



46
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
# File 'lib/raygun/raygun.rb', line 46

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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