bosh_cli 1.2831.0 → 1.2839.0
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 +4 -4
- data/lib/cli.rb +7 -3
- data/lib/cli/archive_builder.rb +119 -0
- data/lib/cli/archive_repository.rb +108 -0
- data/lib/cli/archive_repository_provider.rb +12 -0
- data/lib/cli/base_command.rb +1 -1
- data/lib/cli/build_artifact.rb +75 -0
- data/lib/cli/commands/deployment.rb +4 -9
- data/lib/cli/commands/release/create_release.rb +36 -39
- data/lib/cli/glob_match.rb +32 -0
- data/lib/cli/job_property_collection.rb +5 -5
- data/lib/cli/job_property_validator.rb +8 -8
- data/lib/cli/release_builder.rb +43 -44
- data/lib/cli/release_compiler.rb +11 -11
- data/lib/cli/resources/job.rb +190 -0
- data/lib/cli/resources/package.rb +210 -0
- data/lib/cli/version.rb +1 -1
- data/lib/cli/versions/local_version_storage.rb +4 -4
- data/lib/cli/versions/version_file_resolver.rb +1 -3
- metadata +16 -12
- data/lib/cli/job_builder.rb +0 -277
- data/lib/cli/package_builder.rb +0 -316
- data/lib/cli/packaging_helper.rb +0 -217
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f11dc3119b4347b9e61c770c43d31b09ec3e1aa
|
4
|
+
data.tar.gz: 5d829eee1ce9742ea980476c1b7cb769887ab59e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb7ac41c08a80eee35cec3672d9969c91de24cea903e0ae1c765bfbd1c4c86940e7b4ce3953c3cf5717c610b2988c8e0609ec7621520fc882fc67c449914ab29
|
7
|
+
data.tar.gz: a0ba29122f2ff944793adb8f99473b0e29ffd39ac49db87ad368446bf38e9bdeecaebe3c33d3ccedfaa0c92a70894fbaf70ae019eb615865906108adee3f76ec
|
data/lib/cli.rb
CHANGED
@@ -51,6 +51,7 @@ require 'common/thread_pool'
|
|
51
51
|
require 'cli/config'
|
52
52
|
require 'cli/core_ext'
|
53
53
|
require 'cli/errors'
|
54
|
+
require 'cli/glob_match'
|
54
55
|
require 'cli/yaml_helper'
|
55
56
|
require 'cli/dependency_helper'
|
56
57
|
require 'cli/deployment_manifest'
|
@@ -75,9 +76,12 @@ require 'cli/versions/releases_dir_migrator'
|
|
75
76
|
require 'cli/versions/version_file_resolver'
|
76
77
|
require 'cli/versions/multi_release_support'
|
77
78
|
|
78
|
-
require 'cli/
|
79
|
-
require 'cli/
|
80
|
-
require 'cli/
|
79
|
+
require 'cli/archive_builder'
|
80
|
+
require 'cli/archive_repository_provider'
|
81
|
+
require 'cli/archive_repository'
|
82
|
+
require 'cli/build_artifact'
|
83
|
+
require 'cli/resources/job'
|
84
|
+
require 'cli/resources/package'
|
81
85
|
require 'cli/changeset_helper'
|
82
86
|
require 'cli/deployment_manifest_compiler'
|
83
87
|
require 'cli/task_tracking'
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Bosh::Cli
|
2
|
+
class ArchiveBuilder
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize(archive_repository_provider, options = {})
|
6
|
+
@archive_repository_provider = archive_repository_provider
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def build(resource)
|
11
|
+
@archive_repository = @archive_repository_provider.get(resource)
|
12
|
+
resource.run_script(:prepare)
|
13
|
+
|
14
|
+
artifact = nil
|
15
|
+
with_indent(' ') do
|
16
|
+
artifact = locate_artifact(resource)
|
17
|
+
if artifact.nil?
|
18
|
+
artifact = create_artifact(resource)
|
19
|
+
say("Generated version '#{artifact.fingerprint}'".make_green)
|
20
|
+
|
21
|
+
unless dry_run?
|
22
|
+
artifact = @archive_repository.install(artifact)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if final? && !dry_run?
|
27
|
+
say("Uploading final version '#{artifact.version}'...")
|
28
|
+
artifact, blobstore_id = @archive_repository.upload_to_blobstore(artifact)
|
29
|
+
say("Uploaded, blobstore id '#{blobstore_id}'")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
artifact
|
34
|
+
rescue Bosh::Blobstore::BlobstoreError => e
|
35
|
+
raise BlobstoreError, "Blobstore error: #{e}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def dry_run?
|
39
|
+
!!options[:dry_run]
|
40
|
+
end
|
41
|
+
|
42
|
+
def final?
|
43
|
+
!!options[:final]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def copy_files(resource)
|
49
|
+
resource.files.each do |src, dest|
|
50
|
+
dest_path = Pathname(staging_dir).join(dest)
|
51
|
+
if File.directory?(src)
|
52
|
+
FileUtils.mkdir_p(dest_path)
|
53
|
+
else
|
54
|
+
FileUtils.mkdir_p(dest_path.parent)
|
55
|
+
FileUtils.cp(src, dest_path, :preserve => true)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def locate_artifact(resource)
|
61
|
+
artifact = @archive_repository.lookup(resource)
|
62
|
+
|
63
|
+
if artifact.nil?
|
64
|
+
say("No artifact found for #{resource.name}".make_red)
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
|
68
|
+
if artifact.dev_artifact? && final? && !dry_run?
|
69
|
+
artifact = @archive_repository.copy_from_dev_to_final(artifact)
|
70
|
+
end
|
71
|
+
|
72
|
+
artifact
|
73
|
+
rescue Bosh::Cli::CorruptedArchive => e
|
74
|
+
say "#{"Warning".make_red}: #{e.message}"
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_artifact(resource)
|
79
|
+
tarball_path = safe_temp_file(resource.name, '.tgz')
|
80
|
+
|
81
|
+
say('Generating...')
|
82
|
+
|
83
|
+
copy_files(resource)
|
84
|
+
resource.run_script(:pre_packaging, staging_dir)
|
85
|
+
|
86
|
+
in_staging_dir do
|
87
|
+
tar_out = `tar -chzf #{tarball_path} . 2>&1`
|
88
|
+
unless $?.exitstatus == 0
|
89
|
+
raise PackagingError, "Cannot create tarball: #{tar_out}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
fingerprint = BuildArtifact.make_fingerprint(resource)
|
94
|
+
|
95
|
+
sha1 = BuildArtifact.checksum(tarball_path)
|
96
|
+
BuildArtifact.new(resource.name, fingerprint, tarball_path, sha1, resource.dependencies, true, !final?)
|
97
|
+
end
|
98
|
+
|
99
|
+
def file_checksum(path)
|
100
|
+
Digest::SHA1.file(path).hexdigest
|
101
|
+
end
|
102
|
+
|
103
|
+
def staging_dir
|
104
|
+
@staging_dir ||= Dir.mktmpdir
|
105
|
+
end
|
106
|
+
|
107
|
+
def in_staging_dir
|
108
|
+
Dir.chdir(staging_dir) { yield }
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def safe_temp_file(prefix, suffix, dir = Dir.tmpdir)
|
114
|
+
Dir::Tmpname.create([prefix, suffix], dir) do |tmpname, _, _|
|
115
|
+
File.open(tmpname, File::RDWR|File::CREAT|File::EXCL).close
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Bosh::Cli
|
2
|
+
class ArchiveRepository
|
3
|
+
def initialize(archive_dir, blobstore, resource)
|
4
|
+
@archive_dir = archive_dir
|
5
|
+
@blobstore = blobstore
|
6
|
+
|
7
|
+
dev_builds_dir = Pathname(@archive_dir).join(".dev_builds", resource.plural_type, resource.name).to_s
|
8
|
+
FileUtils.mkdir_p(dev_builds_dir)
|
9
|
+
@dev_index = Versions::VersionsIndex.new(dev_builds_dir)
|
10
|
+
@dev_storage = Versions::LocalVersionStorage.new(dev_builds_dir)
|
11
|
+
|
12
|
+
final_builds_dir = Pathname(@archive_dir).join(".final_builds", resource.plural_type, resource.name).to_s
|
13
|
+
FileUtils.mkdir_p(final_builds_dir)
|
14
|
+
@final_index = Versions::VersionsIndex.new(final_builds_dir)
|
15
|
+
@final_storage = Versions::LocalVersionStorage.new(final_builds_dir)
|
16
|
+
|
17
|
+
@final_resolver = Versions::VersionFileResolver.new(@final_storage, @blobstore)
|
18
|
+
end
|
19
|
+
|
20
|
+
def lookup(resource)
|
21
|
+
fingerprint = BuildArtifact.make_fingerprint(resource)
|
22
|
+
|
23
|
+
artifact_info = @final_index[fingerprint]
|
24
|
+
if artifact_info && artifact_info['blobstore_id']
|
25
|
+
blobstore_id = artifact_info['blobstore_id']
|
26
|
+
version = artifact_info['version'] || fingerprint
|
27
|
+
sha1 = artifact_info['sha1']
|
28
|
+
|
29
|
+
say('Using final version')
|
30
|
+
tarball_path = @final_resolver.find_file(blobstore_id, sha1, version, "#{resource.singular_type} #{resource.name} (#{version})") # todo: 'package' vs 'job'
|
31
|
+
|
32
|
+
BuildArtifact.new(resource.name, fingerprint, tarball_path, sha1, resource.dependencies, false, false)
|
33
|
+
else
|
34
|
+
artifact_info = @dev_index[fingerprint]
|
35
|
+
if artifact_info
|
36
|
+
version = artifact_info['version'] || fingerprint
|
37
|
+
if @dev_storage.has_file?(version)
|
38
|
+
say('Using dev version')
|
39
|
+
|
40
|
+
tarball_path = @dev_storage.get_file(version)
|
41
|
+
if file_checksum(tarball_path) != artifact_info['sha1']
|
42
|
+
raise CorruptedArchive, "#{resource.singular_type} #{resource.name} (#{version}) archive at #{tarball_path} corrupted"
|
43
|
+
end
|
44
|
+
|
45
|
+
BuildArtifact.new(resource.name, fingerprint, tarball_path, artifact_info['sha1'], resource.dependencies, false, true)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
rescue Bosh::Blobstore::NotFound
|
51
|
+
raise BlobstoreError, "Final version of '#{name}' not found in blobstore"
|
52
|
+
rescue Bosh::Blobstore::BlobstoreError => e
|
53
|
+
raise BlobstoreError, "Blobstore error: #{e}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def upload_to_blobstore(artifact)
|
57
|
+
artifact_info = @final_index[artifact.fingerprint]
|
58
|
+
# todo raise if artifact.dev_artifact?
|
59
|
+
return artifact, artifact_info['blobstore_id'] if artifact_info['blobstore_id']
|
60
|
+
|
61
|
+
blobstore_id = nil
|
62
|
+
File.open(artifact.tarball_path, 'r') do |f|
|
63
|
+
blobstore_id = @blobstore.create(f)
|
64
|
+
end
|
65
|
+
|
66
|
+
@final_index.update_version(artifact.fingerprint, {
|
67
|
+
'version' => artifact.version,
|
68
|
+
'sha1' => artifact.sha1,
|
69
|
+
'blobstore_id' => blobstore_id
|
70
|
+
})
|
71
|
+
artifact = BuildArtifact.new(artifact.name, artifact.fingerprint, artifact.tarball_path, artifact.sha1, artifact.dependencies, artifact.new_version?, false)
|
72
|
+
return artifact, blobstore_id
|
73
|
+
end
|
74
|
+
|
75
|
+
def install(artifact)
|
76
|
+
fingerprint = artifact.fingerprint
|
77
|
+
origin_file = artifact.tarball_path
|
78
|
+
new_tarball_path = place_file_and_update_index(fingerprint, origin_file,
|
79
|
+
artifact.dev_artifact? ? @dev_index : @final_index,
|
80
|
+
artifact.dev_artifact? ? @dev_storage : @final_storage)
|
81
|
+
|
82
|
+
BuildArtifact.new(artifact.name, artifact.fingerprint, new_tarball_path, artifact.sha1, artifact.dependencies, artifact.new_version?, artifact.dev_artifact?)
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_from_dev_to_final(artifact)
|
86
|
+
final_tarball_path = place_file_and_update_index(artifact.fingerprint, artifact.tarball_path, @final_index, @final_storage)
|
87
|
+
BuildArtifact.new(artifact.name, artifact.fingerprint, final_tarball_path, artifact.sha1, artifact.dependencies, artifact.new_version?, false)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def place_file_and_update_index(fingerprint, origin_file, index, storage)
|
93
|
+
# add version (with its validation) before adding sha1
|
94
|
+
index.add_version(fingerprint, {'version' => fingerprint} )
|
95
|
+
tarball_path = storage.put_file(fingerprint, origin_file)
|
96
|
+
sha1 = file_checksum(tarball_path)
|
97
|
+
index.update_version(fingerprint, {'version' => fingerprint, 'sha1' => sha1})
|
98
|
+
tarball_path
|
99
|
+
end
|
100
|
+
|
101
|
+
def file_checksum(path)
|
102
|
+
Digest::SHA1.file(path).hexdigest
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class CorruptedArchive < StandardError
|
107
|
+
end
|
108
|
+
end
|
data/lib/cli/base_command.rb
CHANGED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Bosh::Cli
|
2
|
+
class BuildArtifact
|
3
|
+
attr_reader :name, :fingerprint, :tarball_path, :sha1, :dependencies
|
4
|
+
|
5
|
+
def initialize(name, fingerprint, tarball_path, sha1, dependencies, is_new_version, is_dev_artifact)
|
6
|
+
@name = name
|
7
|
+
@fingerprint = fingerprint
|
8
|
+
@tarball_path = tarball_path
|
9
|
+
@sha1 = sha1
|
10
|
+
@dependencies = dependencies
|
11
|
+
@is_dev_artifact = is_dev_artifact
|
12
|
+
@notes = []
|
13
|
+
@is_new_version = is_new_version
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
fingerprint
|
18
|
+
end
|
19
|
+
|
20
|
+
def dev_artifact?
|
21
|
+
@is_dev_artifact
|
22
|
+
end
|
23
|
+
|
24
|
+
def new_version?
|
25
|
+
@is_new_version
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.checksum(tarball_path)
|
31
|
+
if tarball_path && File.exists?(tarball_path)
|
32
|
+
digest_file(tarball_path)
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.digest_file(filename)
|
39
|
+
File.file?(filename) ? Digest::SHA1.file(filename).hexdigest : ''
|
40
|
+
end
|
41
|
+
|
42
|
+
# Git doesn't really track file permissions, it just looks at executable
|
43
|
+
# bit and uses 0755 if it's set or 0644 if not. We have to mimic that
|
44
|
+
# behavior in the fingerprint calculation to avoid the situation where
|
45
|
+
# seemingly clean working copy would trigger new fingerprints for
|
46
|
+
# artifacts with changed permissions. Also we don't want current
|
47
|
+
# fingerprints to change, hence the exact values below.
|
48
|
+
def self.file_mode(path)
|
49
|
+
if File.directory?(path)
|
50
|
+
'40755'
|
51
|
+
elsif File.executable?(path)
|
52
|
+
'100755'
|
53
|
+
else
|
54
|
+
'100644'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: be sure we are handling the case in which there was an index, with a pre-defined fingerprint
|
59
|
+
def self.make_fingerprint(resource)
|
60
|
+
scheme = 2
|
61
|
+
contents = "v#{scheme}"
|
62
|
+
|
63
|
+
resource.files.each do |filename, name|
|
64
|
+
contents << resource.format_fingerprint(digest_file(filename), filename, name, file_mode(filename))
|
65
|
+
end
|
66
|
+
|
67
|
+
contents << resource.additional_fingerprints.join(",")
|
68
|
+
Digest::SHA1.hexdigest(contents)
|
69
|
+
end
|
70
|
+
|
71
|
+
def resource
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -154,18 +154,13 @@ module Bosh::Cli::Command
|
|
154
154
|
end
|
155
155
|
|
156
156
|
say(" - discovering packages")
|
157
|
-
packages = Bosh::Cli::
|
158
|
-
work_dir,
|
159
|
-
:dry_run => true,
|
160
|
-
:final => false
|
161
|
-
)
|
157
|
+
packages = Bosh::Cli::Resources::Package.discover(work_dir)
|
162
158
|
|
163
159
|
say(" - discovering jobs")
|
164
|
-
jobs = Bosh::Cli::
|
160
|
+
jobs = Bosh::Cli::Resources::Job.discover(
|
165
161
|
work_dir,
|
166
|
-
:
|
167
|
-
|
168
|
-
:package_names => packages.map {|package| package.name}
|
162
|
+
# TODO: be sure this is covered in integration
|
163
|
+
packages.map {|package| package['name']}
|
169
164
|
)
|
170
165
|
|
171
166
|
say(" - validating properties")
|
@@ -85,13 +85,13 @@ module Bosh::Cli::Command
|
|
85
85
|
end
|
86
86
|
|
87
87
|
header('Building packages')
|
88
|
-
|
88
|
+
package_artifacts = build_packages(dry_run, final)
|
89
89
|
|
90
90
|
header('Building jobs')
|
91
|
-
|
91
|
+
job_artifacts = build_jobs(package_artifacts.map { |artifact| artifact.name }, dry_run, final)
|
92
92
|
|
93
93
|
header('Building release')
|
94
|
-
release_builder = build_release(dry_run, final,
|
94
|
+
release_builder = build_release(dry_run, final, job_artifacts, manifest_only, package_artifacts, name, version)
|
95
95
|
|
96
96
|
header('Release summary')
|
97
97
|
show_summary(release_builder)
|
@@ -134,22 +134,19 @@ module Bosh::Cli::Command
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def build_packages(dry_run, final)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
:dry_run => dry_run
|
142
|
-
)
|
143
|
-
|
144
|
-
packages.each do |package|
|
137
|
+
archive_builder = Bosh::Cli::ArchiveBuilder.new(archive_repository_provider,
|
138
|
+
dry_run: dry_run, final: final)
|
139
|
+
packages = Bosh::Cli::Resources::Package.discover(work_dir)
|
140
|
+
artifacts = packages.map do |package|
|
145
141
|
say("Building #{package.name.make_green}...")
|
146
|
-
|
142
|
+
artifact = archive_builder.build(package)
|
147
143
|
nl
|
144
|
+
artifact
|
148
145
|
end
|
149
146
|
|
150
147
|
if packages.size > 0
|
151
|
-
package_index =
|
152
|
-
index[
|
148
|
+
package_index = artifacts.inject({}) do |index, artifact|
|
149
|
+
index[artifact.name] = artifact.dependencies
|
153
150
|
index
|
154
151
|
end
|
155
152
|
sorted_packages = tsort_packages(package_index)
|
@@ -161,11 +158,15 @@ module Bosh::Cli::Command
|
|
161
158
|
nl
|
162
159
|
end
|
163
160
|
|
164
|
-
|
161
|
+
artifacts
|
162
|
+
end
|
163
|
+
|
164
|
+
def archive_repository_provider
|
165
|
+
@archive_repository_provider ||= Bosh::Cli::ArchiveRepositoryProvider.new(work_dir, release.blobstore)
|
165
166
|
end
|
166
167
|
|
167
|
-
def build_release(dry_run, final,
|
168
|
-
release_builder = Bosh::Cli::ReleaseBuilder.new(release,
|
168
|
+
def build_release(dry_run, final, job_artifacts, manifest_only, package_artifacts, name, version)
|
169
|
+
release_builder = Bosh::Cli::ReleaseBuilder.new(release, package_artifacts, job_artifacts, name,
|
169
170
|
final: final,
|
170
171
|
commit_hash: commit_hash,
|
171
172
|
version: version,
|
@@ -183,22 +184,18 @@ module Bosh::Cli::Command
|
|
183
184
|
release_builder
|
184
185
|
end
|
185
186
|
|
186
|
-
def build_jobs(
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
:dry_run => dry_run,
|
192
|
-
:package_names => built_package_names
|
193
|
-
)
|
194
|
-
|
195
|
-
jobs.each do |job|
|
187
|
+
def build_jobs(packages, dry_run, final)
|
188
|
+
archive_builder = Bosh::Cli::ArchiveBuilder.new(archive_repository_provider,
|
189
|
+
:final => final, :dry_run => dry_run)
|
190
|
+
jobs = Bosh::Cli::Resources::Job.discover(work_dir, packages)
|
191
|
+
artifacts = jobs.map do |job|
|
196
192
|
say("Building #{job.name.make_green}...")
|
197
|
-
|
193
|
+
artifact = archive_builder.build(job)
|
198
194
|
nl
|
195
|
+
artifact
|
199
196
|
end
|
200
197
|
|
201
|
-
|
198
|
+
artifacts
|
202
199
|
end
|
203
200
|
|
204
201
|
def save_final_release_name
|
@@ -225,15 +222,15 @@ module Bosh::Cli::Command
|
|
225
222
|
def show_summary(builder)
|
226
223
|
packages_table = table do |t|
|
227
224
|
t.headings = %w(Name Version Notes)
|
228
|
-
builder.packages.each do |
|
229
|
-
t << artifact_summary(
|
225
|
+
builder.packages.each do |package_artifact|
|
226
|
+
t << artifact_summary(package_artifact)
|
230
227
|
end
|
231
228
|
end
|
232
229
|
|
233
230
|
jobs_table = table do |t|
|
234
231
|
t.headings = %w(Name Version Notes)
|
235
|
-
builder.jobs.each do |
|
236
|
-
t << artifact_summary(
|
232
|
+
builder.jobs.each do |job_artifact|
|
233
|
+
t << artifact_summary(job_artifact)
|
237
234
|
end
|
238
235
|
end
|
239
236
|
|
@@ -260,12 +257,12 @@ module Bosh::Cli::Command
|
|
260
257
|
end
|
261
258
|
end
|
262
259
|
|
263
|
-
def artifact_summary(
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
260
|
+
def artifact_summary(artifact)
|
261
|
+
[
|
262
|
+
artifact.name,
|
263
|
+
artifact.version,
|
264
|
+
artifact.new_version? ? 'new version' : '',
|
265
|
+
]
|
269
266
|
end
|
270
267
|
|
271
268
|
def commit_hash
|