services-changelog 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []