jets 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -3
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +23 -1
  6. data/jets.gemspec +1 -2
  7. data/lib/jets.rb +5 -11
  8. data/lib/jets/builders/gem_replacer.rb +12 -96
  9. data/lib/jets/builders/ruby_packager.rb +3 -4
  10. data/lib/jets/builders/tidy.rb +9 -0
  11. data/lib/jets/commands.rb +1 -0
  12. data/lib/jets/commands/base.rb +10 -1
  13. data/lib/jets/commands/gems.rb +25 -0
  14. data/lib/jets/commands/help/gems/check.md +7 -0
  15. data/lib/jets/commands/help/import/rails.md +3 -3
  16. data/lib/jets/commands/import.rb +4 -0
  17. data/lib/jets/commands/import/base.rb +10 -0
  18. data/lib/jets/commands/import/cheatsheet.rb +35 -0
  19. data/lib/jets/commands/import/rail.rb +7 -0
  20. data/lib/jets/commands/import/sequence.rb +63 -47
  21. data/lib/jets/commands/import/templates/submodules-cheatsheet.md +89 -0
  22. data/lib/jets/db.rb +9 -0
  23. data/lib/jets/version.rb +1 -1
  24. data/vendor/jets-gems/Gemfile +6 -0
  25. data/vendor/jets-gems/Gemfile.lock +39 -0
  26. data/vendor/jets-gems/LICENSE.txt +21 -0
  27. data/vendor/jets-gems/README.md +19 -0
  28. data/vendor/{lambdagem → jets-gems}/Rakefile +2 -2
  29. data/vendor/jets-gems/bin/console +14 -0
  30. data/vendor/jets-gems/bin/setup +8 -0
  31. data/vendor/jets-gems/jets-gems.gemspec +30 -0
  32. data/vendor/jets-gems/lib/jets-gems.rb +1 -0
  33. data/vendor/jets-gems/lib/jets/gems.rb +16 -0
  34. data/vendor/jets-gems/lib/jets/gems/check.rb +156 -0
  35. data/vendor/jets-gems/lib/jets/gems/exist.rb +54 -0
  36. data/vendor/jets-gems/lib/jets/gems/extract.rb +7 -0
  37. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/base.rb +25 -6
  38. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/gem.rb +10 -8
  39. data/vendor/{lambdagem/lib/lambdagem → jets-gems/lib/jets/gems}/extract/ruby.rb +6 -7
  40. data/vendor/jets-gems/lib/jets/gems/report.rb +53 -0
  41. data/vendor/jets-gems/lib/jets/gems/version.rb +5 -0
  42. data/vendor/jets-gems/spec/jets/gems_spec.rb +5 -0
  43. data/vendor/jets-gems/spec/spec_helper.rb +14 -0
  44. metadata +41 -53
  45. data/vendor/lambdagem/CHANGELOG.md +0 -27
  46. data/vendor/lambdagem/Gemfile +0 -6
  47. data/vendor/lambdagem/Gemfile.lock +0 -73
  48. data/vendor/lambdagem/Guardfile +0 -12
  49. data/vendor/lambdagem/LICENSE.txt +0 -22
  50. data/vendor/lambdagem/README.md +0 -139
  51. data/vendor/lambdagem/exe/lambdagem +0 -14
  52. data/vendor/lambdagem/lambdagem.gemspec +0 -32
  53. data/vendor/lambdagem/lib/lambdagem.rb +0 -18
  54. data/vendor/lambdagem/lib/lambdagem/base.rb +0 -53
  55. data/vendor/lambdagem/lib/lambdagem/build.rb +0 -202
  56. data/vendor/lambdagem/lib/lambdagem/clean.rb +0 -8
  57. data/vendor/lambdagem/lib/lambdagem/cli.rb +0 -62
  58. data/vendor/lambdagem/lib/lambdagem/command.rb +0 -38
  59. data/vendor/lambdagem/lib/lambdagem/exist.rb +0 -50
  60. data/vendor/lambdagem/lib/lambdagem/extract.rb +0 -8
  61. data/vendor/lambdagem/lib/lambdagem/extract/class_methods.rb +0 -50
  62. data/vendor/lambdagem/lib/lambdagem/help.rb +0 -9
  63. data/vendor/lambdagem/lib/lambdagem/help/all.md +0 -11
  64. data/vendor/lambdagem/lib/lambdagem/help/build.md +0 -14
  65. data/vendor/lambdagem/lib/lambdagem/help/clean.md +0 -5
  66. data/vendor/lambdagem/lib/lambdagem/help/extract_gem.md +0 -5
  67. data/vendor/lambdagem/lib/lambdagem/help/extract_ruby.md +0 -5
  68. data/vendor/lambdagem/lib/lambdagem/help/package.md +0 -20
  69. data/vendor/lambdagem/lib/lambdagem/help/upload.md +0 -7
  70. data/vendor/lambdagem/lib/lambdagem/package.rb +0 -33
  71. data/vendor/lambdagem/lib/lambdagem/upload.rb +0 -39
  72. data/vendor/lambdagem/lib/lambdagem/util.rb +0 -30
  73. data/vendor/lambdagem/lib/lambdagem/version.rb +0 -3
  74. data/vendor/lambdagem/spec/lib/build_spec.rb +0 -32
  75. data/vendor/lambdagem/spec/lib/cli_spec.rb +0 -24
  76. data/vendor/lambdagem/spec/lib/upload_spec.rb +0 -25
  77. data/vendor/lambdagem/spec/spec_helper.rb +0 -24
