retag 0.1.2 → 0.1.6

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
  SHA256:
3
- metadata.gz: 0cbe24b954c5ae0cc55386882c55d0d056239c20df8780ed732346e6fc577656
4
- data.tar.gz: e71492bf16f2deb5ca71ca252a8324511c9469c20a5502cd00a703968c0782ae
3
+ metadata.gz: ab9f253e8ff9f3a7bfd637ddaa844cff811d3c75f79fde036bdacd8eb1f58f91
4
+ data.tar.gz: d36f32cb6b21896c28901f18420ef1ccf4207e4cf2683c42407bebd52662f761
5
5
  SHA512:
6
- metadata.gz: bfb8cc1fa4fed581f33e96c53a0258ed9b9532d163a532a554d492e988202411eb70f23a8542f5b68acd7b79f1440d2f9429b0b454ed2f1d1a6873a2427caf1c
7
- data.tar.gz: 7e764cecb0bfd5015a7c7b0f91b2cefbc72008421ede60e40c21d72ca8bb3806812120f7e35faa57c3c41c7da673ed2d7b9a483737e7bb46288dcdbbc1255bcc
6
+ metadata.gz: 484c2c98bf6d72545501c1b4b43e139579ee37af5b8f0e1c7e5bf1c28998a8ba4c039fb4a2e7042edbdbf56304420d28b186104863599834c1a6db3ab8c78249
7
+ data.tar.gz: 390312a1b807c7790a80e4bb5e9f68c6644455b267dcbdd965d260af58106030b9b11cbc1477f21ac78f6a230660e09aef1d32313e94a5301f37b32bef60cd5d
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- retag (0.1.2)
4
+ retag (0.1.6)
5
5
  activesupport (~> 6.0)
6
6
  colorize
7
+ gitlab
7
8
  json
8
9
  thor
9
10
  uri
@@ -28,11 +29,21 @@ GEM
28
29
  rexml
29
30
  diff-lcs (1.5.0)
30
31
  docile (1.4.0)
32
+ gitlab (4.18.0)
33
+ httparty (~> 0.18)
34
+ terminal-table (>= 1.5.1)
31
35
  hashdiff (1.0.1)
36
+ httparty (0.20.0)
37
+ mime-types (~> 3.0)
38
+ multi_xml (>= 0.5.2)
32
39
  i18n (1.8.11)
33
40
  concurrent-ruby (~> 1.0)
34
41
  json (2.6.1)
42
+ mime-types (3.4.1)
43
+ mime-types-data (~> 3.2015)
44
+ mime-types-data (3.2022.0105)
35
45
  minitest (5.15.0)
46
+ multi_xml (0.6.0)
36
47
  parallel (1.21.0)
37
48
  parser (3.1.0.0)
38
49
  ast (~> 2.4.1)
data/bin/retag CHANGED
@@ -5,64 +5,56 @@ require 'thor'
5
5
  require 'colorize'
6
6
  require 'retag'
7
7
 
8
- UTIL = File.basename(__FILE__)
9
8
  ENV_PREFIX = 'RETAG'
10
9
 
11
10
  $logger = ActiveSupport::TaggedLogging.new(Retag::Logger.new(STDOUT))
12
- $logger.level = :debug
13
-
14
- # config = YAML.load_file('release.yml')
15
- # release = config['release']
16
- # services = config['services'].map{|(name, cfg)| Service.new(name, cfg, release)}
17
-
18
- # services.each do |srv|
19
- # $logger.tagged(srv.name, srv.revision) do
20
- # $logger.info "==> Releasing service #{srv.name} from #{srv.repo} at #{srv.branch}:"
21
- # $logger.shift do
22
- # #$logger.info "* Pulling service..."
23
- # #srv.pull
24
- # $logger.info "* Tagging service..."
25
- # srv.release!
26
- # #$logger.info "* Pushing service..."
27
- # #srv.push
28
- # #$logger.info "* Cleaning service..."
29
- # #srv.rm
30
- # end
31
- # end
32
- # end
33
-
34
- # $logger.info "==> #{services.count} relesed as #{release}"
11
+ $logger.level = :info
35
12
 
36
- class Cli < Thor
37
13
 
38
- def self.exit_on_failure?
39
- true
40
- end
41
14
 
42
- # class_option :plugin_gemname, default: ENV.fetch('PLUGIN_GEMNAME', 'unknown'),
43
- # desc: 'Name of the current gem'
44
- # class_option :service_image, default: ENV.fetch('SERVICE_IMAGE', 'tmpimage'),
45
- # desc: 'Docker image name to build. Taken from SERVICE_IMAGE enviroment variable'
46
- # class_option :service_tag, default: ENV.fetch('SERVICE_TAG', 'latest'),
47
- # desc: 'Docker image tag to build. Taken from SERVICE_TAG enviroment variable'
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"
48
23
 
