s3repo 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 037f096771d38b162f01efabbd4f21a3d38d2e54
4
- data.tar.gz: 2639022f0ac61664ed66c9bdd49b28e8b3dc4d13
3
+ metadata.gz: 77fb43c11e189c5bfc7c347fa6b0d2efe566f9ff
4
+ data.tar.gz: 2ce120f3afd0e0b63a6d2f63c84822c3b974bc95
5
5
  SHA512:
6
- metadata.gz: 40e4eba132b5c8374a4c5da86dc5043aca1700daf69c616ee91f018bd214e010cf64bda56b0c1187388252ffc21d95e328be2b68daf1f10d0fdf0d940c2f6978
7
- data.tar.gz: d09e26179074b0c678e798bc814b1a2e4277bea5738d914c7af0c64c306896f4da46423dc03ec2b8af3f0917d432f707f8e8d38614598d50c7fe2dddc6cd7067
6
+ metadata.gz: c0c201ab4c0e8eefc8e7d2ba2490d92fdc9eb6e989c2b1a5cec9436580ca8c0ef5bf874052fac4056725343a9ccfbe5f96747cf1931297d81df5cee6ee251cf5
7
+ data.tar.gz: b2acfdd8d6386b69bddbd772d836b40d825a58b8adcbdf6a0ee64c484e397c94cbaf5d2e8cb99f303030bb031f24ed2e31e2bceab89fa801b587cea1fbfa0da7
@@ -0,0 +1,3 @@
1
+ 2.4.2
2
+ 2.3.5
3
+ 2.2.8
@@ -1,11 +1,25 @@
1
+ Prospectus.extra_dep('file', 'prospectus_circleci')
2
+
3
+ my_slug = 'amylum/s3repo'
4
+
1
5
  item do
2
- expected do
3
- static
4
- set 'green'
5
- end
6
+ noop
6
7
 
7
- actual do
8
- gemnasium
9
- slug 'amylum/server'
8
+ deps do
9
+ item do
10
+ name 'gems'
11
+
12
+ expected do
13
+ static
14
+ set 'green'
15
+ end
16
+
17
+ actual do
18
+ gemnasium
19
+ slug my_slug
20
+ end
21
+ end
10
22
  end
23
+
24
+ extend ProspectusCircleci::Build.new(my_slug)
11
25
  end
@@ -1,2 +1,5 @@
1
- Encoding:
2
- Enabled: false
1
+ inherit_gem:
2
+ goodcop: .rubocop.yml
3
+ AllCops:
4
+ Include:
5
+ - 'bin/*'
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
data/README.md CHANGED
@@ -3,7 +3,7 @@ s3repo
3
3
 