@@ -0,0 +1 @@
1
+ require "jets/gems"
@@ -0,0 +1,16 @@
1
+ require "jets/gems/version"
2
+
3
+ module Jets
4
+ module Gems
5
+ autoload :Check, 'jets/gems/check'
6
+ autoload :Exist, 'jets/gems/exist'
7
+ autoload :Extract, 'jets/gems/extract'
8
+ autoload :Report, 'jets/gems/report'
9
+
10
+ def ruby_version_folder
11
+ major, minor, patch = RUBY_VERSION.split('.')
12
+ [major, minor, '0'].join('.') # 2.5.1 => 2.5.0
13
+ end
14
+ extend self
15
+ end
16
+ end
@@ -0,0 +1,156 @@
1
+ # Assumes gems were just built and checks the filesystem to find and detect for
2
+ # compiled gems. Unless the cli option is set to true, the it'll just check
3
+ # based on the gemspecs.
4
+ module Jets::Gems
5
+ class Check
6
+ extend Memoist
7
+
8
+ attr_reader :missing_gems
9
+ def initialize(options={})
10
+ @options = options
11
+ @missing_gems = [] # keeps track of gems that are not found in any of the lambdagems sources
12
+ end
13
+
14
+ # Checks whether the gem is found on at least one of the lambdagems sources.
15
+ # By the time the loop finishes, found_gems will hold a map of gem names to found
16
+ # url sources. Example:
17
+ #
18
+ # found_gems = {
19
+ # "nokogiri-1.8.4" => "https://lambdagems.com",
20
+ # "pg-0.21.0" => "https://anothersource.com",
21
+ # }
22
+ #
23
+ def run
24
+ puts "Checking projects gems for pre-built Lambda gems..."
25
+ found_gems = {}
26
+ compiled_gems.each do |gem_name|
27
+ puts "Checking #{gem_name}..." if @options[:cli]
28
+ gem_exists = false
29
+ Jets.config.lambdagems.sources.each do |source|
30
+ exist = Jets::Gems::Exist.new(source_url: source)
31
+ found = exist.check(gem_name)
32
+ # gem exists on at least of the lambdagem sources
33
+ if found
34
+ gem_exists = true
35
+ found_gems[gem_name] = source
36
+ break
37
+ end
38
+ end
39
+ unless gem_exists
40
+ @missing_gems << gem_name
41
+ end
42
+ end
43
+ found_gems
44
+ end
45
+
46
+ def missing?
47
+ !@missing_gems.empty?
48
+ end
49
+
50
+ def missing_message
51
+ template = <<-EOL
52
+ Your project requires compiled gems were not available in any of your lambdagems sources. Unavailable pre-compiled gems:
53
+ <% missing_gems.each do |gem| %>
54
+ * <%= gem -%>
55
+ <% end %>
56
+
57
+ Your current lambdagems sources:
58
+ <% Jets.config.lambdagems.sources.map do |source| %>
59
+ * <%= source -%>
60
+ <% end %>
61
+
62
+ Jets is unable to build a deployment package that will work on AWS Lambda without the required pre-compiled gems. To remedy this, you can:
63
+
64
+ * Build the gem yourself and add it to your own custom lambdagems sources. Refer to the Lambda Gems Docs: http://rubyonjets.com/docs/lambdagems
65
+ * Wait until it added to lambdagems.com. No need to report this to us, as we've already been notified.
66
+ * Use another gem that does not require compilation.
67
+
68
+ Compiled gems usually take some time to figure out how to build as they each depend on different libraries and packages. We make an effort add new gems as soon as we can.
69
+ EOL
70
+ erb = ERB.new(template, nil, '-') # trim mode https://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
71
+ erb.result(binding)
72
+ end
73
+
74
+ # If there are subfolders compiled_gem_paths might have files deeper
75
+ # in the directory tree. So lets grab the gem name and figure out the
76
+ # unique paths of the compiled gems from there.
77
+ def compiled_gems
78
+ # @use_gemspec option finds compile gems with Gem::Specification
79
+ # The normal build process does not use this and checks the file system.
80
+ # So @use_gemspec is only used for this command:
81
+ #
82
+ # jets gems:check
83
+ #
84
+ # This is because it seems like some gems like json are remove and screws things up.
85
+ # We'll filter out for the json gem as a hacky workaround, unsure if there are more
86
+ # gems though that exhibit this behavior.
87
+ if @options[:cli]
88
+ gemspec_compiled_gems
89
+ else
90
+ compiled_gems = compiled_gem_paths.map { |p| gem_name_from_path(p) }.uniq
91
+ # Double check that the gems are also in the gemspec list since that
92
+ # one is scoped to Bundler and will only included gems used in the project.
93
+ # This handles the possiblity of stale gems leftover from previous builds
94
+ # in the cache.
95
+ compiled_gems.select { |g| gemspec_compiled_gems.include?(g) }
96
+ end
97
+ end
98
+ memoize :compiled_gems
99
+
100
+ # Use pre-compiled gem because the gem could have development header shared
101
+ # object file dependencies. The shared dependencies are packaged up as part
102
+ # of the pre-compiled gem so it is available in the Lambda execution environment.
103
+ #
104
+ # Example paths:
105
+ # Macosx:
106
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/nokogiri-1.8.1
107
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/byebug-9.1.0
108
+ # Official AWS Lambda Linux AMI:
109
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/nokogiri-1.8.1
110
+ # Circleci Ubuntu based Linux:
111
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0/pg-0.21.0
112
+ def compiled_gem_paths
113
+ Dir.glob("#{Jets.build_root}/cache/bundled/gems/ruby/*/extensions/**/**/*.{so,bundle}")
114
+ end
115
+
116
+ # Input: bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/byebug-9.1.0
117
+ # Output: byebug-9.1.0
118
+ def gem_name_from_path(path)
119
+ regexp = /gems\/ruby\/\d+\.\d+\.\d+\/extensions\/.*?\/.*?\/(.*?)\//
120
+ gem_name = path.match(regexp)[1]
121
+ end
122
+
123
+ # So can also check for compiled gems with Gem::Specification
124
+ # But then also includes the json gem, which then bundler removes?
125
+ # We'll figure out the the json gems.
126
+ # https://gist.github.com/tongueroo/16f4aa5ac5393424103347b0e529495e
127
+ #
128
+ # This is a faster way to check but am unsure if there are more gems than just
129
+ # json that exhibit this behavior. So only using this technique for this commmand:
130
+ #
131
+ # jets gems:check
132
+ #
133
+ # Thanks: https://gist.github.com/aelesbao/1414b169a79162b1d795 and
134
+ # https://stackoverflow.com/questions/5165950/how-do-i-get-a-list-of-gems-that-are-installed-that-have-native-extensions
135
+ def specs_with_extensions
136
+ specs = Gem::Specification.each.select { |spec| spec.extensions.any? }
137
+ specs.reject! { |spec| weird_gems.include?(spec.name) }
138
+ specs
139
+ end
140
+
141
+ def gemspec_compiled_gems
142
+ specs_with_extensions.map(&:full_name)
143
+ end
144
+
145
+ # Filter out the weird special case gems that bundler deletes?
146
+ # Probably to fix some bug.
147
+ #
148
+ # $ bundle show json
149
+ # The gem json has been deleted. It was installed at:
150
+ # /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/json-2.1.0
151
+ #
152
+ def weird_gems
153
+ %w[json]
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,54 @@
1
+ module Jets::Gems
2
+ class Exist
3
+ def initialize(options)
4
+ @options = options
5
+ end
6
+
7
+ # We check all the availability before even downloading so we can provide a
8
+ # full list of gems they might want to research all at once instead of incrementally
9
+ #
10
+ # Examples:
11
+ #
12
+ # check(single_gem)
13
+ # check(list, of, gems)
14
+ def check(*gem_names)
15
+ gem_names = gem_names.flatten
16
+ exists = gem_names.inject({}) do |hash, gem_name|
17
+ exist = url_exists?(gem_url(gem_name))
18
+ hash[gem_name] = exist
19
+ hash.merge(hash)
20
+ end
21
+
22
+ exists.values.all? {|v| v } # all_exist
23
+ end
24
+
25
+ # Example url:
26
+ # https://gems.lambdagems.com/gems/2.5.0/byebug/byebug-9.1.0-x86_64-linux.tgz
27
+ def url_exists?(url)
28
+ url = URI.parse(url)
29
+ req = Net::HTTP.new(url.host, url.port).tap do |http|
30
+ http.use_ssl = true
31
+ end
32
+ res = req.request_head(url.path)
33
+ res.code == "200"
34
+ rescue SocketError, OpenURI::HTTPError
35
+ false
36
+ end
37
+
38
+ def source_url
39
+ @options[:source_url] || s3_url
40
+ end
41
+
42
+ # gem_name: byebug-9.1.0
43
+ # Example url:
44
+ # https://gems.lambdagems.com/gems/2.5.0/byebug/byebug-9.1.0-x86_64-linux.tgz
45
+ def gem_url(gem_name)
46
+ folder = gem_name.gsub(/-(\d+\.\d+\.\d+.*)/,'') # folder: byebug
47
+ "#{source_url}/gems/#{Jets::Gems.ruby_version_folder}/#{folder}/#{gem_name}-x86_64-linux.tgz"
48
+ end
49
+
50
+ def ruby_version_folder
51
+ Jets::Gems.ruby_version_folder
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,7 @@
1
+ module Jets::Gems
2
+ module Extract
3
+ autoload :Base, 'jets/gems/extract/base'
4
+ autoload :Gem, 'jets/gems/extract/gem'
5
+ autoload :Ruby, 'jets/gems/extract/ruby'
6
+ end
7
+ end
@@ -1,13 +1,20 @@
1
1
  require "open-uri"
