keepachangelog 0.3.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d54eca6140fcc5088df9a25e92f0fe50b7df1a82
4
- data.tar.gz: cd1981c05340bc9ec4fb1309d9e422c9cfb008a7
3
+ metadata.gz: 6e63e90c5940db3033ddb2f4e58e77437af51e43
4
+ data.tar.gz: 8f30352f336656f66229df3eba5abbb4e2924149
5
5
  SHA512:
6
- metadata.gz: 721125e2778898619487ef091c5d2783bf7d01d6017721e83220547a794b32a9e13d57ae3d75852adb02c3a371d4ca37fe3ec0e8fca75326b18d768234a777a6
7
- data.tar.gz: 065e781135ea1d0d1ab7dfe01666b118755b7b81aaa3db4b12746b5f1887e2982cdd4e5a4140fb6b4bc293ed941c548b1d3e129daeecf2245861994b70738c37
6
+ metadata.gz: 7d332fc8dc0d944376a22d7419a8e31aff436e89b18c533d5e3f1c26d8639b8c9cbb3b6a57ee5083120869d82e5628b8f2e841dedcac29c5324bf15c10fd4a20
7
+ data.tar.gz: 2bf95c69b9f25c988c53f193735ef3fa254a2d81dd6be3e663c77cf2e7bd3c5909cc981a06f9828572384462a0efa5fd1c508082245a5eff661e0a81c16cf3cb
data/.gitlab-ci.yml CHANGED
@@ -40,10 +40,15 @@ integration:
40
40
  script:
41
41
  - "grunt test:integration"
42
42
 
43
- download.basalt.se:
43
+ fileshare:
44
44
  stage: deploy
45
45
  environment: production
46
46
  script:
47
+ - |
48
+ if [[ "$SSH_KEY" == "" || "$SSH_USER" == "" || "$TARGET_HOST" == "" || "$TARGET_PATH" == "" ]]; then
49
+ echo "Skipping deploy due to missing credentials"
50
+ exit 0
51
+ fi
47
52
  - grunt publish
48
53
  only:
49
54
  - tags
@@ -52,6 +57,11 @@ rubygems.org:
52
57
  stage: deploy
53
58
  environment: production
54
59
  script:
60
+ - |
61
+ if [[ "$RUBYGEMS_API_KEY" == "" ]]; then
62
+ echo "Skipping deploy due to missing credentials"
63
+ exit 0
64
+ fi
55
65
  - mkdir -p ~/.gem
56
66
  - "echo \":rubygems_api_key: $RUBYGEMS_API_KEY\" > ~/.gem/credentials"
57
67
  - chmod 0600 /root/.gem/credentials
data/.rubocop.yml CHANGED
@@ -7,6 +7,9 @@ Style/ClassAndModuleChildren:
7
7
  Style/AsciiComments:
8
8
  Enabled: false
9
9
 
10
+ Metrics/MethodLength:
11
+ Max: 15
12
+
10
13
  Metrics/BlockLength:
11
14
  Exclude:
12
15
  - 'spec/**/*'
