simp-rake-helpers 5.1.4 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/simp/componentinfo.rb +227 -0
- data/lib/simp/rake/helpers/version.rb +1 -1
- data/lib/simp/rake/pkg.rb +115 -0
- data/lib/simp/rake/pupmod/helpers.rb +2 -2
- data/lib/simp/relchecks.rb +172 -0
- data/lib/simp/rpm.rb +2 -0
- data/spec/acceptance/nodesets/default.yml +2 -0
- data/spec/acceptance/pkg_rpm_spec.rb +42 -133
- data/spec/lib/simp/componentinfo_changelog_regex_spec.rb +120 -0
- data/spec/lib/simp/componentinfo_spec.rb +278 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_missing_release/build/asset_missing_release.spec +36 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_missing_version/build/asset_missing_version.spec +36 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_with_dist_in_release/build/asset_with_dist_in_release.spec +31 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_with_multiple_packages/build/asset_with_multiple_packages.spec +64 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_with_single_package/build/asset_with_single_package.spec +37 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_with_two_spec_files/build/asseta.spec +43 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_with_two_spec_files/build/assetb.spec +43 -0
- data/spec/lib/simp/files/componentinfo_spec/asset_without_spec_file/build/README +1 -0
- data/spec/lib/simp/files/componentinfo_spec/module/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_missing_version_metadata/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module_missing_version_metadata/metadata.json +43 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_date_misordered_entries/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_date_misordered_entries/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_invalid_entries/CHANGELOG +8 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_invalid_entries/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_invalid_weekday_entry/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_invalid_weekday_entry/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_malformed_metadata/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_malformed_metadata/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_version_misordered_entries/CHANGELOG +14 -0
- data/spec/lib/simp/files/componentinfo_spec/module_with_version_misordered_entries/metadata.json +44 -0
- data/spec/lib/simp/files/componentinfo_spec/module_without_changelog/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_compare_latest_tag_spec/module/CHANGELOG +5 -0
- data/spec/lib/simp/files/relchecks_compare_latest_tag_spec/module/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_compare_latest_tag_spec/module_without_changelog/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_mismatched_release/build/asset_mismatched_release.spec +35 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_missing_changelog/build/asset_missing_changelog.spec +27 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_with_dist_in_release/build/asset_with_dist_in_release.spec +31 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_with_multiple_packages/build/asset_with_multiple_packages.spec +64 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_with_single_package/build/asset_with_single_package.spec +35 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/asset_without_spec_file/build/README +1 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_misordered_entries/CHANGELOG +14 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_misordered_entries/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_multiple_entries/CHANGELOG +14 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_multiple_entries/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_newer_changelog_entry/CHANGELOG +14 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_newer_changelog_entry/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_no_entry_for_version/CHANGELOG +14 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_no_entry_for_version/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_single_entry/CHANGELOG +7 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_with_single_entry/metadata.json +44 -0
- data/spec/lib/simp/files/relchecks_create_tag_changelog_spec/module_without_changelog/metadata.json +44 -0
- data/spec/lib/simp/relchecks_compare_latest_tag_spec.rb +89 -0
- data/spec/lib/simp/relchecks_create_tag_changelog_spec.rb +143 -0
- metadata +51 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 476fb45c0548c83de14eec268b1970b990a0c50ef8ead160f502bb3c34fa3bd6
|
4
|
+
data.tar.gz: 0d6dde21abf6befaf136b973f324d2cd812f0d36d49c0a6e48971499b0487802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f090fd69b70d38e94f0a71ba57d3e76782b10a7ef6e7987c8a4b8665b17a29b2b5c9b7065c0b150979544f09203b8ac385fea194b2bf5672b44499868302a9e0
|
7
|
+
data.tar.gz: 3671a8e5759091753650ca03fcddfbc68ada6c85fcb12e6c33e6d803e3b9c3d78eafbcf858ef828632ba085d9fe831abd3d4d124227e83afaf7a408c8f310a6c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
### 5.2.0 / 2017-12-20
|
2
|
+
* Create pkg:create_tag_changelog, which is a more thorough version
|
3
|
+
of Simp::Rake::Pupmod::Helpers changelog_annotation task.
|
4
|
+
- Now supports non-Puppet SIMP assets for which version and changelog
|
5
|
+
information is specified in an RPM spec files.
|
6
|
+
- Provides more extensive validation of date strings and changelog
|
7
|
+
entry ordering.
|
8
|
+
- Stops processing at the first invalid changelog entry, to minimize
|
9
|
+
non-catestrophic errors from old changelog entries.
|
10
|
+
* Create pkg:compare_latest_tag, which is a more general replacement
|
11
|
+
for the Simp::Rake::Pupmod::Helpers compare_latest_tag task.
|
12
|
+
- Now supports non-Puppet SIMP assets for which version and changelog
|
13
|
+
information is specified in an RPM spec files.
|
14
|
+
- Does the same validation as the new pkg:create_tag_changelog task.
|
15
|
+
* Fix broken acceptance tests
|
16
|
+
- Remove logic to build SIMP 4 and SIMP 5 RPMs.
|
17
|
+
- Remove mock logic
|
18
|
+
|
1
19
|
### 5.1.4 / 2017-11-27
|
2
20
|
* Switch back to using Gem::Version.new instead of Puppet's vercmp since
|
3
21
|
Gem::Version matches the standard RPM version semantics and Puppet does not.
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Simp; end
|
4
|
+
|
5
|
+
# Class that provides component version, release, and changelog
|
6
|
+
# information
|
7
|
+
class Simp::ComponentInfo
|
8
|
+
attr_accessor :component_dir, :type, :version, :release, :changelog
|
9
|
+
|
10
|
+
# A helpful method for ensuring that the errors can be easily seen
|
11
|
+
ERR_MARKER = "WARNING: !!! "
|
12
|
+
|
13
|
+
# See https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Changelogs
|
14
|
+
# When matched against this regex
|
15
|
+
# match 1 = date of the form {weekday} {month} {day} {year}
|
16
|
+
# match 2 = author of the form {name} <{email}>
|
17
|
+
# match 3 = version
|
18
|
+
# match 4 = optional release qualifier; nil when absent
|
19
|
+
CHANGELOG_ENTRY_REGEX = /^\*\s+((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-3]{1}[0-9]{1} \d{4})\s+(.+<.+>)(?:\s+|\s*-\s*)(\d+\.\d+\.\d+)(?:-(\S+))?\s*$/
|
20
|
+
|
21
|
+
# Load component information from appropriate component files
|
22
|
+
#
|
23
|
+
# Module
|
24
|
+
# version: Top-level 'version' key from the metadata.json file
|
25
|
+
# release: Not set
|
26
|
+
# changelog: Array of valid changelog entries derived from the
|
27
|
+
# CHANGELOG file
|
28
|
+
#
|
29
|
+
# Asset
|
30
|
+
# version: Primary Version tag from build/<component>.spec
|
31
|
+
# release: Primary Release tag from build/<component>.spec
|
32
|
+
# changelog: Array of valid changelog entries derived from the
|
33
|
+
# contents of the %changelog section in
|
34
|
+
# build/<component>.spec. Will be an empty if
|
35
|
+
# %changelog is not present.
|
36
|
+
#
|
37
|
+
# NOTES:
|
38
|
+
# 1. The changelog is only parsed up to the first entry that
|
39
|
+
# fails basic validation.
|
40
|
+
# - First line must be of the form
|
41
|
+
# * {date string} {author info} - {version}
|
42
|
+
# * {date string} {author info} - {version}-{release}
|
43
|
+
#
|
44
|
+
# where,
|
45
|
+
# date string = {weekday} {month} {day} {year}
|
46
|
+
# author info = {author name} <{author email}>
|
47
|
+
# - Weekday must be correct for the specified date
|
48
|
+
# - Entries must be separated by a blank line
|
49
|
+
#
|
50
|
+
# NOTE: This currently does not support the valid RPM `%changelog`
|
51
|
+
# format that places the version number on the next line:
|
52
|
+
#
|
53
|
+
# * Fri Mar 02 2012 Maintenance
|
54
|
+
# 4.0.0-2
|
55
|
+
# - Improved test stubs.
|
56
|
+
#
|
57
|
+
# However, since we are not using this form for recent
|
58
|
+
# changelogs and we stop processing upon reaching such
|
59
|
+
# a changelog entry, this should *not* be an issue.
|
60
|
+
# 2. When RPM spec files contain sub-packages, only the primary
|
61
|
+
# package information is returned.
|
62
|
+
# 3. Some assets have another version in a lib/.../version.rb.
|
63
|
+
# Since there is no definitive way for this code to determine
|
64
|
+
# that version, it will not be loaded here.
|
65
|
+
#
|
66
|
+
# Fails if any of the following occur:
|
67
|
+
# - The metadata.json file for a Puppet module component cannot be
|
68
|
+
# parsed.
|
69
|
+
# - A top-level 'version' key does not exist in the metadata.json file.
|
70
|
+
# - The CHANGELOG file for a Puppet module component does not exist.
|
71
|
+
# - The RPM spec file for a non-Puppet module component does not exist.
|
72
|
+
# - More than 1 RPM spec file for a non-Puppet module component exists.
|
73
|
+
# - The version, release or changelog cannot be extracted from the RPM
|
74
|
+
# spec file for a non-Puppet module.
|
75
|
+
# - Any changelog entry below the first entry has a version greater
|
76
|
+
# than that of the first entry. Changelog entries must be
|
77
|
+
# ordered from latest version to earliest version.
|
78
|
+
# - The changelog entries are out of date order.
|
79
|
+
#
|
80
|
+
# +component_dir+:: The root directory of the component project.
|
81
|
+
# +latest_version_only+:: Whether to only return the changelog
|
82
|
+
# entries for the latest version
|
83
|
+
# +verbose+:: Whether to log a changelog validation failure
|
84
|
+
#
|
85
|
+
def initialize(component_dir, latest_version_only = false, verbose = true)
|
86
|
+
@component_dir = component_dir
|
87
|
+
|
88
|
+
if File.exists?(File.join(@component_dir, 'metadata.json'))
|
89
|
+
@type = :module
|
90
|
+
load_module_info(latest_version_only, verbose)
|
91
|
+
else
|
92
|
+
@type = :asset
|
93
|
+
load_asset_info(latest_version_only, verbose)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
def load_module_info(latest_version_only, verbose)
|
99
|
+
require 'json'
|
100
|
+
metadata_file = File.join(@component_dir, 'metadata.json')
|
101
|
+
metadata = JSON.parse(File.read(metadata_file))
|
102
|
+
@version = metadata['version']
|
103
|
+
@release = nil
|
104
|
+
fail("ERROR: Version missing from #{metadata_file}") if @version.nil?
|
105
|
+
|
106
|
+
changelog_file = File.join(component_dir, 'CHANGELOG')
|
107
|
+
unless File.exists?(changelog_file)
|
108
|
+
fail("ERROR: No CHANGELOG file found in #{component_dir}")
|
109
|
+
end
|
110
|
+
@changelog = parse_changelog(IO.read(changelog_file), latest_version_only, verbose)
|
111
|
+
end
|
112
|
+
|
113
|
+
def load_asset_info(latest_version_only, verbose)
|
114
|
+
rpm_spec_files = Dir.glob(File.join(@component_dir, 'build', '*.spec'))
|
115
|
+
if rpm_spec_files.empty?
|
116
|
+
fail("No RPM spec file found in #{File.join(@component_dir, 'build')}")
|
117
|
+
elsif rpm_spec_files.size > 1
|
118
|
+
fail("More than 1 RPM spec file found: #{rpm_spec_files.join(' ')}")
|
119
|
+
end
|
120
|
+
|
121
|
+
# Determine asset version, which we will ASSUME to be the main
|
122
|
+
# package version. The RPM query, below, will return the main
|
123
|
+
# package followed by subpackages.
|
124
|
+
version_query = "rpm -q --queryformat '%{VERSION} %{RELEASE}\\n'" +
|
125
|
+
" --specfile #{rpm_spec_files[0]}"
|
126
|
+
|
127
|
+
rpm_version_list = `#{version_query} 2> /dev/null`
|
128
|
+
if $?.exitstatus != 0
|
129
|
+
fail("Could not extract version and release from #{rpm_spec_files[0]}." +
|
130
|
+
" To debug, execute:\n #{version_query}")
|
131
|
+
end
|
132
|
+
@version, @release = rpm_version_list.split("\n")[0].split
|
133
|
+
|
134
|
+
changelog_query = "rpm -q --changelog --specfile #{rpm_spec_files[0]}"
|
135
|
+
raw_changelog = `#{changelog_query} 2> /dev/null`
|
136
|
+
if $?.exitstatus != 0
|
137
|
+
fail("Could not extract changelog from #{rpm_spec_files[0]}." +
|
138
|
+
" To debug, execute:\n #{changelog_query}")
|
139
|
+
end
|
140
|
+
@changelog = parse_changelog(raw_changelog, latest_version_only, verbose)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Return an array of changelog entries, optionally for only the
|
144
|
+
# latest version
|
145
|
+
#
|
146
|
+
# Iterates through the changelog entries from the newest to the
|
147
|
+
# oldest, performing basic validation. Stops processing entries
|
148
|
+
# if an entry fails validation.
|
149
|
+
#
|
150
|
+
def parse_changelog(changelog, latest_version_only, verbose)
|
151
|
+
# split on the entry-separating lines
|
152
|
+
changelog_entries = changelog.split(/^\s*$/)
|
153
|
+
latest_version = nil # 1st version found is latest version
|
154
|
+
prev_entry_date = nil
|
155
|
+
changelogs = []
|
156
|
+
changelog_entries.each do |entry|
|
157
|
+
# split each entry into lines, removing the initial, empty line
|
158
|
+
# that occurs on all but the first entry
|
159
|
+
changelog_lines = entry.split("\n").delete_if { |line| line.empty? }
|
160
|
+
match = CHANGELOG_ENTRY_REGEX.match(changelog_lines[0])
|
161
|
+
if match.nil?
|
162
|
+
warn "WARNING: Parsing stopped at invalid changelog entry: \n#{entry}" if verbose
|
163
|
+
break
|
164
|
+
else
|
165
|
+
# verify 1st version is latest version
|
166
|
+
# NOTE: There are edge cases in which comparisons between
|
167
|
+
# versions with and without release qualifiers may give answers
|
168
|
+
# that are not expected. For example, '6.2.0' > '6.2.0-1'.
|
169
|
+
full_version = match[3]
|
170
|
+
full_version += "-#{match[4]}" unless match[4].nil?
|
171
|
+
current_version = Gem::Version.new(full_version)
|
172
|
+
latest_version = current_version if latest_version.nil?
|
173
|
+
|
174
|
+
if current_version > latest_version
|
175
|
+
fail("ERROR: Changelog entries are not properly version ordered")
|
176
|
+
end
|
177
|
+
|
178
|
+
break if latest_version_only and (current_version < latest_version)
|
179
|
+
|
180
|
+
# verify dates are appropriately ordered (newest to oldest)
|
181
|
+
current_entry_date = Date.strptime(match[1], '%a %b %d %Y')
|
182
|
+
prev_entry_date = current_entry_date if prev_entry_date.nil?
|
183
|
+
if current_entry_date > prev_entry_date
|
184
|
+
fail("ERROR: Changelog entries are not properly date ordered")
|
185
|
+
end
|
186
|
+
|
187
|
+
if valid_date_weekday?(match[1], verbose)
|
188
|
+
entry = {
|
189
|
+
:date => match[1],
|
190
|
+
:version => match[3],
|
191
|
+
:release => match[4],
|
192
|
+
:content => changelog_lines
|
193
|
+
}
|
194
|
+
changelogs << entry
|
195
|
+
else
|
196
|
+
warn "WARNING: Parsing stopped at invalid changelog entry: \n#{entry}" if verbose
|
197
|
+
break
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
changelogs
|
203
|
+
end
|
204
|
+
|
205
|
+
# Validate the weekday in the already-format-verified changelog
|
206
|
+
# date string is correct for the date specified
|
207
|
+
#
|
208
|
+
# Returns false if the weekday is incorrect for date specified.
|
209
|
+
#
|
210
|
+
# +changelog_date+:: Date string of the form <weekday> <month> <day> <year>
|
211
|
+
# +verbose+:: Whether to log details about a weekday validation failure
|
212
|
+
def valid_date_weekday?(changelog_date, verbose)
|
213
|
+
date = Date.strptime(changelog_date, '%a %b %d %Y')
|
214
|
+
expected_weekday = date.strftime('%a')
|
215
|
+
actual_weekday = changelog_date.strip.split[0]
|
216
|
+
|
217
|
+
valid = true
|
218
|
+
if actual_weekday != expected_weekday
|
219
|
+
err_msg = ERR_MARKER + "'#{actual_weekday}' should be '#{expected_weekday}' for" +
|
220
|
+
" changelog timestamp '#{changelog_date}'"
|
221
|
+
warn err_msg if verbose
|
222
|
+
valid = false
|
223
|
+
end
|
224
|
+
return valid
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
data/lib/simp/rake/pkg.rb
CHANGED
@@ -6,6 +6,7 @@ require 'rake/clean'
|
|
6
6
|
require 'rake/tasklib'
|
7
7
|
require 'fileutils'
|
8
8
|
require 'find'
|
9
|
+
require 'simp/relchecks'
|
9
10
|
require 'simp/rpm'
|
10
11
|
require 'simp/rake/helpers/rpm_spec'
|
11
12
|
|
@@ -106,6 +107,8 @@ module Simp::Rake
|
|
106
107
|
define_pkg_tar
|
107
108
|
define_pkg_rpm
|
108
109
|
define_pkg_check_version
|
110
|
+
define_pkg_compare_latest_tag
|
111
|
+
define_pkg_create_tag_changelog
|
109
112
|
task :default => 'pkg:tar'
|
110
113
|
|
111
114
|
Rake::Task['pkg:tar']
|
@@ -463,6 +466,118 @@ module Simp::Rake
|
|
463
466
|
end
|
464
467
|
end
|
465
468
|
|
469
|
+
def define_pkg_compare_latest_tag
|
470
|
+
namespace :pkg do
|
471
|
+
desc <<-EOM
|
472
|
+
Compare to latest tag.
|
473
|
+
ARGS:
|
474
|
+
* :tags_source => Set to the remote from which the tags for this
|
475
|
+
project can be fetched. Defaults to 'origin'.
|
476
|
+
* :verbose => Set to 'true' if you want to see detailed messages
|
477
|
+
|
478
|
+
NOTES:
|
479
|
+
Compares mission-impacting (significant) files with the latest
|
480
|
+
tag and identifies the relevant files that have changed.
|
481
|
+
|
482
|
+
Fails if
|
483
|
+
(1) There is any version validation or changelog parsing failure
|
484
|
+
that would prevent an annotated changelog tag from being
|
485
|
+
created. (See pkg::create_tag_changelog)
|
486
|
+
(2) A version bump is required but not recorded in both the
|
487
|
+
CHANGELOG and metadata.json files.
|
488
|
+
(3) The latest version is < latest tag.
|
489
|
+
|
490
|
+
Changes to the following files/directories are not considered
|
491
|
+
significant:
|
492
|
+
- Any hidden file/directory (entry that begins with a '.')
|
493
|
+
- Gemfile
|
494
|
+
- Gemfile.lock
|
495
|
+
- Rakefile
|
496
|
+
- spec directory
|
497
|
+
- doc directory
|
498
|
+
EOM
|
499
|
+
task :compare_latest_tag, [:tags_source, :verbose] do |t,args|
|
500
|
+
tags_source = args[:tags_source].nil? ? 'origin' : args[:tags_source]
|
501
|
+
if args[:verbose].to_s == 'true'
|
502
|
+
verbose = true
|
503
|
+
else
|
504
|
+
verbose = false
|
505
|
+
end
|
506
|
+
Simp::RelChecks::compare_latest_tag(@base_dir, tags_source, verbose)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
def define_pkg_create_tag_changelog
|
512
|
+
namespace :pkg do
|
513
|
+
# :pkg:create_tag_changelog
|
514
|
+
# -----------------------------
|
515
|
+
desc <<-EOM
|
516
|
+
Generate an appropriate changelog for an annotated tag from a
|
517
|
+
component's CHANGELOG or RPM spec file.
|
518
|
+
|
519
|
+
The changelog text will be for the latest version and contain
|
520
|
+
1 or more changelog entries for that version, in reverse
|
521
|
+
chronological order.
|
522
|
+
|
523
|
+
ARGS:
|
524
|
+
* verbose => Set to 'true' if you want to see
|
525
|
+
non-catestrophic warning messages.
|
526
|
+
|
527
|
+
NOTES:
|
528
|
+
* Changelog entries must follow the following rules:
|
529
|
+
- An entry must start with * and be terminated
|
530
|
+
by a blank line.
|
531
|
+
- The first line must be of the form
|
532
|
+
* Wed Jul 05 2017 Author Name <author@simp.com> - 1.2.3-4
|
533
|
+
- The date string must be RPM compatible.
|
534
|
+
- Dates must be in reverse chronological order, with the
|
535
|
+
newest dates occurring at the top of the changelog.
|
536
|
+
- Both an author name and email are required.
|
537
|
+
- The author email must be contained in < >.
|
538
|
+
- The version is required and must be of the form
|
539
|
+
<major>.<minor>.<patch>.
|
540
|
+
- The version may contain a release qualifier.
|
541
|
+
- When the release qualifier is present, it must appear
|
542
|
+
at the end of the version string and be separated from
|
543
|
+
the version by a '-'.
|
544
|
+
|
545
|
+
* This task will fail if any of the following occur:
|
546
|
+
- The metadata.json file for a Puppet module component
|
547
|
+
cannot be parsed.
|
548
|
+
- The CHANGELOG file for a Puppet module component does
|
549
|
+
not exist.
|
550
|
+
- The CHANGELOG entries for the latest version are
|
551
|
+
malformed.
|
552
|
+
- The RPM spec file or a non-Puppet module component does
|
553
|
+
not exist.
|
554
|
+
- More than 1 RPM spec file for a non-Puppet module
|
555
|
+
component exists.
|
556
|
+
- No valid changelog entries for the version specified in
|
557
|
+
the metadata.json/spec file are found.
|
558
|
+
- The latest changelog version is greater than the version
|
559
|
+
in the metadata.json or the RPM spec file.
|
560
|
+
- The RPM release specified in the spec file does not match
|
561
|
+
the release in a changelog entry for the version.
|
562
|
+
- Any changelog entry below the first entry has a version
|
563
|
+
greater than that of the first entry.
|
564
|
+
- The changelog entries for the latest version are out of
|
565
|
+
date order.
|
566
|
+
- The weekday for a changelog entry for the latest version
|
567
|
+
does not match the date specified.
|
568
|
+
|
569
|
+
EOM
|
570
|
+
task :create_tag_changelog, [:verbose] do |t,args|
|
571
|
+
if args[:verbose].to_s == 'true'
|
572
|
+
verbose = true
|
573
|
+
else
|
574
|
+
verbose = false
|
575
|
+
end
|
576
|
+
puts Simp::RelChecks::create_tag_changelog(@base_dir, verbose)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
466
581
|
# ------------------------------------------------------------------------------
|
467
582
|
# helper methods
|
468
583
|
# ------------------------------------------------------------------------------
|
@@ -251,9 +251,9 @@ class Simp::Rake::Pupmod::Helpers < ::Rake::TaskLib
|
|
251
251
|
if curr_module_version < last_tag_version
|
252
252
|
fail("ERROR: Version regression. '#{module_version}' < last tag '#{last_tag}'")
|
253
253
|
elsif curr_module_version == last_tag_version
|
254
|
-
fail("ERROR: Version update beyond last tag '#{last_tag}' is required for
|
254
|
+
fail("ERROR: Version update beyond last tag '#{last_tag}' is required for #{files_changed.count} changed files:\n * #{files_changed.join("\n * ")}")
|
255
255
|
else
|
256
|
-
puts "
|
256
|
+
puts "NOTICE: New tag of version '#{module_version}' is required for #{files_changed.count} changed files:\n * #{files_changed.join("\n * ")}"
|
257
257
|
end
|
258
258
|
end
|
259
259
|
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'simp/componentinfo'
|
3
|
+
|
4
|
+
module Simp; end
|
5
|
+
|
6
|
+
# Class that provide release-related checks
|
7
|
+
class Simp::RelChecks
|
8
|
+
|
9
|
+
# Compares mission-impacting (significant) files with the latest
|
10
|
+
# tag and identifies the relevant files that have changed.
|
11
|
+
#
|
12
|
+
# Fails if
|
13
|
+
# (1) There is any version validation or changelog parsing failure
|
14
|
+
# that would prevent an annotated changelog tag from being
|
15
|
+
# created. (See Simp::RelCheck::create_tag_changelog)
|
16
|
+
# (2) A version bump is required but not recorded in both the
|
17
|
+
# CHANGELOG and metadata.json files.
|
18
|
+
# (3) The latest version is < latest tag.
|
19
|
+
|
20
|
+
# Changes to the following files/directories are not considered
|
21
|
+
# significant:
|
22
|
+
# - Any hidden file/directory (entry that begins with a '.')
|
23
|
+
# - Gemfile
|
24
|
+
# - Gemfile.lock
|
25
|
+
# - Rakefile
|
26
|
+
# - spec directory
|
27
|
+
# - doc directory
|
28
|
+
#
|
29
|
+
# +component_dir+:: The root directory of the component project.
|
30
|
+
# +tags_source+:: The remote from which the tags for this project
|
31
|
+
# can be fetched.
|
32
|
+
# +verbose+:: Set to 'true' if you want to see detailed messages
|
33
|
+
def self.compare_latest_tag(component_dir, tags_source = 'origin', verbose = false)
|
34
|
+
info, changelogs = load_and_validate_changelog(component_dir, verbose)
|
35
|
+
Dir.chdir(component_dir) do
|
36
|
+
# determine last tag
|
37
|
+
`git fetch -t #{tags_source} 2>/dev/null`
|
38
|
+
tags = `git tag -l`.split("\n")
|
39
|
+
puts "Available tags from #{tags_source} = #{tags}" if verbose
|
40
|
+
tags.delete_if { |tag| tag.include?('-') or (tag =~ /^v/) }
|
41
|
+
|
42
|
+
if tags.empty?
|
43
|
+
puts " No tags exist from #{tags_source}"
|
44
|
+
else
|
45
|
+
last_tag = (tags.sort { |a,b| Gem::Version.new(a) <=> Gem::Version.new(b) })[-1]
|
46
|
+
|
47
|
+
# determine mission-impacting files that have changed
|
48
|
+
files_changed = `git diff tags/#{last_tag} --name-only`.strip.split("\n")
|
49
|
+
files_changed.delete_if do |file|
|
50
|
+
file[0] == '.' or file == 'Rakefile' or file =~ /^Gemfile|^spec\/|^doc\//
|
51
|
+
end
|
52
|
+
|
53
|
+
if files_changed.empty?
|
54
|
+
puts " No new tag required: No significant files have changed since '#{last_tag}' tag"
|
55
|
+
else
|
56
|
+
curr_version = Gem::Version.new(info.version)
|
57
|
+
last_tag_version = Gem::Version.new(last_tag)
|
58
|
+
|
59
|
+
if curr_version < last_tag_version
|
60
|
+
fail("ERROR: Version regression. '#{info.version}' < last tag '#{last_tag}'")
|
61
|
+
elsif curr_version == last_tag_version
|
62
|
+
fail("ERROR: Version update beyond last tag '#{last_tag}' is required for #{files_changed.count} changed files:\n * #{files_changed.join("\n * ")}")
|
63
|
+
else
|
64
|
+
puts "NOTICE: New tag of version '#{info.version}' is required for #{files_changed.count} changed files:\n * #{files_changed.join("\n * ")}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Generate an appropriate changelog for an annotated tag from a
|
72
|
+
# component's CHANGELOG or RPM spec file.
|
73
|
+
#
|
74
|
+
# The changelog is only parsed up to the first entry that fails
|
75
|
+
# validation.
|
76
|
+
#
|
77
|
+
# Fails if any of the following occur:
|
78
|
+
# - The metadata.json file for a Puppet module component cannot be
|
79
|
+
# parsed.
|
80
|
+
# - The CHANGELOG file for a Puppet module component does not exist.
|
81
|
+
# - The CHANGELOG entries for the latest version are malformed.
|
82
|
+
# - The RPM spec file for a non-Puppet module component does not exist.
|
83
|
+
# - More than 1 RPM spec file for a non-Puppet module component exists.
|
84
|
+
# - No valid changelog entries for the version specified in the
|
85
|
+
# metadata.json/spec file are found.
|
86
|
+
# - The latest changelog version is greater than the version in the
|
87
|
+
# metadata.json or the RPM spec file.
|
88
|
+
# - The RPM release specified in the spec file does not match the
|
89
|
+
# release in a changelog entry for the version.
|
90
|
+
# - Any changelog entry below the first entry has a version greater
|
91
|
+
# than that of the first entry. Changelog entries must be
|
92
|
+
# ordered from latest version to earliest version.
|
93
|
+
# - The changelog entries for the latest version are out of date
|
94
|
+
# order.
|
95
|
+
# - The weekday for a changelog entry for the latest version
|
96
|
+
# does not match the date specified.
|
97
|
+
#
|
98
|
+
# +component_dir+:: The root directory of the component project.
|
99
|
+
# +verbose+:: Whether to log non-catestrophic changelog parsing
|
100
|
+
# failures.
|
101
|
+
def self.create_tag_changelog(component_dir, verbose = false)
|
102
|
+
info, changelogs = load_and_validate_changelog(component_dir,verbose)
|
103
|
+
|
104
|
+
result = "\nRelease of #{info.version}\n"
|
105
|
+
changelogs.each do |entry|
|
106
|
+
result += "\n#{entry[:content].first}\n"
|
107
|
+
if entry[:content].size > 1
|
108
|
+
entry[:content][1..-1].each do |line|
|
109
|
+
result += " #{line}\n"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
result
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns all changelog entries for the version
|
117
|
+
#
|
118
|
+
# Fails if
|
119
|
+
# - No valid entries for specified version are found
|
120
|
+
# - The latest changelog version is greater than the specified version
|
121
|
+
# - The release qualifier in a changelog entry for the specified
|
122
|
+
# version does not match the specified release.
|
123
|
+
#
|
124
|
+
# +changelog_entries+:: Array containing valid changelog entries, each of
|
125
|
+
# which is a Hash with :date, :version, :release, and :content keys
|
126
|
+
#
|
127
|
+
# +version+:: Target version for which one or more changelog entries
|
128
|
+
# are to be extracted
|
129
|
+
#
|
130
|
+
# +release+:: Optional release qualifier for version
|
131
|
+
# +verbose+:: Whether to log non-catestrophic changelog parsing
|
132
|
+
# failures.
|
133
|
+
def self.extract_version_changelog(changelog_entries, version,
|
134
|
+
release=nil, verbose=false)
|
135
|
+
|
136
|
+
version_entry_found = false
|
137
|
+
changelogs = []
|
138
|
+
changelog_entries.each do |entry|
|
139
|
+
if entry[:version] > version
|
140
|
+
fail("ERROR: Changelog entry for version > #{version} found: \n #{entry[:content].join("\n")}")
|
141
|
+
elsif entry[:version] < version
|
142
|
+
break
|
143
|
+
elsif entry[:version] == version
|
144
|
+
# If release is extracted from an RPM spec file, it may have
|
145
|
+
# a distribution at the end (e.g., 0.el7). We can't extract
|
146
|
+
# distribution from a specfile (query returns 'none' for
|
147
|
+
# DISTRIBUTION and DISTAG tags), so make sure the beginning
|
148
|
+
# of the release matches.
|
149
|
+
if release and entry[:release] and release.match(/^#{entry[:release]}/).nil?
|
150
|
+
fail("ERROR: Version release does not match #{release}: \n #{entry[:content].join("\n")}")
|
151
|
+
end
|
152
|
+
changelogs << entry
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if changelogs.empty?
|
157
|
+
fail("ERROR: No valid changelog entry for version #{version} found")
|
158
|
+
end
|
159
|
+
changelogs
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.load_and_validate_changelog(component_dir, verbose)
|
163
|
+
# only get valid changelog entries for the latest version
|
164
|
+
# (up to the first malformed entry)
|
165
|
+
info = Simp::ComponentInfo.new(component_dir, true)
|
166
|
+
|
167
|
+
changelogs = extract_version_changelog(info.changelog, info.version,
|
168
|
+
info.release, verbose)
|
169
|
+
|
170
|
+
[info, changelogs]
|
171
|
+
end
|
172
|
+
end
|