milestoner 17.0.0 → 17.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -1
  3. data/README.adoc +107 -58
  4. data/lib/milestoner/builders/ascii_doc.rb +32 -0
  5. data/lib/milestoner/builders/container.rb +2 -0
  6. data/lib/milestoner/builders/markdown.rb +32 -0
  7. data/lib/milestoner/cli/actions/build/format.rb +1 -1
  8. data/lib/milestoner/cli/actions/build/label.rb +1 -1
  9. data/lib/milestoner/cli/actions/build/version.rb +1 -1
  10. data/lib/milestoner/cli/actions/cache/delete.rb +1 -4
  11. data/lib/milestoner/cli/actions/cache/find.rb +1 -4
  12. data/lib/milestoner/cli/actions/publish.rb +1 -1
  13. data/lib/milestoner/cli/commands/build.rb +9 -4
  14. data/lib/milestoner/commits/enricher.rb +2 -3
  15. data/lib/milestoner/configuration/contract.rb +4 -3
  16. data/lib/milestoner/configuration/model.rb +2 -0
  17. data/lib/milestoner/configuration/transformers/build/template_paths.rb +1 -4
  18. data/lib/milestoner/configuration/transformers/citations/description.rb +8 -6
  19. data/lib/milestoner/configuration/transformers/citations/label.rb +8 -6
  20. data/lib/milestoner/configuration/transformers/gems/description.rb +4 -6
  21. data/lib/milestoner/configuration/transformers/gems/label.rb +5 -6
  22. data/lib/milestoner/configuration/transformers/gems/name.rb +4 -6
  23. data/lib/milestoner/configuration/transformers/gems/uri.rb +5 -6
  24. data/lib/milestoner/configuration/transformers/generator/label.rb +31 -0
  25. data/lib/milestoner/configuration/transformers/generator/uri.rb +31 -0
  26. data/lib/milestoner/configuration/transformers/project/author.rb +5 -4
  27. data/lib/milestoner/configuration/transformers/project/generator.rb +8 -1
  28. data/lib/milestoner/configuration/transformers/project/label.rb +4 -4
  29. data/lib/milestoner/configuration/transformers/project/name.rb +6 -4
  30. data/lib/milestoner/configuration/transformers/project/version.rb +5 -3
  31. data/lib/milestoner/container.rb +2 -1
  32. data/lib/milestoner/templates/layouts/page.adoc.erb +2 -0
  33. data/lib/milestoner/templates/layouts/page.html.erb +10 -2
  34. data/lib/milestoner/templates/layouts/page.md.erb +2 -0
  35. data/lib/milestoner/templates/layouts/page.stream.erb +1 -0
  36. data/lib/milestoner/templates/milestones/_commit.adoc.erb +1 -0
  37. data/lib/milestoner/templates/milestones/_commit.md.erb +1 -0
  38. data/lib/milestoner/templates/milestones/show.adoc.erb +9 -0
  39. data/lib/milestoner/templates/milestones/show.html.erb +2 -2
  40. data/lib/milestoner/templates/milestones/show.md.erb +9 -0
  41. data/lib/milestoner/templates/milestones/show.stream.erb +4 -0
  42. data/lib/milestoner/templates/public/page.css.erb +19 -2
  43. data/lib/milestoner/views/context.rb +2 -0
  44. data/lib/milestoner/views/milestones/show.rb +3 -2
  45. data/lib/milestoner.rb +1 -1
  46. data/milestoner.gemspec +3 -3
  47. data.tar.gz.sig +0 -0
  48. metadata +16 -6
  49. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62c3705bded27a22253cc186854ca6f39a73aa441fa5ff065ea76c23250e0e5d
4
- data.tar.gz: 187d16fc088ae2f84774f77ba3bfb35b3875481f127c73dd1ac66b082332a814
3
+ metadata.gz: 2069b8a67bf9cf6a786fade18de6256506c610d44c73705f24803d758f606dac
4
+ data.tar.gz: 4f8001a067a33034cd76c378b4e9e6c95f450754354658bcbe3e51169f32bf05
5
5
  SHA512:
6
- metadata.gz: cd2db5bbb280f82e2cc40530e183cc2e822d8df0e5ce3260893606a25b3ca5ba37cc5a016d11ecc26d0f2e306eb0f1f56bc6996cfdc990719dc4ddcca3b7fb22
7
- data.tar.gz: 99d0e185f7861d29bfb701b229a248298a361848bbabbc4c6e43adb96376c3051370eb8546887a134e18eaefa25573455edede1f9d0c0bf519660cea8a2f7740
6
+ metadata.gz: aea11fff1c1b7d10e8910dafae3496b206f0df8be716ad0bb8fd708bf0eb70d3b29280d9b17373b5732c8af720bc4f81912e29584430dbd61959975f4a75c93f
7
+ data.tar.gz: cd130868800665f2fe370edb5cae1a4074672ed8f8743a1636baa74d4336f2681bf4af21efde43285408f836acf87ecd046d214a4f9edf1381957431ee1408c3
checksums.yaml.gz.sig CHANGED
@@ -1 +1,3 @@
1
- ���/��BiF<�/X�Co.��+��t囑��#U}5��Kz޲SYO��������xD��y���BH�?�NZc���sk�*� ���\���`�W30GS��T��As@^C�N��~����ra�&7��`(Ĩ�(�j����Wv��%�I|&%Q�s�R�H( �
1
+ F
2
+ ��M)6x�h���v^��
3
+ UB #����]��$v��^ٝ: ����$�ɭ��
data/README.adoc CHANGED
@@ -2,58 +2,78 @@
2
2
  :toclevels: 5
