Class: Pkgr::Builder
- Inherits:
-
Object
- Object
- Pkgr::Builder
- Defined in:
- lib/pkgr/builder.rb
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#tarball ⇒ Object
readonly
Returns the value of attribute tarball.
Instance Method Summary collapse
-
#app_home_dir ⇒ Object
Some buildpacks may need the target home dir to exist.
-
#build_dir ⇒ Object
Build directory.
-
#buildpack_for_app ⇒ Object
Buildpack detected for the app, if any.
-
#buildpacks ⇒ Object
List of available buildpacks for the current distribution.
-
#call ⇒ Object
Launch the full packaging procedure.
-
#check ⇒ Object
Check configuration, and verifies that the current distribution’s requirements are satisfied.
-
#compile ⇒ Object
Pass the app through the buildpack.
-
#compile_cache_dir ⇒ Object
Directory where the buildpacks can store stuff.
-
#compile_env_dir ⇒ Object
Directory where the buildpacks can store config envs.
- #config_file ⇒ Object
-
#distribution ⇒ Object
Returns the current distribution we’re packaging for.
-
#extract ⇒ Object
Extract the given tarball to the target directory.
- #fpm_command ⇒ Object
-
#initialize(tarball, config) ⇒ Builder
constructor
Accepts a path to a tarball (gzipped or not), or you can pass ‘-’ to read from stdin.
-
#package(remaining_attempts = 3) ⇒ Object
Launch the FPM command that will generate the package.
- #pipeline ⇒ Object
-
#proc_dir ⇒ Object
Directory where binstubs will be created for the corresponding Procfile commands.
-
#procfile ⇒ Object
Returns the path to the app’s (supposedly present) Procfile.
- #procfile_entries ⇒ Object
-
#release_file ⇒ Object
Path to the release file generated after the buildpack compilation.
- #scaling_dir ⇒ Object
-
#setup ⇒ Object
Setup the build directory structure.
-
#setup_crons ⇒ Object
Write cron files.
- #setup_pipeline ⇒ Object
-
#source_dir ⇒ Object
Path to the directory containing the main app files.
- #store_cache ⇒ Object
-
#teardown ⇒ Object
Make sure to get rid of the build directory.
-
#update_config ⇒ Object
Update existing config with the one from .pkgr.yml file, if any.
- #vendor_dir ⇒ Object
- #verify ⇒ Object
-
#write_env ⇒ Object
Parses the output of buildpack/bin/release executable to find out its default Procfile commands.
-
#write_init ⇒ Object
Write startup scripts.
Constructor Details
#initialize(tarball, config) ⇒ Builder
Accepts a path to a tarball (gzipped or not), or you can pass ‘-’ to read from stdin.
15 16 17 18 19 |
# File 'lib/pkgr/builder.rb', line 15 def initialize(tarball, config) @tarball = tarball @config = config Pkgr.debug "Initializing builder with the following config: #{config.inspect}" end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
12 13 14 |
# File 'lib/pkgr/builder.rb', line 12 def config @config end |
#tarball ⇒ Object (readonly)
Returns the value of attribute tarball.
12 13 14 |
# File 'lib/pkgr/builder.rb', line 12 def tarball @tarball end |
Instance Method Details
#app_home_dir ⇒ Object
Some buildpacks may need the target home dir to exist
269 270 271 |
# File 'lib/pkgr/builder.rb', line 269 def app_home_dir config.home end |
#build_dir ⇒ Object
Build directory. Will be used by fpm to make the package.
246 247 248 |
# File 'lib/pkgr/builder.rb', line 246 def build_dir @build_dir ||= Dir.mktmpdir end |
#buildpack_for_app ⇒ Object
Buildpack detected for the app, if any.
294 295 296 297 298 299 300 |
# File 'lib/pkgr/builder.rb', line 294 def buildpack_for_app raise "#{source_dir} does not exist" unless File.directory?(source_dir) @buildpack_for_app ||= buildpacks.find do |buildpack| buildpack.setup(config.edge, config.home) buildpack.detect(source_dir) end end |
#buildpacks ⇒ Object
List of available buildpacks for the current distribution.
289 290 291 |
# File 'lib/pkgr/builder.rb', line 289 def buildpacks distribution.buildpacks end |
#call ⇒ Object
Launch the full packaging procedure
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/pkgr/builder.rb', line 22 def call extract update_config check setup setup_pipeline compile write_env write_init setup_crons package store_cache ensure teardown if config.clean end |
#check ⇒ Object
Check configuration, and verifies that the current distribution’s requirements are satisfied
88 89 90 91 |
# File 'lib/pkgr/builder.rb', line 88 def check raise Errors::ConfigurationInvalid, config.errors.join("; ") unless config.valid? distribution.check end |
#compile ⇒ Object
Pass the app through the buildpack
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/pkgr/builder.rb', line 109 def compile if buildpack_for_app puts "-----> #{buildpack_for_app.} app" begin FileUtils.mkdir_p(app_home_dir) rescue Errno::EACCES => e Pkgr.logger.warn "Can't create #{app_home_dir.inspect}, which may be needed by some buildpacks." end FileUtils.mkdir_p(compile_cache_dir) FileUtils.mkdir_p(compile_env_dir) run_hook config.before_hook buildpack_for_app.compile(source_dir, compile_cache_dir, compile_env_dir) buildpack_for_app.release(source_dir) run_hook config.after_hook else raise Errors::UnknownAppType, "Can't find a buildpack for your app" end end |
#compile_cache_dir ⇒ Object
Directory where the buildpacks can store stuff.
274 275 276 |
# File 'lib/pkgr/builder.rb', line 274 def compile_cache_dir config.compile_cache_dir || File.join(source_dir, ".git/cache") end |
#compile_env_dir ⇒ Object
Directory where the buildpacks can store config envs.
279 280 281 |
# File 'lib/pkgr/builder.rb', line 279 def compile_env_dir config.compile_env_dir ||= Dir.mktmpdir end |
#config_file ⇒ Object
236 237 238 |
# File 'lib/pkgr/builder.rb', line 236 def config_file File.join(source_dir, ".pkgr.yml") end |
#distribution ⇒ Object
Returns the current distribution we’re packaging for.
284 285 286 |
# File 'lib/pkgr/builder.rb', line 284 def distribution @distribution ||= Distributions.current(config) end |
#extract ⇒ Object
Extract the given tarball to the target directory
39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/pkgr/builder.rb', line 39 def extract FileUtils.mkdir_p source_dir opts = {} if tarball == "-" # FIXME: not really happy with reading everything in memory opts[:input] = $stdin.read end tarball_extract = Mixlib::ShellOut.new("tar xzf #{tarball} -C #{source_dir}", opts) tarball_extract.logger = Pkgr.logger tarball_extract.run_command tarball_extract.error! end |
#fpm_command ⇒ Object
302 303 304 |
# File 'lib/pkgr/builder.rb', line 302 def fpm_command distribution.fpm_command(build_dir) end |
#package(remaining_attempts = 3) ⇒ Object
Launch the FPM command that will generate the package.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/pkgr/builder.rb', line 178 def package(remaining_attempts = 3) app_package = Mixlib::ShellOut.new(fpm_command) app_package.logger = Pkgr.logger app_package.run_command app_package.error! begin verify rescue Mixlib::ShellOut::ShellCommandFailed => e if remaining_attempts > 0 package(remaining_attempts - 1) else raise end end end |
#pipeline ⇒ Object
77 78 79 80 81 82 83 84 85 |
# File 'lib/pkgr/builder.rb', line 77 def pipeline @pipeline ||= begin components = [] unless config.wizards.empty? || config.installer == false components << Installer.new(config.installer, distribution).setup end components end end |
#proc_dir ⇒ Object
Directory where binstubs will be created for the corresponding Procfile commands.
255 256 257 |
# File 'lib/pkgr/builder.rb', line 255 def proc_dir File.join(vendor_dir, "processes") end |
#procfile ⇒ Object
Returns the path to the app’s (supposedly present) Procfile.
264 265 266 |
# File 'lib/pkgr/builder.rb', line 264 def procfile File.join(source_dir, "Procfile") end |
#procfile_entries ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/pkgr/builder.rb', line 211 def procfile_entries @procfile_entries ||= begin default_process_types = YAML.load_file(release_file)["default_process_types"] default_process_types = {} unless default_process_types entries = if File.exist?(procfile) File.read(procfile).gsub("\r\n","\n").split("\n").map do |line| if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/ [$1, $2] end end.compact else [] end default_process_types.merge(Hash[entries]).map{|name, command| Process.new(name, command)} end end |
#release_file ⇒ Object
Path to the release file generated after the buildpack compilation.
232 233 234 |
# File 'lib/pkgr/builder.rb', line 232 def release_file File.join(source_dir, ".release") end |
#scaling_dir ⇒ Object
259 260 261 |
# File 'lib/pkgr/builder.rb', line 259 def scaling_dir File.join(vendor_dir, "scaling") end |
#setup ⇒ Object
Setup the build directory structure
94 95 96 97 98 99 100 |
# File 'lib/pkgr/builder.rb', line 94 def setup Dir.chdir(build_dir) do distribution.templates.each do |template| template.install(config.sesame) end end end |
#setup_crons ⇒ Object
Write cron files
164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/pkgr/builder.rb', line 164 def setup_crons crons_dir = File.join("/", distribution.crons_dir) config.crons.map! do |cron_path| Cron.new(File.(cron_path, config.home), File.join(crons_dir, File.basename(cron_path))) end config.crons.each do |cron| puts "-----> [cron] #{cron.source} => #{cron.destination}" end end |
#setup_pipeline ⇒ Object
102 103 104 105 106 |
# File 'lib/pkgr/builder.rb', line 102 def setup_pipeline pipeline.each do |component| @config = component.call(config) end end |
#source_dir ⇒ Object
Path to the directory containing the main app files.
241 242 243 |
# File 'lib/pkgr/builder.rb', line 241 def source_dir File.join(build_dir, config.home) end |
#store_cache ⇒ Object
199 200 201 202 203 204 |
# File 'lib/pkgr/builder.rb', line 199 def store_cache return true unless config.store_cache generate_cache_tarball = Mixlib::ShellOut.new %{tar czf cache.tar.gz -C #{compile_cache_dir} .} generate_cache_tarball.logger = Pkgr.logger generate_cache_tarball.run_command end |
#teardown ⇒ Object
Make sure to get rid of the build directory
207 208 209 |
# File 'lib/pkgr/builder.rb', line 207 def teardown FileUtils.rm_rf(build_dir) end |
#update_config ⇒ Object
Update existing config with the one from .pkgr.yml file, if any
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/pkgr/builder.rb', line 55 def update_config if File.exist?(config_file) Pkgr.debug "Loading #{distribution.slug} from #{config_file}." @config = Config.load_file(config_file, distribution.slug).merge(config) Pkgr.debug "Found .pkgr.yml file. Updated config is now: #{config.inspect}" # update distribution config distribution.config = @config # FIXME: make Config the authoritative source of the runner config (distribution only tells the default runner) if @config.runner type, *version = @config.runner.split("-") distribution.runner = Distributions::Runner.new(type, version.join("-")) end end config.distribution = distribution config.env.variables.push("TARGET=#{distribution.target}") # useful for templates that need to read files config.source_dir = source_dir config.build_dir = build_dir end |
#vendor_dir ⇒ Object
250 251 252 |
# File 'lib/pkgr/builder.rb', line 250 def vendor_dir File.join(source_dir, "vendor", "pkgr") end |
#verify ⇒ Object
194 195 196 197 |
# File 'lib/pkgr/builder.rb', line 194 def verify return true unless config.verify distribution.verify(Dir.pwd) end |
#write_env ⇒ Object
Parses the output of buildpack/bin/release executable to find out its default Procfile commands. Then merges those with the ones from the app’s Procfile (if any). Finally, generates a binstub in vendor/pkgr/processes/ so that these commands can be called using the app’s executable.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/pkgr/builder.rb', line 133 def write_env FileUtils.mkdir_p proc_dir procfile_entries.each do |process| process_file = File.join(proc_dir, process.name) File.open(process_file, "w+") do |f| f.puts "#!/bin/sh" f << "exec " f << process.command f << " $@" end FileUtils.chmod 0755, process_file end end |
#write_init ⇒ Object
Write startup scripts.
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/pkgr/builder.rb', line 151 def write_init FileUtils.mkdir_p scaling_dir Dir.chdir(scaling_dir) do distribution.initializers_for(config.name, procfile_entries).each do |(process, file)| process_config = config.dup process_config.process_name = process.name process_config.process_command = process.command file.install(process_config.sesame) end end end |