milestoner 16.2.1 → 17.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -1
  3. data/README.adoc +333 -57
  4. data/lib/milestoner/builders/ascii_doc.rb +32 -0
  5. data/lib/milestoner/builders/container.rb +17 -0
  6. data/lib/milestoner/builders/import.rb +9 -0
  7. data/lib/milestoner/builders/markdown.rb +32 -0
  8. data/lib/milestoner/builders/stream.rb +29 -0
  9. data/lib/milestoner/builders/web.rb +41 -0
  10. data/lib/milestoner/cli/actions/build/format.rb +24 -0
  11. data/lib/milestoner/cli/actions/build/label.rb +26 -0
  12. data/lib/milestoner/cli/actions/build/layout.rb +36 -0
  13. data/lib/milestoner/cli/actions/build/root.rb +25 -0
  14. data/lib/milestoner/cli/actions/build/version.rb +31 -0
  15. data/lib/milestoner/cli/actions/cache/create.rb +35 -0
  16. data/lib/milestoner/cli/actions/cache/delete.rb +31 -0
  17. data/lib/milestoner/cli/actions/cache/find.rb +31 -0
  18. data/lib/milestoner/cli/actions/cache/info.rb +29 -0
  19. data/lib/milestoner/cli/actions/cache/list.rb +33 -0
  20. data/lib/milestoner/cli/actions/publish.rb +9 -5
  21. data/lib/milestoner/cli/commands/build.rb +60 -0
  22. data/lib/milestoner/cli/commands/cache.rb +27 -0
  23. data/lib/milestoner/cli/shell.rb +3 -2
  24. data/lib/milestoner/commits/categorizer.rb +21 -29
  25. data/lib/milestoner/commits/collector.rb +18 -0
  26. data/lib/milestoner/commits/enricher.rb +51 -0
  27. data/lib/milestoner/commits/enrichers/author.rb +26 -0
  28. data/lib/milestoner/commits/enrichers/body.rb +28 -0
  29. data/lib/milestoner/commits/enrichers/colleague.rb +33 -0
  30. data/lib/milestoner/commits/enrichers/container.rb +25 -0
  31. data/lib/milestoner/commits/enrichers/format.rb +23 -0
  32. data/lib/milestoner/commits/enrichers/import.rb +11 -0
  33. data/lib/milestoner/commits/enrichers/issue.rb +28 -0
  34. data/lib/milestoner/commits/enrichers/milestone.rb +24 -0
  35. data/lib/milestoner/commits/enrichers/note.rb +28 -0
  36. data/lib/milestoner/commits/enrichers/review.rb +23 -0
  37. data/lib/milestoner/commits/enrichers/uri.rb +14 -0
  38. data/lib/milestoner/commits/versioner.rb +48 -0
  39. data/lib/milestoner/configuration/contract.rb +30 -3
  40. data/lib/milestoner/configuration/defaults.yml +31 -8
  41. data/lib/milestoner/configuration/model.rb +26 -1
  42. data/lib/milestoner/configuration/transformers/build/root.rb +21 -0
  43. data/lib/milestoner/configuration/transformers/build/template_paths.rb +32 -0
  44. data/lib/milestoner/configuration/transformers/citations/description.rb +39 -0
  45. data/lib/milestoner/configuration/transformers/citations/label.rb +39 -0
  46. data/lib/milestoner/configuration/transformers/gems/description.rb +34 -0
  47. data/lib/milestoner/configuration/transformers/gems/label.rb +35 -0
  48. data/lib/milestoner/configuration/transformers/gems/name.rb +34 -0
  49. data/lib/milestoner/configuration/transformers/gems/uri.rb +35 -0
  50. data/lib/milestoner/configuration/transformers/generator/label.rb +31 -0
  51. data/lib/milestoner/configuration/transformers/generator/uri.rb +31 -0
  52. data/lib/milestoner/configuration/transformers/project/author.rb +34 -0
  53. data/lib/milestoner/configuration/transformers/project/generator.rb +35 -0
  54. data/lib/milestoner/configuration/transformers/project/label.rb +23 -0
  55. data/lib/milestoner/configuration/transformers/project/name.rb +21 -0
  56. data/lib/milestoner/configuration/transformers/project/version.rb +33 -0
  57. data/lib/milestoner/configuration/transformers/uri/avatar.rb +21 -0
  58. data/lib/milestoner/configuration/transformers/uri/commit.rb +24 -0
  59. data/lib/milestoner/configuration/transformers/uri/profile.rb +21 -0
  60. data/lib/milestoner/configuration/transformers/uri/review.rb +24 -0
  61. data/lib/milestoner/configuration/transformers/uri/tracker.rb +24 -0
  62. data/lib/milestoner/container.rb +52 -9
  63. data/lib/milestoner/models/commit.rb +42 -0
  64. data/lib/milestoner/models/link.rb +12 -0
  65. data/lib/milestoner/models/user.rb +12 -0
  66. data/lib/milestoner/renderers/asciidoc.rb +20 -0
  67. data/lib/milestoner/renderers/markdown.rb +20 -0
  68. data/lib/milestoner/renderers/universal.rb +26 -0
  69. data/lib/milestoner/tags/creator.rb +31 -23
  70. data/lib/milestoner/tags/publisher.rb +5 -5
  71. data/lib/milestoner/tags/pusher.rb +9 -3
  72. data/lib/milestoner/templates/layouts/page.adoc.erb +2 -0
  73. data/lib/milestoner/templates/layouts/page.html.erb +37 -0
  74. data/lib/milestoner/templates/layouts/page.md.erb +2 -0
  75. data/lib/milestoner/templates/layouts/page.stream.erb +2 -0
  76. data/lib/milestoner/templates/milestones/_avatar.html.erb +5 -0
  77. data/lib/milestoner/templates/milestones/_commit.adoc.erb +1 -0
  78. data/lib/milestoner/templates/milestones/_commit.html.erb +104 -0
  79. data/lib/milestoner/templates/milestones/_commit.md.erb +1 -0
  80. data/lib/milestoner/templates/milestones/_commit.stream.erb +1 -0
  81. data/lib/milestoner/templates/milestones/_icon.html.erb +6 -0
  82. data/lib/milestoner/templates/milestones/_profile.html.erb +5 -0
  83. data/lib/milestoner/templates/milestones/show.adoc.erb +9 -0
  84. data/lib/milestoner/templates/milestones/show.html.erb +46 -0
  85. data/lib/milestoner/templates/milestones/show.md.erb +9 -0
  86. data/lib/milestoner/templates/milestones/show.stream.erb +9 -0
  87. data/lib/milestoner/templates/public/page.css.erb +373 -0
  88. data/lib/milestoner/views/context.rb +27 -0
  89. data/lib/milestoner/views/milestones/show.rb +47 -0
  90. data/lib/milestoner/views/parts/commit.rb +85 -0
  91. data/lib/milestoner.rb +1 -1
  92. data/milestoner.gemspec +17 -11
  93. data.tar.gz.sig +0 -0
  94. metadata +182 -26
  95. metadata.gz.sig +1 -1
  96. data/lib/milestoner/cli/actions/status.rb +0 -37
  97. data/lib/milestoner/presenters/commit.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbe6e0c5b29d0f5ac3ecd7f5b33522568795e026507909af03c3cd086507cd66
4
- data.tar.gz: 2f8c2579f56cb5938f8ec0f354befea5e7599dfd0acba1ea7897fbadd5a356c6
3
+ metadata.gz: 2069b8a67bf9cf6a786fade18de6256506c610d44c73705f24803d758f606dac
4
+ data.tar.gz: 4f8001a067a33034cd76c378b4e9e6c95f450754354658bcbe3e51169f32bf05
5
5
  SHA512:
6
- metadata.gz: c98f61d7e94b8dd933d0c41f80bedb215ae389ed20fe89f03614f73fb9b5ca98fc2b58b3fea53edc77313d27b98cb61ed0ad8def52305794e83f69272dcc9fc8
7
- data.tar.gz: f8e0f4e2fb1810a9f472d5b4c706e6d28b18d5afffb509e2a766381e077098a74da869c9128322732814f5fa6d765d674319ce013a85d8f54ea1bc7a5c9de7d2
6
+ metadata.gz: aea11fff1c1b7d10e8910dafae3496b206f0df8be716ad0bb8fd708bf0eb70d3b29280d9b17373b5732c8af720bc4f81912e29584430dbd61959975f4a75c93f
7
+ data.tar.gz: cd130868800665f2fe370edb5cae1a4074672ed8f8743a1636baa74d4336f2681bf4af21efde43285408f836acf87ecd046d214a4f9edf1381957431ee1408c3
checksums.yaml.gz.sig CHANGED
@@ -1 +1,3 @@
1
- 3vl[+>�R���]���4y�7�@�:䉱�жU&�/M� <Q'`�ﲒd )�®=;!3�毜E��A����b��aA�P����$`�y;Vb��`�^��~� ��eR&�.}�~#,�u�8@�x
1
+ F
2
+ ��M)6x�h���v^��
3
+ UB #����]��$v��^ٝ: ����$�ɭ��
data/README.adoc CHANGED
@@ -2,40 +2,78 @@
2
2
  :toclevels: 5
3
3
  :figure-caption!:
4
4
 
5
+ :ascii_doc_link: link:https://asciidoctor.org/docs/what-is-asciidoc[ASCII Doc]
6
+ :cff_link: link:https://github.com/citation-file-format/ruby-cff[CFF]
7
+ :etcher_link: link:https://alchemists.io/projects/etcher[Etcher]
8
+ :gem_specification_link: link:https://guides.rubygems.org/specification-reference[Gem Specification]
9
+ :gemsmith_link: link:https://alchemists.io/projects/gemsmith[Gemsmith]
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]
12
+ :git_lint_link: link:https://alchemists.io/projects/git-lint[Git Lint]
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]
16
+ :lode_link: link:https://alchemists.io/projects/lode[Lode]
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]
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]
23
+ :string_formats_link: link:https://ruby-doc.org/3.3.0/format_specifications_rdoc.html[String Formats]
24
+ :versionaire_link: link:https://alchemists.io/projects/versionaire[Versionaire]
25
+ :xdg_link: link:https://alchemists.io/projects/xdg[XDG]
26
+
5
27
  = Milestoner
6
28
 
7
- Milestoner is a command line interface for crafting Git repository tags (milestones) using
8
- link:https://semver.org[semantic versions]. Each milestone is a summary of all commits made since
9
- the last milestone. You can use Milestoner to inspect what is currently pending or create a new
10
- release via a single command. By having a tool, like Milestoner, you can automate releases in a
11
- 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.
30
+
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:
12
34
 
13
- - link:https://alchemists.io/projects/git-lint[Git Lint] - Ensures your commit messages are of
14
- high quality which feed into the release notes built by Milestoner.
15
- - link:https://alchemists.io/projects/rubysmith[Rubysmith] - Use Milestoner to automate the
16
- publishing of new or existing Ruby project versions.
17
- - link:https://alchemists.io/projects/gemsmith[Gemsmith] - Is built on top of Milestoner and is
18
- used to publish new Ruby gem versions.
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.
19
39
 
20
40
  toc::[]
21
41
 
42
+ == Screenshots
43
+
44
+ *ASCII Doc Format* (i.e. `milestoner build --format ascii_doc`)
45
+
46
+ image:https://alchemists.io/images/projects/milestoner/screenshots/build-ascii_doc.png[Usage,width=787,height=257,role=focal_point]
47
+
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]
51
+
52
+ *Stream Format* (i.e. `milestoner build --format stream`)
53
+
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]
61
+
22
62
  == Features
23
63
 
24
- * Uses link:https://alchemists.io/projects/versionaire[Versionaire] for
25
- link:https://semver.org[Semantic Versioning].
64
+ * Uses {versionaire_link} for {strict_semantic_versioning_link}. Example:
26
65
  ** Format: `+<major>.<minor>.<patch>+`.
27
- ** Example: `+0.1.0+`.
28
- * Ensures Git commits since last tag (or initialization of repository) are included.
29
- * Ensures Git commit messages are grouped by prefix, in order defined. For more details, see
30
- link:https://alchemists.io/projects/git-lint/#_commit_subject_prefix[Git Lint Commit Subject
31
- Prefix] for details. Defaults (can be customized):
32
- ** Fixed
33
- ** Added
34
- ** Updated
35
- ** Removed
36
- ** Refactored
37
- * Ensures Git commit messages are alphabetically sorted.
38
- * Ensures duplicate Git commit messages are removed (if any).
66
+ ** Example: `0.0.0`.
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):
69
+ ** image:https://alchemists.io/images/projects/milestoner/icons/commits/fixed.png[Fixed] Fixed
70
+ ** image:https://alchemists.io/images/projects/milestoner/icons/commits/added.png[Added] Added
71
+ ** image:https://alchemists.io/images/projects/milestoner/icons/commits/updated.png[Updated] Updated
72
+ ** image:https://alchemists.io/images/projects/milestoner/icons/commits/removed.png[Removed] Removed
73
+ ** image:https://alchemists.io/images/projects/milestoner/icons/commits/refactored.png[Refactored] Refactored
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.
39
77
 
40
78
  == Requirements
41
79
 
@@ -67,7 +105,7 @@ gem install milestoner
67
105
 
68
106
  From the command line, type: `milestoner --help`
69
107
 
70
- image:https://alchemists.io/images/projects/milestoner/screenshots/usage.png[Usage,width=593,height=366,role=focal_point]
108
+ image:https://alchemists.io/images/projects/milestoner/screenshots/usage.png[Usage,width=690,height=398,role=focal_point]
71
109
 
72
110
  === Customization
73
111
 
@@ -77,38 +115,279 @@ This gem can be configured via a global configuration:
77
115
  ~/.config/milestoner/configuration.yml
78
116
  ....
79
117
 
80
- It can also be configured via https://alchemists.io/projects/xdg[XDG] environment variables.
118
+ It can also be configured via {xdg_link} environment variables.
81
119
 
82
- The default configuration is as follows:
120
+ The default configuration is:
83
121
 
84
122
  [source,yaml]
85
123
  ----
86
- documentation:
87
- format: "adoc"
88
- prefixes:
89
- - Fixed
90
- - Added
91
- - Updated
92
- - Removed
93
- - Refactored
94
- ----
95
-
96
- The `configuration.yml` file can be configured as follows:
97
-
98
- * *Documentation Format* (i.e. `documentation`): Determines what format the release notes should be
99
- rendered as. This effects both status information from the command line and the release notes
100
- embedded within the body of a Git tag. Defaults to
101
- link:https://asciidoctor.org/docs/what-is-asciidoc[ASCII Doc] (i.e. `adoc`) but
102
- link:https://daringfireball.net/projects/markdown[Markdown] (i.e. `md`) is supported too.
103
- * *Git Commit Prefixes* (i.e. `prefixes`): Should the default prefixes not be desired, you can
104
- define Git commit prefixes that match your style. _NOTE: Prefix order is important with the first
105
- prefix defined taking precedence over the second and so forth._ Special characters are allowed for
106
- prefixes but should be enclosed in quotes. To disable prefix usage completely, use an empty array.
107
- Example: `prefixes: []`.
124
+ avatar:
125
+ domain: https://avatars.githubusercontent.com
126
+ uri: "%<domain>s/u/%<id>s"
127
+ build:
128
+ format: web
129
+ layout: page
130
+ root: tmp/milestone
131
+ commit:
132
+ categories:
133
+ - emoji: ✅
134
+ label: Fixed
135
+ - emoji: 🟢
136
+ label: Added
137
+ - emoji: 🔼
138
+ label: Updated
139
+ - emoji: ⛔️
140
+ label: Removed
141
+ - emoji: 🔁
142
+ label: Refactored
143
+ domain: https://github.com
144
+ format: asciidoc
145
+ uri: "%<domain>s/%<owner>s/%<name>s/commit/%<id>s"
146
+ generator:
147
+ label:
148
+ uri:
149
+ profile:
150
+ domain: https://github.com
151
+ uri: "%<domain>s/%<id>s"
152
+ project:
153
+ author:
154
+ description:
155
+ generator:
156
+ label:
157
+ name:
158
+ owner:
159
+ uri:
160
+ version:
161
+ review:
162
+ domain: https://github.com
163
+ uri: "%<domain>s/%<owner>s/%<name>s/pulls/%<id>s"
164
+ tracker:
165
+ domain: https://github.com
166
+ uri: "%<domain>s/%<owner>s/%<name>s/issues/%<id>s"
167
+ ----
168
+
169
+ The above can be customized as follows:
170
+
171
+ * `avatar`: Manages team member avatar information.
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.
174
+ * `build`: Manages release note builds.
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.
178
+ * `commit`: Manages commit categories, emojis, and hyperlinks.
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.
188
+ * `profile`: Manages team member profile information.
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.
191
+ * `project`: Manages project information.
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.
200
+ * `review`: Manages code review information.
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}.
206
+
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.
208
+
209
+ === Config
210
+
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.
214
+
215
+ === Cache
216
+
217
+ image:https://alchemists.io/images/projects/milestoner/screenshots/usage-cache.png[Usage,width=625,height=318,role=focal_point]
218
+
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.
220
+
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:
222
+
223
+ [source,bash]
224
+ ----
225
+ milestoner cache --list
226
+ # 🟢 Listing users...
227
+ # 🟢 No users found.
228
+
229
+ milestoner cache --create "111,jsmith,Jane Smith"
230
+ # 🟢 Created: "Jane Smith"
231
+
232
+ milestoner cache --create "222,jdoe,John Doe"
233
+ # 🟢 Created: "John Doe"
234
+
235
+ milestoner cache --create "333,jgrey,Jill Grey"
236
+ # 🟢 Created: "Jill Grey"
237
+
238
+ milestoner cache --list
239
+ # 🟢 Listing users...
240
+ # 111, jsmith, Jane Smith
241
+ # 222, jdoe, John Doe
242
+ # 333, jgrey, Jill Grey
243
+
244
+ milestoner cache --delete "Jill Grey"
245
+ 🟢 Deleted: "Jill Grey".
246
+
247
+ milestoner cache --list
248
+ # 🟢 Listing users...
249
+ # 111, jsmith, Jane Smith
250
+ # 222, jdoe, John Doe
251
+
252
+ milestoner cache --info
253
+ # 🟢 Path: /Users/demo/.cache/milestoner/database.store.
254
+ ----
255
+
256
+ 💡 Use `+https://api.github.com/users/<handle>+` to acquire the external ID for any GitHub user.
257
+
258
+ Once team member information is stored in your cache, you'll be able to build release notes which automatically link to GitHub user information without constantly hitting the GitHub API. _Users are identified by name so the full author name used for each commit message needs to match the same user name as stored in your source repository hosting service._
259
+
260
+ === Build
261
+
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:
265
+
266
+ [source,bash]
267
+ ----
268
+ milestoner build --format web
269
+ # 🟢 Building milestone...
270
+ # 🟢 Milestone built: /Users/bkuhlmann/Engineering/OSS/milestoner/tmp/milestone
271
+ ----
272
+
273
+ 💡 The above command is so useful that I use the following `msb` (i.e. Milestoner Build) Bash alias: `rm -rf tmp/milestone && milestoner build --format html && open tmp/milestone/index.html`. This allows me to quickly rebuild release notes for any project and immediately view them in my default browser.
274
+
275
+ Check out the help documentation (i.e. `milestoner build --help`) for addition usage that explains what command line options you can use to overwrite the current configuration.
276
+
277
+ ==== Automatic Versioning
278
+
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:
280
+
281
+ [source,bash]
282
+ ----
283
+ milestoner build --help
284
+ ----
285
+
286
+ Running the above will dynamically show you latest version information -- along with help documentation -- in case you have doubts. You can use this as a status check as well. If you don't want to use the automatic version, you can override by using the `--version` option when building. Example:
287
+
288
+ [source,bash]
289
+ ----
290
+ # Uses automatic version.
291
+ milestoner build --format stream
292
+
293
+ # Uses manual version.
294
+ milestoner build --format stream --version 1.2.3
295
+ ----
296
+
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:
298
+
299
+ ....
300
+ # First commit.
301
+ Milestone: patch
302
+
303
+ # Second commit.
304
+ Milestone: minor
305
+
306
+ # Third commit
307
+ Milestone: patch
308
+ ....
309
+
310
+ Given the above, the resulting version would be: 1.1.0. This is because the highest milestone was a _minor_ milestone. The highest milestone wins and doesn't matter how many commits you made with the same milestone trailer information or the order in which the commits were made. Here's another example:
311
+
312
+ ....
313
+ # First commit.
314
+ Milestone: patch
315
+
316
+ # Second commit.
317
+ Milestone: patch
318
+
319
+ # Third commit
320
+ Milestone: patch
321
+ ....
322
+
323
+ Given the above, the resulting version would be: 1.0.1. This is because the highest milestone was a _patch_. Here's a final example:
324
+
325
+ ....
326
+ # First commit.
327
+ Milestone: major
328
+
329
+ # Second commit.
330
+ Milestone: minor
331
+
332
+ # Third commit
333
+ Milestone: patch
334
+ ....
335
+
336
+ Given the above, the resulting version would be: 2.0.0. This is because the highest milestone was a _major_ milestone.
337
+
338
+ ==== Templates
339
+
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:
341
+
342
+ ....
343
+ lib/milestoner/templates
344
+ ├── layouts
345
+ │ ├── page.adoc.erb
346
+ │ ├── page.html.erb
347
+ │ ├── page.md.erb
348
+ │ └── page.stream.erb
349
+ ├── milestones
350
+ │ ├── _avatar.html.erb
351
+ │ ├── _commit.adoc.erb
352
+ │ ├── _commit.html.erb
353
+ │ ├── _commit.md.erb
354
+ │ ├── _commit.stream.erb
355
+ │ ├── _icon.html.erb
356
+ │ ├── _profile.html.erb
357
+ │ ├── show.adoc.erb
358
+ │ ├── show.html.erb
359
+ │ ├── show.md.erb
360
+ │ └── show.stream.erb
361
+ └── public
362
+ └── page.css.erb
363
+ ....
364
+
365
+ This means you could, for example, copy all of this gem's templates to your own {runcom_link} configuration to customize how you like. Example:
366
+
367
+ [source,bash]
368
+ ----
369
+ cp -r <milestoner_gem_root>/lib/milestoner/templates $HOME/.config/milestoner/templates
370
+ ----
371
+
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.
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.
108
387
 
109
388
  == Security
110
389
 
111
- 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]:
112
391
 
113
392
  [source,bash]
114
393
  ----
@@ -131,8 +410,7 @@ To obtain your key, run the following and take the part after the forward slash:
131
410
  gpg --list-keys | grep pub
132
411
  ....
133
412
 
134
- Add your key to your global (or local) Git configuration and ensure GPG signing for your tag is
135
- enabled. Example:
413
+ Add your key to your global (or local) {git_link} configuration and ensure GPG signing for your tag is enabled. Example:
136
414
 
137
415
  ....
138
416
  [tag]
@@ -142,10 +420,8 @@ enabled. Example:
142
420
  ....
143
421
 
144
422
  Now, when publishing a new milestone (i.e. `milestoner --publish <version>`), the signing of your
145
- Git tag will happen automatically. You will be prompted for the GPG Passphrase each time unless you
146
- are running the
147
- link:https://gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html#Invoking-GPG_002dAGENT[GPG
148
- 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).
149
425
 
150
426
  == Development
151
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
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-container"
4
+
5
+ module Milestoner
6
+ module Builders
7
+ # Registers all builders for injection.
8
+ module Container
9
+ extend Dry::Container::Mixin
10
+
11
+ register(:ascii_doc, memoize: true) { ASCIIDoc.new }
12
+ register(:markdown, memoize: true) { Markdown.new }
13
+ register(:stream, memoize: true) { Stream.new }
14
+ register(:web, memoize: true) { Web.new }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "infusible"
4
+
5
+ module Milestoner
6
+ module Builders
7
+ Import = Infusible.with Container
8
+ end
9
+ 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
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Milestoner
4
+ module Builders
5
+ # Builds I/O stream output.
6
+ class Stream
7
+ include Milestoner::Import[:input, :kernel]
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
18
+ enricher.call.fmap do |commits|
19
+ kernel.puts view.call(commits:, layout: input.build_layout, format: :stream).to_s
20
+ kernel
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :view, :enricher
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Milestoner
4
+ module Builders
5
+ # Builds web page output (i.e. HTML and CSS).
6
+ class Web
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
18
+ input.build_root.tap do |path|
19
+ stylesheet_path.copy path.make_path.join("page.css")
20
+ write path
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :view, :enricher
27
+
28
+ def stylesheet_path
29
+ input.build_template_paths
30
+ .map { |path| path.join "public/page.css.erb" }
31
+ .find(&:exist?)
32
+ end
33
+
34
+ def write path
35
+ enricher.call.fmap do |commits|
36
+ path.join("index.html").write view.call commits:, layout: input.build_layout
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sod"
4
+
5
+ module Milestoner
6
+ module CLI
7
+ module Actions
8
+ module Build
9
+ # Handles build output format.
10
+ class Format < Sod::Action
11
+ include Import[:input]
12
+
13
+ description "Set output format."
14
+
15
+ on %w[-f --format], argument: "[KIND]", allow: %w[ascii_doc markdown stream web]
16
+
17
+ default { Container[:configuration].build_format }
18
+
19
+ def call(kind = nil) = input.build_format = kind || default
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end