Class: S3GemHost::TaskHelper

Inherits:
Object
  • Object
show all
Extended by:
Rake::DSL
Includes:
Rake::DSL
Defined in:
lib/s3_gem_host/task_helper.rb

Overview

Service used for S3 Gem Host rake tasks

Constant Summary collapse

CACHE_DIR =
'./s3_gem_host_cache'
PACKAGE_DIR =
'./pkg'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(aws_access_key_id:, aws_secret_access_key:, bucket_name:, aws_region:) ⇒ TaskHelper

Returns a new instance of TaskHelper.



16
17
18
19
20
21
# File 'lib/s3_gem_host/task_helper.rb', line 16

def initialize(aws_access_key_id:, aws_secret_access_key:, bucket_name:, aws_region:)
  self.aws_access_key_id = aws_access_key_id
  self.aws_secret_access_key = aws_secret_access_key
  self.bucket_name = bucket_name
  self.aws_region = aws_region
end

Instance Attribute Details

#aws_access_key_idObject

Returns the value of attribute aws_access_key_id.



11
12
13
# File 'lib/s3_gem_host/task_helper.rb', line 11

def aws_access_key_id
  @aws_access_key_id
end

#aws_regionObject

Returns the value of attribute aws_region.



11
12
13
# File 'lib/s3_gem_host/task_helper.rb', line 11

def aws_region
  @aws_region
end

#aws_secret_access_keyObject

Returns the value of attribute aws_secret_access_key.



11
12
13
# File 'lib/s3_gem_host/task_helper.rb', line 11

def aws_secret_access_key
  @aws_secret_access_key
end

#bucket_nameObject

Returns the value of attribute bucket_name.



11
12
13
# File 'lib/s3_gem_host/task_helper.rb', line 11

def bucket_name
  @bucket_name
end

Class Method Details

.installObject

rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/BlockLength



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
75
76
77
78
79
80
81
82
83
84
# File 'lib/s3_gem_host/task_helper.rb', line 24

def self.install
  namespace :s3_gem_host do
    desc 'Publish a newly built gem version to S3. Run `rake build` first.'
    task :push do
      unless ENV['S3_GEM_HOST_BUCKET'] && ENV['S3_GEM_HOST_AWS_ACCESS_KEY_ID'] &&
          ENV['S3_GEM_HOST_AWS_SECRET_ACCESS_KEY']
        raise 'S3_GEM_HOST_BUCKET, S3_GEM_HOST_AWS_ACCESS_KEY_ID, and S3_GEM_HOST_AWS_SECRET_ACCESS_KEY '\
    'are required to be set in ENV'
      end

      helper = S3GemHost::TaskHelper.new(
        aws_access_key_id: ENV['S3_GEM_HOST_AWS_ACCESS_KEY_ID'],
        aws_secret_access_key: ENV['S3_GEM_HOST_AWS_SECRET_ACCESS_KEY'],
        bucket_name: ENV['S3_GEM_HOST_BUCKET'],
        aws_region: ENV['S3_GEM_HOST_AWS_REGION'] || 'us-east-1'
      )

      begin
        helper.bootstrap_directories!
        helper.clone_from_s3
        helper.copy_in_gem
        helper.create_index
        helper.upload_to_s3
      ensure
        helper.cleanup!
      end

      rake_output_message "#{helper.built_gem_file} pushed to S3 successfully."
    end

    desc 'Remove a previously published gem version from S3'
    task :yank, [:version] do |_t, args|
      raise ArgumentError, 'version is required' unless (version = args[:version])

      unless ENV['S3_GEM_HOST_BUCKET'] && ENV['S3_GEM_HOST_AWS_ACCESS_KEY_ID'] &&
          ENV['S3_GEM_HOST_AWS_SECRET_ACCESS_KEY']
        raise 'S3_GEM_HOST_BUCKET, S3_GEM_HOST_AWS_ACCESS_KEY_ID, and S3_GEM_HOST_AWS_SECRET_ACCESS_KEY '\
    'are required to be set in ENV'
      end

      helper = S3GemHost::TaskHelper.new(
        aws_access_key_id: ENV['S3_GEM_HOST_AWS_ACCESS_KEY_ID'],
        aws_secret_access_key: ENV['S3_GEM_HOST_AWS_SECRET_ACCESS_KEY'],
        bucket_name: ENV['S3_GEM_HOST_BUCKET'],
        aws_region: ENV['S3_GEM_HOST_AWS_REGION'] || 'us-east-1'
      )

      begin
        helper.bootstrap_directories!
        helper.clone_from_s3
        helper.delete_version!(version)
        helper.create_index
        helper.upload_to_s3
      ensure
        helper.cleanup!
      end

      rake_output_message "Yanked version #{version} from S3 successfully."
    end
  end
end

Instance Method Details