3
3
  :figure-caption!:
4
4
 
5
- :asciidoc_link: link:https://asciidoctor.org/docs/what-is-asciidoc[ASCII Doc]
5
+ :ascii_doc_link: link:https://asciidoctor.org/docs/what-is-asciidoc[ASCII Doc]
6
6
  :cff_link: link:https://github.com/citation-file-format/ruby-cff[CFF]
7
7
  :etcher_link: link:https://alchemists.io/projects/etcher[Etcher]
8
- :gem_specification_link: link:https://guides.rubygems.org/specification-reference/[Gem Specification]
8
+ :gem_specification_link: link:https://guides.rubygems.org/specification-reference[Gem Specification]
9
+ :gemsmith_link: link:https://alchemists.io/projects/gemsmith[Gemsmith]
9
10
  :git_commit_anatomy_link: link:https://alchemists.io/articles/git_commit_anatomy[Git Commit Anatomy]
11
+ :git_link: link:https://git-scm.com[Git]
10
12
  :git_lint_link: link:https://alchemists.io/projects/git-lint[Git Lint]
11
- :hanami_views_link: link:https://alchemists.io/articles/hanami_views[Hanami Views]
13
+ :hanami_link: link:https://hanamirb.org[Hanami]
14
+ :hanami_views_link: link:https://alchemists.io/articles/hanami_views[Hanami View]
15
+ :hanamismith_link: link:https://alchemists.io/projects/hanamismith[Hanamismith]
12
16
  :lode_link: link:https://alchemists.io/projects/lode[Lode]
13
17
  :markdown_link: link:https://daringfireball.net/projects/markdown[Markdown]
18
+ :ruby_link: link:https://www.ruby-lang.org[Ruby]
19
+ :rubygems_link: link:https://rubygems.org[RubyGems]
20
+ :rubysmith_link: link:https://alchemists.io/projects/rubysmith[Rubysmith]
14
21
  :runcom_link: link:https://alchemists.io/projects/runcom[Runcom]
22
+ :strict_semantic_versioning_link: link:https://alchemists.io/articles/strict_semantic_versioning[Strict Semantic Versioning]
15
23
  :string_formats_link: link:https://ruby-doc.org/3.3.0/format_specifications_rdoc.html[String Formats]
16
24
  :versionaire_link: link:https://alchemists.io/projects/versionaire[Versionaire]
17
25
  :xdg_link: link:https://alchemists.io/projects/xdg[XDG]
18
26
 
19
27
  = Milestoner
20
28
 
21
- Milestoner is a Command Line Interface (CLI) for automating software deployments complete with feature rich release notes that celebrate the team members who worked on the version release. This includes the automation of Git repository tags (milestones) using link:https://semver.org[semantic versions]. Each milestone is a summary of all commits made since the last milestone. You can use Milestoner to inspect what is currently pending or create a new release via a single command. By having a tool, like Milestoner, you can automate releases in a consistent and reliable fashion. Milestoner pairs well with the following gems:
29
+ Milestoner is a pure {git_link} based Command Line Interface (CLI) for software deployment automation that is agnostic of the programming language or source control service you use (i.e. GitHub, GitLab, Bitbucket, etc). Each milestone (i.e. {git_link} tag) includes the automatic generation of feature rich release notes sourced from the {git_link} commits that make up the milestone. Finally, each milestone adheres to {strict_semantic_versioning_link} so your milestones remain consistent.
22
30
 
23
- - link:https://alchemists.io/projects/git-lint[Git Lint] - Ensures your commit messages are of
24
- high quality for release note purposes.
25
- - link:https://alchemists.io/projects/rubysmith[Rubysmith] - Automates the publishing of new or existing Ruby project versions.
26
- - link:https://alchemists.io/projects/gemsmith[Gemsmith] - Automates the publishing of new or existing Ruby gem versions.
31
+ You can use Milestoner to inspect the current state of the next milestone, celebrate the team members that contribute to each milestone, and share information with stakeholders with minimal effort. By having a tool, like Milestoner, you can automate software releases in a consistent and reliable fashion. 🎉
32
+
33
+ Milestoner pairs well with the following gems:
34
+
35
+ * {git_lint_link}: Lints each {git_link} commit to ensure they are of high quality for historic inspection and release note generation.
36
+ * {rubysmith_link}: Automates building new {ruby_link} projects.
37
+ * {gemsmith_link}: Automates building new {rubygems_link} projects.
38
+ * {hanamismith_link}: Automates building new {hanami_link} projects.
27
39
 
28
40
  toc::[]
29
41
 
30
42
  == Screenshots
31
43
 
