releasehx 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +4 -2
  3. data/build/docs/_config.yml +17 -1
  4. data/build/docs/_release_index.adoc +9 -0
  5. data/build/docs/config-reference.adoc +6 -6
  6. data/build/docs/config-reference.json +4 -3
  7. data/build/docs/index.adoc +3 -2
  8. data/build/docs/landing.adoc +10 -3
  9. data/build/docs/releases.adoc +28 -0
  10. data/build/docs/sample-config.adoc +2 -0
  11. data/build/docs/sample-config.yml +2 -2
  12. data/lib/releasehx/cli.rb +16 -7
  13. data/lib/releasehx/generated.rb +1 -1
  14. data/lib/releasehx/mcp/assets/config-def.yml +4 -2
  15. data/lib/releasehx/mcp/assets/config-reference.adoc +6 -6
  16. data/lib/releasehx/mcp/assets/config-reference.json +4 -3
  17. data/lib/releasehx/mcp/assets/sample-config.yml +2 -2
  18. data/lib/releasehx/rhyml/adapter.rb +13 -6
  19. data/lib/releasehx/rhyml/mappings/github.yaml +3 -1
  20. data/lib/releasehx/rhyml/templates/changelog.adoc.liquid +14 -0
  21. data/lib/releasehx/rhyml/templates/changelog.html.liquid +14 -0
  22. data/lib/releasehx/rhyml/templates/changelog.md.liquid +11 -0
  23. data/lib/releasehx/rhyml/templates/changes-sorter.liquid +64 -0
  24. data/lib/releasehx/rhyml/templates/config-cascade.liquid +61 -0
  25. data/lib/releasehx/rhyml/templates/entry.adoc.liquid +22 -0
  26. data/lib/releasehx/rhyml/templates/entry.html.liquid +38 -0
  27. data/lib/releasehx/rhyml/templates/entry.md.liquid +24 -0
  28. data/lib/releasehx/rhyml/templates/groupby.liquid +12 -0
  29. data/lib/releasehx/rhyml/templates/groupings.liquid +97 -0
  30. data/lib/releasehx/rhyml/templates/groups-parser.liquid +60 -0
  31. data/lib/releasehx/rhyml/templates/head-parser.liquid +34 -0
  32. data/lib/releasehx/rhyml/templates/header.liquid +17 -0
  33. data/lib/releasehx/rhyml/templates/history.adoc.liquid +11 -0
  34. data/lib/releasehx/rhyml/templates/history.html.liquid +54 -0
  35. data/lib/releasehx/rhyml/templates/history.md.liquid +16 -0
  36. data/lib/releasehx/rhyml/templates/item.liquid +35 -0
  37. data/lib/releasehx/rhyml/templates/metadata-entry.adoc.liquid +45 -0
  38. data/lib/releasehx/rhyml/templates/metadata-entry.html.liquid +2 -0
  39. data/lib/releasehx/rhyml/templates/metadata-entry.md.liquid +130 -0
  40. data/lib/releasehx/rhyml/templates/metadata-note.adoc.liquid +45 -0
  41. data/lib/releasehx/rhyml/templates/metadata-note.html.liquid +36 -0
  42. data/lib/releasehx/rhyml/templates/metadata-note.md.liquid +30 -0
  43. data/lib/releasehx/rhyml/templates/note.adoc.liquid +14 -0
  44. data/lib/releasehx/rhyml/templates/note.html.liquid +25 -0
  45. data/lib/releasehx/rhyml/templates/note.md.liquid +33 -0
  46. data/lib/releasehx/rhyml/templates/parts-listing.liquid +61 -0
  47. data/lib/releasehx/rhyml/templates/release-notes.adoc.liquid +14 -0
  48. data/lib/releasehx/rhyml/templates/release-notes.html.liquid +14 -0
  49. data/lib/releasehx/rhyml/templates/release-notes.md.liquid +14 -0
  50. data/lib/releasehx/rhyml/templates/release.adoc.liquid +16 -0
  51. data/lib/releasehx/rhyml/templates/release.html.liquid +20 -0
  52. data/lib/releasehx/rhyml/templates/release.md.liquid +20 -0
  53. data/lib/releasehx/rhyml/templates/rhyml-change-append.yaml.liquid +7 -0
  54. data/lib/releasehx/rhyml/templates/rhyml-change.yaml.liquid +40 -0
  55. data/lib/releasehx/rhyml/templates/rhyml.yaml.liquid +14 -0
  56. data/lib/releasehx/rhyml/templates/section-text.liquid +9 -0
  57. data/lib/releasehx/rhyml/templates/sections.liquid +47 -0
  58. data/lib/releasehx/rhyml/templates/tags-listing.liquid +61 -0
  59. data/lib/schemagraphy/regexp_utils.rb +21 -1
  60. data/specs/data/config-def.yml +4 -2
  61. metadata +42 -2
  62. data/build/docs/Gemfile.lock +0 -95
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36a63bdf0f36ba445d5fa83993aa354dcf3ded8d562bec625ddaf07dd94b4967
4
- data.tar.gz: c10c4bf04cbe1c7654f552b2c01ee8304db375d8eb4cade74cd5534e9d152b4e
3
+ metadata.gz: b1a5f031876899a54910d8cf53694c15fc56f7ded648e2f30e0da4321bac0489
4
+ data.tar.gz: f2d8c4c2e09bb013844aa1915456c1d30dd7e6499ab546c86ade44ba34fce037
5
5
  SHA512:
6
- metadata.gz: ce79b848b9cd3cd72cf27b54aa6ab0351f3b1c921d5399ac0b9bceeaed7abcbf75ae0eff7a937edbc5d097bf4e2097ec221e96cba0ce379d4f79b03fbdc2787e
7
- data.tar.gz: 35d211eedd404ff1b41f4f6884eb558a41ea91ebf98ecdf3ec76db668f567c845134cdb2882d37b9bf587f95dd11df0299214404723c2697e76ed18bade406ec
6
+ metadata.gz: 3041a79a2f37e0277710ff11f66b46e2afb82a9c54e667719fc8f8ecb17a5f9902d43123d6fdadddb9aae39323d1d6c38e89f2544058460ae542382c3c8c2a6e
7
+ data.tar.gz: ede775257fe7a1661dc8f37b2a7f5211cb99400c6926e662fcb8b4f83abee82d83cff74ad2ccdd423a5a4079e84d26925786589e4777b8561229a73c8a6f6b21
data/README.adoc CHANGED
@@ -1,5 +1,6 @@
1
1
  :page-layout: default
2
- :page-permalink: /docs
2
+ :page-permalink: /docs/
3
+ :page-title: ReleaseHx Docs
3
4
  :page-nav_order: 1
4
5
  [[releasehx]]
5
6
  = ReleaseHx
@@ -15,7 +16,7 @@
15
16
  :this_prod_vrsn_major: 0
16
17
  :this_prod_vrsn_minor: 1
17
18
  :this_prod_vrsn_major-minor: {this_prod_vrsn_major}.{this_prod_vrsn_minor}
18
- :this_prod_vrsn_patch: 0
19
+ :this_prod_vrsn_patch: 2
19
20
  :this_prod_vrsn: {this_prod_vrsn_major-minor}.{this_prod_vrsn_patch}
20
21
  :next_prod_vrsn: 0.2.0
21
22
  :tagline: Generate formatted release histories from Jira, GitHub, GitLab, YAML, or JSON sources.
@@ -2475,6 +2476,7 @@ Use `PORT=NNNN` environment argument to specify a different port.
2475
2476
  [.prompt]
2476
2477
  PORT=4000 bundle exec rake serve
2477
2478
 
2479
+ [[docopslab-devtool]]
2478
2480
  ==== DocOps Lab Devtool (`docopslab-dev`)
2479
2481
 
2480
2482
  Special dev Rake tasks and libraries are available via the `docopslab-dev` gem.
@@ -4,12 +4,24 @@ baseurl: /
4
4
 
5
5
  plugins:
6
6
  - jekyll-asciidoc
7
+ - jekyll-redirect-from
8
+
9
+ collections:
10
+ releases:
11
+ output: true
12
+ permalink: /docs/releases/:name/
7
13
 
8
14
  defaults:
9
15
  - scope:
10
- path: "api"
16
+ path: "docs/api"
11
17
  values:
12
18
  render_with_liquid: false
19
+ - scope:
20
+ path: ""
21
+ type: "releases"
22
+ values:
23
+ layout: default
24
+ nav_exclude: true
13
25
 
14
26
  include:
15
27
  - index.adoc
@@ -17,6 +29,10 @@ include:
17
29
 
18
30
  exclude:
19
31
  - manpage.adoc
32
+ - jekyll/
33
+ - payloads/
34
+ - release/
35
+ - yard/
20
36
 
21
37
  # Enable Rouge for syntax highlighting in AsciiDoc blocks
22
38
  asciidoctor:
@@ -0,0 +1,9 @@
1
+ == Available Releases
2
+
3
+ Each release includes detailed notes about new features, improvements, bug fixes, and breaking changes.
4
+
5
+ * link:../release/0.1.2.html[0.1.2] - 2026-01-29
6
+
7
+ == Latest Release
8
+
9
+ include::release/0.1.2.adoc[leveloffset=+1]
@@ -1,7 +1,4 @@
1
- :page-layout: default
2
- :page-permalink: /config-reference/
3
- :page-nav_order: 2
4
- :page-title: Configuration Reference
1
+
5
2
 
6
3
  [[conf_ppty_DOLLARSIGN_meta,config.$meta]]
7
4
  $meta::
@@ -359,6 +356,9 @@ Defaults to `issue_body` for GitHub and GitLab, but to `custom_field` for Jira.
359
356
 
360
357
  [horizontal]
361
358
  type;; String
359
+ default;;
360
+ +
361
+ `+++issue_body+++`
362
362
  path;; `xref:conf_ppty_conversions_note[config.conversions.note]`
363
363
  --
364
364
 
@@ -395,7 +395,7 @@ type;; RegExp
395
395
  default;;
396
396
  +
397
397
  ....