2
2
 
3
- module Lambdagem::Extract
4
- autoload :ClassMethods, 'lambdagem/extract/class_methods'
3
+ module Jets::Gems::Extract
4
+ class Base
5
+ class NotFound < RuntimeError; end
5
6
 
6
- class Base < Lambdagem::Base
7
- extend ClassMethods
7
+ attr_reader :source_url
8
+ def initialize(name, options={})
9
+ @name = name
10
+ @options = options
11
+
12
+ @downloads_root = options[:downloads_root] || "/tmp/jets/lambdagems"
13
+ @source_url = options[:source_url] || "https://gems.lambdagems.com"
14
+ end
8
15
 
9
16
  def clean_downloads(folder)
10
- path = "#{@build_root}/downloads/#{folder}"
17
+ path = "#{@downloads_root}/downloads/#{folder}"
11
18
  say "Removing cache: #{path}"
12
19
  FileUtils.rm_rf(path)
13
20
  end
@@ -31,7 +38,8 @@ module Lambdagem::Extract
31
38
  end
32
39
 
33
40
  def url_exists?(url)
34
- self.class.url_exists?(url)
41
+ exist = Jets::Gems::Exist.new(@options)
42
+ exist.url_exists?(url)
35
43
  end
36
44
 
37
45
  # Returns the dest path