32
- *Web Format* (i.e. `milestoner build --format web`)
44
+ *ASCII Doc Format* (i.e. `milestoner build --format ascii_doc`)
33
45
 
34
- image:https://alchemists.io/images/projects/milestoner/screenshots/build-web-collapsed.png[Usage,width=1011,height=345,role=focal_point]
46
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-ascii_doc.png[Usage,width=787,height=257,role=focal_point]
35
47
 
36
- image:https://alchemists.io/images/projects/milestoner/screenshots/build-web-expanded.png[Usage,width=1005,height=643,role=focal_point]
48
+ *Markdown Format* (i.e. `milestoner build --format markdown`)
49
+
50
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-markdown.png[Usage,width=765,height=257,role=focal_point]
37
51
 
38
52
  *Stream Format* (i.e. `milestoner build --format stream`)
39
53
 
40
- image:https://alchemists.io/images/projects/milestoner/screenshots/build-stream.png[Usage,width=464,height=245,role=focal_point]
54
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-stream.png[Usage,width=464,height=280,role=focal_point]
55
+
56
+ *Web Format* (i.e. `milestoner build --format web`)
57
+
58
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-web-collapsed.png[Usage,width=998,height=409,role=focal_point]
59
+
60
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-web-expanded.png[Usage,width=983,height=701,role=focal_point]
41
61
 
42
62
  == Features
43
63
 
44
- * Uses link:https://alchemists.io/projects/versionaire[Versionaire] for
45
- link:https://semver.org[Semantic Versioning].
64
+ * Uses {versionaire_link} for {strict_semantic_versioning_link}. Example:
46
65
  ** Format: `+<major>.<minor>.<patch>+`.
47
66
  ** Example: `0.0.0`.
48
- * Ensures Git commits since last tag (or initialization of repository) are included in the release notes.
49
- * Ensures Git commit messages are grouped by prefix, in order defined, for categorization. For more details, see link:https://alchemists.io/projects/git-lint/#_commit_subject_prefix[Git Lint Commit Subject Prefix]. Defaults (can be customized):
67
+ * Ensures {git_link} commits since last tag (or initialization of repository) are included in the release notes.
68
+ * Ensures {git_link} commit messages are grouped by prefix, in order defined, for categorization. For more details, see link:https://alchemists.io/projects/git-lint/#_commit_subject_prefix[Git Lint Commit Subject Prefix]. Defaults (can be customized):
50
69
  ** image:https://alchemists.io/images/projects/milestoner/icons/commits/fixed.png[Fixed] Fixed
51
70
  ** image:https://alchemists.io/images/projects/milestoner/icons/commits/added.png[Added] Added
52
71
  ** image:https://alchemists.io/images/projects/milestoner/icons/commits/updated.png[Updated] Updated
53
72
  ** image:https://alchemists.io/images/projects/milestoner/icons/commits/removed.png[Removed] Removed
54
73
  ** image:https://alchemists.io/images/projects/milestoner/icons/commits/refactored.png[Refactored] Refactored
55
- * Ensures Git commit messages are alphabetically sorted for release note categorization and readability.
56
- * Provides automatic versioning based on last Git tag and current Git commit trailers. See {git_commit_anatomy_link} for details.
74
+ * Ensures {git_link} commit messages are alphabetically sorted for release note categorization and readability.
75
+ * Provides automatic versioning based on last {git_link} tag and current commit trailers. See {git_commit_anatomy_link} for details.
76
+ * Supports multiple release note build formats: {ascii_doc_link}, {markdown_link}, Stream (console), and Web (HTML). Each are fully customizable via your personal {xdg_link} configuration and {hanami_views_link} templates.
57
77
 
58
78
  == Requirements
59
79
 
@@ -123,6 +143,9 @@ commit:
123
143
  domain: https://github.com
124
144
  format: asciidoc
125
145
  uri: "%<domain>s/%<owner>s/%<name>s/commit/%<id>s"
146
+ generator:
147
+ label:
148
+ uri:
126
149
  profile:
127
150
  domain: https://github.com
128
151
  uri: "%<domain>s/%<id>s"
@@ -146,46 +169,53 @@ tracker:
146
169
  The above can be customized as follows:
147
170
 
148
171
  * `avatar`: Manages team member avatar information.
149
- ** `domain`: The domain of your team member avatars.
150
- ** `uri`: The URI format for linking to avatars as formatted using {string_formats_link}. The `id` is dynamically calculated via the `external_id` of the user stored in the {lode_link} cache.
172
+ ** `domain`: Required. The domain of your team member avatars. Default: GitHub.
173
+ ** `uri`: Required. The URI format for linking to avatars as formatted using {string_formats_link}. Default: GitHub. The `id` is dynamically calculated via the `external_id` of the user stored in the {lode_link} cache.
151
174
  * `build`: Manages release note builds.
152
- ** `format`: The build output format. Multiple formats are supported.
153
- ** `layout`: The layout used by {hanami_views_link} when building release notes.
154
- ** `root`: The output location. This can be a relative or absolute path.
175
+ ** `format`: Required. The build output format. Multiple formats are supported. Default: web.
176
+ ** `layout`: Required. The layout used by the {hanami_views_link} gem when building release notes. Default: page.
177
+ ** `root`: Required. The output location. This can be a relative or absolute path. Defaults to the `tmp` directory of your current project. The path is automatically created if missing.
155
178
  * `commit`: Manages commit categories, emojis, and hyperlinks.
