Module: PDK::Util::ChangelogGenerator

Defined in:
lib/pdk/util/changelog_generator.rb

Constant Summary collapse

VERSION_REGEX =

Taken from the version regex in forgeapi.puppet.com/schemas/module.json

/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/.freeze
GEM =
'github_changelog_generator'.freeze

Class Method Summary collapse

Class Method Details

.changelog_contentObject



131
132
133
134
135
# File 'lib/pdk/util/changelog_generator.rb', line 131

def self.changelog_content
  return '' if changelog_file.nil?

  PDK::Util::Filesystem.read_file(changelog_file, open_args: 'rb:utf-8')
end

.changelog_fileObject



126
127
128
129
# File 'lib/pdk/util/changelog_generator.rb', line 126

def self.changelog_file
  # Default Changelog file is CHANGELOG.md, but also search for the .MD prefix as well.
  @changelog_file ||= ['CHANGELOG.md', 'CHANGELOG.MD'].map { |file| PDK::Util::Filesystem.expand_path(file) }.find { |path| PDK::Util::Filesystem.file?(path) }
end

.compute_next_version(current_version) ⇒ String

Computes the next version, based on the content of a changelog

Parameters:

  • current_version (String, Gem::Version)

    The current version of the module

Returns:

  • (String)

    The new version. May be the same as the current version if there are no notable changes

Raises:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/pdk/util/changelog_generator.rb', line 45

def self.compute_next_version(current_version)
  raise PDK::CLI::ExitWithError, format('Invalid version string %{version}', version: current_version) unless VERSION_REGEX.match?(current_version)

  version = Gem::Version.create(current_version).segments
  PDK.logger.info format('Determing the target version from \'%{file}\'', file: changelog_file)

  # Grab all lines that start with ## between from the latest changes
  # For example given the changelog below

  # ```
  # # Change log
  #
  # All notable changes to this project will be documented in this file.
  #
  # ## [v4.0.0](https://github.com/puppetlabs/puppetlabs-inifile/tree/v4.
  #
  # [Full Changelog](https://github.com/puppetlabs/puppetlabs-inifile/com   --+
  #                                                                           |
  # ### Changed                                                               |
  #                                                                           |
  # - pdksync - FM-8499 - remove ubuntu14 support [\#363](https://github.     |  It's this piece of text we are interested in
  #                                                                           |
  # ### Added                                                                 |
  #                                                                           |
  # - FM-8402 add debian 10 support [\#352](https://github.com/puppetlabs     |
  #                                                                           |
  # ## [v3.1.0](https://github.com/puppetlabs/puppetlabs-inifile/tree/v3.     |
  #                                                                         --+
  # [Full Changelog](https://github.com/puppetlabs/puppetlabs-inifile/com
  #
  # ### Added
  #
  # - FM-8222 - Port Module inifile to Litmus [\#344](https://github.com/
  # - \(FM-8154\) Add Windows Server 2019 support [\#340](https://github.
  # - \(FM-8041\) Add RedHat 8 support [\#339](https://github.com/puppetl
  # ````
  data = ''
  in_changelog_entry = false
  changelog_content.each_line do |line|
    line.strip!
    if line.start_with?('[')
      # We're leaving the latest changes so we can break
      break if in_changelog_entry

      in_changelog_entry = true
    end
    data += line if in_changelog_entry && line.start_with?('##')
  end

  # Check for meta headers in first two header line matches
  case data
  when /^### Changed/
    # Major Version bump
    version[0] += 1
    version[1] = 0
    version[2] = 0
  when /^### Added/
    # Minor Version bump
    version[1] += 1
    version[2] = 0
  when /^### Fixed/
    # Patch Version bump
    version[2] += 1
  end

  version.join('.')
end

.generate_changelogObject

Runs the Changelog Generator gem (in the module’s context) to automatically create a CHANGLELOG.MD file



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/pdk/util/changelog_generator.rb', line 25

def self.generate_changelog
  github_changelog_generator_available!

  changelog_command = PDK::CLI::Exec::InteractiveCommand.new(PDK::CLI::Exec.bundle_bin, 'exec', 'rake', 'changelog')
  changelog_command.context = :module

  result = changelog_command.execute!
  raise PDK::CLI::ExitWithError, format('Error generating changelog: %{stdout}', stdout: result[:stdout]) unless result[:exit_code].zero?

  output = changelog_content

  raise PDK::CLI::ExitWithError, format('The generated changelog contains uncategorized Pull Requests. Please label them and try again. See %{changelog_file} for more details', changelog_file: changelog_file) if output.include?('UNCATEGORIZED PRS; GO LABEL THEM') # rubocop:disable Layout/LineLength

  output
end

.github_changelog_generator_available!Object

Raises if the github_changelog_generator is not available



11
12
13
14
15
16
17
18
19
20
# File 'lib/pdk/util/changelog_generator.rb', line 11

def self.github_changelog_generator_available!
  check_command = PDK::CLI::Exec::InteractiveCommand.new(PDK::CLI::Exec.bundle_bin, 'info', 'github_changelog_generator')
  check_command.context = :module

  result = check_command.execute!

  return if result[:exit_code].zero?

  raise PDK::CLI::ExitWithError, format('Unable to generate the changelog as the %{gem} gem is not included in this module\'s Gemfile', gem: GEM)
end

.latest_versionObject

Returns the top most version from the CHANGELOG file



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/pdk/util/changelog_generator.rb', line 114

def self.latest_version
  latest = nil
  changelog_content.each_line do |line|
    line.strip!
    if line.start_with?('## [')
      latest = line[line.index('[') + 1..line.index(']') - 1].delete('v')
      break # stops after the top version is extracted
    end
  end
  latest
end