retag 0.1.1 → 0.1.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91558c109a6f2bf1cc988a0bf375404ca035c229d0abd031fd52cbe084cc1d23
4
- data.tar.gz: be5c10c2e9d85588f412b81c92fb22dfcac5117360e47c9bd20eb02d8219f992
3
+ metadata.gz: c3eecc35217225b65ef71c75cc8cf5c5ee199291eadcc61b97a58b4899ab4ae3
4
+ data.tar.gz: 372810234ee2c03c9829ff86e11ee2b8942831d1fbc18c0ab9e19e34bd5985c3
5
5
  SHA512:
6
- metadata.gz: 3093e65db866569cc3a28ffc09ce9b97241d6fb7c3e4793ff880e24a521b83bc4861ee172a27ef8d7e99d71c639da30fbbff7614574712bc5804525f48d5bd68
7
- data.tar.gz: 7381e35cc1934e8a78e9a4514a8f6dd3863e3744c5f516c083ccd88255dbe2b25b4eba111f69430fc1b91d8d80e98923d19c3cb298379404f7f268555efd3419
6
+ metadata.gz: 3bd613b85fee317a71a86fa8fff244826e06ca3d02be87e5ac3297ad418c569e895a9ba6e09349e121b749ca7e4f44b00c245b684867f3f8a8925071f8f36a97
7
+ data.tar.gz: c12042f6c60820062ab9761ab749ebe904ad843af76f1ef06a9666e9b0c851b436499ca8f3ad787a6961546a022a74c5cd06717eb0012296f9320b906cc42bb9
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in retag.gemspec
6
+ gemspec
7
+
8
+ # gem "rake", "~> 13.0"
9
+
10
+ # gem "rspec", "~> 3.0"
11
+
12
+ # gem "rubocop", "~> 1.21"
13
+
data/Gemfile.lock ADDED
@@ -0,0 +1,121 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ retag (0.1.4)
5
+ activesupport (~> 6.0)
6
+ colorize
7
+ gitlab
8
+ json
9
+ thor
10
+ uri
11
+ yaml
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ activesupport (6.1.4.4)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (>= 1.6, < 2)
19
+ minitest (>= 5.1)
20
+ tzinfo (~> 2.0)
21
+ zeitwerk (~> 2.3)
22
+ addressable (2.8.0)
23
+ public_suffix (>= 2.0.2, < 5.0)
24
+ ansi (1.5.0)
25
+ ast (2.4.2)
26
+ colorize (0.8.1)
27
+ concurrent-ruby (1.1.9)
28
+ crack (0.4.5)
29
+ rexml
30
+ diff-lcs (1.5.0)
31
+ docile (1.4.0)
32
+ gitlab (4.18.0)
33
+ httparty (~> 0.18)
34
+ terminal-table (>= 1.5.1)
35
+ hashdiff (1.0.1)
36
+ httparty (0.20.0)
37
+ mime-types (~> 3.0)
38
+ multi_xml (>= 0.5.2)
39
+ i18n (1.8.11)
40
+ concurrent-ruby (~> 1.0)
41
+ json (2.6.1)
42
+ mime-types (3.4.1)
43
+ mime-types-data (~> 3.2015)
44
+ mime-types-data (3.2022.0105)
45
+ minitest (5.15.0)
46
+ multi_xml (0.6.0)
47
+ parallel (1.21.0)
48
+ parser (3.1.0.0)
49
+ ast (~> 2.4.1)
50
+ public_suffix (4.0.6)
51
+ rainbow (3.1.1)
52
+ rake (13.0.6)
53
+ regexp_parser (2.2.0)
54
+ rexml (3.2.5)
55
+ rspec (3.10.0)
56
+ rspec-core (~> 3.10.0)
57
+ rspec-expectations (~> 3.10.0)
58
+ rspec-mocks (~> 3.10.0)
59
+ rspec-core (3.10.1)
60
+ rspec-support (~> 3.10.0)
61
+ rspec-expectations (3.10.2)
62
+ diff-lcs (>= 1.2.0, < 2.0)
63
+ rspec-support (~> 3.10.0)
64
+ rspec-mocks (3.10.2)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.10.0)
67
+ rspec-support (3.10.3)
68
+ rspec_junit_formatter (0.5.1)
69
+ rspec-core (>= 2, < 4, != 2.12.0)
70
+ rubocop (1.25.0)
71
+ parallel (~> 1.10)
72
+ parser (>= 3.1.0.0)
73
+ rainbow (>= 2.2.2, < 4.0)
74
+ regexp_parser (>= 1.8, < 3.0)
75
+ rexml
76
+ rubocop-ast (>= 1.15.1, < 2.0)
77
+ ruby-progressbar (~> 1.7)
78
+ unicode-display_width (>= 1.4.0, < 3.0)
79
+ rubocop-ast (1.15.1)
80
+ parser (>= 3.0.1.1)
81
+ ruby-progressbar (1.11.0)
82
+ simplecov (0.21.2)
83
+ docile (~> 1.1)
84
+ simplecov-html (~> 0.11)
85
+ simplecov_json_formatter (~> 0.1)
86
+ simplecov-console (0.9.1)
87
+ ansi
88
+ simplecov
89
+ terminal-table
90
+ simplecov-html (0.12.3)
91
+ simplecov_json_formatter (0.1.3)
92
+ terminal-table (3.0.2)
93
+ unicode-display_width (>= 1.1.1, < 3)
94
+ thor (1.2.1)
95
+ tzinfo (2.0.4)
96
+ concurrent-ruby (~> 1.0)
97
+ unicode-display_width (2.1.0)
98
+ uri (0.11.0)
99
+ webmock (3.14.0)
100
+ addressable (>= 2.8.0)
101
+ crack (>= 0.3.2)
102
+ hashdiff (>= 0.4.0, < 2.0.0)
103
+ yaml (0.2.0)
104
+ zeitwerk (2.5.3)
105
+
106
+ PLATFORMS
107
+ x86_64-linux
108
+
109
+ DEPENDENCIES
110
+ bundler (~> 2.2, >= 2.2.1)
111
+ rake
112
+ retag!
113
+ rspec
114
+ rspec_junit_formatter
115
+ rubocop
116
+ simplecov
117
+ simplecov-console
118
+ webmock
119
+
120
+ BUNDLED WITH
121
+ 2.2.33
data/bin/console ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'retag'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
16
+
data/bin/retag ADDED
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'thor'
5
+ require 'colorize'
6
+ require 'retag'
7
+
8
+ ENV_PREFIX = 'RETAG'
9
+
10
+ $logger = ActiveSupport::TaggedLogging.new(Retag::Logger.new(STDOUT))
11
+ $logger.level = :info
12
+
13
+
14
+
15
+ class RepoCommand < Thor
16
+ desc "tag <project> <tag>", "Create tag in Gitlab project"
17
+ long_desc <<-LONGDESC
18
+ LONGDESC
19
+ option :force, default: false,
20
+ required: false,
21
+ type: :boolean,
22
+ desc: "Override Gitlab tag if exists"
23
+
24
+ option :ref, default: ENV.fetch("#{ENV_PREFIX}_TAG_REF", 'master'),
25
+ required: true,
26
+ type: :string,
27
+ desc: "Gtilab refspec from which create tag"
28
+
29
+ option :message, default: nil,
30
+ type: :string,
31
+ desc: "Tag message"
32
+
33
+ def tag(project, tag)
34
+ opts = options.to_h.dup
35
+ $logger.level = :debug if opts['verbose']
36
+
37
+ begin
38
+ Gitlab.client.delete_tag(project, tag).inspect
39
+ rescue Gitlab::Error::NotFound
40
+ # Success: there is no such tag
41
+ end if opts['force']
42
+
43
+ puts Gitlab.client.create_tag(project, tag, options['ref'], options['message']).inspect
44
+ end
45
+ end
46
+
47
+ class DockerCommand < Thor
48
+ desc "tag", "Tag Docker image without downloading"
49
+ long_desc <<-LONGDESC
50
+ LONGDESC
51
+ option :image, default: ENV.fetch("#{ENV_PREFIX}_TAG_IMAGE", nil),
52
+ required: true,
53
+ desc: "Env: #{ENV_PREFIX}_TAG_IMAGE. Full image to be tagged. Ex: docker.rnds.pro/aggredator/service-uprid3:latest"
54
+
55
+ option :tag, default: ENV.fetch("#{ENV_PREFIX}_TAG_TAG", nil),
56
+ required: true,
57
+ desc: "Env: #{ENV_PREFIX}_TAG_TAG. New tag"
58
+
59
+ option :suffix, default: ENV.fetch("#{ENV_PREFIX}_TAG_SUFFIX", nil),
60
+ required: false,
61
+ desc: "Env: #{ENV_PREFIX}_TAG_SUFFIX. Optional suffix added to image tag: <image>:<tag>[-<suffix>].
62
+ Example:
63
+ # retag tag --image=registry/image:0a4bfc5 --tag v1.2.3 --suffix stable is equivalent to
64
+ docker tag registry/image:0a4bfc5-stable registry/image:v1.2.3
65
+ "
66
+
67
+ def tag(*_args)
68
+ opts = options.to_h.dup
69
+ $logger.level = :debug if opts['verbose']
70
+
71
+ img, tag = opts['image'].split(':')
72
+ tag ||= 'latest'
73
+ tag = opts['suffix'].present? ? "#{tag}-#{opts['suffix']}" : tag
74
+
75
+ image = ::Retag::Image.new(img, tag)
76
+ image.retag!(opts['tag'])
77
+ end
78
+
79
+ end
80
+
81
+ class ReleaseCommand < Thor
82
+ default_command :release
83
+
84
+ desc "release", "Release projects bundler from release.yml manifest"
85
+ long_desc <<-LONGDESC
86
+ LONGDESC
87
+ option :config, default: ENV.fetch("#{ENV_PREFIX}_RELEASE_CONFIG", './release.yml'),
88
+ required: true,
89
+ desc: "Env: #{ENV_PREFIX}_RELEASE_CONFIG. Path to release manifest"
90
+
91
+ option :name, default: ENV.fetch("#{ENV_PREFIX}_RELEASE_NAME", nil),
92
+ required: false,
93
+ desc: "Env: #{ENV_PREFIX}_RELEASE_NAME. Name of the current release"
94
+
95
+ def release(*_args)
96
+ opts = options.to_h.dup
97
+ $logger.level = :debug if opts['verbose']
98
+
99
+ config = YAML.load_file(File.expand_path(opts['config']))
100
+ config['release'] = opts['name'] || config['release']
101
+
102
+ release = config['release'].to_s
103
+ suffix = config['suffix']
104
+ branch = config['branch']
105
+
106
+ services = config['services'].map do|(name, cfg)|
107
+ Retag::Service.new(name, cfg, release, suffix: cfg.fetch('suffix', suffix), branch: cfg.fetch('branch', branch)) unless name.start_with?('.')
108
+ end.compact
109
+
110
+ tag_message = "Release #{release} at #{DateTime.now.iso8601}"
111
+
112
+ $logger.info "*** Starting '#{tag_message.colorize(mode: :bold)}'...".colorize(:cyan)
113
+
114
+ services.each do |srv|
115
+ $logger.tagged(srv.name.colorize(:yellow), "#{srv.revision.colorize(mode: :bold)}@#{srv.branch}") do
116
+ $logger.info "#{'==>'.colorize(mode: :bold, color: :white)} Releasing service #{srv.name.colorize(mode: :bold)} from #{srv.repo.repo} at #{srv.branch.colorize(mode: :bold)}:".colorize(:green)
117
+ $logger.shift do
118
+ srv.images.each do |img|
119
+ $logger.info ">>> Image #{img.image}"
120
+
121
+ $logger.shift do
122
+ $logger.info "From ".ljust(5) + "[#{img.tag.colorize(:yellow)}]: ".ljust(35) + img.full
123
+ newimg = img.retag!(release)
124
+ $logger.info "To ".ljust(5) + "[#{newimg.tag.colorize(:yellow)}]: ".ljust(35) + newimg.full
125
+ end
126
+
127
+ $logger.info ">>> Repo #{srv.repo.repo}"
128
+
129
+ $logger.shift do
130
+ $logger.info "From ".ljust(5) + "[#{srv.revision.colorize(:yellow)}]: ".ljust(35) + "#{srv.repo.repo}~#{srv.revision}@#{srv.branch}"
131
+ newimg = img.retag!(release)
132
+ $logger.info "To ".ljust(5) + "[#{release.colorize(:yellow)}]: ".ljust(35) + "#{srv.repo.repo}~#{srv.revision}@#{release}"
133
+ end
134
+
135
+ srv.repo.tag!(release, message: tag_message)
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ $logger.info "*** Completed '#{tag_message.colorize(mode: :bold)}'".colorize(:cyan)
142
+
143
+ end
144
+
145
+ end
146
+
147
+
148
+ class Cli < Thor
149
+
150
+ def self.exit_on_failure?
151
+ true
152
+ end
153
+
154
+ package_name "Retag is cli to manipulate docker images in handy way.
155
+
156
+ # Gitlab authorization
157
+ Using GITLAB_API_ENDPOINT and GITLAB_API_PRIVATE_TOKEN environment variable used for authorization
158
+
159
+ #{File.basename(__FILE__)}"
160
+
161
+ class_option :verbose, type: :boolean
162
+
163
+ desc 'version', 'Display version'
164
+ map %w[-v --version] => :version
165
+
166
+ def version
167
+ say Retag::VERSION
168
+ end
169
+
170
+ desc "repo SUBCOMMAND ...ARGS", "Manage git repository stuffs"
171
+ subcommand "repo", RepoCommand
172
+
173
+ desc "docker SUBCOMMAND ...ARGS", "Manage docker stuffs"
174
+ subcommand "docker", DockerCommand
175
+
176
+ desc "release SUBCOMMAND ...ARGS", "Manage releases"
177
+ subcommand "release", ReleaseCommand
178
+ end
179
+
180
+ ::Cli.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/retag/image.rb CHANGED
@@ -35,18 +35,6 @@ module Retag
35
35
  Image.new(image, newtag)