49
- desc 'version', 'Display version'
50
- map %w[-v --version] => :version
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"
51
28
 
52
- def version
53
- say Retag::VERSION
54
- end
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']
55
36
 
56
- desc 'tag', 'Tag Docker image without downloading'
57
- map %w[--tag] => :tag
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']
58
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
59
51
  option :image, default: ENV.fetch("#{ENV_PREFIX}_TAG_IMAGE", nil),
60
52
  required: true,
61
53
  desc: "Env: #{ENV_PREFIX}_TAG_IMAGE. Full image to be tagged. Ex: docker.rnds.pro/aggredator/service-uprid3:latest"
62
54
 
63
55
  option :tag, default: ENV.fetch("#{ENV_PREFIX}_TAG_TAG", nil),
64
56
  required: true,
65
- desc: "Env: #{ENV_PREFIX}_TAG_TAG. New tag."
57
+ desc: "Env: #{ENV_PREFIX}_TAG_TAG. New tag"
66
58
 
67
59
  option :suffix, default: ENV.fetch("#{ENV_PREFIX}_TAG_SUFFIX", nil),
68
60
  required: false,
@@ -74,6 +66,8 @@ class Cli < Thor
74
66
 
75
67
  def tag(*_args)
76
68
  opts = options.to_h.dup
69
+ $logger.level = :debug if opts['verbose']
70
+
77
71
  img, tag = opts['image'].split(':')
78
72
  tag ||= 'latest'
79
73
  tag = opts['suffix'].present? ? "#{tag}-#{opts['suffix']}" : tag
@@ -82,9 +76,14 @@ class Cli < Thor
82
76
  image.retag!(opts['tag'])
83
77
  end
84
78
 
85
- desc 'release', 'Release projects bundler from release.yml manifest'
86
- map %w[--release] => :release
79
+ end
80
+
81
+ class ReleaseCommand < Thor
82
+ default_command :release
87
83
 
84
+ desc "release", "Release projects bundler from release.yml manifest"
85
+ long_desc <<-LONGDESC
86
+ LONGDESC
88
87
  option :config, default: ENV.fetch("#{ENV_PREFIX}_RELEASE_CONFIG", './release.yml'),
89
88
  required: true,
90
89
  desc: "Env: #{ENV_PREFIX}_RELEASE_CONFIG. Path to release manifest"
@@ -95,73 +94,87 @@ class Cli < Thor
95
94
 
96
95
  def release(*_args)
97
96
  opts = options.to_h.dup
97
+ $logger.level = :debug if opts['verbose']
98
+
98
99
  config = YAML.load_file(File.expand_path(opts['config']))
99
100
  config['release'] = opts['name'] || config['release']
100
101
 
101
- release = config['release']
102
+ release = config['release'].to_s
102
103
  suffix = config['suffix']
104
+ branch = config['branch']
103
105
 
104
106
  services = config['services'].map do|(name, cfg)|
105
- Retag::Service.new(name, cfg, release, suffix: cfg.fetch('suffix', suffix)) unless name.start_with?('.')
107
+ Retag::Service.new(name, cfg, release, suffix: cfg.fetch('suffix', suffix), branch: cfg.fetch('branch', branch)) unless name.start_with?('.')
106
108
  end.compact
107
109
 
110
+ tag_message = "Release #{release} at #{DateTime.now.iso8601}"
111
+
112
+ $logger.info "*** Starting '#{tag_message.colorize(mode: :bold)}'...".colorize(:cyan)
113
+
108
114
  services.each do |srv|
109
115
  $logger.tagged(srv.name.colorize(:yellow), "#{srv.revision.colorize(mode: :bold)}@#{srv.branch}") do
110
- $logger.info "#{'==>'.colorize(mode: :bold, color: :white)} Releasing service #{srv.name.colorize(:yellow)} from #{srv.repo} at #{srv.branch}:"
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)
111
117
  $logger.shift do
112
118
  srv.images.each do |img|
113
- $logger.info "Source image: #{img.full}"
114
- newimg = img.retag!(release)
115
- $logger.info "Release image: #{newimg.full}"
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)
116
136
  end
117
-
118
- #$logger.info "* Pulling service..."
119
- #srv.pull
120
- #$logger.info "* Tagging service..."
121
- #srv.release!
122
- #$logger.info "* Pushing service..."
123
- #srv.push
124
- #$logger.info "* Cleaning service..."
125
- #srv.rm
126
137
  end