156
- ** `categories`: By default, only five categories are supported which pairs well with the {git_lint_link} gem. Category order is important with the first taking precedence over the second and so forth. Special characters are allowed for prefixes but should be enclosed in quotes. To disable categories, use an empty array. Example: `categories: []`.
157
- *** `emoji`: The emoji associated with the label for output purposes. _Only used by the stream build format_.
158
- *** `label`: Allows you to customize the category label. All commits are grouped by label which equates to the prefix, or first word, used in each commit message. The defaults pair well with the {git_lint_link} gem.
159
- ** `domain`: The Git repository domain for all commits.
160
- ** `format`: Defines the default format used for rendering commit messages unless specified in the commit trailer metadata which takes higher precedence. Defaults to {asciidoc_link} but {markdown_link} is also supported.
161
- ** `uri`: The URI format for linking to commits as formatted using {string_formats_link}. The `id` is dynamically calculated via the commit SHA of each commit analyzed at runtime.
179
+ ** `categories`: Required. By default, only five categories are supported which pairs well with the {git_lint_link} gem. Category order is important with the first taking precedence over the second and so forth. Special characters are allowed for prefixes but should be enclosed in quotes. To disable categories, use an empty array. Example: `categories: []`.
180
+ *** `emoji`: Required. The emoji associated with the label for output purposes. _Used by the {ascii_doc_link}, {markdown_link}, and stream build formats_. Defaults to the provided emojis.
181
+ *** `label`: Required. Allows you to customize the category label. All commits are grouped by label which equates to the prefix, or first word, used in each commit message. The defaults pair well with the {git_lint_link} gem. Defaults to the provided labels.
182
+ ** `domain`: Required. The {git_link} repository domain for all commits. Default: GitHub.
183
+ ** `format`: Required. Defines the default format used for rendering commit messages unless specified in the commit trailer metadata which takes higher precedence. Default: {ascii_doc_link}.
184
+ ** `uri`: Required. The URI format for linking to commits as formatted using {string_formats_link}. Default: GitHub. The `id` is dynamically calculated via the commit SHA of each commit analyzed at runtime.
185
+ * `generator`: Manages generator information.
186
+ ** `label`: Required. The label of the generator used for all software milestones. Default: Milestoner.
187
+ ** `uri`: Required. The URI of the generator used for all software milestones. Defaults to Milestoner's homepage URL as provided by the {gem_specification_link} of this project.
162
188
  * `profile`: Manages team member profile information.
163
- ** `domain`: The domain of your Git repository.
164
- ** `uri`: The URI format for linking to profiles as formatted using {string_formats_link}. The `id` is dynamically calculated via the `handle` of the user stored in the {lode_link} cache.
189
+ ** `domain`: Required. The domain of your {git_link} repository. Default: GitHub.
190
+ ** `uri`: Required. The URI format for linking to profiles as formatted using {string_formats_link}. The `id` is dynamically calculated via the `handle` of the user stored in the {lode_link} cache. Default: GitHub.
165
191
  * `project`: Manages project information.
166
- ** `author`: Optional. The project author. Dynamically calculated by the {etcher_link} gem in the following order: Git configuration user name or this value.
167
- ** `description`: Optional. The project description. Dynamically calculated by the {etcher_link} gem in the following order: {gem_specification_link} summary, {cff_link} abstract, or this value.
168
- ** `generator`: Optional. The project generator (i.e. this gem).
169
- ** `label`: Optional. The project label. Dynamically calculated by the {etcher_link} gem in the following order: {gem_specification_link} metadata label, {cff_link} title, or this value.
170
- ** `name`: Optional. The project name. Dynamically calculated by the {etcher_link} gem in the following order: {gem_specification_link} name or this value.
171
- ** `owner`: Required. The project owner. This would be your source code organization or user handle. This is used when formatting URL information (mentioned above).
172
- ** `uri`: Optional. The project URI. Dynamically calculated by the {etcher_link} gem in the following order: {gem_specification_link} homepage or this value.
173
- ** `version`: Optional. The project version. Dynamically calculated based on the last Git tag of your project and Git `Milestone` commit trailer metadata. Otherwise, defaults to: `0.0.0`. For more on this see, the _Automatic Versioning_ section below.
192
+ ** `author`: Required. The project author. Dynamically calculated by the {etcher_link} gem in the following order: This value or {git_link} configuration user name.
193
+ ** `description`: Optional. The project description. Dynamically calculated by the {etcher_link} gem in the following order: This value, {gem_specification_link} summary, or {cff_link} abstract.
194
+ ** `generator`: ⚠️ Deprecated and will be removed in the next major version. Please use the `generator` configuration section mentioned above instead.
195
+ ** `label`: Optional. The project label. Dynamically calculated by the {etcher_link} gem in the following order: This value, {gem_specification_link} metadata label, or {cff_link} title.
196
+ ** `name`: Required. The project name. Dynamically calculated by the {etcher_link} gem in the following order: This value or {gem_specification_link} name.
197
+ ** `owner`: Optional. The project owner. This is your source code organization or user handle. Used when formatting URLs (mentioned above). Despite being optional, it is strongly recommended you configure this value so all links are formatted properly.
198
+ ** `uri`: Optional. The project URI. Dynamically calculated by the {etcher_link} gem in the following order: This value or {gem_specification_link} homepage.
199
+ ** `version`: Required. The project version. Dynamically calculated based on the last {git_link} tag of your project and {git_link} `Milestone` commit trailer metadata. The default is: `0.0.0`. For more on this see, the _Automatic Versioning_ section below. You can configure a value but, keep in mind, the value will be used for _all_ deployments and release notes. Better to let this gem compute this for you.
174
200
  * `review`: Manages code review information.
