services-changelog 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 56dba570ee5ae94f62f527c77da48d0865d8f46f5705bc56a4f27130cdf36a83
4
+ data.tar.gz: eadf192e93fefc3f32860398b4103c2b4f87f5e9b311378f883e299ada0dab56
5
+ SHA512:
6
+ metadata.gz: 90324b6fce93ecb8949346d0797da147f344959cbb75880af491794c34814a3687dfa460dad0587e7e2d03cb0d94c1f2b93a477054b455c2addceafcec1ba437
7
+ data.tar.gz: 22f2c30e43bf8e04934c25281e96ab37e64e118ce19c585b62c846bc64c5f470539fe5160def91a4f262f9349b5e22d3c42a1090fc430872ac4b80d0a9751c94
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Nexus Mods Test Changelog
2
+
3
+
4
+ ## [2022-10-22]
5
+ This is the original release for this gem. I setup a basic proof-of-concept
6
+
7
+ ### Added
8
+ - Added initial proof of concept and basic ideas
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "rake", "~> 13.0"
4
+ gem 'activesupport'
5
+ gem 'dry-cli'
6
+ gem 'rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (6.1.4.1)
5
+ concurrent-ruby (~> 1.0, >= 1.0.2)
6
+ i18n (>= 1.6, < 2)
7
+ minitest (>= 5.1)
8
+ tzinfo (~> 2.0)
9
+ zeitwerk (~> 2.3)
10
+ concurrent-ruby (1.1.10)
11
+ diff-lcs (1.5.0)
12
+ dry-cli (0.7.0)
13
+ i18n (1.10.0)
14
+ concurrent-ruby (~> 1.0)
15
+ minitest (5.15.0)
16
+ rake (13.0.6)
17
+ rspec (3.11.0)
18
+ rspec-core (~> 3.11.0)
19
+ rspec-expectations (~> 3.11.0)
20
+ rspec-mocks (~> 3.11.0)
21
+ rspec-core (3.11.0)
22
+ rspec-support (~> 3.11.0)
23
+ rspec-expectations (3.11.1)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.11.0)
26
+ rspec-mocks (3.11.1)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.11.0)
29
+ rspec-support (3.11.1)
30
+ tzinfo (2.0.4)
31
+ concurrent-ruby (~> 1.0)
32
+ zeitwerk (2.6.1)
33
+
34
+ PLATFORMS
35
+ x86_64-linux
36
+
37
+ DEPENDENCIES
38
+ activesupport
39
+ dry-cli
40
+ rake (~> 13.0)
41
+ rspec
42
+
43
+ BUNDLED WITH
44
+ 2.3.5
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # ServicesChangelog
2
+
3
+ This gem is intended to be used from the CLI. If needed, it can be importing and extended as required.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'services-changelog'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install services-changelog
20
+
21
+ ## Usage
22
+
23
+ The available commands are:
24
+
25
+ ```
26
+ Commands:
27
+ changelog new [NAME] # Creates a new changelog entry
28
+ changelog parse # Lists all changelog entries
29
+ changelog version # Print version
30
+ ```
31
+
32
+ The system expects a folder structure setup in your project, with a list of yaml files documenting your changelog entries:
33
+
34
+ ```
35
+ changelog/
36
+ 2022.01.01/
37
+ feature1.yaml
38
+ feature2.yaml
39
+ ```
40
+
41
+ ## Configuration
42
+
43
+ The changelog generation config can be changed at multiple levels:
44
+
45
+ ### changelog/config.yaml
46
+
47
+ This is the base config for the changelog and has the following options:
48
+
49
+ ```yaml
50
+ title: "Changelog" # Change the default title of the changelog
51
+ intro: "This is my changelog"
52
+ ```
53
+
54
+ ### changelog/VERSION/meta.yaml
55
+
56
+ This is the version meta file - allowing extra metadata for the version declaration.
57
+
58
+ ```yaml
59
+ description: "This version was aimed at improving the application."
60
+ ```
61
+
62
+ ### changelog/VERSION/FEATURE.yaml
63
+
64
+ These files are added for every line of the changelog you wish to add:
65
+
66
+ ```yaml
67
+ title: 'Added initial proof of concept and basic ideas'
68
+ type: 'Added'
69
+ description: ''
70
+ merge_request: null
71
+ issue: null
72
+ author: null
73
+ ```
74
+
75
+ ## Development
76
+
77
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
78
+
79
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
80
+
81
+ ## Contributing
82
+
83
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/example-ruby-gem.
84
+
85
+
86
+ ## License
87
+
88
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: 'Added initial proof of concept and basic ideas'
3
+ type: 'Added'
4
+ description: ''
5
+ merge_request: null
6
+ issue: null
7
+ author: null
@@ -0,0 +1,2 @@
1
+ ---
2
+ description: "This is the original release for this gem. I setup a basic proof-of-concept"
@@ -0,0 +1 @@
1
+ title: "Nexus Mods Test Changelog"
data/exe/changelog ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ require 'bundler/setup'
4
+
5
+ require_relative '../lib/services_changelog'
6
+
7
+ Dry::CLI.new(ServicesChangelog::CLI::Commands).call
@@ -0,0 +1,33 @@
1
+ module ServicesChangelog
2
+ class Changelog
3
+ # @return [Hash{String => Release}] versions All versions parsed.
4
+ attr_accessor :versions
5
+
6
+ attr_accessor :title, :url, :intro
7
+
8
+ def initialize
9
+ self.versions = {}
10
+ end
11
+
12
+ def initialize_version(version)
13
+ return if versions[version]
14
+
15
+ versions[version] = Release.new
16
+ versions[version].title = version
17
+ versions[version].description = "Description"
18
+ end
19
+
20
+ def as_json(_options = {})
21
+ {
22
+ title: title,
23
+ intro: intro,
24
+ url: url,
25
+ versions: versions
26
+ }
27
+ end
28
+
29
+ def to_json(*options)
30
+ as_json(*options).to_json(*options)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+ # typed: true
3
+ require 'dry/cli'
4
+ require 'active_support/core_ext/string/inflections'
5
+
6
+ module ServicesChangelog
7
+ TOOL_VERSION = '1.0.0'
8
+
9
+ module CLI
10
+ module Commands
11
+ extend Dry::CLI::Registry
12
+
13
+ class Version < Dry::CLI::Command
14
+ desc 'Print version'
15
+
16
+ def call(*)
17
+ puts TOOL_VERSION
18
+ end
19
+ end
20
+
21
+ class Parse < Dry::CLI::Command
22
+ desc 'Lists all changelog entries'
23
+
24
+ option :format, default: 'json', values: %w[json yaml md markdown], desc: 'Output format'
25
+ option :paths, default: 'changelog', desc: 'Input paths to pull changelog entries from. Can be comma seperated'
26
+
27
+ def call(**options)
28
+ # Get Formatters
29
+ out_formatter = Object.const_get("ServicesChangelog::Formatters::#{options.fetch(:format).to_s.capitalize}Formatter")
30
+
31
+ parser = Parser.new(formatter: out_formatter.new)
32
+ parser.load(options.fetch(:paths))
33
+
34
+ puts parser.output
35
+ end
36
+ end
37
+
38
+ class New < Dry::CLI::Command
39
+ include Logging
40
+ require 'erb'
41
+
42
+ desc 'Creates a new changelog entry'
43
+
44
+ argument :name, desc: 'Name of the changelog entry'
45
+
46
+ example [
47
+ 'added new feature # Creates a new changelog entry pre-populated with a basic template'
48
+ ]
49
+
50
+ def call(**options)
51
+ logger.debug 'Finding changelogs directory'
52
+ if Dir.exist? 'changelog'
53
+
54
+ logger.debug 'Creating new entry'
55
+
56
+ contents = <<~EOL
57
+ ---#{' '}
58
+ title: 'TODO: Add title'
59
+ type: 'Updated'
60
+ description: 'TODO'
61
+ merge_request: null
62
+ issue: null
63
+ author: null
64
+ EOL
65
+ dir = "changelog/#{Time.new.strftime('%Y-%m-%d')}"
66
+
67
+ filename = options.fetch(:name).to_s.parameterize(separator: '_')
68
+
69
+ Dir.mkdir(dir) unless Dir.exist? dir
70
+
71
+ File.write("#{dir}/#{filename}.yaml", contents)
72
+
73
+ else
74
+ logger.error 'Cannot find changelogs directory'
75
+ end
76
+ end
77
+ end
78
+
79
+ register 'version', Version, aliases: ['v', '-v', '--version']
80
+ register 'parse', Parse
81
+ register 'new', New
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ module ServicesChangelog
2
+ class ChangelogEntry
3
+ attr_accessor :title, :type, :description, :merge_request, :issue, :author
4
+
5
+ def initialize(title:, type:, description:, merge_request:, issue:, author:)
6
+ self.title = title
7
+ self.type = type
8
+ self.description = description
9
+ self.merge_request = merge_request
10
+ self.issue = issue
11
+ self.author = author
12
+ end
13
+
14
+ def as_json(_options = {})
15
+ {
16
+ title: title,
17
+ type: type,
18
+ description: description,
19
+ merge_request: merge_request,
20
+ issue: issue,
21
+ author: author
22
+ }
23
+ end
24
+
25
+ def to_json(*options)
26
+ as_json(*options).to_json(*options)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+
3
+ module ServicesChangelog
4
+ module Formatters
5
+ class JsonFormatter
6
+ # @param [ServicesChangelog::Changelog] data
7
+ def output(data)
8
+ JSON.pretty_generate(data)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ require 'erb'
2
+
3
+ module ServicesChangelog
4
+ module Formatters
5
+ class MarkdownFormatter
6
+ # @param [ServicesChangelog::Changelog] data
7
+ def output(data)
8
+ template = ERB.new File.read 'lib/services_changelog/templates/changelog.md.erb'
9
+
10
+ versions = data.versions.values
11
+
12
+ result = template.result binding
13
+
14
+ File.write("CHANGELOG.md", result)
15
+ File.chmod(0777, "CHANGELOG.md")
16
+
17
+ result
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module ServicesChangelog
2
+ module Formatters
3
+ class YamlFormatter
4
+ def output(data)
5
+ data.to_yaml
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,56 @@
1
+ require 'logger'
2
+
3
+ class Logger
4
+ module Colors
5
+ VERSION = '1.0.0'
6
+
7
+ NOTHING = '0;0'
8
+ BLACK = '0;30'
9
+ RED = '0;31'
10
+ GREEN = '0;32'
11
+ BROWN = '0;33'
12
+ BLUE = '0;34'
13
+ PURPLE = '0;35'
14
+ CYAN = '0;36'
15
+ LIGHT_GRAY = '0;37'
16
+ DARK_GRAY = '1;30'
17
+ LIGHT_RED = '1;31'
18
+ LIGHT_GREEN = '1;32'
19
+ YELLOW = '1;33'
20
+ LIGHT_BLUE = '1;34'
21
+ LIGHT_PURPLE = '1;35'
22
+ LIGHT_CYAN = '1;36'
23
+ WHITE = '1;37'
24
+
25
+ SCHEMA = {
26
+ STDOUT => %w[nothing green brown red purple cyan],
27
+ STDERR => %w[nothing green yellow light_red light_purple light_cyan]
28
+ }
29
+ end
30
+ end
31
+
32
+ class Logger
33
+ alias format_message_colorless format_message
34
+
35
+ def format_message(level, *args)
36
+ if Logger::Colors::SCHEMA[@logdev.dev]
37
+ color = begin
38
+ Logger::Colors.const_get \
39
+ Logger::Colors::SCHEMA[@logdev.dev][Logger.const_get(level.sub('ANY', 'UNKNOWN'))].to_s.upcase
40
+ rescue NameError
41
+ '0;0'
42
+ end
43
+ "\e[#{color}m#{format_message_colorless(level, *args)}\e[0;0m"
44
+ else
45
+ format_message_colorless(level, *args)
46
+ end
47
+ end
48
+ end
49
+
50
+ module ServicesChangelog
51
+ module Logging
52
+ def logger
53
+ @logger || Logger.new(STDOUT)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,94 @@
1
+ require 'yaml'
2
+
3
+ module ServicesChangelog
4
+ class Parser
5
+ include Logging
6
+
7
+ attr_accessor :parsed_content
8
+
9
+ # @return [ServicesChangelog::Changelog]
10
+ attr_accessor :changelog
11
+
12
+ # @return [Formatter]
13
+ attr_accessor :formatter
14
+
15
+ def initialize(formatter:)
16
+ self.formatter = formatter
17
+ self.changelog = Changelog.new
18
+ end
19
+
20
+ def output
21
+ formatter.output(changelog)
22
+ end
23
+
24
+ # Parse a folder with YAML files
25
+ def load(path = nil)
26
+ path ||= 'changelog'
27
+ logger.debug "Loading from '#{path}'"
28
+ load_config("#{path}/config.yaml")
29
+ Dir.glob("#{path}/*").each { |f| parse_version(f) }
30
+ end
31
+
32
+ private
33
+
34
+ def load_config(path)
35
+ unless File.exist?(path)
36
+ logger.debug "No config.yaml file found at #{path}"
37
+ return
38
+ end
39
+
40
+ content = File.open(path, &:read)
41
+ yaml = YAML.safe_load content
42
+ unless yaml
43
+ logger.debug 'config.yaml file is empty or invalid'
44
+ return
45
+ end
46
+ changelog.title = yaml['title']
47
+ changelog.url = yaml['url']
48
+ changelog.intro = yaml['intro']
49
+ end
50
+
51
+ def add_change(yaml, version)
52
+ type = yaml['type'] || 'Updated'
53
+ changelog.versions[version].entries[type] = [] if changelog.versions[version].entries[type].nil?
54
+
55
+ changelog.versions[version].entries[type] << ChangelogEntry.new(
56
+ title: yaml['title'],
57
+ type: yaml['type'],
58
+ description: yaml['description'],
59
+ merge_request: yaml['merge_request'],
60
+ issue: yaml['issue'],
61
+ author: yaml['author']
62
+ )
63
+ end
64
+
65
+ def parse_version(folder)
66
+ version = File.basename(folder)
67
+ return if version == 'config.yaml'
68
+
69
+ changelog.initialize_version version
70
+ metafile = "#{folder}/meta.yaml"
71
+
72
+ files = Dir.glob("#{folder}/*.yaml").reject { |i| i == metafile }
73
+
74
+ if File.exists? metafile
75
+ meta = YAML.safe_load File.open(metafile, &:read)
76
+
77
+ return if meta.nil?
78
+
79
+ changelog.versions[version].description = meta["description"]
80
+ end
81
+
82
+ logger.debug "Found #{files.count} file(s) for version #{version}"
83
+ files.sort.each { |f| parse_file(f, version) }
84
+ end
85
+
86
+ def parse_file(filename, version)
87
+ logger.debug "Parsing #{filename} for version #{version}"
88
+ yaml = YAML.safe_load File.open(filename, &:read)
89
+ return {} unless yaml
90
+
91
+ add_change yaml, version
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,22 @@
1
+ class Release
2
+ attr_accessor :title, :description
3
+
4
+ # @return [Hash{String => Array(ServicesChangelog::Entry)}]
5
+ attr_accessor :entries
6
+
7
+ def initialize
8
+ self.entries = {}
9
+ end
10
+
11
+ def as_json(_options = {})
12
+ {
13
+ title: title,
14
+ description: description,
15
+ entries: entries
16
+ }
17
+ end
18
+
19
+ def to_json(*options)
20
+ as_json(*options).to_json(*options)
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # <%= data.title %>
2
+ <%= data.intro %>
3
+ <% versions.each { |version| %>
4
+ ## [<%= version.title %>]<% unless version.description.nil? %>
5
+ <%= version.description %><% end %>
6
+ <% version.entries.each_pair { |type, changes| %>
7
+ ### <%= type %>
8
+ <% changes.each { |change| %>- <%= change.title %>
9
+ <% } } } %>
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ServicesChangelog
4
+ # Leave this as 0.1.0 in order for CI process to replace with the tagged version.
5
+ VERSION = '0.1.0'
6
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'services_changelog/version'
2
+ require_relative 'services_changelog/logging'
3
+ require_relative 'services_changelog/cli'
4
+ require_relative 'services_changelog/parser'
5
+ require_relative 'services_changelog/formatters/yaml_formatter'
6
+ require_relative 'services_changelog/formatters/json_formatter'
7
+ require_relative 'services_changelog/formatters/markdown_formatter'
8
+ require_relative 'services_changelog/changelog'
9
+ require_relative 'services_changelog/entry'
10
+ require_relative 'services_changelog/release'
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/services_changelog/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "services-changelog"
7
+ spec.version = ServicesChangelog::VERSION
8
+ spec.authors = ["Dean Lovett"]
9
+ spec.email = ["dean.lovett@nexusmods.com"]
10
+
11
+ spec.summary = "Converts a group of yaml files, broken down by date, to generate a changelog."
12
+ spec.description = <<EOF
13
+ Using this tool, changelogs can be created from a single project's changelog folder, or alternatively, multiple directories
14
+ can be provied to collate all entries together.
15
+ EOF
16
+ spec.homepage = "https://www.nexusmods.com"
17
+ spec.required_ruby_version = ">= 2.6.0"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = 'https://gitlab.nexdev.uk/Lovett/services-changelog'
21
+ spec.metadata["changelog_uri"] = spec.homepage
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
28
+ end
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ # spec.add_dependency "example-gem", "~> 1.0"
36
+
37
+ # For more information and examples about making a new gem, check out our
38
+ # guide at: https://bundler.io/guides/creating_gem.html
39
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: services-changelog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dean Lovett
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-10-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ Using this tool, changelogs can be created from a single project's changelog folder, or alternatively, multiple directories
15
+ can be provied to collate all entries together.
16
+ email:
17
+ - dean.lovett@nexusmods.com
18
+ executables:
19
+ - changelog
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - CHANGELOG.md
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - Rakefile
28
+ - changelog/2022-10-22/added_new_thing.yaml
29
+ - changelog/2022-10-22/meta.yaml
30
+ - changelog/config.yaml
31
+ - exe/changelog
32
+ - lib/services_changelog.rb
33
+ - lib/services_changelog/changelog.rb
34
+ - lib/services_changelog/cli.rb
35
+ - lib/services_changelog/entry.rb
36
+ - lib/services_changelog/formatters/json_formatter.rb
37
+ - lib/services_changelog/formatters/markdown_formatter.rb
38
+ - lib/services_changelog/formatters/yaml_formatter.rb
39
+ - lib/services_changelog/logging.rb
40
+ - lib/services_changelog/parser.rb
41
+ - lib/services_changelog/release.rb
42
+ - lib/services_changelog/templates/changelog.md.erb
43
+ - lib/services_changelog/version.rb
44
+ - services-changelog.gemspec
45
+ homepage: https://www.nexusmods.com
46
+ licenses: []
47
+ metadata:
48
+ homepage_uri: https://www.nexusmods.com
49
+ source_code_uri: https://gitlab.nexdev.uk/Lovett/services-changelog
50
+ changelog_uri: https://www.nexusmods.com
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 2.6.0
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubygems_version: 3.3.5
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: Converts a group of yaml files, broken down by date, to generate a changelog.
70
+ test_files: []