127
138
  end
128
139
  end
129
140
 
141
+ $logger.info "*** Completed '#{tag_message.colorize(mode: :bold)}'".colorize(:cyan)
142
+
130
143
  end
131
144
 
132
- private
145
+ end
133
146
 
134
- def cache_image(opts)
135
- "#{opts['service_image']}_cache:latest"
136
- end
137
147
 
138
- end
148
+ class Cli < Thor
139
149
 
140
- ::Cli.start
150
+ def self.exit_on_failure?
151
+ true
152
+ end
153
+
154
+ package_name "Retag is cli to manipulate docker images in handy way.
141
155
 
142
- # puts ARGV.inspect
156
+ # Gitlab authorization
157
+ Using GITLAB_API_ENDPOINT and GITLAB_API_PRIVATE_TOKEN environment variable used for authorization
143
158
 
144
- # parser.parse!
159
+ #{File.basename(__FILE__)}"
145
160
 
146
- # puts ARGV.inspect
161
+ class_option :verbose, type: :boolean
147
162
 
148
- # warn parser.help
149
- # exit 1
163
+ desc 'version', 'Display version'
164
+ map %w[-v --version] => :version
150
165
 
151
- # config = {
152
- # services: [
153
- # {core: {images: []}}
154
- # ]
155
- # }
166
+ def version
167
+ say Retag::VERSION
168
+ end
156
169
 
157
- # release=$(cat .release | head -n 1)
170
+ desc "repo SUBCOMMAND ...ARGS", "Manage git repository stuffs"
171
+ subcommand "repo", RepoCommand
158
172
 
159
- # for line in "${services[@]}"; do
160
- # module=$(echo $line | cut -f1 -d '|')
161
- # repo=$(echo $line | cut -f2 -d '|')
162
- # branch=$(echo $line | cut -f3 -d '|')
173
+ desc "docker SUBCOMMAND ...ARGS", "Manage docker stuffs"
174
+ subcommand "docker", DockerCommand
163
175
 
164
- # echo "Tagging ${module} from ${branch} of ${repo}"
165
- # git subtree push --prefix="src/${module}" "${repo}" "feature/otr"
166
- # done
176
+ desc "release SUBCOMMAND ...ARGS", "Manage releases"
177
+ subcommand "release", ReleaseCommand
178
+ end
167
179
 
180
+ ::Cli.start
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,57 @@
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
+ # "^{}" means the object could be a tag. https://mirrors.edge.kernel.org/pub/software/scm/git/docs/gitrevisions.html#_specifying_revisions
35
+ # Example:
36
+ # git ls-remote git@gir.example.com:repo.git | grep release-latest
37
+ # 174cf2b6685df563e59c5cd0d367996fcf24f0ae refs/tags/release-latest <-- annotated tag itself
38
+ # 47208e276cd277896887417a383e05973278438c refs/tags/release-latest^{} <-- WE NEED: original commit tag is references to
39
+ rev_name_pair = remote_refs(repo, branch+"^{}") # try to find commit tag is references to
40
+ rev_name_pair ||= remote_refs(repo, branch) # try to find simple branch or commit
41
+
42
+ raise "There is no '#{branch}' revision at #{repo}" if rev_name_pair.nil?
43
+
44
+ rev, _name = rev_name_pair.split
45
+ rev[0..7]
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def remote_refs repo, branch
52
+ cmd!("git ls-remote #{repo} #{branch}", capture: true).split("\n").select{|line| line.strip.end_with?("/#{branch}") }.first
53
+ end
54
+
55
+ end
56
+ end
57
+
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.2'
5
+ VERSION = '0.1.6'
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 CHANGED
@@ -35,5 +35,7 @@ Gem::Specification.new 'retag' do |spec|
35
35
  spec.add_runtime_dependency 'thor'
36
36
  spec.add_runtime_dependency 'uri'
37
37
  spec.add_runtime_dependency 'yaml'
38
+ spec.add_runtime_dependency 'gitlab'
39
+
38
40
  end
39
41
 
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.2
4
+ version: 0.1.6
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,6 +212,20 @@ 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
@@ -230,6 +244,7 @@ files:
230
244
  - lib/retag.rb
231
245
  - lib/retag/image.rb
232
246
  - lib/retag/logger.rb
247
+ - lib/retag/repo.rb
233
248
  - lib/retag/service.rb
234
249
  - lib/retag/utils.rb
235
250
  - lib/retag/version.rb