175
- ** `domain`: The domain of your code review service.
176
- ** `uri`: The URI format for linking to code reviews as formatted using {string_formats_link}. The `id` is currently a _placeholder_ for future feature support when API support is added. For now this links to _all_ code reviews with the goal to link to individual code reviews based on issue tracker metadata from Git commit trailers.
177
- * `tracker`: Allows you to customize the issue tracker service you are using.
178
- ** `domain`: The domain of your issue tracker service.
179
- ** `uri`: The URI format for linking to issues as formatted using {string_formats_link}. The `id` is dynamically calculated via the commit `Issue` trailer as linted by {git_lint_link}.
201
+ ** `domain`: Required. The domain of your code review service. Default: GitHub.
202
+ ** `uri`: Required. The URI format for linking to code reviews as formatted using {string_formats_link}. Default: GitHub. The `id` is currently a _placeholder_ for future feature support when API support is added. For now this links to _all_ code reviews with the goal to link to individual code reviews based on issue tracker metadata from {git_link} commit trailers.
203
+ * `tracker`: Required. Allows you to customize the issue tracker service you are using. Default: GitHub.
204
+ ** `domain`: Required. The domain of your issue tracker service. Default: GitHub.
205
+ ** `uri`: Required. The URI format for linking to issues as formatted using {string_formats_link}. Default: GitHub. The `id` is dynamically calculated via the commit `Issue` trailer as linted by {git_lint_link}.
180
206
 
181
- 💡 If you ever need to know what your currrent configuration looks like you can jump into your applications IRB console and inspect `Milestoner::Container[:configuration]` to see full details.
207
+ 💡 If you ever need to know what your current configuration looks like you can jump into your applications IRB console and inspect `Milestoner::Container[:configuration]` to see full details.
182
208
 
183
209
  === Config
184
210
 
185
- Milestoner can be configured via the command line using: `milestoner config`. Using this command will allow you to create, edit, view, and/or delete your global or local configuration as desired. The configuration is managed by the {runcom_link} gem which is built atop the {xdg_link} gem for managing global or local configurations. Please read the documentation of each gem to learn more.
211
+ image:https://alchemists.io/images/projects/milestoner/screenshots/usage-config.png[Usage,width=632,height=352,role=focal_point]
212
+
213
+ Milestoner can be configured via the command line using: `milestoner config`. This allows you to create, edit, view, and/or delete your global or local configuration as desired. The configuration is managed by the {runcom_link} gem which is built atop the {xdg_link} gem for managing global or local configurations. Please read the documentation of each gem to learn more.
186
214
 
187
215
  === Cache
188
216
 
217
+ image:https://alchemists.io/images/projects/milestoner/screenshots/usage-cache.png[Usage,width=625,height=318,role=focal_point]
218
+
189
219
  Milestoner's cache allows you to enrich user information (i.e. authors, collaborators, etc) by storing information in a `PStore` database as managed by the {lode_link} gem. Cache location, as with the Config, is managed by the {runcom_link} gem.
190
220
 
191
221
  User information should be sourced from whatever service you use for managing your source code. For example, when using GitHub, your workflow might look like this:
@@ -229,11 +259,13 @@ Once team member information is stored in your cache, you'll be able to build re
229
259
 
230
260
  === Build
231
261
 
232
- The build command allows you to quickly build release notes for checking the current status of your project or for deployment automation. By default, the build command uses either the default or custom configuration as documented in the _Configuration_ section above. This means, when using the defaults, you can immediately build the release notes for your project in a temporary directory:
262
+ image:https://alchemists.io/images/projects/milestoner/screenshots/usage-build.png[Usage,width=679,height=437,role=focal_point]
263
+
264
+ The build command allows you to quickly build release notes to check the current status of your project or deploy a new milestone. By default, the build command uses either the default or custom configuration as documented in the _Configuration_ section above. This means, when using the defaults, you can immediately build the release notes for your project in a temporary directory:
233
265
 
234
266
  [source,bash]
235
267
  ----
236
- milestoner build --format html
268
+ milestoner build --format web
237
269
  # 🟢 Building milestone...
238
270
  # 🟢 Milestone built: /Users/bkuhlmann/Engineering/OSS/milestoner/tmp/milestone
239
271
  ----
@@ -244,7 +276,7 @@ Check out the help documentation (i.e. `milestoner build --help`) for addition u
244
276
 
245
277
  ==== Automatic Versioning
246
278
 
247
- As mentioned earlier, the calculation of version information happens automatically for you based on your last Git tag and any Git commit trailer metadata used. If none of this information is present, then the default version of `0.0.0` is used instead. All of this information is available to you via the following command:
279
+ As mentioned earlier, the calculation of version information happens automatically for you based on your last {git_link} tag and any {git_link} commit trailer metadata used. If none of this information is present, then the default version of `0.0.0` is used instead. All of this information is available to you via the following command:
248
280
 
249
281
  [source,bash]
250
282
  ----
@@ -262,7 +294,7 @@ milestoner build --format stream
262
294
  milestoner build --format stream --version 1.2.3
263
295
  ----
264
296
 
265
- By default, automatic versioning is based on your last known Git tag and the version is bumped based on Git commit trailer information from untagged commits (i.e. those commits created since the last tag). All of this is managed via the {versionaire_link} gem. To ensure automatic versioning works properly, you only need to add the `Milestone` Git commit trailer with a value of: `patch`, `minor`, or `major`. Here's an example assuming you have published Version 1.0.0:
297
+ By default, automatic versioning is based on your last known {git_link} tag and the version is bumped based on {git_link} commit trailer information from untagged commits (i.e. those commits created since the last tag). All of this is managed via the {versionaire_link} gem. To ensure automatic versioning works properly, you only need to add the `Milestone` {git_link} commit trailer with a value of: `patch`, `minor`, or `major`. Here's an example assuming you have published Version 1.0.0:
266
298
 
267
299
  ....
268
300
  # First commit.
@@ -305,20 +337,26 @@ Given the above, the resulting version would be: 2.0.0. This is because the high
305
337
 
306
338
  ==== Templates
307
339
 
308
- Build template functionality is powered by {hanami_views_link} which means you can customize the HTML structure, CSS style, and more. The quickest way to get started is to copy the `templates` folder structure -- included with this gem -- to your preferred {runcom_link} configuration. For example, this gem's template structure is:
340
+ Build template functionality is powered by the {hanami_views_link} gem which means you can customize the HTML structure, CSS style, and more. The quickest way to get started is to copy the `templates` folder structure -- included with this gem -- to your preferred {runcom_link} configuration. For example, this gem's template structure is:
309
341
 
310
342
  ....
311
343
  lib/milestoner/templates
312
344
  ├── layouts
345
+ │ ├── page.adoc.erb
313
346
  │ ├── page.html.erb
347
+ │ ├── page.md.erb
314
348
  │ └── page.stream.erb
315
349
  ├── milestones
316
350
  │ ├── _avatar.html.erb
351
+ │ ├── _commit.adoc.erb
317
352
  │ ├── _commit.html.erb
353
+ │ ├── _commit.md.erb
318
354
  │ ├── _commit.stream.erb
319
355
  │ ├── _icon.html.erb
320
356
  │ ├── _profile.html.erb
357
+ │ ├── show.adoc.erb
321
358
  │ ├── show.html.erb
359
+ │ ├── show.md.erb
322
360
  │ └── show.stream.erb
323
361
  └── public
324
362
  └── page.css.erb
@@ -333,9 +371,23 @@ cp -r <milestoner_gem_root>/lib/milestoner/templates $HOME/.config/milestoner/te
333
371
 
334
372
  Milestoner searches your {runcom_link} configuration first and, if templates are detected, will be used instead. Otherwise, Milestoner will fall back to it's own templates. Once {runcom_link} has calculated all possible template locations, {hanami_views_link} handles the final loading and evaluation of your templates.
335
373
 
374
+ ==== Web Format
375
+
376
+ Of all the build formats supported, the web format is the most powerful, feature rich, and is why it's the default format. The following showcases _some_ of the information rendered in this format based on commit activity.
377
+
378
+ *Wit Basic Git Commit*
379
+
380
+ image:https://alchemists.io/images/projects/milestoner/screenshots/web_format-overview.png[Usage,width=1228,height=808,role=focal_point]
381
+
382
+ *With Git Commit Notes and Trailers*
383
+
384
+ image:https://alchemists.io/images/projects/milestoner/screenshots/web_format-notes_and_collaborators.png[Usage,width=1228,height=808,role=focal_point]
385
+
386
+ Each milestone is meant to provide you with the right amount of statistical information you can make informed decisions.
387
+
336
388
  == Security
337
389
 
338
- To securely sign your Git tags, install and configure https://www.gnupg.org[GPG]:
390
+ To securely sign your {git_link} tags, install and configure https://www.gnupg.org[GPG]:
339
391
 
340
392
  [source,bash]
341
393
  ----
@@ -358,8 +410,7 @@ To obtain your key, run the following and take the part after the forward slash:
358
410
  gpg --list-keys | grep pub
359
411
  ....
360
412
 
361
- Add your key to your global (or local) Git configuration and ensure GPG signing for your tag is
362
- enabled. Example:
413
+ Add your key to your global (or local) {git_link} configuration and ensure GPG signing for your tag is enabled. Example:
363
414
 
364
415
  ....
365
416
  [tag]
@@ -369,10 +420,8 @@ enabled. Example:
369
420
  ....
370
421
 
371
422
  Now, when publishing a new milestone (i.e. `milestoner --publish <version>`), the signing of your
372
- Git tag will happen automatically. You will be prompted for the GPG Passphrase each time unless you
373
- are running the
374
- link:https://gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html#Invoking-GPG_002dAGENT[GPG
375
- Agent] in the background (highly recommend).
423
+ {git_link} tag will happen automatically. You will be prompted for the GPG Passphrase each time unless you are running the
424
+ link:https://gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html#Invoking-GPG_002dAGENT[GPG Agent] in the background (highly recommend).
376
425
 
377
426
  == Development
378
427
 
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Milestoner
4
+ module Builders
5
+ # Builds Markdown page output.
6
+ class ASCIIDoc
7
+ include Milestoner::Import[:input]
8
+
9
+ using Refinements::Pathname
10
+
11
+ def initialize(view: Views::Milestones::Show.new, enricher: Commits::Enricher.new, **)
12
+ @view = view
13
+ @enricher = enricher
14
+ super(**)
15
+ end
16
+
17
+ def call at: Time.now.utc
18
+ input.build_root.join("index.adoc").make_ancestors.tap { |path| write path, at }
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :view, :enricher
24
+
25
+ def write path, at
26
+ enricher.call.fmap do |commits|
27
+ path.write view.call commits:, at:, layout: input.build_layout, format: :adoc
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -8,6 +8,8 @@ module Milestoner
8
8
  module Container
9
9
  extend Dry::Container::Mixin
10
10
 
11
+ register(:ascii_doc, memoize: true) { ASCIIDoc.new }
12
+ register(:markdown, memoize: true) { Markdown.new }
11
13
  register(:stream, memoize: true) { Stream.new }
12
14
  register(:web, memoize: true) { Web.new }
13
15
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Milestoner
4
+ module Builders
5
+ # Builds Markdown page output.
6
+ class Markdown
7
+ include Milestoner::Import[:input]
8
+
9
+ using Refinements::Pathname
10
+
11
+ def initialize(view: Views::Milestones::Show.new, enricher: Commits::Enricher.new, **)
12
+ @view = view
13
+ @enricher = enricher
14
+ super(**)
15
+ end
16
+
17
+ def call at: Time.now.utc
18
+ input.build_root.join("index.md").make_ancestors.tap { |path| write path, at }
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :view, :enricher
24
+
25
+ def write path, at
26
+ enricher.call.fmap do |commits|
27
+ path.write view.call commits:, at:, layout: input.build_layout, format: :md
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -12,7 +12,7 @@ module Milestoner
12
12
 
13
13
  description "Set output format."
14
14
 
15
- on %w[-f --format], argument: "[KIND]", allow: %w[stream web]
15
+ on %w[-f --format], argument: "[KIND]", allow: %w[ascii_doc markdown stream web]
16
16
 
17
17
  default { Container[:configuration].build_format }
18
18
 
@@ -16,7 +16,7 @@ module Milestoner
16
16
 
17
17
  on %w[-l --label], argument: "[TEXT]"
18
18
 
19
- default { Spek::Loader.call("#{Pathname.pwd.basename}.gemspec").label }
19
+ default { Container[:configuration].project_label }
20
20
 
21
21
  def call(label = nil) = input.project_label = label || default
22
22
  end
@@ -21,7 +21,7 @@ module Milestoner
21
21
 
22
22
  on %w[-v --version], argument: "[VERSION]"
23
23
 
24
- default { Commits::Versioner.new.call }
24
+ default { Container[:configuration].project_version }
25
25
 
26
26
  def call(version = nil) = input.project_version = Version(version || default)
27
27
  end
@@ -23,10 +23,7 @@ module Milestoner
23
23
 
24
24
  def success(user) = logger.info { "Deleted: #{user.name.inspect}." }
25
25
 
26
- def failure message
27
- logger.error { message }
28
- kernel.abort
29
- end
26
+ def failure(message) = logger.abort message
30
27
  end
31
28
  end
32
29
  end
@@ -23,10 +23,7 @@ module Milestoner
23
23
 
24
24
  def success(user) = kernel.puts user.to_h.values.join(", ")
25
25
 
26
- def failure message
27
- logger.error { message }
28
- kernel.abort
29
- end
26
+ def failure(message) = logger.abort message
30
27
  end
31
28
  end
32
29
  end
@@ -20,7 +20,7 @@ module Milestoner
20
20
 
21
21
  on %w[-p --publish], argument: "[VERSION]"
22
22
 
23
- default { Commits::Versioner.new.call }
23
+ default { Container[:configuration].project_version }
24
24
 
25
25
  def initialize(publisher: Tags::Publisher.new, **)
26
26
  super(**)
@@ -9,7 +9,7 @@ module Milestoner
9
9
  # Handles the building of milestone output.
10
10
  class Build < Sod::Command
11
11
  include Import[:input, :logger, :kernel]
12
- include Builders::Import[:stream, :web]
12
+ include Builders::Import[:ascii_doc, :markdown, :stream, :web]
13
13
 
14
14
  using Refinements::Pathname