@@ -58,5 +66,16 @@ module Lambdagem::Extract
58
66
  def project_root
59
67
  @options[:project_root] || "."
60
68
  end
69
+
70
+ @@log_level = :info # default level is :info
71
+ # @@log_level = :debug # uncomment to debug
72
+ def log_level=(val)
73
+ @@log_level = val
74
+ end
75
+
76
+ def say(message, level=:info)
77
+ enabled = @@log_level == :debug || level == :debug
78
+ puts(message) if enabled
79
+ end
61
80
  end
62
81
  end
@@ -2,18 +2,17 @@ require "gems"
2
2
 
3
3
  # Usage:
4
4
  #
5
- # Lambdagem::Extract::Gem.new("pg-0.21.0",
6
- # s3: "lambdagems",
7
- # build_root: cache_area, # defaults to /tmp/lambdagem
5
+ # Jets::Gems::Extract::Gem.new("pg-0.21.0",
6
+ # downloads_root: cache_area, # defaults to /tmp/lambdagem
8
7
  # dest: cache_area, # defaults to . (project_root)
9
8
  # ).run
10
9
  #
11
- module Lambdagem::Extract
10
+ module Jets::Gems::Extract
12
11
  class Gem < Base
13
12
  VERSION_PATTERN = /-(\d+\.\d+\.\d+.*)/