4
4
  [![Gem Version](https://img.shields.io/gem/v/s3repo.svg)](https://rubygems.org/gems/s3repo)
5
5
  [![Dependency Status](https://img.shields.io/gemnasium/amylum/s3repo.svg)](https://gemnasium.com/amylum/s3repo)
6
- [![Build Status](https://img.shields.io/circleci/project/amylum/s3repo.svg)](https://circleci.com/gh/amylum/s3repo)
6
+ [![Build Status](https://img.shields.io/circleci/project/amylum/s3repo/master.svg)](https://circleci.com/gh/amylum/s3repo)
7
7
  [![Coverage Status](https://img.shields.io/codecov/c/github/amylum/s3repo.svg)](https://codecov.io/github/amylum/s3repo)
8
8
  [![Code Quality](https://img.shields.io/codacy/eef971ff937642219c1d4094001c33e7.svg)](https://www.codacy.com/app/akerl/s3repo)
9
9
  [![MIT Licensed](https://img.shields.io/badge/license-MIT-green.svg)](https://tldrlegal.com/license/mit-license)
data/Rakefile CHANGED
@@ -7,8 +7,7 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  desc 'Run Rubocop on the gem'
9
9
  RuboCop::RakeTask.new(:rubocop) do |task|
10
- task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'bin/*']
11
10
  task.fail_on_error = true
12
11
  end
13
12
 
14
- task default: [:spec, :rubocop, :build, :install]
13
+ task default: %i[spec rubocop build install]
data/bin/s3repo CHANGED
@@ -2,49 +2,72 @@
2
2
 
3
3
  require 's3repo'
4
4
  require 'mercenary'
5
+ require 'yaml'
6
+ require 'cymbal'
5
7
 
6
8
  def find(pattern, limits)
7
9
  Dir.glob(pattern).select { |x| !limits || limits.include?(File.dirname(x)) }
8
10
  end
9
11
 
12
+ def common_opts(cmd)
13
+ cmd.option :config_file, '-c', '--config FILE', 'Path of config file'
14
+ end
15
+
16
+ def load_config(file)
17
+ file ||= 'config.yml'
18
+ file = File.expand_path(file)
19
+ raise("Config file not found: #{file}") unless File.exist? file
20
+ Cymbal.symbolize YAML.safe_load(File.read(file))
21
+ end
22
+
23
+ def repo(options)
24
+ config = load_config(options[:config_file])
25
+ S3Repo.new(config)
26
+ end
27
+
28
+ # rubocop:disable Metrics/BlockLength
10
29
  Mercenary.program(:s3repo) do |p|
11
30
  p.version S3Repo::VERSION
12
31
  p.description 'Package management tool for Archlinux repos'
13
32
  p.syntax 's3repo <subcommand> [args]'
14
33
 
15
34
  p.command(:build) do |c|
35
+ common_opts(c)
16
36
  c.syntax 'build [package...]'
17
37
  c.description 'Build package files from PKGBUILDs'
18
38
 
19
- c.action do |args, _|
20
- S3Repo.new.build_packages find('*/PKGBUILD', args), ENV['MAKEPKG_FLAGS']
39
+ c.action do |args, opts|
40
+ repo(opts).build_packages find('*/PKGBUILD', args)
21
41
  end
22
42
  end
23
43
 
24
44
  p.command(:upload) do |c|
45
+ common_opts(c)
25
46
  c.syntax 'upload [package...]'
26
47
  c.description 'Upload packages to repo'
27
48
 
28
- c.action do |args, _|
29
- S3Repo.new.add_packages find('*/*.pkg.tar.xz', args)
49
+ c.action do |args, opts|
50
+ repo(opts).add_packages find('*/*.pkg.tar.xz', args)
30
51
  end
31
52
  end
32
53
 
33
54
  p.command(:remove) do |c|
55
+ common_opts(c)
34
56
  c.syntax 'remove [package...]'
35
57
  c.description 'Remove packages from repo DB'
36
58
 
37
- c.action do |args, _|
38
- S3Repo.new.remove_packages args
59
+ c.action do |args, opts|
60
+ repo(opts).remove_packages args
39
61
  end
40
62
  end
41
63
 
42
64
  p.command(:prune) do |c|
65
+ common_opts(c)
43
66
  c.syntax 'prune'
44
67
  c.description 'Prune orphaned files from the repo'
45
68
 
46
- c.action do
47
- S3Repo.new.prune_files
69
+ c.action do |_, opts|
70
+ repo(opts).prune_files
48
71
  end
49
72
  end
50
73
 
data/circle.yml CHANGED
@@ -1,8 +1,11 @@
1
+ machine:
2
+ environment:
3
+ AWS_ACCESS_KEY_ID: '1'
4
+ AWS_SECRET_ACCESS_KEY: '1'
1
5
  dependencies:
2
6
  override:
3
- - 'rvm-exec 2.1.6 bundle install'
4
- - 'rvm-exec 2.2.2 bundle install'
7
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i gem update --system --no-doc || exit 1 ; done'
8
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle install || exit 1 ; done'
5
9
  test:
6
10
  override:
7
- - 'rvm-exec 2.1.6 bundle exec rake'
8
- - 'rvm-exec 2.2.2 bundle exec rake'
11
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle exec rake || exit 1 ; done'
@@ -13,7 +13,9 @@ end
13
13
 
14
14
  require 's3repo/version'
15
15
  require 's3repo/base'
16
+ require 's3repo/signer'
16
17
  require 's3repo/metadata'
17
18
  require 's3repo/cache'
18
19
  require 's3repo/client'
20
+ require 's3repo/templates'
19
21
  require 's3repo/repo'
@@ -13,23 +13,19 @@ module S3Repo
13
13
  def run(cmd)
14
14
  results = `#{cmd} 2>&1`
15
15
  return results if $CHILD_STATUS.success?
16
- fail "Failed running #{cmd}:\n#{results}"
16
+ raise "Failed running #{cmd}:\n#{results}"
17
17
  end
18
18
 
19
19
  def bucket
20
- @bucket ||= @options[:bucket] || ENV['S3_BUCKET']
21
- return @bucket if @bucket
22
- fail('No bucket given')
20
+ @options[:bucket] || raise('No bucket given')
23
21
  end
24
22
 
25
23
  def client
26
- @client ||= @options[:client] || Client.new(bucket: bucket)
24
+ @options[:client] ||= Client.new(@options)
27
25
  end
28
26
 
29
27
  def file_cache
30
- @file_cache ||= @options[:file_cache] || Cache.new(
31
- client: client, tmpdir: @options[:tmpdir]
32
- )
28
+ @file_cache ||= @options[:file_cache] || Cache.new(@options)
33
29
  end
34
30
  end
35
31
  end
@@ -7,7 +7,6 @@ module S3Repo
7
7
  # Cache object, stores S3 objects on disk
8
8
  class Cache < Base
9
9
  TMPDIRS = [
10
- ENV['S3REPO_TMPDIR'],
11
10
  ENV['TMPDIR'],
12
11
  Dir.tmpdir,
13
12
  '/tmp/s3repo'
@@ -18,20 +17,18 @@ module S3Repo
18
17
  [partialdir, cachedir].each { |x| FileUtils.mkdir_p x }
19
18
  end
20
19
 
21
- def serve(key, refresh = true)
22
- File.open(download(key, refresh), &:read)
23
- rescue Aws::S3::Errors::NoSuchKey
24
- nil
25
- end
26
-
27
- private
28
-
29
20
  def download(key, refresh = true)
30
21
  path = expand_path key
31
22
  get_object(key, path) if refresh || !cached?(path)
32
23
  path
33
24
  end
34
25
 
26
+ private
27
+
28
+ def file_cache
29
+ raise('Tried to call file_cache recursively')
30
+ end
31
+
35
32
  def expand_path(key)
36
33
  File.absolute_path(key, cachedir)
37
34
  end
@@ -71,7 +68,13 @@ module S3Repo
71
68
  end
72
69
 
73
70
  def tmpdir
74
- @tmpdir ||= File.absolute_path(@options[:tmpdir] || TMPDIRS.compact.first)
71
+ @tmpdir ||= Dir.mktmpdir 's3repo', tmpdir_root
72
+ end
73
+
74
+ def tmpdir_root
75
+ @tmpdir_root ||= File.absolute_path(
76
+ @options[:tmpdir] || TMPDIRS.compact.first
77
+ )
75
78
  end
76
79
  end
77
80
  end
@@ -5,21 +5,33 @@ module S3Repo
5
5
  # AWS API client
6
6
  class Client
7
7
  def initialize(params = {})
8
- @api = Aws::S3::Client.new
9
- @defaults = params
8
+ @options = params
9
+ @api = Aws::S3::Client.new(region: region)
10
10
  end
11
11
 
12
- def respond_to?(method, include_all = false)
12
+ def respond_to_missing?(method, include_all = false)
13
13
  @api.respond_to?(method, include_all) || super
14
14
  end
15
15
 
16
- def upload!(key, path)
16
+ def upload(key, body)
17
17
  puts "Uploading #{key}"
18
- put_object key: key, body: File.open(path), &:read
18
+ put_object key: key, body: body
19
+ end
20
+
21
+ def upload_file(key, path)
22
+ upload(key, File.open(path).read)
19
23
  end
20
24
 
21
25
  private
22
26
 
27
+ def region
28
+ @options[:region] || raise('AWS region not set')
29
+ end
30
+
31
+ def bucket
32
+ @options[:bucket] || raise('Bucket not set')
33
+ end
34
+
23
35
  def method_missing(method, *args, &block)
24
36
  return super unless @api.respond_to?(method)
25
37
  define_singleton_method(method) do |*singleton_args|
@@ -30,10 +42,11 @@ module S3Repo
30
42
  end
31
43
 
32
44
  def build_params(args)
33
- fail 'Too many arguments given' if args.size > 1
45
+ raise 'Too many arguments given' if args.size > 1
34
46
  params = args.first || {}
35
- fail 'Argument must be a hash' unless params.is_a? Hash
36
- @defaults.dup.merge!(params)
47
+ raise 'Argument must be a hash' unless params.is_a? Hash
48
+ params[:bucket] ||= bucket
49
+ params
37
50
  end
38
51
  end
39
52
  end
@@ -5,11 +5,6 @@ module S3Repo
5
5
  ##
6
6
  # Metadata object, represents repo's DB file
7
7
  class Metadata < Base
8
- def initialize(params = {})
9
- super
10
- FileUtils.mkdir_p db_dir
11
- end
12
-
13
8
  def add_packages(paths)
14
9
  @db_path = nil
15
10
  paths.each do |path|
@@ -29,38 +24,31 @@ module S3Repo
29
24
  end
30
25
 
31
26
  def update!
32
- sign_db if ENV['S3REPO_SIGN_DB']
33
- client.upload!('repo.db', db_path)
27
+ sign_db if @options[:sign_db]
28
+ client.upload_file('repo.db', db_path)
29
+ client.upload_file('repo.db.tar.xz', db_path)
34
30
  end
35
31
 
36
32
  def packages
37
33
  return @packages if @packages
38
- cmd = "tar tf #{db_path}"
34
+ cmd = "bsdtar tf #{db_path}"
39
35
  @packages = run(cmd).split.map { |x| x.split('/').first }.uniq
40
36
  end
41
37
 
42
38
  private
43
39
 
44
- def sign_db
45
- run "gpg --detach-sign --use-agent #{db_path}"
46
- client.upload!('repo.db.sig', "#{db_path}.sig")
47
- end
48
-
49
- def db_path
50
- @db_path ||= download_db
40
+ def signer
41
+ @options[:signer] ||= Signer.new(@options)
51
42
  end
52
43
 
53
- def download_db
54
- tmpfile = Tempfile.create(['repo', '.db.tar.xz'], db_dir)
55
- tmpfile << file_cache.serve('repo.db')
56
- tmpfile.close
57
- tmpfile.path
44
+ def sign_db
45
+ sig_path = signer.sign(db_path)
46
+ client.upload_file('repo.db.sig', sig_path)
47
+ client.upload_file('repo.db.tar.xz.sig', sig_path)
58
48
  end
59
49
 
60
- def db_dir
61
- @db_dir ||= File.absolute_path(
62
- @options[:tmpdir] || Cache::TMPDIRS.compact.first
63
- )
50
+ def db_path
51
+ @db_path ||= file_cache.download('repo.db.tar.xz')
64
52
  end
65
53
  end
66
54
  end
@@ -5,25 +5,23 @@ module S3Repo
5
5
  ##
6
6
  # Repo object, represents an Arch repo inside an S3 bucket
7
7
  class Repo < Base
8
- def initialize(params = {})
9
- super
10
- end
11
-
12
- def build_packages(paths, makepkg_flags = '')
8
+ def build_packages(paths)
13
9
  paths.each do |path|
14
10
  dir = File.dirname(path)
15
11
  puts "Building #{File.basename(dir)}"
16
- Dir.chdir(dir) { run "makepkg #{makepkg_flags}" }
12
+ Dir.chdir(dir) { run "makepkg #{@options[:makepkg_flags]}" }
17
13
  end
18
14
  end
19
15
 
20
16
  def add_packages(paths)
21
17
  paths.select! { |path| upload_package(path) }
22
18
  metadata.add_packages(paths) unless paths.empty?
19
+ templates.update! unless paths.empty?
23
20
  end
24
21
 
25
22
  def remove_packages(packages)
26
23
  metadata.remove_packages(packages)
24
+ templates.update!
27
25
  end
28
26
 
29
27
  def prune_files
@@ -47,19 +45,15 @@ module S3Repo
47
45
  !packages.find { |x| x.key == key }.nil?
48
46
  end
49
47
 
50
- def serve(key)
51
- refresh = !key.match(/\.pkg\.tar\.xz$/)
52
- file_cache.serve(key, refresh)
53
- end
54
-
55
48
  private
56
49
 
57
50
  def upload_package(path)
58
51
  key = File.basename(path)
59
- sig_key, sig_path = [key, path].map { |x| x + '.sig' }
60
52
  return false if include? key
61
- client.upload!(sig_key, sig_path) if ENV['S3REPO_SIGN_PACKAGES']
62
- client.upload!(key, path)
53
+ sig_path = signer.sign(path)
54
+ sig_key = key + '.sig'
55
+ client.upload_file(sig_key, sig_path) if @options[:sign_packages]
56
+ client.upload_file(key, path)
63
57
  true
64
58
  end
65
59
 
@@ -70,7 +64,15 @@ module S3Repo
70
64
  end
71
65
 
72
66
  def metadata
73
- @metadata ||= Metadata.new(client: client, file_cache: file_cache)
67
+ @options[:metadata] ||= Metadata.new(@options)
68
+ end
69
+
70
+ def signer
71
+ @options[:signer] ||= Signer.new(@options)
72
+ end
73
+
74
+ def templates
75
+ @templates ||= Templates.new(@options)
74
76
  end
75
77
 
76
78
  def package_cache