15
15
 
@@ -23,15 +23,18 @@ module Milestoner
23
23
  on Actions::Build::Format
24
24
  on Actions::Build::Root
25
25
 
26
+ # :reek:TooManyStatements
26
27
  def call
27
28
  log_info "Building milestone..."
28
29
 
29
30
  format = input.build_format
30
31
 
31
32
  case format
33
+ when "ascii_doc" then build_ascii_doc
34
+ when "markdown" then build_markdown
32
35
  when "stream" then build_stream
33
36
  when "web" then build_web
34
- else log_error "Invalid build format: #{format}."
37
+ else logger.abort "Invalid build format: #{format}."
35
38
  end
36
39
  end
37
40
 
@@ -39,6 +42,10 @@ module Milestoner
39
42
 
40
43
  attr_reader :view, :enricher
41
44
 
45
+ def build_ascii_doc = log_info("Milestone built: #{ascii_doc.call}.")
46
+
47
+ def build_markdown = log_info("Milestone built: #{markdown.call}.")
48
+
42
49
  def build_stream
43
50
  kernel.puts
44
51
  stream.call
@@ -47,8 +54,6 @@ module Milestoner
47
54
  def build_web = log_info "Milestone built: #{web.call}."
48
55
 
49
56
  def log_info(message) = logger.info { message }
50
-
51
- def log_error(message) = logger.error { message }
52
57
  end
53
58
  end
54
59
  end
@@ -27,7 +27,6 @@ module Milestoner
27
27
  @categorizer = categorizer
28
28
  @model = model
29
29
  super(**)
30
- @commands = %i[author body collaborators format issue milestone notes review signers uri]
31
30
  end
32
31
 
33
32
  def call
@@ -38,12 +37,12 @@ module Milestoner
38
37
 
39
38
  private
40
39
 
41
- attr_reader :categorizer, :model, :commands
40
+ attr_reader :categorizer, :model
42
41
 
43
42
  def record_for(commit) = model.for(commit, **build_attributes(commit))
44
43
 
45
44
  def build_attributes commit
46
- commands.each.with_object({}) do |command, attributes|
45
+ infused_keys.each.with_object({}) do |command, attributes|
47
46
  attributes[command] = __send__(command).call commit
48
47
  end
49
48
  end
@@ -23,15 +23,16 @@ module Milestoner
23
23
  required(:commit_domain).filled :string
24
24
  required(:commit_format).filled :string
25
25
  required(:commit_uri).filled :string
26
+ required(:generator_label).filled :string
27
+ required(:generator_uri).filled :string
26
28
  required(:profile_domain).filled :string
27
29
  required(:profile_uri).filled :string
28
30
  required(:project_author).filled :string
29
- optional(:project_description).filled :string
30
- required(:project_generator).filled :string
31
+ optional(:project_description).maybe :string
31
32
  optional(:project_label).filled :string
32
33
  required(:project_name).filled :string
33
34
  optional(:project_owner).filled :string
34
- optional(:project_uri).filled :string
35
+ optional(:project_uri).maybe :string
35
36
  required(:project_version).filled Etcher::Types::Version
36
37
  required(:review_domain).filled :string
37
38
  required(:review_uri).filled :string
@@ -13,6 +13,8 @@ module Milestoner
13
13
  :commit_domain,
14
14
  :commit_format,
15
15
  :commit_uri,
16
+ :generator_label,
17
+ :generator_uri,
16
18
  :profile_domain,
17
19
  :profile_uri,
18
20
  :project_author,
@@ -20,10 +20,7 @@ module Milestoner
20
20
  @xdg_config = xdg_config
21
21
  end
22
22
 
23
- def call content
24
- content[key] = xdg_config.all.append default
25
- Success content
26
- end
23
+ def call(content) = Success content.merge!(key => xdg_config.all.append(default))
27
24
 
28
25
  private
29
26
 
@@ -3,6 +3,7 @@
3
3
  require "cff"
4
4
  require "dry/monads"
5
5
  require "pathname"
6
+ require "refinements/hash"
6
7
 
7
8
  module Milestoner
8
9
  module Configuration
@@ -12,6 +13,8 @@ module Milestoner
12
13
  class Description
13
14
  include Dry::Monads[:result]
14
15
 
16
+ using Refinements::Hash
17
+
15
18
  def initialize key = :project_description,
16
19
  path: Pathname.pwd.join("CITATION.cff"),
17
20
  citation: CFF::File
@@ -20,16 +23,15 @@ module Milestoner
20
23
  @citation = citation
21
24
  end
22
25
 
23
- def call(content) = Success process(content)
26
+ def call content
27
+ content.fetch_value(key) { citation.open(path).abstract }
28
+ .then { |value| value unless String(value).empty? }
29
+ .then { |value| Success content.merge!(key => value) }
30
+ end
24
31
 
25
32
  private
26
33
 
27
34
  attr_reader :key, :path, :citation
28
-
29
- def process content
30
- content.fetch(key) { citation.open(path).abstract }
31
- .then { |value| String(value).empty? ? content : content.merge!(key => value) }
32
- end
33
35
  end
34
36
  end
35
37
  end