14
13
 
15
14
  def run
16
- say "Looking for #{full_gem_name} gem in: #{@options[:lambdagems_url]}"
15
+ say "Looking for #{full_gem_name} gem in: #{@options[:source_url]}"
17
16
  clean_downloads(:gems) if @options[:clean]
18
17
  tarball_path = download_gem
19
18
  remove_current_gem
@@ -25,7 +24,6 @@ module Lambdagem::Extract
25
24
  def full_gem_name
26
25
  return @full_gem_name if @full_gem_name
27
26
 
28
- @name # TODO: make sure that we always have the full gem name with version number
29
27
  if @name.match(VERSION_PATTERN)
30
28
  @full_gem_name = @name
31
29
  return @full_gem_name
@@ -67,7 +65,7 @@ module Lambdagem::Extract
67
65
  end
68
66
 
69
67
  def download_path(filename)
70
- "#{@build_root}/downloads/gems/#{filename}"
68
+ "#{@downloads_root}/downloads/gems/#{filename}"
71
69
  end
72
70
 
73
71
  # Finds any currently install gems that matched with the gem name and version
@@ -90,7 +88,11 @@ module Lambdagem::Extract
90
88
 
91
89
  # full_gem_name: byebug-9.1.0
92
90
  def gem_url
93
- "#{lambdagems_url}/gems/#{jets_ruby_version}/#{gem_name}/#{full_gem_name}-x86_64-linux.tgz"
91
+ "#{source_url}/gems/#{ruby_version_folder}/#{gem_name}/#{full_gem_name}-x86_64-linux.tgz"
92
+ end
93
+
94
+ def ruby_version_folder
95
+ Jets::Gems.ruby_version_folder
94
96
  end