398
- /^((#|=)+ (Draft )?Release Note.*)|(<!-- (draft )?release note -->)\n(?<note>\w(.|\n)+)/gmi
398
+ /^(((#|=)+ (Draft )?Release Note.*?)|(<!-- (draft )?release note -->))\n+(?<note>(.| )+)/gmi
399
399
  ....
400
400
  path;; `xref:conf_ppty_conversions_note_pattern[config.conversions.note_pattern]`
401
401
  --
@@ -3161,7 +3161,7 @@ This value will apply either when <<conf_ppty_rhyml_max_parts>> is set to `1` or
3161
3161
  type;; String
3162
3162
  default;;
3163
3163
  +
3164
- `+++Part+++`
3164
+ `+++Component+++`
3165
3165
  path;; `xref:conf_ppty_history_labeling_part_label[config.history.labeling.part_label]`
3166
3166
  --
3167
3167
 
@@ -129,7 +129,8 @@
129
129
  "note": {
130
130
  "path": "conversions.note",
131
131
  "desc": "The source of the release notes content.\nMust be `issue_body`, `custom_field`, or `commit_message`.\n\nDefaults to `issue_body` for GitHub and GitLab, but to `custom_field` for Jira.\n",
132
- "type": "String"
132
+ "type": "String",
133
+ "default": "issue_body"
133
134
  },
134
135
  "note_custom_field": {
135
136
  "path": "conversions.note_custom_field",
@@ -140,7 +141,7 @@
140
141
  "path": "conversions.note_pattern",
141
142
  "desc": "The Regular Expressions pattern to match in the body of an issue or commit message, after which all content is considered the release `note` matter.\n\nDefaults to a Markdown or AsciiDoc header or HTML comment with the case-insensitive string `release note` in it.\n\nUses Capture group `note` in the Regular Expression to establish the entire note content.\n\nSee the `conversions.head_pattern` property for details on extracting a heading (`head` in RHYML) from the `note` content.\n",
142
143
  "type": "RegExp",
143
- "default": "/^((#|=)+ (Draft )?Release Note.*)|(<!-- (draft )?release note -->)\\n(?<note>\\w(.|\\n)+)/gmi"
144
+ "default": "/^(((#|=)+ (Draft )?Release Note.*?)|(<!-- (draft )?release note -->))\\n+(?<note>(.| )+)/gmi"
144
145
  },
145
146
  "head_pattern": {
146
147
  "path": "conversions.head_pattern",
@@ -1228,7 +1229,7 @@
1228
1229
  "path": "history.labeling.part_label",
1229
1230
  "desc": "The label to use for the _singular_ part/component affected by the change, when only one part is permitted.\n\nThis value will apply either when <<conf_ppty_rhyml_max_parts>> is set to `1` or when the change has only one part _and_ <<conf_ppty_history_labeling_singularize_labels>> is `true`.\n",
1230
1231
  "type": "String",
1231
- "default": "Part"
1232
+ "default": "Component"
1232
1233
  },
1233
1234
  "parts_icon": {
1234
1235
  "path": "history.labeling.parts_icon",
@@ -1,5 +1,6 @@
1
1
  :page-layout: default
2
- :page-permalink: /docs
2
+ :page-permalink: /docs/
3
+ :page-title: ReleaseHx Docs
3
4
  :page-nav_order: 1
4
5
  [[releasehx]]
5
6
  = ReleaseHx
@@ -15,7 +16,7 @@
15
16
  :this_prod_vrsn_major: 0
16
17
  :this_prod_vrsn_minor: 1
17
18
  :this_prod_vrsn_major-minor: {this_prod_vrsn_major}.{this_prod_vrsn_minor}
18
- :this_prod_vrsn_patch: 0
19
+ :this_prod_vrsn_patch: 2
19
20
  :this_prod_vrsn: {this_prod_vrsn_major-minor}.{this_prod_vrsn_patch}
20
21
  :next_prod_vrsn: 0.2.0
21
22
  :tagline: Generate formatted release histories from Jira, GitHub, GitLab, YAML, or JSON sources.
@@ -1,6 +1,7 @@
1
1
  :page-permalink: /
2
2
  :page-layout: minimal
3
3
  :page-liquid: true
4
+ :page-nav_exclude: true
4
5
  = ReleaseHx
5
6
 
6
7
  ++++
@@ -10,9 +11,15 @@
10
11
  <h1 class="title">
11
12
  ReleaseHx
12
13
  </h1>
13
- <h2 class="subtitle">
14
- {{ site.tagline }}
15
- </h2>
14
+ <nav class="top-nav">
15
+ <a href="/docs/" class="button is-primary is-medium">
16
+ Documentation
17
+ </a>
18
+ &nbsp;|&nbsp;
19
+ <a href="/docs/releases/" class="button is-link is-medium">
20
+ Releases
21
+ </a>
22
+ </nav>
16
23
  </div>
17
24
  </div>
18
25
  </div>
@@ -0,0 +1,28 @@
1
+ ---
2
+ layout: default
3
+ title: Releases
4
+ nav_order: 90
5
+ permalink: /docs/releases/
6
+ ---
7
+ = Release History
8
+ :page-layout: default
9
+ :page-title: Releases
10
+ :page-nav_order: 90
11
+ :page-permalink: /docs/releases/
12
+
13
+ Complete release history for ReleaseHx, generated using ReleaseHx itself.
14
+
15
+ ifdef::env-site[]
16
+ // Generated during prebuild - includes release index and content
17
+ include::_release_index.adoc[]
18
+ endif::[]
19
+
20
+ ifndef::env-site[]
21
+ == Development Mode
22
+
23
+ Release history is generated during the prebuild process. Run `bundle exec rake prebuild` to generate the full release index.
24
+ endif::[]
25
+
26
+ ---
27
+
28
+ For more information about ReleaseHx, see the link:/docs/[main documentation].
@@ -1,4 +1,6 @@
1
1
  :page-nav_order: 3
2
+ :page-permalink: /docs/sample-config/
3
+ :page-redirect_from: /sample-config.html
2
4
  = Sample Configuration File
3
5
 
4
6
  This is a "`kitchen sink`" example of the ReleaseHx configuration settings.
@@ -22,7 +22,7 @@ origin: # The API or file source for the issues.
22
22
  conversions: # Details about content origination, as well as markup sources and conversion.
23
23
  summ: issue # The source of the summary (Changelog) content.
24
24
  # head: # The source of release-note headlines, when it is not the same as the summary.
25
- # note: # The source of the release notes content.
25
+ note: issue_body # The source of the release notes content.
26
26
  # note_custom_field: # The name of the custom field to use for the release notes content.Liquid error: wrong number of arguments (given 3, expected 1..2)Liquid error: wrong number of arguments (given 3, expected 1..2)
27
27
  markup: markdown # The origin markup format for notes.
28
28
  # engine: # The markup converter to use for the issues.
@@ -195,7 +195,7 @@ history: # Configurations for the overall document, when applicable.Liquid error
195
195
  type_label: type # The label to use for the type of change.
196
196
  # type_icon: # The icon to use for the type of change.
197
197
  parts_label: Components # The label to use for the part/component affected by the change.
198
- part_label: Part # The label to use for the singular part/component affected by the change, when only one part is permitted.
198
+ part_label: Component # The label to use for the singular part/component affected by the change, when only one part is permitted.
199
199
  parts_icon: puzzle-piece # The icon to use for the part/component affected by the change.
200
200
  tags_label: # The tags associated with the change, if any.
201
201
  - Tags
data/lib/releasehx/cli.rb CHANGED
@@ -688,23 +688,32 @@ module ReleaseHx
688
688
  end
689
689
 
690
690
  def create_rhyml_from_source source_path, version
691
- # Determine source type from configuration, not just file extension
692
- configured_source_type = @settings.dig('origin', 'source') || 'json'
693
-
694
- # Handle different source types based on configuration
695
- case configured_source_type
696
- when 'rhyml'
691
+ # First check if source_path is actually a file (overrides config)
692
+ if version_or_file(source_path) == :file && File.exist?(source_path)
697
693
  # Load RHYML data directly from YAML file
694
+ ReleaseHx.logger.debug "Loading RHYML from file: #{source_path}" if options[:verbose]
698
695
  rhyml_data = SchemaGraphy::Loader.load_yaml_with_tags(source_path)
699
696
  release_data = rhyml_data['releases'] ? rhyml_data['releases'].first : rhyml_data
700
697
 
701
698
  # Convert hash keys to keyword arguments for Release constructor
702
- ReleaseHx::RHYML::Release.new(
699
+ return ReleaseHx::RHYML::Release.new(
703
700
  code: release_data['code'] || version,
704
701
  date: release_data['date'],
705
702
  hash: release_data['hash'],
706
703
  memo: release_data['memo'],
707
704
  changes: release_data['changes'] || [])
705
+ end
706
+
707
+ # Determine source type from configuration
708
+ configured_source_type = @settings.dig('origin', 'source') || 'json'
709
+
710
+ # Handle different source types based on configuration
711
+ case configured_source_type
712
+ when 'rhyml'
713
+ # Config says rhyml but source_path is not a file - error
714
+ raise Thor::Error,
715
+ "ERROR: origin.source is 'rhyml' but no YAML file provided. " \
716
+ 'Specify a YAML file path as the first argument.'
708
717
  when 'json'
709
718
  # For json type, only use local files (never API calls)
710
719
  if options[:api_data]
@@ -2,7 +2,7 @@
2
2
  # Auto-generated by Sourcerer::Builder
3
3
 
4
4
  module ReleaseHx
5
- ATTRIBUTES = {:globals=>{"attribute-undefined"=>"drop-line", "attribute-missing"=>"skip", "appendix-caption"=>"Appendix", "appendix-refsig"=>"Appendix", "caution-caption"=>"Caution", "chapter-refsig"=>"Chapter", "example-caption"=>"Example", "figure-caption"=>"Figure", "important-caption"=>"Important", "last-update-label"=>"Last updated", "note-caption"=>"Note", "part-refsig"=>"Part", "prewrap"=>"", "sectids"=>"", "section-refsig"=>"Section", "table-caption"=>"Table", "tip-caption"=>"Tip", "toc-placement"=>"macro", "toc-title"=>"Table of Contents", "untitled-label"=>"Untitled", "version-label"=>"Version", "warning-caption"=>"Warning", "notitle"=>"", "docfile"=>"/home/brian/Documents/work/releasehx/README.adoc", "docdir"=>"/home/brian/Documents/work/releasehx", "docfilesuffix"=>".adoc", "docname"=>"README", "embedded"=>"", "asciidoctor"=>"", "asciidoctor-version"=>"2.0.23", "safe-mode-name"=>"unsafe", "safe-mode-unsafe"=>"", "safe-mode-level"=>0, "max-include-depth"=>64, "user-home"=>"/home/brian", "doctype"=>"article", "htmlsyntax"=>"html", "backend-html5-doctype-article"=>"", "doctype-article"=>"", "backend-html5"=>"", "backend"=>"html5", "outfilesuffix"=>".html", "filetype"=>"html", "filetype-html"=>"", "basebackend-html-doctype-article"=>"", "basebackend-html"=>"", "basebackend"=>"html", "stylesdir"=>".", "iconsdir"=>"./images/icons", "localdate"=>"2026-01-01", "localyear"=>"2026", "localtime"=>"13:06:29 -0500", "localdatetime"=>"2026-01-01 13:06:29 -0500", "docdate"=>"2026-01-01", "docyear"=>"2026", "doctime"=>"04:37:26 -0500", "docdatetime"=>"2026-01-01 04:37:26 -0500", "page-layout"=>"default", "page-permalink"=>"/docs", "page-nav_order"=>"1", "doctitle"=>"ReleaseHx", "docopslab_git_www"=>"https://github.com/DocOps", "this_prod_slug"=>"releasehx", "releasehx_prod_repo"=>"https://github.com/DocOps/releasehx", "releasehx_demo_repo"=>"https://github.com/DocOps/releasehx-demo", "this_prod_repo"=>"https://github.com/DocOps/releasehx", "this_prod_vrsn_major"=>"0", "this_prod_vrsn_minor"=>"1", "this_prod_vrsn_major-minor"=>"0.1", "this_prod_vrsn_patch"=>"0", "this_prod_vrsn"=>"0.1.0", "next_prod_vrsn"=>"0.2.0", "tagline"=>"Generate formatted release histories from Jira, GitHub, GitLab, YAML, or JSON sources.", "description"=>"CLI utility and Ruby API for generating structured release notes and changelog documents from various issue-tracking platforms or YAML definitions into plaintext drafts (<strong>AsciiDoc</strong>, <strong>Markdown</strong>, <strong>YAML</strong>) and rich-text output (<strong>HTML</strong> and <strong>PDF</strong>).", "gem_config_definition_path"=>"./specs/data/config-def.yml", "app_default_config_path"=>"./.releasehx.yml", "default_markup"=>"markdown", "default_slug_type"=>"kebab", "default_tplt_lang"=>"liquid", "default_drafts_dir"=>"_drafts", "default_enrich_dir"=>"_publish", "default_output_dir"=>".", "default_payloads_dir"=>"_payloads", "default_templates_dir"=>"_templates", "default_mappings_dir"=>"_mappings", "default_api_clients_dir"=>"_apis", "default_cache_dir"=>".releasehx/cache", "default_api_cred_env"=>"RELEASEHX_API_CRED", "default_api_key_env"=>"RELEASEHX_API_KEY", "default_api_user_env"=>"RELEASEHX_API_USER", "default_api_org_env"=>"RELEASEHX_API_ORG", "markdown_extensions"=>".md, .markdown", "asciidoc_extensions"=>".adoc, .ad, .asciidoc", "yaml_extensions"=>".yml, .yaml, .rhyml", "draft_source_file_types"=>"AsciiDoc, Markdown, YAML", "draft_source_extensions"=>".md, .markdown, .adoc, .ad, .asciidoc, .yml, .yaml, .rhyml", "enrich_file_types"=>"HTML, PDF", "enrich_extensions"=>".html, .pdf", "docker_base_command"=>"docker run -it --rm --user $(id -u):$(id -g) -v $(pwd):/workdir docopslab/releasehx rhx", "this_prod_repo_branch"=>"https://github.com/DocOps/releasehx/tree/release/0.1", "docs_extn"=>"", "toc"=>"", "toclevels"=>"3", "authorcount"=>0, "toc-position"=>"content"}}
5
+ ATTRIBUTES = {:globals=>{"attribute-undefined"=>"drop-line", "attribute-missing"=>"skip", "appendix-caption"=>"Appendix", "appendix-refsig"=>"Appendix", "caution-caption"=>"Caution", "chapter-refsig"=>"Chapter", "example-caption"=>"Example", "figure-caption"=>"Figure", "important-caption"=>"Important", "last-update-label"=>"Last updated", "note-caption"=>"Note", "part-refsig"=>"Part", "prewrap"=>"", "sectids"=>"", "section-refsig"=>"Section", "table-caption"=>"Table", "tip-caption"=>"Tip", "toc-placement"=>"macro", "toc-title"=>"Table of Contents", "untitled-label"=>"Untitled", "version-label"=>"Version", "warning-caption"=>"Warning", "notitle"=>"", "docfile"=>"/home/brian/Documents/work/releasehx/README.adoc", "docdir"=>"/home/brian/Documents/work/releasehx", "docfilesuffix"=>".adoc", "docname"=>"README", "embedded"=>"", "asciidoctor"=>"", "asciidoctor-version"=>"2.0.23", "safe-mode-name"=>"unsafe", "safe-mode-unsafe"=>"", "safe-mode-level"=>0, "max-include-depth"=>64, "user-home"=>"/home/brian", "doctype"=>"article", "htmlsyntax"=>"html", "backend-html5-doctype-article"=>"", "doctype-article"=>"", "backend-html5"=>"", "backend"=>"html5", "outfilesuffix"=>".html", "filetype"=>"html", "filetype-html"=>"", "basebackend-html-doctype-article"=>"", "basebackend-html"=>"", "basebackend"=>"html", "stylesdir"=>".", "iconsdir"=>"./images/icons", "localdate"=>"2026-01-30", "localyear"=>"2026", "localtime"=>"01:33:36 -0500", "localdatetime"=>"2026-01-30 01:33:36 -0500", "docdate"=>"2026-01-30", "docyear"=>"2026", "doctime"=>"00:47:36 -0500", "docdatetime"=>"2026-01-30 00:47:36 -0500", "page-layout"=>"default", "page-permalink"=>"/docs/", "page-title"=>"ReleaseHx Docs", "page-nav_order"=>"1", "doctitle"=>"ReleaseHx", "docopslab_git_www"=>"https://github.com/DocOps", "this_prod_slug"=>"releasehx", "releasehx_prod_repo"=>"https://github.com/DocOps/releasehx", "releasehx_demo_repo"=>"https://github.com/DocOps/releasehx-demo", "this_prod_repo"=>"https://github.com/DocOps/releasehx", "this_prod_vrsn_major"=>"0", "this_prod_vrsn_minor"=>"1", "this_prod_vrsn_major-minor"=>"0.1", "this_prod_vrsn_patch"=>"2", "this_prod_vrsn"=>"0.1.2", "next_prod_vrsn"=>"0.2.0", "tagline"=>"Generate formatted release histories from Jira, GitHub, GitLab, YAML, or JSON sources.", "description"=>"CLI utility and Ruby API for generating structured release notes and changelog documents from various issue-tracking platforms or YAML definitions into plaintext drafts (<strong>AsciiDoc</strong>, <strong>Markdown</strong>, <strong>YAML</strong>) and rich-text output (<strong>HTML</strong> and <strong>PDF</strong>).", "gem_config_definition_path"=>"./specs/data/config-def.yml", "app_default_config_path"=>"./.releasehx.yml", "default_markup"=>"markdown", "default_slug_type"=>"kebab", "default_tplt_lang"=>"liquid", "default_drafts_dir"=>"_drafts", "default_enrich_dir"=>"_publish", "default_output_dir"=>".", "default_payloads_dir"=>"_payloads", "default_templates_dir"=>"_templates", "default_mappings_dir"=>"_mappings", "default_api_clients_dir"=>"_apis", "default_cache_dir"=>".releasehx/cache", "default_api_cred_env"=>"RELEASEHX_API_CRED", "default_api_key_env"=>"RELEASEHX_API_KEY", "default_api_user_env"=>"RELEASEHX_API_USER", "default_api_org_env"=>"RELEASEHX_API_ORG", "markdown_extensions"=>".md, .markdown", "asciidoc_extensions"=>".adoc, .ad, .asciidoc", "yaml_extensions"=>".yml, .yaml, .rhyml", "draft_source_file_types"=>"AsciiDoc, Markdown, YAML", "draft_source_extensions"=>".md, .markdown, .adoc, .ad, .asciidoc, .yml, .yaml, .rhyml", "enrich_file_types"=>"HTML, PDF", "enrich_extensions"=>".html, .pdf", "docker_base_command"=>"docker run -it --rm --user $(id -u):$(id -g) -v $(pwd):/workdir docopslab/releasehx rhx", "this_prod_repo_branch"=>"https://github.com/DocOps/releasehx/tree/release/0.1", "docs_extn"=>"", "toc"=>"", "toclevels"=>"3", "authorcount"=>0, "toc-position"=>"content"}}
6
6
 
7
7
  SNIPPET_LOOKUP = {"helpscreen"=>"helpscreen.txt"}
8
8
 
@@ -165,6 +165,7 @@ properties:
165
165
  Must be `issue_body`, `custom_field`, or `commit_message`.
166
166
 
167
167
  Defaults to `issue_body` for GitHub and GitLab, but to `custom_field` for Jira.
168
+ dflt: issue_body
168
169
  note_custom_field:
169
170
  type: String
170
171
  desc: |
@@ -182,7 +183,8 @@ properties:
182
183
  Uses Capture group `note` in the Regular Expression to establish the entire note content.
183
184
 
184
185
  See the `conversions.head_pattern` property for details on extracting a heading (`head` in RHYML) from the `note` content.
185
- dflt: '/^((#|=)+ (Draft )?Release Note.*)|(<!-- (draft )?release note -->)\n(?<note>\w(.|\n)+)/gmi'
186
+ dflt: '/^(((#|=)+ (Draft )?Release Note.*?)|(<!-- (draft )?release note -->))\n+(?<note>(.|
187
+ )+)/gmi'
186
188
  head_pattern:
187
189
  type: RegExp
188
190
  desc: |
@@ -1162,7 +1164,7 @@ properties:
1162
1164
  The label to use for the _singular_ part/component affected by the change, when only one part is permitted.
1163
1165
 
1164
1166
  This value will apply either when <<conf_ppty_rhyml_max_parts>> is set to `1` or when the change has only one part _and_ <<conf_ppty_history_labeling_singularize_labels>> is `true`.
1165
- dflt: Part
1167
+ dflt: Component
1166
1168
  parts_icon:
1167
1169
  type: String
1168
1170
  desc: |
@@ -1,7 +1,4 @@
1
- :page-layout: default
2
- :page-permalink: /config-reference/
3
- :page-nav_order: 2
4
- :page-title: Configuration Reference
1
+
5
2
 
6
3
  [[conf_ppty_DOLLARSIGN_meta,config.$meta]]
7
4
  $meta::
@@ -359,6 +356,9 @@ Defaults to `issue_body` for GitHub and GitLab, but to `custom_field` for Jira.
359
356
 
360
357
  [horizontal]
361
358
  type;; String
359
+ default;;
360
+ +
361
+ `+++issue_body+++`
362
362
  path;; `xref:conf_ppty_conversions_note[config.conversions.note]`
363
363
  --
364
364
 
@@ -395,7 +395,7 @@ type;; RegExp
395
395
  default;;
396
396
  +
397
397
  ....
398
- /^((#|=)+ (Draft )?Release Note.*)|(<!-- (draft )?release note -->)\n(?<note>\w(.|\n)+)/gmi
398
+ /^(((#|=)+ (Draft )?Release Note.*?)|(<!-- (draft )?release note -->))\n+(?<note>(.| )+)/gmi
399
399
  ....
400
400
  path;; `xref:conf_ppty_conversions_note_pattern[config.conversions.note_pattern]`
401
401
  --
@@ -3161,7 +3161,7 @@ This value will apply either when <<conf_ppty_rhyml_max_parts>> is set to `1` or
3161
3161
  type;; String
3162
3162
  default;;
3163
3163
  +
3164
- `+++Part+++`
3164
+ `+++Component+++`
3165
3165
  path;; `xref:conf_ppty_history_labeling_part_label[config.history.labeling.part_label]`
3166
3166
  --
3167
3167
 
@@ -129,7 +129,8 @@
129
129
  "note": {
130
130
  "path": "conversions.note",
131
131
  "desc": "The source of the release notes content.\nMust be `issue_body`, `custom_field`, or `commit_message`.\n\nDefaults to `issue_body` for GitHub and GitLab, but to `custom_field` for Jira.\n",
132
- "type": "String"
132
+ "type": "String",
133
+ "default": "issue_body"
133
134
  },
134
135
  "note_custom_field": {
135
136
  "path": "conversions.note_custom_field",
@@ -140,7 +141,7 @@
140
141
  "path": "conversions.note_pattern",
141
142
  "desc": "The Regular Expressions pattern to match in the body of an issue or commit message, after which all content is considered the release `note` matter.\n\nDefaults to a Markdown or AsciiDoc header or HTML comment with the case-insensitive string `release note` in it.\n\nUses Capture group `note` in the Regular Expression to establish the entire note content.\n\nSee the `conversions.head_pattern` property for details on extracting a heading (`head` in RHYML) from the `note` content.\n",
142
143
  "type": "RegExp",
143
- "default": "/^((#|=)+ (Draft )?Release Note.*)|(<!-- (draft )?release note -->)\\n(?<note>\\w(.|\\n)+)/gmi"
144
+ "default": "/^(((#|=)+ (Draft )?Release Note.*?)|(<!-- (draft )?release note -->))\\n+(?<note>(.| )+)/gmi"
144
145
  },
145
146
  "head_pattern": {
146
147
  "path": "conversions.head_pattern",
@@ -1228,7 +1229,7 @@
1228
1229
  "path": "history.labeling.part_label",
1229
1230
  "desc": "The label to use for the _singular_ part/component affected by the change, when only one part is permitted.\n\nThis value will apply either when <<conf_ppty_rhyml_max_parts>> is set to `1` or when the change has only one part _and_ <<conf_ppty_history_labeling_singularize_labels>> is `true`.\n",
1230
1231
  "type": "String",
1231
- "default": "Part"
1232
+ "default": "Component"
1232
1233
  },
1233
1234
  "parts_icon": {
1234
1235
  "path": "history.labeling.parts_icon",
@@ -22,7 +22,7 @@ origin: # The API or file source for the issues.
22
22
  conversions: # Details about content origination, as well as markup sources and conversion.
23
23
  summ: issue # The source of the summary (Changelog) content.
24
24
  # head: # The source of release-note headlines, when it is not the same as the summary.
25
- # note: # The source of the release notes content.
25
+ note: issue_body # The source of the release notes content.
26
26
  # note_custom_field: # The name of the custom field to use for the release notes content.Liquid error: wrong number of arguments (given 3, expected 1..2)Liquid error: wrong number of arguments (given 3, expected 1..2)
27
27
  markup: markdown # The origin markup format for notes.
28
28
  # engine: # The markup converter to use for the issues.
@@ -195,7 +195,7 @@ history: # Configurations for the overall document, when applicable.Liquid error
195
195
  type_label: type # The label to use for the type of change.
196
196
  # type_icon: # The icon to use for the type of change.
197
197
  parts_label: Components # The label to use for the part/component affected by the change.
198
- part_label: Part # The label to use for the singular part/component affected by the change, when only one part is permitted.
198
+ part_label: Component # The label to use for the singular part/component affected by the change, when only one part is permitted.
199
199
  parts_icon: puzzle-piece # The icon to use for the part/component affected by the change.
200
200
  tags_label: # The tags associated with the change, if any.
201
201
  - Tags
@@ -349,7 +349,7 @@ module ReleaseHx
349
349
  note_pattern = sources['note_pattern'] || templates['note_pattern']
350
350
  head_pattern = sources['head_pattern'] || templates['head_pattern']
351
351
  head_source = sources['head_source']
352
- note_source = sources['note_source']
352
+ note_source = sources['note']
353
353
 
354
354
  extract_note!(data, note_source, note_pattern)
355
355
  extract_head!(data, head_source, head_pattern)
@@ -406,10 +406,10 @@ module ReleaseHx
406
406
  end
407
407
 
408
408
  # STEP 2: Apply regex pattern extraction if configured
409
- return unless note_source =~ /issue_body/i && original_content.is_a?(String) && note_pattern.is_a?(String)
409
+ return unless note_source == 'issue_body' && original_content.is_a?(String) && note_pattern
410
410
 
411
411
  ReleaseHx.logger.debug "Extracting note using pattern: #{note_pattern}"
412
- ReleaseHx.logger.debug "Original content: #{original_content}"
412
+ ReleaseHx.logger.debug "Original content: #{original_content[0..100]}..."
413
413
 
414
414
  begin
415
415
  # Apply sensible default flag 'm' (multiline/dotall in Ruby) when no flags provided
@@ -421,11 +421,18 @@ module ReleaseHx
421
421
  pattern_info,
422
422
  'note')
423
423
 
424
- # Only update if we got a match
425
- data['note'] = extracted_note.strip if extracted_note
424
+ if extracted_note
425
+ # Pattern matched - use extracted content
426
+ data['note'] = extracted_note.strip
427
+ ReleaseHx.logger.debug "Extracted note (#{extracted_note.length} chars)"
428
+ else
429
+ # Pattern didn't match - clear the note so empty_notes policy applies
430
+ ReleaseHx.logger.warn "Note pattern did not match for issue #{data['tick']} - no Release Note section found"
431
+ data['note'] = nil
432
+ end
426
433
  rescue RegexpError => e
427
434
  ReleaseHx.logger.warn "Invalid note_pattern '#{note_pattern}': #{e.message}"
428
- data['note'] = original_content # Restore original on error
435
+ # Preserve original content on pattern error - don't lose data due to bad config
429
436
  end
430
437
  end
431
438
 
@@ -25,7 +25,9 @@ note:
25
25
 
26
26
  # Extract type from the native GitHub Issues type field (modern approach)
27
27
  type:
28
- path: "issue_type.name"
28
+ path: "type.name"
29
+ ruby: |
30
+ path&.downcase
29
31
 
30
32
  # Derive `parts` from labels using direct key matching or slug override
31
33
  parts:
@@ -0,0 +1,14 @@
1
+ {%- assign content_config = config.changelog %}
2
+ {%- assign section_type = "changelog" %}
3
+ {%- embed config-cascade.liquid %}
4
+ {%- embed changes-sorter.liquid %}
5
+ {%- assign level = content_config.htag | replace: "h", "" | default: dflt_next_header_level | plus: 0 %}
6
+ {%- capture header_chars %}
7
+ {%- for i in (1..level) %}{{ header_char }}{% endfor %}
8
+ {%- endcapture %}
9
+ {%- include header.liquid format=format level=level text=content_config.head %}
10
+ {%- assign dflt_next_header_level = level | plus: 1 -%}
11
+ {%- assign item_count = 0 %}
12
+ {%- embed section-text.liquid %}
13
+
14
+ {%- embed groupings.liquid %}
@@ -0,0 +1,14 @@
1
+ {%- assign content_config = config.changelog %}
2
+ {%- embed changes-sorter.liquid %}
3
+ {%- assign level = content_config.htag | replace: "h", "" | default: dflt_next_header_level | plus: 0 %}
4
+ {%- assign dflt_next_header_level = level | plus: 1 -%}
5
+ {%- assign item_count = 0 %}
6
+
7
+ <div class="changelog-section">
8
+ {%- include header.liquid format=format level=level text=content_config.head %}
9
+
10
+ {%- embed section-text.liquid %}
11
+
12
+ {%- embed groupings.liquid %}
13
+ </div>
14
+
@@ -0,0 +1,11 @@
1
+ {%- assign content_config = config.changelog %}
2
+ {%- assign section_type = "changelog" %}
3
+ {%- embed config-cascade.liquid %}
4
+ {% embed changes-sorter.liquid %}
5
+ {%- assign level = content_config.htag | replace: "h", "" | default: dflt_next_header_level | plus: 0 %}
6
+ {%- include header.liquid format=format level=level text=content_config.head %}
7
+ {%- assign dflt_next_header_level = level | plus: 1 -%}
8
+ {%- assign item_count = 0 %}
9
+ {%- embed section-text.liquid %}
10
+
11
+ {%- embed groupings.liquid %}
@@ -0,0 +1,64 @@
1
+ {%- assign groups = '' | split: ',' %}
2
+ {%- assign grouping1 = '' | split: ',' %}
3
+ {%- assign grouping2 = '' | split: ',' %}
4
+
5
+ {%- for group_expr in content_config.sort %}
6
+ {%- assign kind = group_expr | split: ':' | first %}
7
+ {%- assign target = group_expr | split: ':' | last %}
8
+
9
+ {%- if kind == 'tag' or kind == 'tags' %}
10
+ {%- for tag_entry in config.tags %}
11
+ {%- assign tag_name = tag_entry[0] %}
12
+ {%- if tag_name == '_include' or tag_name == '_exclude' %}
13
+ {%- continue %}
14
+ {%- endif %}
15
+ {%- assign group = 'tag:' | append: tag_name %}
16
+ {%- assign group = group | split: ',' %}
17
+ {%- if target == 'grouping1' %}
18
+ {%- assign grouping1 = grouping1 | concat: group %}
19
+ {%- elsif target == 'grouping2' %}
20
+ {%- assign grouping2 = grouping2 | concat: group %}
21
+ {%- endif %}
22
+ {%- endfor %}
23
+
24
+ {%- elsif kind == 'type' %}
25
+ {%- for type_entry in config.types %}
26
+ {%- assign type_name = type_entry[0] %}
27
+ {%- if type_name contains "<" %}
28
+ {%- continue %}
29
+ {%- endif %}
30
+ {%- assign group = 'type:' | append: type_name | split: ',' %}
31
+ {%- if target == 'grouping1' %}
32
+ {%- assign grouping1 = grouping1 | concat: group %}
33
+ {%- elsif target == 'grouping2' %}
34
+ {%- assign grouping2 = grouping2 | concat: group %}
35
+ {%- endif %}
36
+ {%- endfor %}
37
+
38
+ {%- elsif kind == 'part' %}
39
+ {%- for part_entry in config.parts %}
40
+ {%- assign part_name = part_entry[0] %}
41
+ {%- if part_name contains "<" or part_name == 'label_prefix' %}
42
+ {%- continue %}
43
+ {%- endif %}
44
+ {%- assign group = 'part:' | append: part_name | split: ',' %}
45
+ {%- if target == 'grouping1' %}
46
+ {%- assign grouping1 = grouping1 | concat: group %}
47
+ {%- elsif target == 'grouping2' %}
48
+ {%- assign grouping2 = grouping2 | concat: group %}
49
+ {%- endif %}
50
+ {%- endfor %}
51
+
52
+ {%- else %}
53
+ {%- assign group = 'tag:' | append: kind | split: ',' %}
54
+ {%- if target == 'grouping1' %}
55
+ {%- assign grouping1 = grouping1 | concat: group %}
56
+ {%- elsif target == 'grouping2' %}
57
+ {%- assign grouping2 = grouping2 | concat: group %}
58
+ {%- endif %}
59
+ {%- endif %}
60
+ {%- endfor %}
61
+
62
+ {%- if grouping2.size > 0 and grouping1 == empty %}
63
+ Invalid sort: cannot define grouping2 without grouping1
64
+ {%- endif %}