36
36
  end
37
37
 
38
- def pull(img = full)
39
- cmd!("docker pull -q #{img}")
40
- end
41
-
42
- def push(img = full)
43
- cmd!("docker push -q #{img}")
44
- end
45
-
46
- def rm(img = full)
47
- cmd!("docker rmi #{img}")
48
- end
49
-
50
38
  end
51
39
  end
52
40
 
data/lib/retag/repo.rb ADDED
@@ -0,0 +1,43 @@
1
+
2
+ module Retag
3
+ class Repo
4
+
5
+ include Utils
6
+ attr_reader :repo, :branch, :revision, :name
7
+
8
+ def initialize(repo, branch)
9
+ @repo = repo
10
+ @branch = branch
11
+ @gitlab = Gitlab.client
12
+ end
13
+
14
+ def tag!(tag, message: nil)
15
+ begin
16
+ result = @gitlab.tag(name, tag)
17
+ if result.to_h.dig('commit', 'short_id').to_s == revision
18
+ # Success: tag with same revision already exists
19
+ return true
20
+ end
21
+ rescue Gitlab::Error::NotFound
22
+ # Success: there is no such tag
23
+ end
24
+
25
+ @gitlab.create_tag(name, tag, revision, message)
26
+ end
27
+
28
+ def name
29
+ @name ||= @repo.split(':').last.gsub('.git', '')
30
+ end
31
+
32
+ def revision
33
+ @revision ||= begin
34
+ rev_name_pair = cmd!("git ls-remote #{repo} #{branch}", capture: true).split("\n").select{|line| line[/\/#{branch}$/] }.first
35
+ raise "There is no #{branch} revision at #{repo}" if rev_name_pair.nil?
36
+ rev, _name = rev_name_pair.split
37
+ rev[0..7]
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+
data/lib/retag/service.rb CHANGED
@@ -1,15 +1,18 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
1
3
  module Retag
2
4
  class Service
3
5
 
4
6
  include Retag::Utils
5
7
 
6
- attr_reader :name, :config, :repo, :branch, :release, :suffix
8
+ attr_reader :name, :config, :repo, :release, :suffix
9
+
10
+ delegate :revision, :branch, to: :repo
7
11
 
8
- def initialize(name, config, release, suffix: )
12
+ def initialize(name, config, release, branch:, suffix:)
9
13
  @name = name
10
14
  @config = config
11
- @repo = config['repo']
12
- @branch = config['branch']
15
+ @repo = Retag::Repo.new(config['repo'], branch)
13
16
  @release = release
14
17
  @suffix = suffix
15
18
  end
@@ -17,33 +20,6 @@ module Retag
17
20
  def images
18
21
  @images ||= config['images'].map{|img| Retag::Image.new(img, revision, suffix: @suffix) }
19
22
  end
20
-
21
- def pull
22
- images.each(&:pull)
23
- end
24
-
25
- def push
26
- images.each(&:push)
27
- end
28
-
29
- def rm
30
- images.each(&:rm)
31
- end
32
-
33
- def release!(tag = release)
34
- images.each do |image|
35
- image.retag!(tag)
36
- end
37
- end
38
-
39
- def revision
40
- @revision ||= begin
41
- rev, _name = cmd!("git ls-remote #{repo} #{branch}", capture: true).split("\n").select{|line| line["heads/#{branch}"] }.first.split
42
- rev[0..7]
43
- end
44
- end
45
-
46
-
47
23
  end
48
24
  end
49
25
 
data/lib/retag/version.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Retag
4
4
 
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.5'
6
6
 
7
7
  end
8
8
 
data/lib/retag.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support'
4
+ require 'gitlab'
4
5
  require_relative 'retag/version'
5
6
  require_relative 'retag/logger'
6
7
  require_relative 'retag/utils'
7
8
  require_relative 'retag/image'
9
+ require_relative 'retag/repo'
8
10
  require_relative 'retag/service'
9
11
 
10
12
  module Retag
data/retag.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/retag/version'
4
+
5
+ Gem::Specification.new 'retag' do |spec|
6
+ spec.version = ENV['BUILDVERSION'].to_i > 0 ? "#{Retag::VERSION}.#{ENV['BUILDVERSION'].to_i}" : Retag::VERSION
7
+ spec.authors = ['Samoilenko Yuri']
8
+ spec.email = ['kinnalru@gmail.com']
9
+ spec.description = spec.summary = 'Retag is cli to manipulate docker images in handy way'
10
+ spec.homepage = 'https://github.com/RnD-Soft/retag'
11
+ spec.license = 'MIT'
12
+
13
+ spec.required_ruby_version = '>= 2.5.0'
14
+ spec.metadata['homepage_uri'] = spec.homepage
15
+ spec.metadata['source_code_uri'] = 'https://github.com/RnD-Soft/retag'
16
+
17
+ spec.files = Dir['bin/**/*', 'lib/**/*', 'sig/**/*', 'Gemfile*', 'LICENSE', 'README.md', '*.gemspec']
18
+
19
+ spec.bindir = 'bin'
20
+ spec.executables = spec.files.grep(%r{^bin/retag}) {|f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 2.2', '>= 2.2.1'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'rspec_junit_formatter'
27
+ spec.add_development_dependency 'rubocop'
28
+ spec.add_development_dependency 'simplecov'
29
+ spec.add_development_dependency 'simplecov-console'
30
+ spec.add_development_dependency 'webmock'
31
+
32
+ spec.add_runtime_dependency 'activesupport', '~> 6.0'
33
+ spec.add_runtime_dependency 'colorize'
34
+ spec.add_runtime_dependency 'json'
35
+ spec.add_runtime_dependency 'thor'
36
+ spec.add_runtime_dependency 'uri'
37
+ spec.add_runtime_dependency 'yaml'
38
+ spec.add_runtime_dependency 'gitlab'
39
+
40
+ end
41
+
data/sig/retag.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Retag
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samoilenko Yuri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-20 00:00:00.000000000 Z
11
+ date: 2022-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -212,21 +212,44 @@ dependencies:
212
212
  - - ">="
213
213
  - !ruby/object:Gem::Version
214
214
  version: '0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: gitlab
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ type: :runtime
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
215
229
  description: Retag is cli to manipulate docker images in handy way
216
230
  email:
217
231
  - kinnalru@gmail.com
218
- executables: []
232
+ executables:
233
+ - retag
219
234
  extensions: []
220
235
  extra_rdoc_files: []
221
236
  files:
237
+ - Gemfile
238
+ - Gemfile.lock
222
239
  - LICENSE
223
240
  - README.md
241
+ - bin/console
242
+ - bin/retag
243
+ - bin/setup
224
244
  - lib/retag.rb
225
245
  - lib/retag/image.rb
226
246
  - lib/retag/logger.rb
247
+ - lib/retag/repo.rb
227
248
  - lib/retag/service.rb
228
249
  - lib/retag/utils.rb
229
250
  - lib/retag/version.rb
251
+ - retag.gemspec
252
+ - sig/retag.rbs
230
253
  homepage: https://github.com/RnD-Soft/retag
231
254
  licenses:
232
255
  - MIT