#bootstrap_directories!Object

rubocop:enable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/BlockLength



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/s3_gem_host/task_helper.rb', line 87

def bootstrap_directories!
  cleanup!

  mkdir CACHE_DIR
  rake_output_message "created #{CACHE_DIR}"

  gem_base_dir = "#{CACHE_DIR}/#{gem_name}"
  mkdir gem_base_dir
  rake_output_message "created #{gem_base_dir}"

  gems_dir = "#{CACHE_DIR}/#{gem_name}/gems"
  mkdir gems_dir
  rake_output_message "created #{gems_dir}"

  true
end

#bucketObject



175
176
177
178
179
180
# File 'lib/s3_gem_host/task_helper.rb', line 175

def bucket
  @bucket ||= Aws::S3::Resource.new(
    credentials: Aws::Credentials.new(self.aws_access_key_id, self.aws_secret_access_key),
    region: self.aws_region
  ).bucket(self.bucket_name)
end

#built_gem_fileObject



104
105
106
107
108
109
110
111
# File 'lib/s3_gem_host/task_helper.rb', line 104

def built_gem_file
  return @built_gem_file if @built_gem_file

  built_gem_file = File.join('./pkg', "#{gem_name}-#{gem_version}.gem")
  raise "Cannot find #{built_gem_file}" unless File.exist?(built_gem_file)

  @built_gem_file = File.basename(built_gem_file)
end

#cleanup!Object



190
191
192
193
194
195
# File 'lib/s3_gem_host/task_helper.rb', line 190

def cleanup!
  rm_rf(CACHE_DIR)
  rake_output_message "deleted #{CACHE_DIR}"

  true
end

#clone_from_s3Object



113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/s3_gem_host/task_helper.rb', line 113

def clone_from_s3
  prefix = "#{gem_name}/gems/"
  bucket.objects(prefix: prefix, delimiter: '/').each do |s3_obj|
    next if s3_obj.key == prefix # skip the directory S3 object itself

    new_file = File.join(CACHE_DIR, s3_obj.key)
    s3_obj.download_file(new_file)
    rake_output_message "copied #{s3_obj.key} to #{new_file}"
  end

  true
end

#copy_in_gemObject



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/s3_gem_host/task_helper.rb', line 126

def copy_in_gem
  # If the same gem file / version already exists in S3, stop release
  if File.exist?("#{CACHE_DIR}/#{gem_name}/gems/#{built_gem_file}")
    raise "This gem version already exists in the S3 bucket: #{self.bucket_name}"
  end

  # Copy the built gem into the s3 cache dir
  cp "./pkg/#{built_gem_file}", "#{CACHE_DIR}/#{gem_name}/gems"
  rake_output_message "copied #{built_gem_file} to #{CACHE_DIR}/#{gem_name}/gems"

  true
end

#create_indexObject



150
151
152
153
154
155
# File 'lib/s3_gem_host/task_helper.rb', line 150

def create_index
  sh "cd #{CACHE_DIR}/#{gem_name} && gem generate_index ."
  rake_output_message 'created gem version index'

  true
end

#delete_version!(version) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/s3_gem_host/task_helper.rb', line 139

def delete_version!(version)
  file = "#{CACHE_DIR}/#{gem_name}/gems/#{gem_name}-#{version}.gem"
  raise "Gem #{File.basename(file)} could not be found" unless File.exist?(file)

  rm_f file
  obj = bucket.object(file.sub(%r{^#{CACHE_DIR}/}, ''))
  obj.delete

  true
end

#gem_nameObject



182
183
184
# File 'lib/s3_gem_host/task_helper.rb', line 182

def gem_name
  gemspec.name
end

#gem_versionObject



186
187
188
# File 'lib/s3_gem_host/task_helper.rb', line 186

def gem_version
  gemspec.version
end

#gemspecObject



197
198
199
200
201
202
203
204
# File 'lib/s3_gem_host/task_helper.rb', line 197

def gemspec
  return @gemspec if @gemspec

  gemspecs = Dir[File.join(Dir.getwd, '{,*}.gemspec')]
  raise 'Unable to find gemspec' unless gemspecs.any?

  @gemspec = Bundler.load_gemspec(gemspecs.first)
end

#upload_to_s3Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/s3_gem_host/task_helper.rb', line 157

def upload_to_s3
  # Sync the local cache dir up to S3
  files_to_upload = Dir["#{CACHE_DIR}/**/*"]
  files_to_upload.each do |f|
    next if File.directory?(f)

    obj = bucket.object(f.sub(%r{^#{CACHE_DIR}/}, ''))

    # Don't re-upload existing gem versions
    next if File.extname(f) == '.gem' && obj.exists?

    obj.upload_file(f)
    rake_output_message "uploaded #{f} to S3"
  end

  true
end