bundler-source-aws-s3 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +87 -0
  3. data/plugins.rb +146 -0
  4. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a4d5919d913b511b4bd0cc2bbc5cb08bed308eb5ccc10d8790d094c107eb88e1
4
+ data.tar.gz: 120ca809b0c776de957420b09c6ce851d3cd1b02f67ab0fd66c0ca8f122c9c81
5
+ SHA512:
6
+ metadata.gz: 458a8571991308cc317c652a6aabeebf37eaaa58572ee2e6829135dd369ca653419fb6138574258cdf9da47f272996750c714d8301915a68c625ef421a044b5a
7
+ data.tar.gz: ff95b41d255ce9e9a8e691c0778f15e2b32c5bda6daa6829ab5bdaf47f1159e4753cd8f2956233ab329d687ad0ab6f5cc2dbc297bc1ca96248a89a72bdf1de9a
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Bundler-Source-Aws-S3
2
+
3
+ This is a bundler plugin which adds support for s3 as a source for gems.
4
+
5
+ ## Installation
6
+
7
+ ### Setup the aws cli
8
+
9
+ There are multiple ways to [install the aws
10
+ cli](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
11
+ (including [homebrew](https://formulae.brew.sh/formula/awscli)). This plugin
12
+ will use the aws cli to pull gems from your s3 source. There is an expectation
13
+ that if you want to use s3 as a gem source, you'll probably already have this
14
+ installed.
15
+
16
+ ### Setup s3 as a gem source
17
+
18
+ First, you should already have gems in s3 and you should be able to install
19
+ them with Rubygems. Follow the [guide for using s3 as a gem
20
+ source](https://guides.rubygems.org/using-s3-source/).
21
+
22
+ For this plugin to work the aws cli should be able to fetch your gems. The
23
+ plugin will run a command like `aws s3 sync s3://your-source <local path>` and
24
+ you may want to verify that you have aws cli setup correctly (permissions,
25
+ etc) to be able to run that command.
26
+
27
+ ### Add aws-s3 source to your Gemfile
28
+
29
+ In your Gemfile, add a source like this:
30
+
31
+ ```ruby
32
+ source('s3://my-bucket/gems', type: 'aws-s3') do
33
+ gem 'my-cool-gem'
34
+ end
35
+ ```
36
+
37
+ When Bundler sees the `type: 'aws-s3'` it will automatically install and use
38
+ this plugin to install gems from your s3 source.
39
+
40
+ ## Development
41
+
42
+ We don't have a very good development story (there are no tests, yay!). You'll
43
+ want to fork this repository and use your own fork by adding this to a
44
+ `Gemfile` that you plan to use to test your fork:
45
+
46
+ ```ruby
47
+ plugin 'bundler-source-aws-s3', git: 'https://github.com/<you>/bundler-source-aws-s3.git'
48
+ ```
49
+
50
+ You may also want to wipe a few directories out as you test:
51
+
52
+ ```
53
+ rm -rf ./.bundle/plugin
54
+ rm -rf ~/.bundle/bundler-source-aws-s3
55
+ ```
56
+
57
+ You may also want to wipe out the `install_path` for the s3 uri you're testing
58
+ against. You can find that in irb by instantiating your plugin like:
59
+
60
+ ```ruby
61
+ >> BundlerSourceAwsS3::S3Source.new(uri: 's3://vying-gems').send(:install_path)
62
+ ```
63
+
64
+ Although this will only work if you're running irb in a directory with a
65
+ Gemfile and a `.bundle/` directory. These can be empty as of this writing.
66
+
67
+ It can also help to poke at the plugin in irb:
68
+
69
+ ```
70
+ irb -I . -r bundler -r plugins.rb
71
+ ```
72
+
73
+ ## Other s3 source plugins
74
+
75
+ As of this writing there is another gem called
76
+ [bundler-source-s3](https://rubygems.org/gems/bundler-source-s3) that doesn't
77
+ work and you probably don't want to confuse with this gem. If you use type 's3'
78
+ (instead of 'aws-s3') in your Gemfile you'll get that plugin, not this one.
79
+
80
+ ## Contributing
81
+
82
+ Bug reports and pull requests are welcome on GitHub at
83
+ https://github.com/eki/bundler-source-aws-s3.
84
+
85
+ ## License
86
+
87
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/plugins.rb ADDED
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'open3'
5
+ require 'rubygems/package'
6
+
7
+ class BundlerSourceAwsS3 < Bundler::Plugin::API
8
+ class S3Source < Bundler::Source
9
+ # Bundler plugin api, we need to install the gem for the given spec and
10
+ # then call post_install.
11
+ def install(spec, opts)
12
+ print_using_message "Using #{spec.name} #{spec.version} from #{self}"
13
+
14
+ validate!(spec)
15
+
16
+ package = package_for(spec)
17
+ destination = install_path.join(spec.full_name)
18
+
19
+ Bundler.mkdir_p(destination)
20
+ package.extract_files(destination)
21
+ File.open(spec.loaded_from, 'wb') { |f| f.write spec.to_ruby }
22
+
23
+ post_install(spec)
24
+ end
25
+
26
+ # Bundler plugin api, we need to return a Bundler::Index
27
+ def specs
28
+ # Only pull gems if bundler tells us to check remote
29
+ pull if remote?
30
+
31
+ # We haven't pulled any s3 gems if the directory doesn't exist, so we'll
32
+ # give bundler an empty index.
33
+ return Bundler::Index.new unless File.directory?(s3_gems_path)
34
+
35
+ Bundler::Index.build do |index|
36
+ packages.map(&:spec).each do |spec|
37
+ spec.source = self
38
+ spec.loaded_from = loaded_from_for(spec)
39
+
40
+ Bundler.rubygems.validate(spec)
41
+ index << spec
42
+ end
43
+ end
44
+ end
45
+
46
+ # Bundler calls this to tell us fetching remote gems is okay.
47
+ def remote!
48
+ @remote = true
49
+ end
50
+
51
+ def remote?
52
+ @remote
53
+ end
54
+
55
+ # TODO What is bundler telling us if unlock! is called?
56
+ def unlock!
57
+ puts "[aws-s3] DEBUG: unlock! called"
58
+ end
59
+
60
+ # TODO What is bundler telling us if cached! is called?
61
+ def cached!
62
+ puts "[aws-s3] DEBUG: cached! called"
63
+ end
64
+
65
+ def to_s
66
+ "aws-s3 plugin with uri #{uri}"
67
+ end
68
+
69
+ private
70
+
71
+ # This is a guard against attempting to install a spec that doesn't match
72
+ # our requirements / expectations.
73
+ #
74
+ # If we want to be more trusting, we could probably safely remove this
75
+ # method.
76
+ def validate!(spec)
77
+ unless spec.source == self && spec.loaded_from == loaded_from_for(spec)
78
+ raise "[aws-s3] Error #{spec.full_name} spec is not valid"
79
+ end
80
+ end
81
+
82
+ # We will use this value as the given spec's loaded_from. It should be the
83
+ # path fo the installed gem's gemspec.
84
+ def loaded_from_for(spec)
85
+ destination = install_path.join(spec.full_name)
86
+ destination.join("#{spec.full_name}.gemspec").to_s
87
+ end
88
+
89
+ # This path is going to be under bundler's gem_install_dir and we'll then
90
+ # mirror the bucket/path directory structure from the source. This is where
91
+ # we want to place our gems. This directory can hold multiple installed
92
+ # gems.
93
+ def install_path
94
+ @install_path ||= gem_install_dir.join(bucket).join(path)
95
+ end
96
+
97
+ # This is the path to the s3 gems for our source uri. We will pull the s3
98
+ # gems into this directory.
99
+ def s3_gems_path
100
+ Bundler.user_bundle_path.
101
+ join('bundler-source-aws-s3').join(bucket).join(path)
102
+ end
103
+
104
+ # Pull s3 gems from the source and store them in
105
+ # .bundle/bundler-source-aws-s3/<bucket>/<path>. We will install, etc, from
106
+ # this directory.
107
+ def pull
108
+ # We only want to pull once in a single bundler run.
109
+ return @pull if defined?(@pull)
110
+
111
+ Bundler.mkdir_p(s3_gems_path)
112
+
113
+ output, status = Open3.capture2e(sync_cmd)
114
+
115
+ @pull = status.success?
116
+ end
117
+
118
+ # Produces a list of Gem::Package for the s3 gems.
119
+ def packages
120
+ @packages ||= Dir.entries(s3_gems_path.join('gems')).
121
+ map { |entry| s3_gems_path.join('gems').join(entry) }.
122
+ select { |gem_path| File.file?(gem_path) }.
123
+ map { |gem_path| Gem::Package.new(gem_path.to_s) }
124
+ end
125
+
126
+ # Find the Gem::Package for a given spec.
127
+ def package_for(spec)
128
+ packages.find { |package| package.spec.full_name == spec.full_name }
129
+ end
130
+
131
+ def sync_cmd
132
+ "aws s3 sync --delete #{uri} #{s3_gems_path}"
133
+ end
134
+
135
+ def bucket
136
+ URI.parse(uri).normalize.host
137
+ end
138
+
139
+ def path
140
+ # Remove the leading slash from the path.
141
+ URI.parse(uri).normalize.path[1..-1]
142
+ end
143
+ end
144
+
145
+ source 'aws-s3', S3Source
146
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bundler-source-aws-s3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric K Idema
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Add aws-s3 source to bundler via plugin.
14
+ email:
15
+ - eki@vying.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - plugins.rb
22
+ homepage: https://github.com/eki/bundler-source-aws-s3
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.0.3
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Add aws-s3 source to bundler via plugin.
45
+ test_files: []