95
97
  end
96
98
  end
@@ -1,12 +1,11 @@
1
1
  # Usage:
2
2
  #
3
- # Lambdagem::Extract::Ruby.new("2.5.0",
4
- # s3: "lambdagems",
5
- # build_root: cache_area, # defaults to /tmp/lambdagem
3
+ # Jets::Gems::Extract::Ruby.new("2.5.0",
4
+ # downloads_root: cache_area, # defaults to /tmp/lambdagem
6
5
  # dest: cache_area, # defaults to . (project_root)
7
6
  # ).run
8
7
  #
9
- module Lambdagem::Extract
8
+ module Jets::Gems::Extract
10
9
  class Ruby < Base
11
10
  class NotFound < RuntimeError; end
12
11
 
@@ -25,7 +24,7 @@ module Lambdagem::Extract
25
24
  message = "Url: #{url} not found"
26
25
  if @options[:exit_on_error]
27
26
  say message
28
- # exit # TODO: ADD BACK IN
27
+ exit
29
28
  else
30
29
  raise NotFound.new(message)
31
30
  end
@@ -35,7 +34,7 @@ module Lambdagem::Extract
35
34
  end
36
35
 
37
36
  def download_path(filename)
38
- "#{@build_root}/downloads/rubies/#{filename}"
37
+ "#{@downloads_root}/downloads/rubies/#{filename}"
39
38
  end
40
39
 
41
40
  # If only the ruby version is given, then append ruby- in front. Otherwise
@@ -57,7 +56,7 @@ module Lambdagem::Extract
57
56
  end
58
57
 
59
58
  def ruby_url
60
- "#{lambdagems_url}/rubies/#{full_ruby_name}"
59
+ "#{source_url}/rubies/#{full_ruby_name}"
61
60
  end
62
61
  end
63
62
  end
@@ -0,0 +1,53 @@
1
+ require "net/http"
2
+
3
+ module Jets::Gems
4
+ class Report
5
+ LAMBDAGEM_API_URL = ENV["LAMBDAGEM_API_URL"] || "https://api.lambdagems.com/api/v1"
6
+
7
+ def self.missing(gems)
8
+ new(gems).report
9
+ end
10
+
11
+ def initialize(gems)
12
+ @gems = gems
13
+ end
14
+
15
+ def report
16
+ version_pattern = /(.*)-(\d+\.\d+\.\d+.*)/
17
+ threads = []
18
+ @gems.each do |gem_name|
19
+ if md = gem_name.match(version_pattern)
20
+ name, version = md[1], md[2]
21
+ threads << Thread.new do
22
+ call_api("report/missing?name=#{name}&version=#{version}")
23
+ end
24
+ else
25
+ puts "WARN: Unable to extract the version from the gem name."
26
+ end
27
+ end
28
+ # Wait for request to finish because the command might finish before
29
+ # the Threads even send the request. So we join them just case
30
+ threads.each(&:join)
31
+ end
32
+
33
+ def api_url(path)
34
+ "#{LAMBDAGEM_API_URL}/#{path}"
35
+ end
36
+
37
+ def call_api(path)
38
+ # raise "HI"
39
+ uri = URI(api_url(path))
40
+ http = Net::HTTP.new(uri.host, uri.port)
41
+ http.use_ssl = uri.scheme == "https"
42
+ request = Net::HTTP::Get.new(uri)
43
+ response = http.request(request)
44
+ resp = {
45
+ status: response.code.to_i,
46
+ headers: response.each_header.to_h,
47
+ body: response.body,
48
+ }
49
+ # pp resp # Uncomment to debug
50
+ resp
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module Jets
2
+ module Gems
3
+ VERSION = "0.1.0"
4
+ end
5
+ end