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 +4 -4
- data/Gemfile.lock +12 -1
- data/bin/retag +96 -83
- data/lib/retag/image.rb +0 -12
- data/lib/retag/repo.rb +57 -0
- data/lib/retag/service.rb +7 -31
- data/lib/retag/version.rb +1 -1
- data/lib/retag.rb +2 -0
- data/retag.gemspec +2 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab9f253e8ff9f3a7bfd637ddaa844cff811d3c75f79fde036bdacd8eb1f58f91
|
4
|
+
data.tar.gz: d36f32cb6b21896c28901f18420ef1ccf4207e4cf2683c42407bebd52662f761
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 = :
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
86
|
-
|
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(:
|
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 "
|
114
|
-
|
115
|
-
$logger.
|
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
|
-
|
145
|
+
end
|
133
146
|
|
134
|
-
def cache_image(opts)
|
135
|
-
"#{opts['service_image']}_cache:latest"
|
136
|
-
end
|
137
147
|
|
138
|
-
|
148
|
+
class Cli < Thor
|
139
149
|
|
140
|
-
|
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
|
-
#
|
156
|
+
# Gitlab authorization
|
157
|
+
Using GITLAB_API_ENDPOINT and GITLAB_API_PRIVATE_TOKEN environment variable used for authorization
|
143
158
|
|
144
|
-
#
|
159
|
+
#{File.basename(__FILE__)}"
|
145
160
|
|
146
|
-
|
161
|
+
class_option :verbose, type: :boolean
|
147
162
|
|
148
|
-
|
149
|
-
|
163
|
+
desc 'version', 'Display version'
|
164
|
+
map %w[-v --version] => :version
|
150
165
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
# ]
|
155
|
-
# }
|
166
|
+
def version
|
167
|
+
say Retag::VERSION
|
168
|
+
end
|
156
169
|
|
157
|
-
|
170
|
+
desc "repo SUBCOMMAND ...ARGS", "Manage git repository stuffs"
|
171
|
+
subcommand "repo", RepoCommand
|
158
172
|
|
159
|
-
|
160
|
-
|
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
|
-
|
165
|
-
|
166
|
-
|
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, :
|
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
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
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.
|
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-
|
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
|