data/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [0.4.1]
8
+ ### Fixed
9
+ - Deploy job in CI will no longer be skipped even though it should run. (#8)
10
+
11
+ ## [0.4.0] - 2017-03-30
12
+ ### New
13
+ - Ability to output changelog to yaml file structure. (!9)
14
+ - The code is pushed into a public repo at gitlab.com.
15
+
16
+ ### Fixed
17
+ - Sort versions in reverse numerical order in Markdown output. (#7)
18
+
7
19
  ## [0.3.1] - 2017-03-27
8
20
  ### Fixed
9
21
  - Remove duplicates in Changelog for this project. (#6)
@@ -31,8 +43,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
31
43
  - Tool for reading Changelog in Markdown format.
32
44
  - Ability to convert Changelog to YAML.
33
45
 
34
- [0.3.1]: https://git.basalt.se/chbr/keepachangelog/compare/0.3.0...0.3.1
35
- [0.3.0]: https://git.basalt.se/chbr/keepachangelog/compare/0.2.1...0.3.0
36
- [0.2.1]: https://git.basalt.se/chbr/keepachangelog/compare/0.2.0...0.2.1
37
- [0.2.0]: https://git.basalt.se/chbr/keepachangelog/compare/0.1.0...0.2.0
38
- [0.1.0]: https://git.basalt.se/chbr/keepachangelog/compare/77986bc...0.1.0
46
+ [0.4.1]: https://gitlab.com/ephracis/keepachangelog/compare/0.4.0...0.4.1
47
+ [0.4.0]: https://gitlab.com/ephracis/keepachangelog/compare/0.3.1...0.4.0
48
+ [0.3.1]: https://gitlab.com/ephracis/keepachangelog/compare/0.3.0...0.3.1
49
+ [0.3.0]: https://gitlab.com/ephracis/keepachangelog/compare/0.2.1...0.3.0
50
+ [0.2.1]: https://gitlab.com/ephracis/keepachangelog/compare/0.2.0...0.2.1
51
+ [0.2.0]: https://gitlab.com/ephracis/keepachangelog/compare/0.1.0...0.2.0
52
+ [0.1.0]: https://gitlab.com/ephracis/keepachangelog/compare/77986bc...0.1.0
data/CONTRIBUTING.md CHANGED
@@ -1,2 +1,3 @@
1
- Se [metodanvisning utveckling](http://doc.basalt.se/docs/beans-metodanvisning-testdriven-utveckling/sv/stable/)
2
- för detaljer hur man utvecklar i detta projekt.
1
+ You can help out in several ways:
2
+ - File or discuss issues
3
+ - Send merge requests
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keepachangelog (0.3.1)
4
+ keepachangelog (0.4.1)
5
5
  json (~> 2.0)
6
6
  thor (~> 0.19)
7
7
 
data/LICENSE.md CHANGED
@@ -1,3 +1,19 @@
1
- Copyright © 2016 Basalt
1
+ Copyright © 2017 Basalt
2
2
 
3
- All rights reserved - Do Not Redistribute
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
+ [![build status](https://gitlab.com/ephracis/keepachangelog/badges/master/build.svg)](https://gitlab.com/ephracis/keepachangelog/commits/master)
2
+ [![coverage report](https://gitlab.com/ephracis/keepachangelog/badges/master/coverage.svg)](https://gitlab.com/ephracis/keepachangelog/commits/master)
3
+ [![Gem Version](https://badge.fury.io/rb/keepachangelog.svg)](https://badge.fury.io/rb/keepachangelog)
4
+
1
5
  # Changelog parser and transformer
2
6
 
3
7
  Ruby gem for parsing Changelogs based on the format described at
4
8
  [keepachangelog.com](http://keepachangelog.com).
5
9
 
6
10
  The parser can read either a Markdown file or a folder structure with
7
- YAML-files.
11
+ YAML files.
8
12
 
9
- The output can be Markdown, YAML or JSON.
13
+ The output can be Markdown, YAML files or JSON.
10
14
 
11
15
  ## Installation
12
16
 
@@ -28,17 +32,26 @@ Or install it yourself as:
28
32
 
29
33
  ### Command line
30
34
 
35
+ When using the parser there are four important options to pay attention to:
36
+ - `from` - The input format
37
+ - `to` - The output format
38
+ - `in` - The input file or folder
39
+ - `out` - The output folder (only used when output format is `yaml`)
40
+
41
+ See `keepachangelog help parse` for more information.
42
+
31
43
  #### Markdown input
32
44
  To dump a Changelog to JSON run the following command:
33
45
 
34
- keepachangelog --path CHANGELOG.md --format json
46
+ keepachangelog --in CHANGELOG.md --from md --to json
35
47
 
36
48
  #### YAML input
37
49
  You can also express your changelog in YAML files inside a folder structure
38
50
  where each version is its own folder containing each change in a YAML-file.
39
51
 
40
52
  Here's an example of a folder structure:
41
- ```
53
+
54
+ ```shell
42
55
  changelog
43
56
  ├── 0.1.0
44
57
  │   └── 1-first-merge-request.yaml
@@ -63,14 +76,15 @@ type: New
63
76
  ```
64
77
 
65
78
 
66
- - `title`: A single sentence without punctiation that describes the change
79
+ - `title`: A single sentence that describes the change
67
80
  - `merge_request`: The ID of the MR or PR (optional)
68
81
  - `issue`: The ID of the issue (optional)
69
82
  - `author`: The author of the change (optional)
70
83
  - `type`: The type of change, for example *New*, *Changed*, *Fixed*,
71
84
  *Removed* or *Security*.
72
85
 
73
- To turn this into a Markdown document, simply run `keepachangelog yaml -f md`
86
+ To turn this into a Markdown document, simply run
87
+ `keepachangelog --in ./changelog --from yaml --to md`
74
88
 
75
89
  You can add meta data to your changelog in the file `meta.yaml`, placed inside
76
90
  the changelog folder, like so:
@@ -0,0 +1,4 @@
1
+ ---
2
+ title: Ability to output changelog to yaml file structure
3
+ merge_request: 9
4
+ type: New
@@ -0,0 +1,4 @@
1
+ ---
2
+ title: Sort versions in reverse numerical order in Markdown output
3
+ issue: 7
4
+ type: Fixed
@@ -0,0 +1,3 @@
1
+ ---
2
+ title: The code is pushed into a public repo at gitlab.com
3
+ type: New
@@ -0,0 +1,4 @@
1
+ ---
2
+ title: Deploy job in CI will no longer be skipped even though it should run
3
+ issue: 8
4
+ type: Fixed
data/changelog/meta.yaml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- url: https://git.basalt.se/chbr/keepachangelog
2
+ url: https://gitlab.com/ephracis/keepachangelog
@@ -8,5 +8,5 @@ Feature: Show help
8
8
  Then the output should contain "Keepachangelog commands"
9
9
 
10
10
  Scenario: Getting help about a command
11
- When I successfully run `keepachangelog help markdown`
11
+ When I successfully run `keepachangelog help parse`
12
12
  Then the output should contain "Usage"
@@ -0,0 +1,57 @@
1
+ Feature: Parse changelogs
2
+
3
+ Parse a changelog by running `keepachangelog parse` or just simply
4
+ `keepachangelog`.
5
+
6
+ Scenario: Convert from Markdown to JSON
7
+ Given a file "CHANGELOG.md" with:
8
+ """
9
+ # My Changes
10
+ Some intro goes here.
11
+ ## [Unreleased]
12
+ ### New
13
+ - Feature A
14
+ """
15
+ When I successfully run `keepachangelog --from md --to json --in CHANGELOG.md`
16
+ Then the output should contain:
17
+ """
18
+ {"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}},"intro":"Some intro goes here.","title":"My Changes"}
19
+ """
20
+
21
+ Scenario: Convert from YAML files to Markdown
22
+ Given a file "changelog/1.0.0/1.yml" with:
23
+ """
24
+ ---
25
+ title: Feature A
26
+ type: New
27
+ """
28
+ When I successfully run `keepachangelog --from yaml --to md`
29
+ Then the output should contain:
30
+ """
31
+ # Change log
32
+ All notable changes to this project will be documented in this file.
33
+
34
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
35
+ and this project adheres to [Semantic Versioning](http://semver.org/).
36
+
37
+ ## 1.0.0
38
+ ### New
39
+ - Feature A.
40
+ """
41
+
42
+ Scenario: Convert from Markdown to YAML files
43
+ Given a file "CHANGELOG.md" with:
44
+ """
45
+ # My Changes
46
+ Some intro goes here.
47
+ ## [Unreleased]
48
+ ### New
49
+ - Feature A
50
+ """
51
+ When I successfully run `keepachangelog --from md --to yaml --in CHANGELOG.md --out test`
52
+ Then the file "test/Unreleased/feature-a.yaml" should contain:
53
+ """
54
+ ---
55
+ title: Feature A
56
+ type: New
57
+ """
@@ -14,12 +14,12 @@ Gem::Specification.new do |spec|
14
14
  spec.version = Keepachangelog.version
15
15
  spec.authors = ['Basalt AB']
16
16
  spec.email = %w(christoffer.brodd-reijer@basalt.se)
17
- spec.licenses = ['Nonstandard']
17
+ spec.licenses = ['MIT']
18
18
  spec.summary = 'Parser for changelogs based on keepachangelog.com'
19
19
  spec.description = 'Tool for parsing changelogs that are based on the '\
20
20
  'keepachangelog.com standard. Changelogs can be dumped '\
21
21
  'to JSON or YAML.'
22
- spec.homepage = 'http://www.basalt.se'
22
+ spec.homepage = 'https://gitlab.com/ephracis/keepachangelog'
23
23
  spec.files = gem_files
24
24
  spec.bindir = 'exe'
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -1,6 +1,9 @@
1
- # require 'active_support'
2
- # require 'active_support/core_ext'
3
1
  require 'keepachangelog/version'
4
2
  require 'keepachangelog/parser'
3
+ require 'keepachangelog/parser/markdown'
4
+ require 'keepachangelog/parser/yaml'
5
+ require 'keepachangelog/printer'
6
+ require 'keepachangelog/printer/markdown'
7
+ require 'keepachangelog/printer/yaml'
5
8
  require 'json'
6
9
  require 'yaml'
@@ -14,42 +14,66 @@ module Keepachangelog
14
14
  desc 'version', 'Show current version'
15
15
  long_desc 'Show the version of the tool'
16
16
  def version
17
- require 'keepachangelog/version'
18
17
  shell.say Keepachangelog.version
19
18
  end
20
19
 
21
- desc 'markdown', 'Parse a changelog in markdown'
22
- option :format, type: :string,
23
- desc: 'The output format',
24
- default: 'json',
25
- banner: 'json|yaml',
26
- aliases: '-f'
27
- option :path, type: :string,
28
- desc: 'Path to the Changelog file',
29
- default: 'CHANGELOG.md',
30
- aliases: '-p'
31
- def markdown
32
- require 'keepachangelog/parser/markdown'
33
- p = MarkdownParser.load(options[:path])
34
- shell.say p.send("to_#{options[:format]}")
20
+ desc 'parse', 'Parse a changelog'
21
+ option :from, type: :string,
22
+ desc: 'The input format',
23
+ default: 'md',
24
+ banner: 'yaml|md',
25
+ aliases: '-f'
26
+ option :to, type: :string,
27
+ desc: 'The output format',
28
+ default: 'json',
29
+ banner: 'json|yaml|md',
30
+ aliases: '-t'
31
+ option :in, type: :string,
32
+ desc: 'Path to the input file/folder',
33
+ aliases: '-i'
34
+ option :out, type: :string,
35
+ desc: 'Path to the output file/folder',
36
+ aliases: '-o'
37
+ def parse
38
+ case options[:from].to_sym
39
+ when :md then parse_markdown
40
+ when :yaml then parse_yaml
41
+ else
42
+ shell.error "Unknown input format #{options[:from]}"
43
+ exit 1
44
+ end
35
45
  end
36
46
 
37
- desc 'yaml', 'Parse a folder of YAML files'
38
- option :format, type: :string,
39
- desc: 'The output format',
40
- default: 'json',
41
- banner: 'json|yaml|md',
42
- aliases: '-f'
43
- option :path, type: :string,
44
- desc: 'Path to the yaml folder',
45
- default: 'changelog',
46
- aliases: '-p'
47
- def yaml
48
- require 'keepachangelog/parser/yaml'
49
- p = YamlParser.load(options[:path])
50
- shell.say p.send("to_#{options[:format]}")
47
+ default_task :parse
48
+
49
+ private
50
+
51
+ def parse_markdown
52
+ parser = MarkdownParser.load(options[:in])
53
+ print parser
51
54
  end
52
55
 
53
- default_task :markdown
56
+ def parse_yaml
57
+ parser = YamlParser.load(options[:in])
58
+ print parser
59
+ end
60
+
61
+ # rubocop:disable Metrics/AbcSize
62
+ def print(parser)
63
+ case options[:to].to_sym
64
+ when :json
65
+ shell.say parser.to_json
66
+ when :s, :string
67
+ shell.say parser.to_s
68
+ when :md, :markdown
69
+ shell.say parser.to_md
70
+ when :yaml, :yml
71
+ parser.to_yaml(options[:out])
72
+ shell.say "Finished writing changelog to '#{options[:out]}'"
73
+ else
74
+ shell.error "Unknown output format #{options[:to]}"
75
+ exit 2
76
+ end
77
+ end
54
78
  end
55
79
  end
@@ -1,5 +1,3 @@
1
- require 'keepachangelog/markdown_printer'
2
-
3
1
  module Keepachangelog
4
2
  class Parser
5
3
  attr_accessor :parsed_content
@@ -28,8 +26,11 @@ module Keepachangelog
28
26
  # New:
29
27
  # - Feature A
30
28
  # ```
31
- def to_yaml
32
- parsed_content.to_yaml
29
+ def to_yaml(path = nil)
30
+ path ||= 'changelog'
31
+ require 'keepachangelog/printer/yaml'
32
+ p = YamlPrinter.new(parsed_content)
33
+ p.write(path)
33
34
  end
34
35
 
35
36
  # Changelog as a Ruby string
@@ -44,11 +45,12 @@ module Keepachangelog
44
45
 
45
46
  # Changelog as Markdown
46
47
  def to_md
47
- md = MarkdownPrinter.new(parsed_content['versions'],
48
- title: parsed_content['title'],
49
- intro: parsed_content['intro'],
50
- url: parsed_content['url'])
51
- md.to_s
48
+ require 'keepachangelog/printer/markdown'
49
+ p = MarkdownPrinter.new(parsed_content['versions'],
50
+ title: parsed_content['title'],
51
+ intro: parsed_content['intro'],
52
+ url: parsed_content['url'])
53
+ p.to_s
52
54
  end
53
55
  end
54
56
  end
@@ -7,16 +7,19 @@ module Keepachangelog
7
7
  end
8
8
 
9
9
  # Parse a file with markdown content
10
- def self.load(filename = 'CHANGELOG.md')
10
+ def self.load(filename = nil)
11
+ filename ||= 'CHANGELOG.md'
11
12
  p = new
12
13
  p.parse File.open(filename, &:read)
13
14
  p
14
15
  end
15
16
 
16
17
  def parse(content)
17
- content = "\n" + clean(content).strip + "\n"
18
+ content = "\n" + content.strip + "\n"
18
19
  anchors = extract_anchors! content
19
- versions = content.split(/\n\s*## /)[1..-1]
20
+ sections = content.split(/\n\s*## /)
21
+ parse_meta anchors, sections[0]
22
+ versions = sections[1..-1]
20
23
  parsed_content['versions'] = versions.map do |v|
21
24
  parse_version v, anchors
22
25
  end.to_h
@@ -25,26 +28,44 @@ module Keepachangelog
25
28
 
26
29
  private
27
30
 
28
- def clean(content)
29
- content.sub(/^.*?\n\s*## /, '## ')
31
+ def parse_meta(anchors, header)
32
+ url = get_repo_url(anchors)
33
+ title = extract_title!(header)
34
+ intro = header.strip
35
+ parsed_content['url'] = url if url
36
+ parsed_content['intro'] = intro unless intro.to_s.empty?
37
+ parsed_content['title'] = title if title
38
+ end
39
+
40
+ def extract_title!(text)
41
+ title_pattern = /# (?<title>.*)/
42
+ match = text.match(title_pattern)
43
+ return nil unless match && match[:title]
44
+ text.gsub!(title_pattern, '').strip!
45
+ match[:title]
30
46
  end
31
47
 
32
48
  def parse_version(content, anchors)
33
- header_pattern = /\[(?<name>.*)\]( - (?<date>\d\d\d\d-\d\d-\d\d))?/
49
+ header_pattern = /\[?(?<name>[^\]]*)\]?( - (?<date>\d\d\d\d-\d\d-\d\d))?/
34
50
  sections = content.split(/\n\s*### /)
35
51
  header = sections[0].match header_pattern
36
- [header[:name],
52
+ [header[:name].strip,
37
53
  {
38
- 'url' => get_url(header[:name], anchors),
54
+ 'url' => get_version_url(header[:name], anchors),
39
55
  'date' => header[:date],
40
56
  'changes' => sections[1..-1].map { |s| parse_section s }.to_h
41
57
  }]
42
58
  end
43
59
 
44
- def get_url(version, anchors)
60
+ def get_version_url(version, anchors)
45
61
  anchors.keys.include?(version) ? anchors[version] : nil
46
62
  end
47
63
 
64
+ def get_repo_url(anchors)
65
+ return nil unless anchors && anchors.values && anchors.values.first
66
+ anchors.values.first.gsub(%r{/compare/.*}, '')
67
+ end
68
+
48
69
  def parse_section(content)
49
70
  lines = content.split("\n")
50
71
  bullets = lines[1..-1]
@@ -54,7 +75,7 @@ module Keepachangelog
54
75
  end
55
76
 
56
77
  def clean_bullet(string)
57
- string.strip.gsub(/^\s*- /, '').gsub(/\(.*#\d+\)\.?$/, '').strip
78
+ string.strip.gsub(/^\s*- /, '').strip
58
79
  end
59
80
 
60
81
  def extract_anchors!(content)
@@ -39,7 +39,8 @@ module Keepachangelog
39
39
  end
40
40
 
41
41
  # Parse a folder with YAML files
42
- def self.load(path = 'changelog')
42
+ def self.load(path = nil)
43
+ path ||= 'changelog'
43
44
  p = new
44
45
  p.load(path)
45
46
  p
@@ -54,7 +55,8 @@ module Keepachangelog
54
55
  end
55
56
 
56
57
  # Parse a folder with YAML files
57
- def load(path = 'changelog')
58
+ def load(path = nil)
59
+ path ||= 'changelog'
58
60
  read_meta("#{path}/meta.yaml")
59
61
  Dir.glob("#{path}/*").each { |f| parse_version(f) }
60
62
  end
@@ -92,7 +94,8 @@ module Keepachangelog
92
94
  end
93
95
 
94
96
  def generate_line(yaml)
95
- line = yaml['title'] + '.'
97
+ line = yaml['title']
98
+ line += + '.' unless line =~ /[[:punct:]]$/
96
99
  line += " (!#{yaml['merge_request']})" if yaml['merge_request']
97
100
  line += " (##{yaml['issue']})" if yaml['issue']
98
101
  line += " (#{yaml['author']})" if yaml['author']
@@ -0,0 +1,4 @@
1
+ module Keepachangelog
2
+ class Printer
3
+ end
4
+ end
@@ -1,5 +1,5 @@
1
1
  module Keepachangelog
2
- class MarkdownPrinter
2
+ class MarkdownPrinter < Printer
3
3
  attr_accessor :options
4
4
  attr_accessor :versions
5
5
 
@@ -13,18 +13,29 @@ module Keepachangelog
13
13
  "# #{options[:title] || default_title}",
14
14
  clean_intro(options[:intro]) || default_intro,
15
15
  '',
16
- versions.reverse_each.map do |k, v|
17
- version(k, v)
18
- end,
16
+ parse_versions(versions),
19
17
  anchors
20
18
  ].flatten.join("\n")
21
19
  end
22
20
 
23
21
  private
24
22
 
23
+ def parse_versions(versions)
24
+ versions.sort { |a, b| compare_versions(a[0], b[0]) }
25
+ .reverse_each.map { |k, v| version(k, v) }
26
+ end
27
+
28
+ def compare_versions(a, b)
29
+ a = Gem::Version.new(a) if Gem::Version.correct?(a)
30
+ b = Gem::Version.new(b) if Gem::Version.correct?(b)
31
+ return -1 if b == 'Unreleased'
32
+ return 1 if a == 'Unreleased'
33
+ a <=> b
34
+ end
35
+
25
36
  def clean_intro(text)
26
37
  return nil unless text
27
- text.to_s.strip.gsub("\n", "\n\n")
38
+ text.to_s.strip
28
39
  end
29
40
 
30
41
  def version(header, content)
@@ -0,0 +1,79 @@
1
+ require 'fileutils'
2
+
3
+ module Keepachangelog
4
+ class YamlPrinter < Printer
5
+ attr_accessor :changelog
6
+
7
+ def initialize(changelog)
8
+ self.changelog = changelog
9
+ end
10
+
11
+ def write(path)
12
+ FileUtils.mkdir_p(path)
13
+ write_meta File.join(path, 'meta.yaml')
14
+ write_versions path, changelog['versions']
15
+ end
16
+
17
+ private
18
+
19
+ def write_meta(path)
20
+ meta = {}
21
+ %w(url title intro).each do |key|
22
+ meta[key] = changelog[key] unless changelog[key].to_s.empty?
23
+ end
24
+ File.write(path, meta.to_yaml)
25
+ end
26
+
27
+ def write_versions(path, versions)
28
+ versions.each do |version, data|
29
+ folder = File.join(path, version)
30
+ FileUtils.mkdir_p folder
31
+ write_changes folder, data['changes']
32
+ end
33
+ end
34
+
35
+ def write_changes(path, changes)
36
+ changes.each do |section, lines|
37
+ lines.each do |line|
38
+ change = parse_line(line)
39
+ change['type'] = section
40
+ write_change path, change
41
+ end
42
+ end
43
+ end
44
+
45
+ def write_change(folder, change)
46
+ fname = change['title'].gsub(/\W/, ' ').strip.tr(' ', '-').downcase
47
+ fname = "#{change['issue']}-#{fname}" if change['issue']
48
+ fname = "#{change['merge_request']}-#{fname}" if change['merge_request']
49
+ path = create_unique_file(folder, fname + '.yaml')
50
+ File.write(path, change.to_yaml)
51
+ end
52
+
53
+ def parse_line(line)
54
+ issue = extract_field! line, /\s*\(#(?<issue>\d+)\)\s*/, :issue
55
+ mr = extract_field! line, /\s*\(!(?<mr>\d+)\)\s*/, :mr
56
+ author = extract_field! line, /\s*\((?<author>.*@.*)\)\s*/, :author
57
+ data = { 'title' => line }
58
+ data['author'] = author if author
59
+ data['merge_request'] = mr.to_i if mr
60
+ data['issue'] = issue.to_i if issue
61
+ data
62
+ end
63
+
64
+ def extract_field!(line, pattern, name)
65
+ match = line.match(pattern)
66
+ return nil unless match && match[name]
67
+ line.gsub!(pattern, '').strip
68
+ match[name]
69
+ end
70
+
71
+ def create_unique_file(folder, filename)
72
+ if File.exist? File.join(folder, filename)
73
+ randstr = SecureRandom.hex(3)
74
+ filename = "#{randstr}-#{filename}"
75
+ end
76
+ File.join(folder, filename)
77
+ end
78
+ end
79
+ end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keepachangelog",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Parser for changelogs based on keepachangelog.com",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git@git.basalt.se:chbr/keepachangelog.git"
11
+ "url": "git@gitlab.com:ephracis/keepachangelog.git"
12
12
  },
13
13
  "author": "Christoffer Reijer",
14
14
  "license": "ISC",
@@ -28,7 +28,8 @@ module Keepachangelog
28
28
  'Fixed' => ['Feature B']
29
29
  }
30
30
  }
31
- }
31
+ },
32
+ 'url' => 'http://test.io'
32
33
  )
33
34
  end
34
35
 
@@ -55,7 +56,8 @@ module Keepachangelog
55
56
  'date' => nil,
56
57
  'changes' => { 'Fixed' => ['Feature B'] }
57
58
  }
58
- }
59
+ },
60
+ 'url' => 'http://test.io'
59
61
  )
60
62
  end
61
63
 
@@ -84,6 +86,22 @@ module Keepachangelog
84
86
  }
85
87
  )
86
88
  end
89
+
90
+ it 'should parse title and intro' do
91
+ content = "
92
+ # My Title
93
+ My test intro.
94
+ ## 1.0.0
95
+ "
96
+ cl = MarkdownParser.parse(content)
97
+ expect(cl).to eq(
98
+ 'versions' => {
99
+ '1.0.0' => { 'url' => nil, 'date' => nil, 'changes' => {} }
100
+ },
101
+ 'title' => 'My Title',
102
+ 'intro' => 'My test intro.'
103
+ )
104
+ end
87
105
  end
88
106
 
89
107
  describe '.load' do
data/spec/parser_spec.rb CHANGED
@@ -11,9 +11,9 @@ module Keepachangelog
11
11
  end
12
12
 
13
13
  describe '.to_yaml' do
14
- it 'should cast parsed content into yaml' do
14
+ it 'should cast parsed content into a yaml files' do
15
15
  p = Parser.new
16
- expect(p.parsed_content).to receive(:to_yaml)
16
+ expect_any_instance_of(YamlPrinter).to receive(:write)
17
17
  p.to_yaml
18
18
  end
19
19
  end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module Keepachangelog
4
+ describe MarkdownPrinter do
5
+ describe '.to_s' do
6
+ it 'should print markdown document' do
7
+ versions = {
8
+ '1.0.0' => {
9
+ 'changes' => { 'New' => ['Feature A'] }
10
+ }
11
+ }
12
+ p = MarkdownPrinter.new(versions, title: 'My Title')
13
+ md = p.to_s
14
+ expect(md).to match('# My Title')
15
+ expect(md).to match('## 1.0.0')
16
+ end
17
+
18
+ it 'should order versions numerically' do
19
+ versions = {
20
+ '0.1.0' => {
21
+ 'changes' => { 'New' => ['Feature A'] }
22
+ },
23
+ '0.10.0' => {
24
+ 'changes' => { 'New' => ['Feature B'] }
25
+ },
26
+ '0.2.0' => {
27
+ 'changes' => { 'New' => ['Feature C'] }
28
+ }
29
+ }
30
+ p = MarkdownPrinter.new(versions)
31
+ md = p.to_s.delete("\n")
32
+ expect(md).to match(/.*0\.10\.0.*0\.2\.0.*0\.1\.0.*/)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Keepachangelog
4
+ describe YamlPrinter do
5
+ let(:changelog) do
6
+ {
7
+ 'versions' => {
8
+ '1.0.0' => {
9
+ 'changes' => {
10
+ 'New' => [
11
+ 'Feature A',
12
+ 'Feature B'
13
+ ],
14
+ 'Fixed' => ['Bug A']
15
+ }
16
+ },
17
+ '1.0.1' => {
18
+ 'changes' => { 'Fixed' => ['Bug B'] }
19
+ }
20
+ },
21
+ 'url' => 'https://git.example.com/foo/bar',
22
+ 'title' => 'Change log',
23
+ 'intro' => 'This is my intro'
24
+ }
25
+ end
26
+ let(:p) { YamlPrinter.new(changelog) }
27
+
28
+ describe '.write' do
29
+ before do
30
+ allow(FileUtils).to receive(:mkdir_p).with('test')
31
+ allow(FileUtils).to receive(:mkdir_p).with('test/1.0.0')
32
+ allow(FileUtils).to receive(:mkdir_p).with('test/1.0.1')
33
+ allow(File).to receive(:write).with('test/**/*.yaml', any_args)
34
+ end
35
+
36
+ it 'should create destination folder' do
37
+ allow(p).to receive(:write_meta)
38
+ allow(p).to receive(:write_versions)
39
+ expect(FileUtils).to receive(:mkdir_p).with('test')
40
+ p.write('test')
41
+ end
42
+
43
+ it 'should create meta file' do
44
+ meta_content = "---\nurl: https://git.example.com/foo/bar\ntitle: "\
45
+ "Change log\nintro: This is my intro\n"
46
+ allow(p).to receive(:write_versions)
47
+ expect(File).to receive(:write).with('test/meta.yaml', meta_content)
48
+ p.write('test')
49
+ end
50
+
51
+ it 'should create version folders' do
52
+ allow(p).to receive(:write_meta)
53
+ allow(p).to receive(:write_changes)
54
+ expect(FileUtils).to receive(:mkdir_p).with('test/1.0.0')
55
+ expect(FileUtils).to receive(:mkdir_p).with('test/1.0.1')
56
+ p.write('test')
57
+ end
58
+
59
+ it 'should write change file' do
60
+ allow(p).to receive(:write_meta)
61
+ expect(File).to receive(:write).with(
62
+ 'test/1.0.0/feature-a.yaml',
63
+ "---\ntitle: Feature A\ntype: New\n"
64
+ )
65
+ expect(File).to receive(:write).with(
66
+ 'test/1.0.0/feature-b.yaml',
67
+ "---\ntitle: Feature B\ntype: New\n"
68
+ )
69
+ expect(File).to receive(:write).with(
70
+ 'test/1.0.0/bug-a.yaml',
71
+ "---\ntitle: Bug A\ntype: Fixed\n"
72
+ )
73
+ expect(File).to receive(:write).with(
74
+ 'test/1.0.1/bug-b.yaml',
75
+ "---\ntitle: Bug B\ntype: Fixed\n"
76
+ )
77
+ p.write('test')
78
+ end
79
+ end
80
+ end
81
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,3 @@
1
1
  require 'simplecov'
2
2
  SimpleCov.start
3
3
  require 'keepachangelog'
4
- require 'keepachangelog/parser/markdown'
5
- require 'keepachangelog/parser/yaml'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keepachangelog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Basalt AB
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-27 00:00:00.000000000 Z
11
+ date: 2017-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -152,31 +152,37 @@ files:
152
152
  - changelog/0.3.0/3-anchors-without-url.yaml
153
153
  - changelog/0.3.0/4-document-meta.yaml
154
154
  - changelog/0.3.1/6-clean-changelog.yaml
155
+ - changelog/0.4.0/5-yaml-files.yaml
156
+ - changelog/0.4.0/7-numeric-order.yaml
157
+ - changelog/0.4.0/share-with-public.yaml
158
+ - changelog/0.4.1/8-fix-deploy.yaml
155
159
  - changelog/meta.yaml
156
160
  - exe/keepachangelog
157
161
  - features/help.feature
158
- - features/markdown.feature
162
+ - features/parser.feature
159
163
  - features/support/aruba.rb
160
164
  - features/version.feature
161
- - features/yaml.feature
162
165
  - keepachangelog.gemspec
163
166
  - lib/keepachangelog.rb
164
167
  - lib/keepachangelog/cli.rb
165
- - lib/keepachangelog/markdown_printer.rb
166
168
  - lib/keepachangelog/parser.rb
167
169
  - lib/keepachangelog/parser/markdown.rb
168
170
  - lib/keepachangelog/parser/yaml.rb
171
+ - lib/keepachangelog/printer.rb
172
+ - lib/keepachangelog/printer/markdown.rb
173
+ - lib/keepachangelog/printer/yaml.rb
169
174
  - lib/keepachangelog/version.rb
170
175
  - package.json
171
- - spec/markdown_printer_spec.rb
172
176
  - spec/parser/markdown_spec.rb
173
177
  - spec/parser/yaml_spec.rb
174
178
  - spec/parser_spec.rb
179
+ - spec/printer/markdown_spec.rb
180
+ - spec/printer/yaml_spec.rb
175
181
  - spec/spec_helper.rb
176
182
  - spec/version_spec.rb
177
- homepage: http://www.basalt.se
183
+ homepage: https://gitlab.com/ephracis/keepachangelog
178
184
  licenses:
179
- - Nonstandard
185
+ - MIT
180
186
  metadata: {}
181
187
  post_install_message:
182
188
  rdoc_options: []
@@ -1,43 +0,0 @@
1
- Feature: List transformators
2
-
3
- Parse a changelog by running `keepachangelog parse` or just simply
4
- `keepachangelog`.
5
-
6
- Scenario: Running with command
7
- Given a file "CHANGELOG.md" with:
8
- """
9
- ## [Unreleased]
10
- ### New
11
- - Feature A
12
- """
13
- When I successfully run `keepachangelog markdown`
14
- Then the output should contain:
15
- """
16
- {"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
17
- """
18
-
19
- Scenario: Running without command
20
- Given a file "CHANGELOG.md" with:
21
- """
22
- ## [Unreleased]
23
- ### New
24
- - Feature A
25
- """
26
- When I successfully run `keepachangelog`
27
- Then the output should contain:
28
- """
29
- {"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
30
- """
31
-
32
- Scenario: Changelog has a non-default filename
33
- Given a file "HISTORY.md" with:
34
- """
35
- ## [Unreleased]
36
- ### New
37
- - Feature A
38
- """
39
- When I successfully run `keepachangelog --path=HISTORY.md`
40
- Then the output should contain:
41
- """
42
- {"versions":{"Unreleased":{"url":null,"date":null,"changes":{"New":["Feature A"]}}}}
43
- """
@@ -1,17 +0,0 @@
1
- Feature: List transformators
2
-
3
- Parse a changelog by running `keepachangelog parse` or just simply
4
- `keepachangelog`.
5
-
6
- Scenario: Running with command
7
- Given a file "changelog/1.0.0/1.yml" with:
8
- """
9
- ---
10
- title: Feature A
11
- type: New
12
- """
13
- When I successfully run `keepachangelog yaml`
14
- Then the output should contain:
15
- """
16
- {"versions":{"1.0.0":{"changes":{"New":["Feature A."]}}}}
17
- """
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Keepachangelog
4
- describe MarkdownPrinter do
5
- describe '.to_s' do
6
- it 'should print markdown document' do
7
- versions = {
8
- '1.0.0' => {
9
- 'changes' => { 'New' => ['Feature A'] }
10
- }
11
- }
12
- p = MarkdownPrinter.new(versions, title: 'My Title')
13
- md = p.to_s
14
- expect(md).to match('# My Title')
15
- expect(md).to match('## 1.0.0')
16
- end
17
- end
18
- end
19
- end