class S3GemHost::TaskHelper

Service used for S3 Gem Host rake tasks

Constants

CACHE_DIR
PACKAGE_DIR

Attributes

aws_access_key_id[RW]
aws_region[RW]
aws_secret_access_key[RW]
bucket_name[RW]

Public Class Methods

install() click to toggle source

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

# 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
new(aws_access_key_id:, aws_secret_access_key:, bucket_name:, aws_region:) click to toggle source
# 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

Public Instance Methods

bootstrap_directories!() click to toggle source

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

# 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
bucket() click to toggle source
# 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_file() click to toggle source
# 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!() click to toggle source
# 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_s3() click to toggle source
# 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_gem() click to toggle source
# 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_index() click to toggle source
# 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) click to toggle source
# 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_name() click to toggle source
# File lib/s3_gem_host/task_helper.rb, line 182
def gem_name
  gemspec.name
end
gem_version() click to toggle source
# File lib/s3_gem_host/task_helper.rb, line 186
def gem_version
  gemspec.version
end
gemspec() click to toggle source
# 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_s3() click to toggle source
# 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