releasehx 0.1.0

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 (91) hide show
  1. checksums.yaml +7 -0
  2. data/README.adoc +2915 -0
  3. data/bin/releasehx +7 -0
  4. data/bin/rhx +7 -0
  5. data/bin/rhx-mcp +7 -0
  6. data/bin/sourcerer +32 -0
  7. data/build/docs/CNAME +1 -0
  8. data/build/docs/Gemfile.lock +95 -0
  9. data/build/docs/_config.yml +36 -0
  10. data/build/docs/config-reference.adoc +4104 -0
  11. data/build/docs/config-reference.json +1546 -0
  12. data/build/docs/index.adoc +2915 -0
  13. data/build/docs/landing.adoc +21 -0
  14. data/build/docs/manpage.adoc +68 -0
  15. data/build/docs/releasehx.1 +281 -0
  16. data/build/docs/releasehx_readme.html +367 -0
  17. data/build/docs/sample-config.adoc +9 -0
  18. data/build/docs/sample-config.yml +251 -0
  19. data/build/docs/schemagraphy_readme.html +0 -0
  20. data/build/docs/sourcerer_readme.html +46 -0
  21. data/build/snippets/helpscreen.txt +29 -0
  22. data/lib/docopslab/mcp/asset_packager.rb +30 -0
  23. data/lib/docopslab/mcp/manifest.rb +67 -0
  24. data/lib/docopslab/mcp/resource_pack.rb +46 -0
  25. data/lib/docopslab/mcp/server.rb +92 -0
  26. data/lib/docopslab/mcp.rb +6 -0
  27. data/lib/releasehx/cli.rb +937 -0
  28. data/lib/releasehx/configuration.rb +215 -0
  29. data/lib/releasehx/generated.rb +17 -0
  30. data/lib/releasehx/helpers.rb +58 -0
  31. data/lib/releasehx/mcp/asset_packager.rb +21 -0
  32. data/lib/releasehx/mcp/assets/agent-config-guide.md +178 -0
  33. data/lib/releasehx/mcp/assets/config-def.yml +1426 -0
  34. data/lib/releasehx/mcp/assets/config-reference.adoc +4104 -0
  35. data/lib/releasehx/mcp/assets/config-reference.json +1546 -0
  36. data/lib/releasehx/mcp/assets/sample-config.yml +251 -0
  37. data/lib/releasehx/mcp/manifest.rb +18 -0
  38. data/lib/releasehx/mcp/resource_pack.rb +26 -0
  39. data/lib/releasehx/mcp/server.rb +57 -0
  40. data/lib/releasehx/mcp.rb +7 -0
  41. data/lib/releasehx/ops/check_ops.rb +136 -0
  42. data/lib/releasehx/ops/draft_ops.rb +173 -0
  43. data/lib/releasehx/ops/enrich_ops.rb +221 -0
  44. data/lib/releasehx/ops/template_ops.rb +61 -0
  45. data/lib/releasehx/ops/write_ops.rb +124 -0
  46. data/lib/releasehx/rest/clients/github.yml +46 -0
  47. data/lib/releasehx/rest/clients/gitlab.yml +31 -0
  48. data/lib/releasehx/rest/clients/jira.yml +31 -0
  49. data/lib/releasehx/rest/yaml_client.rb +418 -0
  50. data/lib/releasehx/rhyml/adapter.rb +740 -0
  51. data/lib/releasehx/rhyml/change.rb +167 -0
  52. data/lib/releasehx/rhyml/liquid.rb +13 -0
  53. data/lib/releasehx/rhyml/loaders.rb +37 -0
  54. data/lib/releasehx/rhyml/mappings/github.yaml +60 -0
  55. data/lib/releasehx/rhyml/mappings/gitlab.yaml +73 -0
  56. data/lib/releasehx/rhyml/mappings/jira.yaml +29 -0
  57. data/lib/releasehx/rhyml/mappings/verb_past_tenses.yml +98 -0
  58. data/lib/releasehx/rhyml/release.rb +144 -0
  59. data/lib/releasehx/rhyml.rb +15 -0
  60. data/lib/releasehx/sgyml/helpers.rb +45 -0
  61. data/lib/releasehx/transforms/adf_to_markdown.rb +307 -0
  62. data/lib/releasehx/version.rb +7 -0
  63. data/lib/releasehx.rb +69 -0
  64. data/lib/schemagraphy/attribute_resolver.rb +48 -0
  65. data/lib/schemagraphy/cfgyml/definition.rb +90 -0
  66. data/lib/schemagraphy/cfgyml/doc_builder.rb +52 -0
  67. data/lib/schemagraphy/cfgyml/path_reference.rb +24 -0
  68. data/lib/schemagraphy/data_query/json_pointer.rb +42 -0
  69. data/lib/schemagraphy/loader.rb +59 -0
  70. data/lib/schemagraphy/regexp_utils.rb +215 -0
  71. data/lib/schemagraphy/safe_expression.rb +189 -0
  72. data/lib/schemagraphy/schema_utils.rb +124 -0
  73. data/lib/schemagraphy/tag_utils.rb +32 -0
  74. data/lib/schemagraphy/templating.rb +104 -0
  75. data/lib/schemagraphy.rb +17 -0
  76. data/lib/sourcerer/builder.rb +120 -0
  77. data/lib/sourcerer/jekyll/bootstrapper.rb +78 -0
  78. data/lib/sourcerer/jekyll/liquid/file_system.rb +74 -0
  79. data/lib/sourcerer/jekyll/liquid/filters.rb +215 -0
  80. data/lib/sourcerer/jekyll/liquid/tags.rb +44 -0
  81. data/lib/sourcerer/jekyll/monkeypatches.rb +73 -0
  82. data/lib/sourcerer/jekyll.rb +26 -0
  83. data/lib/sourcerer/plaintext_converter.rb +75 -0
  84. data/lib/sourcerer/templating.rb +190 -0
  85. data/lib/sourcerer.rb +322 -0
  86. data/specs/data/api-client-schema.yaml +160 -0
  87. data/specs/data/config-def.yml +1426 -0
  88. data/specs/data/mcp-manifest.yml +50 -0
  89. data/specs/data/rhyml-mapping-schema.yaml +410 -0
  90. data/specs/data/rhyml-schema.yaml +152 -0
  91. metadata +376 -0
data/README.adoc ADDED
@@ -0,0 +1,2915 @@
1
+ :page-layout: default
2
+ :page-permalink: /docs
3
+ :page-nav_order: 1
4
+ [[releasehx]]
5
+ = ReleaseHx
6
+ // tag::ai-prompt[]
7
+ // Collects AsciiDoc content for presenting to a generative AI prompt
8
+ // Other AI-only prompt matter could go here
9
+ // tag::globals[]
10
+ :docopslab_git_www: https://github.com/DocOps
11
+ :this_prod_slug: releasehx
12
+ :releasehx_prod_repo: {docopslab_git_www}/{this_prod_slug}
13
+ :releasehx_demo_repo: {docopslab_git_www}/releasehx-demo
14
+ :this_prod_repo: {releasehx_prod_repo}
15
+ :this_prod_vrsn_major: 0
16
+ :this_prod_vrsn_minor: 1
17
+ :this_prod_vrsn_major-minor: {this_prod_vrsn_major}.{this_prod_vrsn_minor}
18
+ :this_prod_vrsn_patch: 0
19
+ :this_prod_vrsn: {this_prod_vrsn_major-minor}.{this_prod_vrsn_patch}
20
+ :next_prod_vrsn: 0.2.0
21
+ :tagline: Generate formatted release histories from Jira, GitHub, GitLab, YAML, or JSON sources.
22
+ :description: pass:q[CLI utility and Ruby API for generating structured release notes and changelog documents from various issue-tracking platforms or YAML definitions into plaintext drafts (*AsciiDoc*, *Markdown*, *YAML*) and rich-text output (*HTML* and *PDF*).]
23
+ :gem_config_definition_path: ./specs/data/config-def.yml
24
+ :app_default_config_path: ./.releasehx.yml
25
+ // Default configuration values - single source of truth for config-def.yml
26
+ :default_markup: markdown
27
+ :default_slug_type: kebab
28
+ :default_tplt_lang: liquid
29
+ :default_drafts_dir: _drafts
30
+ :default_enrich_dir: _publish
31
+ :default_output_dir: .
32
+ :default_payloads_dir: _payloads
33
+ :default_templates_dir: _templates
34
+ :default_mappings_dir: _mappings
35
+ :default_api_clients_dir: _apis
36
+ :default_cache_dir: .releasehx/cache
37
+ :default_api_cred_env: RELEASEHX_API_CRED
38
+ :default_api_key_env: RELEASEHX_API_KEY
39
+ :default_api_user_env: RELEASEHX_API_USER
40
+ :default_api_org_env: RELEASEHX_API_ORG
41
+ :markdown_extensions: .md, .markdown
42
+ :asciidoc_extensions: .adoc, .ad, .asciidoc
43
+ :yaml_extensions: .yml, .yaml, .rhyml
44
+ :draft_source_file_types: AsciiDoc, Markdown, YAML
45
+ :draft_source_extensions: {markdown_extensions}, {asciidoc_extensions}, {yaml_extensions}
46
+ :enrich_file_types: HTML, PDF
47
+ :enrich_extensions: .html, .pdf
48
+ :docker_base_command: docker run -it --rm --user $(id -u):$(id -g) -v $(pwd):/workdir docopslab/releasehx rhx
49
+ :this_prod_repo_branch: {this_prod_repo}/tree/release/{this_prod_vrsn_major-minor}
50
+ ifdef::env-github[]
51
+ :docs_extn: .adoc
52
+ :releasehx_www: https://releasehx.docopslab.org
53
+ :releasehx_docs_www: {releasehx_www}/docs
54
+ :default-config_www: {releasehx_docs_www}/sample-config.html
55
+ :this_prod_docs_www: {releasehx_docs_www}
56
+ endif::[]
57
+ ifndef::env-github[]
58
+ :docs_extn:
59
+ endif::[]
60
+ // end::globals[]
61
+ :toc: macro
62
+ :toclevels: 3
63
+
64
+ // tag::intro[]
65
+ {tagline}
66
+
67
+ {description}
68
+ // end::intro[]
69
+
70
+ [NOTE]
71
+ This README serves as the both landing page and documentation for *Version {this_prod_vrsn}*.
72
+
73
+ [IMPORTANT]
74
+ This repository is for the {this_prod_vrsn} version of ReleaseHx.
75
+ NOT ALL FEATURES are available.
76
+
77
+
78
+ [[overview]]
79
+ == Overview
80
+
81
+ Generate lightweight drafts and rich-text output for your Release Notes or Changelog documents using simple commands with powerful results!
82
+
83
+ [[example-workflow]]
84
+ === Example Workflow
85
+
86
+ Your workflow might look like this example:
87
+
88
+ . *Check for issues with missing release notes*.
89
+ Looks for issues marked `release_note_needed` or similar.
90
+ +
91
+ [.prompt]
92
+ rhx 2.1.0 --check
93
+ > Missing required release notes:
94
+ > - JIRA-3412: Fix the thing (JoePSmith)
95
+ > - JIRA-3482: Add this cool thing (RaeMDoe)
96
+
97
+ . While you are waiting for Joe and Rae to get their outstanding notes entered into Jira... *retrieve Jira issues* for version 2.1.0.
98
+ [.prompt]
99
+ rhx 2.1.0 --yaml
100
+ +
101
+ [NOTE]
102
+ You can edit your Release Notes in Markdown or AsciiDoc files, or in YAML files with AsciiDoc or Markdown text formatting.
103
+ Whatever you prefer.
104
+
105
+ . When Joe and Rae finally post their notes... *append them to the YAML doc*.
106
+ +
107
+ [.prompt]
108
+ rhx 2.1.0 --append
109
+
110
+ . *Generate a Markdown variant* to your website source directory.
111
+ +
112
+ [.prompt]
113
+ rhx 2.1.0 --md
114
+
115
+ . *Generate a PDF* to a documents archive.
116
+ +
117
+ [.prompt]
118
+ rhx 2.1.0 --pdf
119
+
120
+ And you're ready to publish in HTML and PDF format!
121
+
122
+ ReleaseHx can accommodate _numerous permutations_ of workflows.
123
+ It is *adaptable by design*, but if you are just starting or revamping your ReleaseNotes/Changelog setup, there is a *<<strategy-overview,recommended strategy/workflow>>*, as well.
124
+
125
+ [[powerful-potential]]
126
+ === Powerful Potential
127
+
128
+ Numerous backends enable flexible conversions from any source format to HTML or PDF output.
129
+
130
+ ReleaseHx can convert data into content through various processes, which you can adapt to your preferred workflow.
131
+
132
+ ....
133
+ API → Markdown/AsciiDoc/YAML → HTML/PDF
134
+ ....
135
+
136
+ OR, use your Markdown/AsciiDoc-based *static-site generator (SSG)* to perform the final enrichment to HTML!
137
+ // end::ai-prompt[]
138
+
139
+ [[features]]
140
+ === Features
141
+
142
+ ReleaseHx is already packed with capabilities.
143
+
144
+ // tag::features-list[]
145
+ // tag::ai-prompt[]
146
+
147
+ * Generate [.key]*Release Notes* and/or [.key]*Changelogs* from your Issues tracker or Git+++*+++.
148
+ * Source in [.buzz]*Jira*, [.buzz]*GitHub*, [.buzz]*GitLab*, [.key]*Git commits*+++*+++, or our special YAML syntax: *RHYML*.
149
+ * Readily configurable to use *your Issue Management API*.
150
+ * Draft in [.key]*Markdown*, [.key]*AsciiDoc*, or [.key]*YAML*.
151
+ * Render to [.key]*HTML* or [.key]*PDF* with *Asciidoctor*, *Pandoc*, and other converters.
152
+ * Use [.buzz]*Docker* to run ReleaseHx in any environment.
153
+ * Customize output with [.buzz]*Liquid* templates.
154
+ * Configure output without touching templates using advanced settings ([.buzz]*low-code*).
155
+ * Ensure qualifying issues all have release notes.
156
+ * *Link-back* from notes or Changelog entries to issues and Git commits.
157
+ * Use [.key]*Git* to track changes in your release history documents.
158
+ * Auto-update drafts with late-breaking release notes (RHYML only).
159
+ * Group and sort entries by *issue type*, subject *component*, or various *tags*.
160
+ * Invoke labels/tags such as *breaking*, *deprecation*, *experimental*, *highlight*, and *internal*.
161
+ * Use Issue labels or *checkboxes* to indicate Changelog inclusion or Release Note requirement.
162
+ * Use as a [.key]*CLI* or as a [.key]*Ruby API*.
163
+ * Run a local [.key]*MCP server* (`rhx-mcp`) so AI agents can better aid in using ReleaseHx.
164
+ * Extend by configuring a *custom API client* and issue mapping.
165
+ * Convert changelog summaries to past-tense with the *pasterize* filter.
166
+ * Full support for [.buzz]*Jira v3 API* with [.key]*ADF* conversion to Markdown/AsciiDoc.
167
+
168
+ +++*+++ Sourcing issues in Git commits is not yet available but is planned for a future (pre-1.0) version.
169
+
170
+ // end::ai-prompt[]
171
+ // end::features-list[]
172
+
173
+ You can begin editing in YAML and update the file without losing changes, then generate a final draft in Markdown or AsciiDoc.
174
+
175
+ rhx 2.1.0 --yml
176
+ rhx 2.1.0 --append
177
+ rhx 2.1.0 --adoc
178
+
179
+ The second line adds any late-arriving issues from the cloud.
180
+ The third line uses that `.yml` file to generate a `.adoc` file, but you can go directly from YAML to HTML or PDF as well as drafting in Markdown.
181
+
182
+ toc::[]
183
+
184
+
185
+ [[getting-started]]
186
+ == Getting Started
187
+
188
+ To use ReleaseHx in your own projects, you will need either Ruby or Docker.
189
+ Use either the `rhx` CLI utility or the ReleaseHx Ruby API.
190
+
191
+ The only other prerequisite is possibly Git, if wish to draw any content/metadata from Git commits.
192
+
193
+ [[non-ruby-starter]]
194
+ === Non-Ruby Users Setup
195
+
196
+ If you are not already a Ruby user, the `rhx` utility may be best used from our Docker image.
197
+
198
+ [NOTE]
199
+ You will need *Docker Desktop* installed link:https://docs.docker.com/desktop/setup/install/mac-install/[directly on MacOS] or link:https://docs.docker.com/desktop/features/wsl/[with WSL2 backend on Windows].
200
+ For Linux, use the link:https://docs.docker.com/engine/install/[Docker Engine install docs] if you're not already using Docker.
201
+
202
+ With Docker installed and running...
203
+
204
+ . Pull the Docker image.
205
+ +
206
+ [.prompt]
207
+ docker pull docopslab/releasehx
208
+
209
+ . Run the `rhx` command.
210
+ +
211
+ [.prompt,subs=+attributes]
212
+ {docker_base_command}
213
+ +
214
+ This mounts your local directory to be writeable by the Docker container.
215
+ Everything after `rhx` accepts the standard <<rhx,arguments and options>> of the ReleaseHx utility.
216
+
217
+ [TIP]
218
+ ====
219
+ Optionally alias the base Docker command.
220
+
221
+ [.prompt,subs=+attributes]
222
+ alias rhx='{docker_base_command}'
223
+ ====
224
+
225
+ Try the <<demo-setup,demo configs and data>> to get a feel for how ReleaseHx works.
226
+
227
+ [[ruby-starter]]
228
+ === Ruby Users Setup
229
+
230
+ ReleaseHx can be installed as a Ruby gem, for either CLI or API usage.
231
+
232
+ Option 1: System-wide installation::
233
+ [.prompt]
234
+ gem install releasehx
235
+
236
+ Option 2: Project installation::
237
+ +
238
+ --
239
+ . Add the following line to your `Gemfile`:
240
+ +
241
+ [source,ruby]
242
+ [subs="attributes+"]
243
+ ----
244
+ gem 'releasehx'
245
+ ----
246
+
247
+ . Install the gem.
248
+ +
249
+ [.prompt]
250
+ bundle install
251
+
252
+ . Use `bundle exec rhx` to execute.
253
+ --
254
+
255
+ [[mcp-setup]]
256
+ === MCP Server Setup (Optional)
257
+
258
+ ReleaseHx provides an experimental interface for model context protocol (MCP) service over STDIO (local "`server`").
259
+ This should save considerably on the resources required for your preferred LLM client/agent system to learn and use ReleaseHx.
260
+
261
+ [NOTE]
262
+ This experimental MCP server focuses on aiding <<custom-configuration,application configuration>> of your ReleaseHx instance.
263
+ It does not provide assistance for command-line actions or other configurations such as <<custom-source-rhyml-mapping,RHYML mapping>>.
264
+
265
+ For your LLM client (such as Copilot, Claude Code, Codex, Cursor, etc) to interact with this service, it must be configured using a general MCP syntax.
266
+ This data is usually added to a `mcp.json` file or another object.
267
+
268
+ Generic MCP config (global gem install)::
269
+ [source,json]
270
+ ----
271
+ {
272
+ "servers": {
273
+ "releasehx": {
274
+ "command": "rhx-mcp"
275
+ }
276
+ }
277
+ }
278
+ ----
279
+
280
+ Generic MCP config (Docker)::
281
+ +
282
+ --
283
+ Use the Docker image for maximum compatibility across environments.
284
+ This is the **recommended approach** for most users.
285
+
286
+ [source,json]
287
+ ----
288
+ {
289
+ "servers": {
290
+ "releasehx": {
291
+ "command": "docker",
292
+ "args": ["run", "-i", "--rm", "docopslab/releasehx:latest", "rhx-mcp"]
293
+ }
294
+ }
295
+ }
296
+ ----
297
+ --
298
+
299
+ VS Code MCP configuration (Docker)::
300
+ +
301
+ --
302
+ Create or update `~/.config/Code/User/mcp.json` (Linux/Mac) or `%APPDATA%\Code\User\mcp.json` (Windows).
303
+
304
+ [source,json]
305
+ ----
306
+ {
307
+ "servers": {
308
+ "releasehx": {
309
+ "command": "docker",
310
+ "args": ["run", "-i", "--rm", "docopslab/releasehx:latest", "rhx-mcp"]
311
+ }
312
+ }
313
+ }
314
+ ----
315
+ --
316
+
317
+ VS Code MCP configuration (global gem install)::
318
+ +
319
+ --
320
+ If you have ReleaseHx installed globally (`gem install releasehx`), you can use this simpler configuration:
321
+
322
+ [source,json]
323
+ ----
324
+ {
325
+ "servers": {
326
+ "releasehx": {
327
+ "command": "rhx-mcp"
328
+ }
329
+ }
330
+ }
331
+ ----
332
+ --
333
+
334
+ Local repo MCP config (Bundler + cwd)::
335
+ [source,json]
336
+ ----
337
+ {
338
+ "servers": {
339
+ "releasehx-dev": {
340
+ "command": "bundle",
341
+ "args": ["exec", "rhx-mcp"],
342
+ "cwd": "/path/to/releasehx"
343
+ }
344
+ }
345
+ }
346
+ ----
347
+
348
+ [NOTE]
349
+ ====
350
+ If your MCP client does not honor `cwd`, `bundle exec rhx-mcp` will fail with "Could not locate Gemfile".
351
+ Install the gem globally (`gem install releasehx`) and use `command: rhx-mcp`.
352
+ ====
353
+
354
+ [[configuration-basics]]
355
+ === Configuration Basics
356
+
357
+ Once installed, you will need to configure ReleaseHx to connect to your issue-management service (IMS) and to define how you want to organize your release history output.
358
+
359
+ In fact, ReleaseHx has three different forms of "`configuration`": the _application config_, the _API-client config_, and the _issue-mapping config_.
360
+
361
+ application config::
362
+ The main, central settings, split into nested groups like *api*, *sources*, *tags*, *modes*, *rhyml*.
363
+ By default, these are set in the file at `{app_default_config_path}` in your application repo.
364
+ See the <<config-ref>> for complete details on available properties.
365
+
366
+ API-client config::
367
+ This YAML file enables custom configurations of unsupported issue-management system APIs.
368
+ See <<custom-rest-config>> for details.
369
+
370
+ [NOTE]
371
+ To use an alternate config file, provide a path at runtime using `--config PATH/TO/FILE`.
372
+ Ex: `rhx 1.1.0 --config confs/releasehx.yml`.
373
+
374
+ If you are ready to set up your remote issue management system's API, skip to <<issue-sources>>.
375
+
376
+ Otherwise, the <<demo-setup,ReleaseHX Demo>> may be a good way to understand how everything comes together.
377
+
378
+ [[mcp-server]]
379
+ ==== MCP Server Usage (AI Config Assistance)
380
+
381
+ The `rhx-mcp` command starts a local MCP server that exposes ReleaseHx configuration resources for AI clients over STDIO.
382
+ MCP is still new, so use the setup guidance below.
383
+
384
+ Resources::
385
+ `releasehx://agent/guide`:: Short guide for agent usage and navigation.
386
+ `releasehx://config/sample`:: Sample config tree with defaults and comments.
387
+ `releasehx://config/schema`:: Authoritative CFGYML definition.
388
+ `releasehx://config/reference.json`:: JSON reference document for tooling.
389
+ `releasehx://config/reference.adoc`:: AsciiDoc reference document.
390
+
391
+ Tool::
392
+ `config.reference.get`:: Accepts a JSON Pointer (example: `/properties/origin`) and returns the reference entry.
393
+
394
+ Choose how to run the MCP server:
395
+
396
+ Docker (recommended)::
397
+ [.prompt]
398
+ docker run -i --rm docopslab/releasehx:latest rhx-mcp
399
+
400
+ Bundled gem::
401
+ [.prompt]
402
+ bundle exec rhx-mcp
403
+
404
+ Global gem::
405
+ [.prompt]
406
+ rhx-mcp
407
+
408
+ [[mcp-troubleshooting]]
409
+ ===== MCP Troubleshooting
410
+
411
+ If your MCP server isn't working in VS Code or Copilot:
412
+
413
+ . **Verify Docker image exists**: Run `docker images | grep releasehx` to confirm the image is available.
414
+
415
+ . **Test MCP server manually**: Run the following to verify the server responds:
416
+ +
417
+ [.prompt]
418
+ ----
419
+ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | docker run -i --rm docopslab/releasehx:latest rhx-mcp
420
+ ----
421
+ +
422
+ You should see a JSON response with `"serverInfo":{"name":"releasehx-mcp"}`
423
+
424
+ . **Check VS Code MCP config**: Ensure `~/.config/Code/User/mcp.json` exists and uses the correct command format (see examples above).
425
+
426
+ . **Restart VS Code**: After changing `mcp.json`, restart VS Code completely for changes to take effect.
427
+
428
+ . **Check VS Code logs**: Open Output panel (Ctrl+Shift+U) and look for errors related to MCP or the releasehx server.
429
+
430
+ [TIP]
431
+ ====
432
+ Ask your agent to read `releasehx://agent/guide` first.
433
+ Then have it consult `releasehx://config/sample` as a table of contents before using `config.reference.get`.
434
+ ====
435
+
436
+ [[demo-setup]]
437
+ ==== Demo Repo Setup
438
+
439
+ If you want to play around with ReleaseHx before connecting it to your own Issues source via API, use the `link:{releasehx_demo_repo}[DocOps/releasehx-demo]` repository as instructed in this section.
440
+
441
+ Alternately, skip to <<issue-sources>> to begin configuring your own project/environment.
442
+
443
+ [TIP]
444
+ We recommend performing the demo steps to get a feel for the project.
445
+
446
+ [IMPORTANT]
447
+ This demo assumes you have either installed ReleaseHx with `gem install releasehx` or you have aliased the `docker run` command prefix to `rhx`, as instructed in <<non-ruby-starter>>.
448
+
449
+ . Clone the demo repository.
450
+ +
451
+ [.prompt]
452
+ git clone git@github.com:DocOps/releasehx-demo.git
453
+
454
+ . Change to the new repo directory.
455
+ +
456
+ [.prompt]
457
+ cd releasehx-demo
458
+
459
+ . Install ReleaseHx and dependencies.
460
+ +
461
+ [.prompt.testable]
462
+ bundle install
463
+
464
+ . Run the `rhx` command with special arguments.
465
+ For example:
466
+ +
467
+ [.prompt.testable]
468
+ bundle exec rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --md demo-1.1.0.md
469
+ +
470
+ Prepend `bundle exec` if using the local project Ruby installation.
471
+
472
+ In this example, the `jira-customfield-note-1.1.0.json` file fills in for the version 1.1.0 issue tickets in a Jira project, drafting them as a local Markdown file.
473
+
474
+ The demo repo contains several JSON files that simulate the data returned by the Jira, GitHub, and GitLab APIs.
475
+
476
+ // AGENT: DUPLICATE SOURCE WARNING; Re-verify these paths with every release
477
+ .Demo data versions in `_payloads/` directory
478
+ [cols="4m,2,1",options="header"]
479
+ |===
480
+ | File path
481
+ | Note field
482
+ | Tags source
483
+
484
+ | jira-customfield-note-1.1.0.json
485
+ | custom field
486
+ | labels
487
+
488
+ | jira-description-note-1.1.0.json
489
+ | description field
490
+ | labels
491
+
492
+ | github-1.0.0-issues.json
493
+ | description field
494
+ | labels
495
+
496
+ | github-checkbox-tags-1.1.0.json
497
+ | description field
498
+ | checkboxes
499
+
500
+ | github-label-tags-1.1.0.json
501
+ | description field
502
+ | labels
503
+
504
+ | github-live-actual.json
505
+ | description field
506
+ | labels
507
+
508
+ | gitlab-checkbox-tags-1.1.0.json
509
+ | description field
510
+ | checkboxes
511
+
512
+ | gitlab-label-tags-1.1.0.json
513
+ | description field
514
+ | labels
515
+
516
+ | generic-1.1.1.json
517
+ | description field
518
+ | labels
519
+
520
+ | generic-1.1.2.json
521
+ | description field
522
+ | labels
523
+
524
+ | generic-1.2.0.json
525
+ | description field
526
+ | labels
527
+ |===
528
+
529
+ The demo repository also comes with a number of configuration arrangements, which you may switch to or freely edit.
530
+
531
+ // AGENT: DUPLICATE SOURCE WARNING; Re-verify these paths with every release
532
+ .Demo Configurations in `configs/`
533
+ [cols="2m,3"]
534
+ |===
535
+ | jira-customfield.yml
536
+ | Release Notes and Changelog, default sort
537
+
538
+ | jira-description.yml
539
+ | Uses description field instead of custom field for release notes
540
+
541
+ | jira-customfield-resorted.yml
542
+ | Same content as jira-customfield.yml, differently sorted
543
+
544
+ | jira-customfield-changelog.yml
545
+ | Changelog only
546
+
547
+ | jira-customfield-heavy.yml
548
+ | Feature-rich configuration with extensive customization
549
+
550
+ | github-basic.yml
551
+ | Release Notes and Changelog, default sort
552
+
553
+ | github-label-tags.yml
554
+ | GitHub configuration using issue labels for categorization
555
+
556
+ | gitlab-basic.yml
557
+ | Release Notes and Changelog, default sort
558
+
559
+ | gitlab-label-tags.yml
560
+ | GitLab configuration using issue labels for categorization
561
+
562
+ | kitchen-sink.yml
563
+ | Fully loaded configuration demonstrating all available features
564
+ |===
565
+
566
+ Try the following series of commands and steps to see ReleaseHx in action.
567
+
568
+ [NOTE]
569
+ ====
570
+ These commands assume global installation or an <<non-ruby-starter,aliased Docker run command>>.
571
+ They effectively run after alias assignment like:
572
+
573
+ [.testable.hidden]
574
+ alias rhx='bundle exec rhx'
575
+ ====
576
+
577
+ . Check for issues missing release notes.
578
+ +
579
+ [.prompt.testable]
580
+ rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --check
581
+ +
582
+ Out of the box, there are two issues in the `jira-customfield-note-1.1.0.json` file that are marked `release_note_needed` yet have no release note filled out.
583
+
584
+ . Generate a YAML draft.
585
+ +
586
+ [.prompt.testable]
587
+ rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --yaml
588
+
589
+ . Edit the YAML draft in any way, then save.
590
+
591
+ . Add release notes to the two issues that were missing them in `_payloads/jira-customfield-note-1.1.0.json`.
592
+
593
+ . Update the YAML draft with the new issues.
594
+ +
595
+ [.prompt.testable]
596
+ rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --append
597
+
598
+ . Generate a Markdown draft.
599
+ +
600
+ [.prompt.testable]
601
+ rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --md
602
+
603
+ . Edit the Markdown draft in any way.
604
+
605
+ . Generate HTML and PDF output.
606
+ +
607
+ [.prompt.testable]
608
+ rhx 1.1.0 --config configs/jira-customfield.yml --api-data _payloads/jira-customfield-note-1.1.0.json --html --pdf
609
+
610
+ For more on the demo repo, visit its README at {releasehx_demo_repo}.
611
+
612
+ [[custom-configuration]]
613
+ ==== Custom Configuration
614
+
615
+ Your own application will require at least some customization.
616
+ Once configured, the commands you use day-to-day, or release-to-release, will become relatively simple.
617
+
618
+ [TIP]
619
+ ====
620
+ If you use an LLM client to code, consider having it engage with ReleaseHx's <<mcp-setup,built-in MCP service>>.
621
+ ====
622
+
623
+ If any of the demo configs seems like the right arrangement for you, copy it to your project directory and modify it to further suit your needs.
624
+
625
+ .Example -- copy a demo config and rename it to default
626
+ [.prompt,subs=+attributes]
627
+ cp releasehx-demo/configs/github-basic.yml {app_default_config_path}
628
+
629
+ See the <<config-ref>> for an annotated list of available settings.
630
+
631
+ [[strategy-overview]]
632
+ === Recommended Release History Strategy
633
+
634
+ If you came here without a strong opinion about how to approach managing and publishing a Release History, read our <<rh-strategy>>.
635
+
636
+ If that's *tl;dr*, here are some key points:
637
+
638
+ :rhstrategy_release-history: pass:q[Publish a unified document called something like *_Release History_*, with entries for each sequential release of your product.]
639
+
640
+ :rhstrategy_changelog: pass:q[Publish a *_Changelog_* or *_Change Log_* containing summaries for all user-facing product changes.]
641
+
642
+ :rhstrategy_release-notes: pass:q[Publish a *_Release Notes_* section containing an entry for any user-facing product change that requires _explanation_ or deserves special _highlighting_.]
643
+
644
+ :rhstrategy_changelog-entry: pass:q[Use the *_summary/title field_* of your issue-management system as the draft Changelog entry.]
645
+
646
+ :rhstrategy_release-entry: pass:q[Use a *_custom field_* (Jira) or the *issue body* to designate and draft a release note.]
647
+
648
+ :rhstrategy_tags: pass:q[Use labels in your issue-management system to "`tag`" issues as *_belonging in the Changelog_* or *_needing a release note_* draft.]
649
+
650
+ :rhstrategy_check: pass:q[Use `rhx &lt;v.r.sn&gt; --check` to ensure all issues with a release note requirement have a release note.]
651
+
652
+ :rhstrategy_draft-yaml: pass:q[Generate and edit a *_YAML draft_* of your Release History until all release notes are drafted.]
653
+
654
+ :rhstrategy_draft-markup: pass:q[Generate a *_final draft_* in the format you use for the rest of your docs.]
655
+
656
+ :rhstrategy_publish: pass:q[*_Publish_* your Release History to your website or other distribution channels.]
657
+
658
+ Recommended output:::
659
+ * {rhstrategy_release-history}
660
+ * {rhstrategy_changelog}
661
+ * {rhstrategy_release-notes}
662
+
663
+ Manage issues like so:::
664
+ * {rhstrategy_changelog-entry}
665
+ * {rhstrategy_release-entry}
666
+ * {rhstrategy_tags}
667
+ * {rhstrategy_check}
668
+
669
+ Use these procedures for each version:::
670
+ * {rhstrategy_draft-yaml}
671
+ * {rhstrategy_draft-markup}
672
+ * {rhstrategy_publish}
673
+
674
+ For a more-thorough breakdown, see <<rh-strategy>>.
675
+
676
+ ReleaseHx is flexible enough to conform to nearly any series of steps you may already be following.
677
+ This is merely the recommended approach.
678
+
679
+ [[issue-sources]]
680
+ === Establishing Issues Source
681
+
682
+ ReleaseHx is source agnostic.
683
+ Your release history can start in any of the following sources:
684
+
685
+ * <<jira-issues>>
686
+ * <<github-issues>>
687
+ * <<gitlab-issues>>
688
+ * <<custom-api,Any issue-tracking system with a REST API>>
689
+ // * <<issues-commits,Any combination of Issues and Git commits>>
690
+ // * <<raw-git,Git alone>>
691
+ * <<rhyml,A YAML document ("`RHYML`")>>
692
+
693
+ For each instance of ReleaseHx, you will need to configure one source or combination of sources from which to derive Changelog and Release Note content and metadata.
694
+
695
+ The three cloud services (Jira, GitHub, GitLab) are configured similarly.
696
+
697
+ .Example API configuration in `{app_default_config_path}`
698
+ [source,yaml]
699
+ ----
700
+ api:
701
+ from: jira
702
+ href: https://jira.example.com/rest/api/2
703
+ ----
704
+
705
+ [NOTE]
706
+ If you wish to configure an API other than Jira, GitHub, or GitLab, see <<custom-api>>.
707
+
708
+ [[rest-api-auth]]
709
+ ==== REST API Authentication
710
+
711
+ ReleaseHx uses platform-specific environment variables for API authentication.
712
+ Set the appropriate variables for your platform:
713
+
714
+ [[github-authentication]]
715
+ ===== GitHub Authentication
716
+
717
+ [.prompt]
718
+ export GITHUB_TOKEN="ghp_your_personal_access_token"
719
+
720
+ Creating a GitHub Token::
721
+
722
+ . Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
723
+ . Click "Generate new token (classic)"
724
+ . Select scopes: `repo` (required), `read:org` (optional but recommended)
725
+ . Copy and set the token as shown above
726
+
727
+ [[gitlab-authentication]]
728
+ ===== GitLab Authentication
729
+
730
+ [.prompt]
731
+ export GITLAB_TOKEN="glpat-your_personal_access_token"
732
+
733
+ Creating a GitLab Token::
734
+
735
+ . Go to GitLab → User Settings → Access Tokens
736
+ . Create token with `read_api` scope
737
+ . Copy and set the token as shown above
738
+
739
+ [[jira-authentication]]
740
+ ===== Jira Authentication
741
+
742
+ [source,bash]
743
+ ----
744
+ export Jira_USERNAME="your.email@company.com"
745
+ export Jira_API_TOKEN="your_api_token"
746
+ ----
747
+
748
+ Note the capitalization: `Jira_USERNAME` and `Jira_API_TOKEN` (not `JIRA_*`).
749
+
750
+ Creating a Jira API Token::
751
+
752
+ . Go to https://id.atlassian.com/manage-profile/security/api-tokens
753
+ . Click "Create API token"
754
+ . Use your Atlassian account email as `Jira_USERNAME`
755
+ . Copy the token and set as `Jira_API_TOKEN`
756
+
757
+ [[making-environment-variables-permanent]]
758
+ ===== Making Environment Variables Permanent
759
+
760
+ [TIP]
761
+ ====
762
+ To make environment variables permanent, add them to your shell profile:
763
+
764
+ [source,bash]
765
+ ----
766
+ echo 'export GITHUB_TOKEN=ghp_your_token' >> ~/.zshrc
767
+ source ~/.zshrc
768
+ ----
769
+ ====
770
+
771
+ [[testing-api-authentication]]
772
+ ===== Testing API Authentication
773
+
774
+ Test your API setup using the authentication test suite:
775
+
776
+ [.prompt]
777
+ ruby specs/tests/api-auth-test.rb
778
+
779
+ This validates that your tokens work and can fetch issues from the configured repositories/projects.
780
+
781
+ [[security-considerations]]
782
+ ===== Security Considerations
783
+
784
+ [IMPORTANT]
785
+ ====
786
+ * Never commit API tokens to version control
787
+ * Use tokens with minimal required permissions
788
+ * Rotate tokens regularly
789
+ * Consider using separate tokens for testing vs. production
790
+ ====
791
+
792
+ For detailed API setup instructions and troubleshooting, see link:specs/tests/API-INTEGRATION-SETUP.adoc[API Integration Setup Guide].
793
+
794
+ [[advanced-environment-variable-configuration]]
795
+ ===== Advanced Environment Variable Configuration
796
+
797
+ ReleaseHx uses a **layered approach** to environment variable handling that provides flexibility for both simple setups and advanced configurations:
798
+
799
+ . *App Configuration Layer* (`config.origin.auth.*`)
800
+ . *Standard Environment Variables* (`RELEASEHX_API_*`)
801
+ . *Service-specific Environment Variables* (`GITHUB_TOKEN`, `GITLAB_TOKEN`, etc.)
802
+ . *Default Values* (in API client definitions)
803
+
804
+ Standard ReleaseHx variables::
805
+ +
806
+ --
807
+ ReleaseHx defines these standard environment variable names as defaults:
808
+
809
+ [source,bash]
810
+ ----
811
+ export RELEASEHX_API_KEY="your_api_token" # API key/token
812
+ export RELEASEHX_API_USER="your_username" # Username (for Jira)
813
+ export RELEASEHX_API_ORG="your_organization" # Organization
814
+ ----
815
+ --
816
+
817
+ Configuration override::
818
+ +
819
+ --
820
+ You can override which environment variables to use in your app configuration:
821
+
822
+ [source,yaml]
823
+ ----
824
+ api:
825
+ from: github
826
+ auth:
827
+ key_env: GITHUB_TOKEN # Use GitHub-specific variable instead
828
+ ----
829
+ --
830
+
831
+ Template Variable Access::
832
+ +
833
+ --
834
+ API client templates access environment variables using this pattern:
835
+
836
+ [source,liquid]
837
+ ----
838
+ # Primary: Use configured environment variable name
839
+ {{ env[origin.auth.key_env] }}
840
+
841
+ # Fallback: Use service-specific environment variable
842
+ {{ env[origin.auth.key_env] | default: env.GITHUB_TOKEN }}
843
+ ----
844
+ --
845
+
846
+ This layered approach ensures compatibility with both standardized ReleaseHx environment variables and existing service-specific naming conventions.
847
+
848
+ [[jira-issues]]
849
+ ==== Jira Issues
850
+
851
+ ReleaseHx can connect to the Jira REST API to fetch issues that match the release version.
852
+
853
+ The Issue *summary* field is used to draft the Changelog/title, and a custom field called `release_note` is used for the Release note.
854
+
855
+ [TIP]
856
+ Alternatively, configure your custom field with *<<conf_ppty_conversions_note_custom_field>>*.
857
+
858
+ In Jira, what ReleaseHx calls "`tags`" can be assigned using either Jira labels or checkbox custom fields.
859
+
860
+ [[jira-adf-support]]
861
+ ===== ADF (Atlassian Document Format) Support
862
+
863
+ ReleaseHx provides full support for Jira's ADF format used in Jira Cloud API.
864
+
865
+ Issue descriptions and custom fields return rich text content in ADF (JSON format).
866
+ ReleaseHx automatically detects ADF and converts it to Markdown, which can then be further converted to AsciiDoc, HTML, or PDF.
867
+
868
+ Supported ADF Elements::
869
+
870
+ * *Text formatting* (bold, italic, code, links, strikethrough)
871
+ * *Paragraphs and headings* (headings excluded from release notes by default)
872
+ * *Lists* (bullet lists, ordered lists, task lists, including nested lists)
873
+ * *Code blocks* with language syntax
874
+ * *Blockquotes*
875
+ * *Panels* (converted to AsciiDoc admonitions: NOTE, TIP, WARNING, CAUTION)
876
+ * *Tables* (converted to AsciiDoc/Markdown tables)
877
+ * *Hard breaks* and horizontal rules
878
+
879
+ Configuration for ADF::
880
+ +
881
+ --
882
+ .Configure note extraction
883
+ [source,yaml]
884
+ ----
885
+ origin:
886
+ source: jira
887
+
888
+ sources:
889
+ note_heading: "Release Note" # For description-based extraction
890
+ # OR
891
+ note_custom_field: customfield_10039 # For custom field-based
892
+ ----
893
+
894
+ For *description-based* release notes, use `sources.note_heading` to specify the heading that marks the release note section (e.g., "Release Note", "Draft Release Note").
895
+ The converter will extract everything after that heading until the next same-level heading.
896
+
897
+ For *custom field-based* release notes, the entire ADF content in the custom field is converted to Markdown.
898
+ No heading extraction is performed.
899
+ --
900
+
901
+ See link:{releasehx_demo_repo}[releasehx-demo] repository for working examples with ADF payloads and configurations.
902
+
903
+ [[github-issues]]
904
+ ==== GitHub Issues
905
+
906
+ ReleaseHx can connect to the GitHub Issues API to fetch issues from the release version.
907
+
908
+ The issue *title* field is used to draft the Changelog/title, and any text in the body that follows text like `# Release Note` is used for the Release note.
909
+
910
+ In GitHub, what ReleaseHx calls "`tags`" can be assigned using labels or checkboxes embedded after the Release Note text.
911
+
912
+ [[gitlab-issues]]
913
+ ==== GitLab Issues
914
+
915
+ ReleaseHx can connect to the GitLab Issues API to fetch issues from the release version.
916
+
917
+ The issue *title* field is used to draft the Changelog/title, and any text in the body that follows text like `# Release Note` is used for the Release note.
918
+
919
+ In GitLab, what ReleaseHx calls "`tags`" can be assigned using labels or checkboxes embedded after the Release Note text.
920
+
921
+ [[custom-api]]
922
+ ==== Custom API
923
+
924
+ ReleaseHx is extensible.
925
+ While it officially supports Jira, GitHub, and GitLab, you can configure it to connect to any issue-tracking system with a REST API.
926
+
927
+ Use the application config file to designate an API endpoint and any required authentication.
928
+ Then provide a mapping file at `_mappings/<api_from_name>.yml` (or the path configured at *<<conf_ppty_paths_mappings_dir>>*) to define the data conversion to RHYML.
929
+
930
+ See <<custom-rest-config>> for details.
931
+
932
+ // [[issues-commits]]
933
+ // ==== Issues Plus Git Commits
934
+
935
+ // Assuming your Jira instance is integrated with your Git host (which is automatically the case if you use GitLab or GitHub Issues) and you are working in the related repository, you can connect issues to Git commits.
936
+
937
+ // When sourcing Release Note content from Git commits, you will need a few config settings.
938
+
939
+ // .Example `{app_default_config_path}` properties
940
+ // [source,yaml]
941
+ // ----
942
+ // conversions:
943
+ // note: commit_message
944
+ // pattern: '^RELEASE NOTE:'
945
+ // summary: commit_message
946
+ // ----
947
+
948
+ // If `note` is set to `commit_message`, ReleaseHx will extract the content from everything following the `pattern` text in the commit message referenced by the commit SHA/hash in the Issue metadata.
949
+ // To use the entire "`body`" of the commit message as the note, set the `pattern` to `^`.
950
+
951
+ // [NOTE]
952
+ // ReleaseHx expects commit messages to be formatted with the summary/header on the first line, followed by a blank line, then the body.
953
+ // Note content is expected to be the entire body or embedded at the end of it, delineated by the value of [.ppty]*<<conf_ppty_conversions_note_pattern>>*.
954
+
955
+ // If you are not using content from the Git commit as your Changelog/Release Notes entry material, the relationship is just for metadata.
956
+ // Release notes and Changelog entries can reference and/or link to the Git commit when so configured.
957
+ // To enable this, fill out the [.ppty]*<<conf_ppty_links_web>>* and [.ppty]*<<conf_ppty_links_git>>* properties in your config file.
958
+
959
+ // During drafting, ReleaseHx will strip from the `note` property any lines that begin with `#`.
960
+
961
+ // [[raw-git]]
962
+ // ==== Raw Git Commits
963
+ // NOT YET SUPPORTED
964
+
965
+ // You can source a Release History entirely inside Git commits, with largely the same capacity, as long as you are willing to format your commits precisely.
966
+
967
+ // See the explanation in <<issues-commits>> for designating Release Note content in a commit message "`body`", but note you may also replace the labels/tags aspect of issue-management systms, as follows.
968
+
969
+ // Use `\#tagname` or `#tagkind:taglabel` strings to assign tags.
970
+ // ReleaseHx can be configured to detect such tags anywhere in the commit message "`body`", but will strip from the `note` property content any lines that begin with `#`.
971
+
972
+ // During drafting, ReleaseHx will drop from the final note any line that begins with a `#` character from the content, including a line that might be `#changelog`.
973
+
974
+ // The limitations of working this way should be obvious.
975
+ // It is difficult and typically unwise to edit commits after they have been merged, so tags and such would need to be added to the initial merge commit for the changed feature itself.
976
+
977
+ // .Example Git commit string ReleaseHx can parse
978
+ // ....
979
+ // commit a3b14d8e9c2f5e7b0d1a2c3d4e5f6a7b8c9d0e1
980
+ // Author: John Smith <jsmith@example.com>
981
+ // Date: Thu Mar 21 15:32:14 2024 -0400
982
+
983
+ // Add new user authentication flow
984
+
985
+ // Introduces a complete overhaul of the user authentication system.
986
+
987
+ // RELEASE NOTE:
988
+ // The login process now supports multi-factor authentication and single sign-on options.
989
+ // Users will need to re-authenticate on their next login to set up these new security features.
990
+
991
+ // #breaking #highlight #type:improvement #component:auth #component:ui
992
+ // ....
993
+
994
+ // This method requires more discipline on the part of developers, but it is arguably the most streamlined option, especially for working without an issue-tracking system.
995
+
996
+ [[rhyml]]
997
+ ==== RHYML
998
+
999
+ Use a locally stored YAML file as the source of your Release History and Changelog content.
1000
+ This is essentially the same document that is drafted from a REST API source by the `--yaml` flag for the `rhx` command.
1001
+
1002
+ [NOTE]
1003
+ RHYML is referred to as an API source throughout most ReleaseHx documentation, even though it is not a remote/HTTP API.
1004
+
1005
+ All issues associated with a given release are nested together under a `work:` property without further hierarchy.
1006
+ Since the entries are _data_, they can be organized here however you wish, then re-sorted upon generating a Markdown or AsciiDoc draft, or going directly to PDF or HTML.
1007
+
1008
+ The advantage of this method is working without an API.
1009
+ Contributors can simply add their notes to a unified file via Git, and that file can be edited in place.
1010
+
1011
+ The RHYML content can be connected to Issues and Git commits, but only tangentially.
1012
+ The summary and note content needs to be listed in the YAML document.
1013
+ Links back to the source issue or commit are possible but optional.
1014
+
1015
+
1016
+ [[usage]]
1017
+ == Usage
1018
+
1019
+ ReleaseHx can either be used as a command-line tool or as a Ruby library.
1020
+ In both cases it can be powerfully configured with regard to its source matter and its output formats.
1021
+
1022
+ We will first look at what ReleaseHx can _do_, then we will explore _how_ to make ReleaseHx achieve these goals.
1023
+
1024
+ [[terms-of-art]]
1025
+ === Terminology
1026
+
1027
+ ReleaseHx settles on some "`terms of art`" to describe its various components and operations.
1028
+ Let's examine these in order to reduce confusion.
1029
+
1030
+ [[text-transformation-terms]]
1031
+ ==== Text Transformation Terms
1032
+
1033
+ draft/drafting::
1034
+ The process of creating a file in lightweight markup format, such as AsciiDoc, Markdown, or YAMLL, _which is intended to be manually edited by the user_.
1035
+ Drafting operations happen to use templates to _render_ output, but we use the term _draft_ whenever the output format is lightweight markup intended for manual editing.
1036
+
1037
+ enrich/enrichment::
1038
+ These terms describe the process of turning data or a draft into a rich-text output format, such as HTML or PDF.
1039
+ +
1040
+ Some utilities consider this "`rendering`", but _render_ is a term hard-coded into Liquid and Tilt operations, so we use it to describe the act of generating text with a templating engine.
1041
+ Likewise, the term "`convert`" is integral to Asciidoctor and Pandoc operations, and we don't want to confuse them.
1042
+
1043
+ render/rendering::
1044
+ The final step in converting a template (such as Liquid and ERB) into its target format (such as Markdown, AsciiDoc, or HTML).
1045
+ Render operations transform textual content but do not necessarily change formats.
1046
+ The focus is on the _process_, not the output.
1047
+ +
1048
+ In ReleaseHx, you will see this mostly in the context of templated configuration fields and the like, even though _drafting_ operations all technically involve rendering.
1049
+
1050
+ convert/conversion::
1051
+ Generally the transformation from one file format to another.
1052
+ We reserve these terms for specific use with respect to third-party tools such as Asciidoctor and Pandoc.
1053
+ Converters read _standardized markup_ to produce a wide variety of outputs.
1054
+ This typically means converting Markdown or AsciiDoc to HTML or PDF, but it is also used to refer to transforming Markdown to AsciiDoc and other such operations.
1055
+
1056
+ [[issues-changes-versions-and-releases]]
1057
+ ==== Issues, Changes, Versions, and Releases
1058
+
1059
+ We use the term _issues_ to describe the tasks tracked by your cloud-based issue-management system (IMS), such as Jira or GitHub Issues.
1060
+
1061
+ A _change_ is the ReleaseHx term for the report that something is changed in the subject product.
1062
+
1063
+ ReleaseHx uses _issue_ to refer to the state in the source/API, and _change_ to refer to the record of a product change in *RHYML* -- the Release History YAML-based Modeling Language.
1064
+ Issues get turned into changes, a subtle but important difference.
1065
+
1066
+ Likewise, _version_ and _release_ are somewhat interchangeable.
1067
+ _Version_ is the associative reference, typically the way software changes are identified in Git (branch), GitHub Issues (`milestone`) or Jira (`fixVersion`).
1068
+
1069
+ Whereas _release_ is more of the concept of a revision of the subject product, and it is represented by a property in RHYML listed in an Array called `releases`.
1070
+
1071
+ Typically, ReleaseHx refers to a _release_ as the subject of a "`Release History`", and _version_ or version `code` is the way a release is identified.
1072
+
1073
+ A _code_ is the literal string used to identify a version or release.
1074
+ In RHYML, `code` is the property of a _release_ that identifies the _version_.
1075
+
1076
+ [[api-and-source-disambiguation]]
1077
+ ==== API and Source Disambiguation
1078
+
1079
+ REST API::
1080
+ A remote, HTTP-based service, in our case used as the source for _issue_ data.
1081
+ In certain contexts, this is shorthanded as simply _API_.
1082
+
1083
+ ReleaseHx API::
1084
+ The Ruby library that provides the ReleaseHx functionality for downstream Ruby applications, including the `rhx` CLI (command-line interface).
1085
+
1086
+ source::
1087
+ In ReleaseHx parlance, this is the means, location, and format of the data that will be used to generate a Release History.
1088
+ Typically a REST API, this could also be a local YAML file or a Git repository.
1089
+
1090
+ API client::
1091
+ A local utility or component that is able to connect to a REST API and retrieve data from it.
1092
+
1093
+ [[output-strategy]]
1094
+ === Output Strategy
1095
+
1096
+ You can output ReleaseHx-generated histories as HTML or PDF, each with styling capabilities.
1097
+
1098
+ Other options include which history types to output: Changelog, Release Notes, or hybrid.
1099
+ If outputting both sequentially, in which order, and what exactly to include in each resource.
1100
+
1101
+ [NOTE]
1102
+ If all you ever want to report is a 1-line summary of changes, you just need a Changelog.
1103
+
1104
+ Some logic rules that may help you decide:
1105
+
1106
+ Upstream/Source rules::
1107
+
1108
+ . Any issue with a Release Note entry will also be included in the Changelog.
1109
+ . For issues with no Release Note entry, a `changelog` label or checkbox is needed for inclusion.
1110
+
1111
+ Output rules/policies::
1112
+
1113
+ . Changelog entries will link to any corresponding release note.
1114
+ . Changelogs and Release Notes sections may be organized and ordered distinctly.
1115
+ . The entries within each section (Changelog or Release Notes) may be arranged and sorted according to different rules.
1116
+
1117
+ [[output-configuration]]
1118
+ ==== Output Configuration
1119
+
1120
+ For designating _what_ to output, the following blocks or properties in the config file are relevant:
1121
+
1122
+ `history`::
1123
+ This block defines the overall document and establishes defaults that apply to `notes` and `changelog` sections.
1124
+
1125
+ `notes`::
1126
+ This block defines the Release Notes output.
1127
+
1128
+ `changelog`::
1129
+ This block defines the Changelog output.
1130
+
1131
+ For more, see <<config-ref>> and <<advanced-template-configuration>>.
1132
+
1133
+ [[output-templates]]
1134
+ ==== Output Templating
1135
+
1136
+ Place templates in the directory established in `*paths.templates_dir*` in the config (defaults to `./_templates`).
1137
+
1138
+ Templates replace their namesakes built into the ReleaseHx application or API.
1139
+
1140
+ By default, ReleaseHx expects templates to be formatted in link:https://shopify.github.io[Liquid], but it uses the Jekyll-enhanced Liquid 4.
1141
+ See <<templating>> for details.
1142
+
1143
+ [[sourcing-strategy]]
1144
+ === Sourcing Strategy
1145
+
1146
+ Where will your release history content come from, and in what format(s) will you _edit_ it?
1147
+
1148
+ [[source-issue-tracking]]
1149
+ ==== Issue-tracking Source
1150
+
1151
+ If your team uses a supported issue-management system (Jira, GitHub Issues, or GitLab Issues), you will almost certainly wish to integrate that platform.
1152
+
1153
+ Additionally, assuming your team uses Git, you _may_ wish to derive content from Git commits.
1154
+ This is only the case if your commit messages are suited to including drafts of release notes or changelog entries, which is fairly rare.
1155
+
1156
+ Generally, you will derive change summaries, notes, and metadata from your IMS, but hybrid sourcing (with Git) is readily configurable.
1157
+ Since you operate ReleaseHx in your product repository, it _uses Git directly on your system_ rather than relying on your cloud-hosted Git service.
1158
+
1159
+ [[source-flat-file]]
1160
+ ==== Local Flat-file Source
1161
+
1162
+ Once the relevant "`issues`" have been derived from your API or Git, they become "`changes`" in ReleaseHx terminology, and they are held as a data object in RHYML format.
1163
+
1164
+ At this point, these changes can be converted to YAML, Markdown, or AsciiDoc so you can tinker with them.
1165
+ This process is called "`drafting`" -- it compiles your changes into one document.
1166
+
1167
+ The recommended procedure is to use YAML at this phase.
1168
+ Only the YAML format maintains the changes as data and as a single source of truth.
1169
+ If you make a change in the RHYML/YAML document, you can still readily convert to Markdown or AsciiDoc at any point.
1170
+
1171
+ Edit-at-source method::
1172
+ However, if you are confident in the overall shape of your issues at the source, drafting directly to Markdown or AsciiDoc, or even converting directly to HTML or PDF, are available options.
1173
+ +
1174
+ Indeed, _if you wish to do all of your editing in the IMS interface_, this is the way to go.
1175
+ You can generate Markdown or HTML, review, and make further changes to the IMS issues, then re-fetch and generate anew.
1176
+
1177
+ [[rh-strategy]]
1178
+ === Recommended Strategy for Release Documentation
1179
+
1180
+ We stand behind the following design principles, but ReleaseHx can enable all this and more.
1181
+
1182
+ We highly recommend the sites link:https://keepachangelog.com[keep a changelog] and link:https://common-changelog.org[Common Changelog] for guidance.
1183
+
1184
+ For guidance on Release Notes authoring, check out link:https://www.releasepad.io/the-complete-guide-to-release-notes-what-are-they-and-what-are-they-used-for/[ReleasePad's "`Complete Guide`"] and link:https://www.prodpad.com/blog/release-notes/[ProdPad's "`How-to`" article], and this link:https://medium.com/@DigitalGov/the-life-changing-magic-of-writing-release-notes-4c460970565[Digital.gov essay].
1185
+
1186
+ {rhstrategy_release-history}::
1187
+ The constituent documents, Changelog and Release Notes, are both part of the Release History.
1188
+ The recommended order is Changelog first, Release Notes second, with links from applicable Changelog entries to corresponding Release Notes.
1189
+ +
1190
+ The hybrid strategy would basically be an annotated Changelog, where every designated summary is listed with relevant metadata and a release note, when available.
1191
+
1192
+ {rhstrategy_changelog}::
1193
+ Any and all changes that affect users _must_ be listed here.
1194
+ +
1195
+ A separate, more complete changelog can be published for developers, with issues marked `internal` also displayed, possibly annotated as such.
1196
+ Using `rhx &lt;v.r.sn&gt; --md --internal` will include internal issues in the (Markdown) draft.
1197
+
1198
+ {rhstrategy_release-notes}::
1199
+ The general rule of thumb is that any change that is not obvious from its summary should have a release note.
1200
+ +
1201
+ Release notes can be fairly involved, including short bulleted lists or tables.
1202
+ Anything longer than a few sentences or a short list or table should link to documentation or a release appendix.
1203
+
1204
+ {rhstrategy_changelog-entry}::
1205
+ Alternatively, use the first line of Git commits or the release-note body as the Changelog entry draft.
1206
+ +
1207
+ If original entries are in present tense or imperative, you can use the [.ppty]*<<conf_ppty_rhyml_pasterize_summ>>* property to convert verbs to past tense.
1208
+
1209
+ {rhstrategy_release-entry}::
1210
+ A distinct field is optimal, but on any platform you can demarcate release-note content with a comment like `<!-- release note +++-->+++` or a heading like `## Release note`.
1211
+
1212
+ {rhstrategy_tags}::
1213
+ Jira supports custom checkboxes, and GitHub/GitLab enable Markdown checboxes, all of which ReleaseHx can scan.
1214
+ +
1215
+ Also mark issues with tags like `breaking`, `deprecation`, `experimental`, `highlight`, and `internal`.
1216
+
1217
+ {rhstrategy_check}::
1218
+ As long as you have marked relevant issues with the `release_note_needed` tag, you can use the `--check` option to ensure all issues with that tag have a release note.
1219
+ +
1220
+ The exact tag is configurable at [.ppty]*<<conf_ppty_tags_release_note_needed>>*.
1221
+
1222
+ {rhstrategy_draft-yaml}::
1223
+ This means generating an RHYML document and editing it in place if release notes are still streaming in from the IMS.
1224
+ Use `--append` to integrate last-minute release notes before generating a final draft.
1225
+
1226
+ {rhstrategy_draft-markup}::
1227
+ When all the release notes have been added, generate a final draft in your preferred lightweight markup format.
1228
+ This is the best place to perform a final once-over and see the content more or less as it will be published.
1229
+ +
1230
+ Generate rich-text drafts as needed.
1231
+ These are easy to overwrite.
1232
+
1233
+ {rhstrategy_publish}::
1234
+ ReleaseHx makes it possible to generate full web pages, but you probably want to situate the content in your static-site generator.
1235
+ +
1236
+ If you wish to edit in one markup format (Markdown or AsciiDoc) but your SSG expects the other format, you can use the flags `--html --no-wrap --frontmatter` to generate the innards of a page, which most SSGs can publish wrapped in an HTML layout.
1237
+
1238
+ These recommendations are of course flexible, but they largely reflect the _default_ setup for a minimally configured ReleaseHx instance.
1239
+ The more your structure and policies deviate from these basic tenets, the more configuration you will need to do.
1240
+
1241
+ But ReleaseHx can probably handle your customizations.
1242
+
1243
+ [[ci-cd-strategy-caveats]]
1244
+ ==== CI/CD Strategy Caveats
1245
+
1246
+ If your team works in a continuous-deployment environment, you may wish to maintain one ongoing Release History.
1247
+
1248
+ To do so, modify your API request template with some logical filter, and always use the `--append` option, drafting to YAML.
1249
+
1250
+ Continuous deployment environments will likely get better treatment in this application prior to the 1.0 release.
1251
+ I just don't have enough experience with them to predict the optimal workflow.
1252
+
1253
+ [NOTE]
1254
+ DocOps Labs' YAML-extension framework (SGYML) will support serializing large Arrays like one might have for an ongoing changelog.
1255
+
1256
+ [[rhx]]
1257
+ === The `rhx` Utility
1258
+
1259
+ For usage outside (or within) a Ruby development environment, ReleaseHx provides the `rhx` command-line tool.
1260
+
1261
+ .Help screen
1262
+ // tag::helpscreen[]
1263
+ // tag::helpscreen_attrs[]
1264
+ :cli_option_message_md: Draft to Markdown
1265
+ :cli_option_message_adoc: Draft to AsciiDoc
1266
+ :cli_option_message_yaml: Draft to YAML
1267
+ :cli_option_message_html: Enrich to HTML
1268
+ :cli_option_message_pdf: Enrich to PDF
1269
+ :cli_option_message_output_dir: Establish base target path for generated files
1270
+ :cli_option_message_api_data: Ingest from a JSON file instead of REST response
1271
+ :cli_option_message_config: Config location (default: ./{app_default_config_path})
1272
+ :cli_option_message_mapping: Alternate API mapping location
1273
+ :cli_option_message_payload: Store payload as JSON file at PATH or default
1274
+ :cli_option_message_fetch: Refresh data from source
1275
+ :cli_option_message_append: Add any new issues to the end of local YAML source
1276
+ :cli_option_message_over: Overwrite any existing files without prompting
1277
+ :cli_option_message_check: Find issues with missing release note
1278
+ :cli_option_message_emptynotes: Set/reverse policy on issues "awaiting notes"
1279
+ :cli_option_message_internal: Include issues marked internal or likewise
1280
+ :cli_option_message_wrap: Enrich HTML with/out head and body tags
1281
+ :cli_option_message_frontmatter: Enrich or draft with/out frontmatter
1282
+ :cli_option_message_manpage: Show the full manpage documentation
1283
+ :cli_option_message_verbose: Express each step to console
1284
+ :cli_option_message_debug: Express each step and show inferred states
1285
+ :cli_option_message_debug_dump: Complete debugging with raw data
1286
+ :cli_option_message_quiet: Suppress all output, including warnings
1287
+ :cli_option_message_version: Display the ReleaseHx version code
1288
+ :cli_option_message_check_long: Scans issues for those missing release notes and reports findings.
1289
+
1290
+ // end::helpscreen_attrs[]
1291
+ [subs="attributes+"]
1292
+ ....
1293
+ Usage: rhx VERSION|FILE [options]
1294
+
1295
+ Options:
1296
+ --md [PATH] {cli_option_message_md}
1297
+ --adoc, --ad [PATH] {cli_option_message_adoc}
1298
+ --yaml, --yml [PATH] {cli_option_message_yaml}
1299
+ --html [PATH] {cli_option_message_html}
1300
+ --pdf [PATH] {cli_option_message_pdf}
1301
+ --output-dir PATH {cli_option_message_output_dir}
1302
+ --api-data PATH {cli_option_message_api_data}
1303
+
1304
+ --config PATH {cli_option_message_config}
1305
+ --mapping PATH {cli_option_message_mapping}
1306
+ --payload PATH {cli_option_message_payload}
1307
+ --fetch {cli_option_message_fetch}
1308
+ --append {cli_option_message_append}
1309
+ --over, --force {cli_option_message_over}
1310
+ --check, --scan {cli_option_message_check}
1311
+ --empty, -e [RULE] {cli_option_message_emptynotes}
1312
+ --internal {cli_option_message_internal}
1313
+ --[no-]wrap {cli_option_message_wrap}
1314
+ --[no-]frontmatter {cli_option_message_frontmatter}
1315
+
1316
+ --manpage, --man {cli_option_message_manpage}
1317
+ --verbose {cli_option_message_verbose}
1318
+ --debug {cli_option_message_debug}
1319
+ --debug-dump {cli_option_message_debug_dump}
1320
+ --quiet {cli_option_message_quiet}
1321
+ --version {cli_option_message_version}
1322
+ ....
1323
+ // end::helpscreen[]
1324
+
1325
+ See <<cli-options-ref>> for detailed descriptions of each option.
1326
+
1327
+ [[workflows]]
1328
+ ==== Potential Workflows
1329
+
1330
+ ReleaseHx enables several workflow combinations for drafting and enriching release histories.
1331
+
1332
+ ....
1333
+ API → Markdown
1334
+ API → Markdown → HTML
1335
+ API → Markdown → PDF
1336
+ API → AsciiDoc
1337
+ API → AsciiDoc → HTML
1338
+ API → AsciiDoc → PDF
1339
+ API → YAML → HTML
1340
+ API → YAML → AsciiDoc → HTML
1341
+ API → YAML → AsciiDoc → PDF
1342
+ API → YAML → Markdown → HTML
1343
+ API → YAML → Markdown → PDF
1344
+ ....
1345
+
1346
+ The *API* element of the above workflows could be a *RHYML* file, in which case the *API → YAML* conversions are unnecessary, as the YAML step in those workflows is a proper RHYML document already.
1347
+
1348
+ .Why RHYML drafts?
1349
+ ****
1350
+ Some reasons you might wish to use *RHYML (YAML) drafts* as an interim state:
1351
+
1352
+ If you expect late-arriving issues, but you want to get started copy editing the ones that exist.
1353
+
1354
+ Going directly from YAML to HTML gives more control over the final output, as Markdown and even AsciiDoc are quite limited in the semantic HTML they can produce.
1355
+
1356
+ You may even come to prefer editing serialized short content in YAML, as I have.
1357
+ ****
1358
+
1359
+ Most of the workflow cases can be executed using fairly straightforward command combinations.
1360
+
1361
+ Take this *API → Markdown → HTML/PDF* workflow for instance:
1362
+
1363
+ . Ensure all release notes are added in the IMS source.
1364
+ +
1365
+ rhx 2.1.0 --check
1366
+
1367
+ . Create a Markdown draft from API data.
1368
+ +
1369
+ rhx 2.1.0 --md
1370
+
1371
+ . Edit and save the Markdown draft.
1372
+
1373
+ . Enrich HTML and PDF files from the Markdown draft.
1374
+ +
1375
+ rhx 2.1.0 --html --pdf
1376
+
1377
+ But for cases where you wish to draft/edit in YAML and then in Markdown or AsciiDoc, such as *API → YAML → AsciiDoc → HTML/PDF*, the following series of steps is exemplary:
1378
+
1379
+ . Create a YAML draft from API data.
1380
+ +
1381
+ rhx 2.1.0 --yaml
1382
+
1383
+ . Edit and save the YAML draft.
1384
+
1385
+ . Add any newly annotated issues to the end of the YAML draft.
1386
+ +
1387
+ rhx 2.1.0 --append
1388
+
1389
+ . Create an AsciiDoc draft from the YAML draft.
1390
+ +
1391
+ rhx 2.1.0 --adoc
1392
+ +
1393
+ NOTE: ReleaseHx looks for `2.1.0.yml` and creates an AsciiDoc draft like `2.1.0.adoc`.
1394
+
1395
+ . Edit that draft as AsciiDoc and save.
1396
+
1397
+ . Enrich HTML and PDF from the AsciiDoc draft.
1398
+ +
1399
+ rhx 2.1.0 --html --pdf
1400
+ +
1401
+ NOTE: ReleaseHx finds both `2.1.0.yml` and `2.1.0.adoc`, choosing the latter.
1402
+
1403
+ It is also possible to *source directly in RHYML* files and draft to Markdown or AsciiDoc or else directly to HTML/PDF.
1404
+
1405
+ [[cli-sourcing-priority]]
1406
+ ==== CLI Sourcing Priority
1407
+
1408
+ Certain CLI arguments and options will take precedence over others, especially in determining what sources are actively used during a given operation.
1409
+
1410
+ ReleaseHx determines the data source using the following priority order, where higher priority options override lower priority ones:
1411
+
1412
+ .Source Determination Priority (Highest to Lowest)
1413
+ [cols="1,2,3"]
1414
+ |===
1415
+ |Priority |Source Type |How Determined
1416
+
1417
+ |1 |Local YAML file |File path argument ends with `.yml` or `.yaml`
1418
+ |2 |JSON data file |`--api-data PATH` option provided
1419
+ |3 |REST API |Configuration `origin.source` set to `github`, `gitlab`, or `jira`
1420
+ |4 |Default API |Configuration `origin.source` defaults to `json` (requires `--api-data`)
1421
+ |===
1422
+
1423
+ [[source-override-examples]]
1424
+ ===== Source Override Examples
1425
+
1426
+ .Uses configured API (from config)
1427
+ [.prompt]
1428
+ rhx 1.2.0 --md
1429
+
1430
+ .Overrides to use JSON file instead
1431
+ [.prompt]
1432
+ rhx 1.2.0 --api-data issues.json --md
1433
+
1434
+ .Overrides to use YAML file instead
1435
+ [.prompt]
1436
+ rhx _drafts/1.2.0.yml --md
1437
+
1438
+ File extension determines source type directly::
1439
+ [.prompt]
1440
+ rhx my-issues.yml --md
1441
+
1442
+ API data option forces JSON source::
1443
+ [.prompt]
1444
+ rhx 1.2.0 --api-data cached-issues.json --md
1445
+
1446
+ [[source-determination-logic]]
1447
+ ===== Source Determination Logic
1448
+
1449
+ The source determination follows this logic in `CLI#determine_payload_type`:
1450
+
1451
+ . *File Extension Check:* If the identifier (first argument) ends with `.yml` or `.yaml`, use YAML source.
1452
+ . *CLI Option Check:* If `--api-data` option is provided, use JSON source.
1453
+ . *Default to API:* Otherwise, use the REST API source (determined by configuration).
1454
+
1455
+ This allows users to override the configured default source at runtime while maintaining predictable behavior based on file extensions.
1456
+
1457
+ [[cli-options-ref]]
1458
+ ==== Full CLI Options Reference
1459
+
1460
+ The following options are available for the `releasehx`/`rhx` commands.
1461
+
1462
+ // tag::cli_options[]
1463
+ // tag::ai-prompt[]
1464
+ :drafts_path_key: pass:q[Where `&lt;drafts_dir>` is the value of `paths.drafts_dir` in the config, and `&lt;template>` is the value of `templates.drafts_filename` in the config.]
1465
+
1466
+ *--adoc, --ad* [_PATH_]::
1467
+ {cli_option_message_adoc}.
1468
+ Outputs to `<drafts_dir>/<file_template>` or `<PATH>`.
1469
+ +
1470
+ {drafts_path_key}
1471
+
1472
+ *--api-data* _PATH_::
1473
+ {cli_option_message_api_data}.
1474
+ Point to any local JSON source file that is formatted like a response payload for your configured API (see <<conf_ppty_origin_source>>); this overrides the normal REST request even if `--fetch` is argued (though a warning will appear if you pass both options).
1475
+
1476
+ *--append*::
1477
+ {cli_option_message_append}.
1478
+ +
1479
+ When drafting in YAML, adds new issues to the end of the file.
1480
+ Be sure to save edits before appending.
1481
+
1482
+ *--check, --scan*::
1483
+ {cli_option_message_check}.
1484
+ {cli_option_message_check_long}
1485
+
1486
+ *--config* _PATH_::
1487
+ {cli_option_message_config}.
1488
+ Use the configuration file at the specified path instead of the default location (`{app_default_config_path}`).
1489
+
1490
+ *--debug*::
1491
+ {cli_option_message_debug}.
1492
+ Conveys all INFO and DEBUG messages.
1493
+
1494
+ *--debug-dump*::
1495
+ {cli_option_message_debug_dump}.
1496
+ Includes all INFO and DEBUG output, as well as raw data objects.
1497
+
1498
+ *--empty, -e* [_RULE_]::
1499
+ {cli_option_message_emptynotes}.
1500
+ +
1501
+ Argue a specific drafting policy, or argue the "`opposite`" policy, for handling issues that are marked as `release_note_needed` but no note is provided.
1502
+ Set a specific rule (`skip`, `empty`, `dump`, or `ai``) to have ReleaseHx include the issue when converting issues to changes, even if no expected note content has been added.
1503
+ +
1504
+ Using `-e dump` will draft the issue with the entire issue body and commit message as the note content, for any qualifying change entry.
1505
+ Whereas `-e ai` will use generative AI to draft note properties from issue body and commit message.
1506
+ +
1507
+ Otherwise use just `--empty` or `-e` to toggle between `skip` and `empty`, if either of those is your default in [.ppty]*<<conf_ppty_rhyml_empty_notes>>*.
1508
+ If your default is `blank`, `dump`, or `ai`, using `--empty` or `-e` with no argument will toggle a `skip` policy.
1509
+
1510
+ *--fetch*::
1511
+ {cli_option_message_fetch}.
1512
+ +
1513
+ Retrieves fresh data rather than using cached/draft files when converting to HTML/PDF.
1514
+ Typically used like:
1515
+ +
1516
+ rhx 1.1.0 --fetch --html
1517
+ +
1518
+ The fetch procedure does write a cached RHYML document before generating final output.
1519
+
1520
+ *--frontmatter, --no-frontmatter*::
1521
+ {cli_option_message_frontmatter}.
1522
+ When generating drafts or enriching to HTML output, _include_ (`--frontmatter`) or _exclude_ (`--no-frontmatter`) frontmatter.
1523
+
1524
+ *--html* [_PATH_]::
1525
+ {cli_option_message_html}.
1526
+ Writes to `<output_path>/<file_template>` or `<PATH>`.
1527
+
1528
+ *--internal*::
1529
+ {cli_option_message_internal}.
1530
+ Include issues marked as internal or similarly restricted when drafting content.
1531
+ Has no effect on enrichment operations.
1532
+
1533
+ *--api-data* _PATH_::
1534
+ {cli_option_message_api_data}.
1535
+ For API responses, this option saves the payload as PATH.
1536
+ During normal output generating, this option writes a copy of RHYML object to PATH.
1537
+
1538
+ *--md* [_PATH_]::
1539
+ {cli_option_message_md}.
1540
+ Outputs to `<drafts_dir>/<file_template>` or `<PATH>`.
1541
+ +
1542
+ {drafts_path_key}
1543
+
1544
+ *--manpage, --man*::
1545
+ {cli_option_message_manpage}.
1546
+ Includes this options reference and other documentation, all in the terminal.
1547
+ +
1548
+ TIP: Use `q` to quit back to prompt.
1549
+
1550
+ *--mapping*::
1551
+ {cli_option_message_mapping}.
1552
+ File must be a valid RHYML mapping config, usually stored at `_mapping/<apiname>.yaml`.
1553
+ +
1554
+ The mapping base directory can be changed in [.ppty]*<<conf_ppty_paths_mappings_dir>>*, but this option must include a complete relative or absolute path.
1555
+
1556
+ *--payload* [_PATH_]::
1557
+ {cli_option_message_payload}
1558
+ If no path is argued, defaults to that set in *<<conf_ppty_paths_payloads_dir>>*.
1559
+
1560
+ *--output-dir* _DIRECTORY_::
1561
+ {cli_option_message_output_dir}.
1562
+
1563
+ *--over, --force*::
1564
+ {cli_option_message_over}.
1565
+ When writing files, overwrite existing files without prompting for confirmation.
1566
+
1567
+ *--pdf* [_PATH_]::
1568
+ Enriches to PDF from default or designated source.
1569
+ Writes to `<output_path>/<file_template>` or `<PATH>`.
1570
+
1571
+ *--scan, --check*::
1572
+ {cli_option_message_check}.
1573
+ {cli_option_message_check_long}.
1574
+
1575
+ *--verbose*::
1576
+ {cli_option_message_verbose} during execution.
1577
+
1578
+ *--version*::
1579
+ {cli_option_message_version}.
1580
+
1581
+ *--wrap, --no-wrap*::
1582
+ {cli_option_message_wrap}.
1583
+ When enriching to HTML, _include_ (`--wrap`) or _exclude_ (`--no-wrap`) the `<head>` and `<body>` tags and their content.
1584
+ For use when the opposite value is set in the config file ([.ppty]*<<conf_ppty_modes_wrapped>>*).
1585
+
1586
+ *--quiet*::
1587
+ {cli_option_message_quiet}.
1588
+
1589
+ *--yaml, --yml* [_PATH_]::
1590
+ {cli_option_message_yaml}.
1591
+ Outputs to `<drafts_dir>/<file_template>` or `<PATH>`.
1592
+ +
1593
+ {drafts_path_key}
1594
+ // end::cli_options[]
1595
+ // end::ai-prompt[]
1596
+
1597
+ [[advanced-rhyml]]
1598
+ === Advanced RHYML
1599
+
1600
+ The RHYML syntax is designed specifically for tracking product changes and collecting them as "`releases`".
1601
+
1602
+ RHYML is also designed particularly for YAML so it can be read, edited, and even authored by humans, including non-programmers.
1603
+
1604
+ A complete Release History is a collection of planned product releases as, including patch releases, so RHYML has blocks for major/minor releases and for their subordinate patch releases.
1605
+
1606
+ The basic RHYML structure is:
1607
+
1608
+ // tag::basic-rhyml-example[]
1609
+ [source,yaml]
1610
+ ----
1611
+ releases: # Optional key to contain multiple releases
1612
+ - # Array (sequence) of releases
1613
+ code: 1.2.1 # Required key for an individual release
1614
+ date: 2025-07-21 # Optional key for release date
1615
+ memo: |
1616
+ A note of any length, formatted as Markdown (default) or AsciiDoc (configured).
1617
+ changes: # Required key for Array of changes
1618
+ - # Array (seqence) of changes
1619
+ chid: 1234 # change ID
1620
+ tick: ACME-API-5678 # issue ticket ID
1621
+ hash: abcdef0123456789abcdef0123456789abcdef01
1622
+ type: feature
1623
+ part: auth
1624
+ summ: Added new user-authentication flow
1625
+ note: |
1626
+ The login process now supports multi-factor authentication and single sign-on options.
1627
+ Users will need to re-authenticate on their next login to set up these new security features.
1628
+ tags: # issue labels
1629
+ - breaking
1630
+ - highlight
1631
+ ----
1632
+ // end::basic-rhyml-example[]
1633
+
1634
+ However, here we will focus on the matter that ReleaseHx deals with: individual, sequential _releases_, which are identically structured whether for major/minor or patch releases, and _changes_ that make up a release entry.
1635
+
1636
+ [NOTE]
1637
+ *_Ruby developers:_*
1638
+ This YAML representation of the RHYML data structure has a Ruby-native counterpart, documented at .
1639
+
1640
+ [[rhyml-release]]
1641
+ ==== Release Entries
1642
+
1643
+ The two required properties for a release are `code` (version ID) and `changes`, but a release can also have a `date` and a `memo`.
1644
+
1645
+ `code`::
1646
+ The version identifier string.
1647
+ (Required.)
1648
+
1649
+ `date`::
1650
+ A proper date formatted as `YYYY-MM-DD`.
1651
+
1652
+ `memo`::
1653
+ An open text field for any description of the release you wish to appear in the overall release entry.
1654
+ Memos can be formatted with Markdown or AsciiDoc.
1655
+ This format must be set either in an individual RHYML file or configured at [.ppty]*<<conf_ppty_rhyml_markup>>*.
1656
+
1657
+ `changes`::
1658
+ Every valid Release object must contain an Array containing at least one change entry.
1659
+ (Required.)
1660
+
1661
+ [[rhyml-change]]
1662
+ ==== Change Entries
1663
+
1664
+ A release may include any number of changes (including zero).
1665
+ Within each "`change`" entry, the following properties are available:
1666
+
1667
+ `chid`::
1668
+ The change identifier.
1669
+ This is a contiguous String (no spaces) that MUST be among all changes in its own release and is recommended to be universally unique (across all releases).
1670
+
1671
+ `tick`::
1672
+ The issue ticket number for the change.
1673
+
1674
+ `hash`::
1675
+ The commit hash for the change.
1676
+
1677
+ `type`::
1678
+ The type of change.
1679
+ Must be registered in the `types` block of the config.
1680
+
1681
+ `part`::
1682
+ The component, interface, feature, or aspect of the product affected by the change.
1683
+ Must be registered in the `parts` block of the config.
1684
+ +
1685
+ NOTE: If more than one part is affected, use the `parts` property instead.
1686
+
1687
+ `parts`::
1688
+ When more than one component, interface, feature, or aspect of the product is affected by the change, and you wish all such "`parts`" to be noted, use this property instead of `part`.
1689
+ All items must be listed in the `parts` block of the config.
1690
+
1691
+ `summ`::
1692
+ A brief summary of the change.
1693
+ Typically used as the Changelog entry.
1694
+
1695
+ `head`::
1696
+ The headline for a release note, if the value of the `summ` property is not preferred.
1697
+ In standard templates, the headline placeholder looks for a `head` property but falls back to `summ`.
1698
+
1699
+ `note`::
1700
+ A note about the change.
1701
+ May include markup formatting.
1702
+
1703
+ `tags`::
1704
+ An array of tags associated with the change.
1705
+ Each must be registered in the `tags` block of the config.
1706
+ Several tags are registered by default, but you can add as many as you like.
1707
+
1708
+ `links`::
1709
+ A list of documentation or marketing links for the change.
1710
+ The `xref` and `href` properties are mutually exclusive; `href` will supersede.
1711
+
1712
+ `lead`::
1713
+ The primary contributor to the change.
1714
+ Associated with a username in the Issues system.
1715
+
1716
+ `auths`::
1717
+ An array of contributors to the change.
1718
+ Each item must have a `user` property that matches a username in the Issues system, and may have a `memo` property to describe the user's role or involvement in the change.
1719
+
1720
+ [[config-ref]]
1721
+ === Application Configuration Reference
1722
+
1723
+ These pertain the to the main configuration file, which is defined specifically for your _application_ of ReleaseHx.
1724
+ By default, the application config is found at `{app_default_config_path}.`
1725
+
1726
+ The full configuration reference is published at link:{releasehx_docs_www}/config-reference{docs_extn}[].
1727
+
1728
+ [[sample-config]]
1729
+ === Sample Application Configurations
1730
+
1731
+ ReleaseHx comes with a complete default configuration file as well as a series of sample configs.
1732
+
1733
+ The complete link:{default-config_www}[default config file] displays default values with commented descriptions of all available properties.
1734
+
1735
+ The various sample configurations stored in the link:{releasehx_demo_repo}/blob/main/configs/[demo repository] may be a good start toward establishing your own setup.
1736
+
1737
+ [[env-vars]]
1738
+ === Environment Variables in ReleaseHx
1739
+
1740
+ The only stated environment variables intended to work with ReleaseHx at this time are those related to user or project private data, mainly for integrating with AIs.
1741
+
1742
+ Most settings for customizing a given instance (application) of ReleaseHx are stored in the config.
1743
+
1744
+ See <<rest-api-auth>> for details on how to set up authentication for the REST API client.
1745
+
1746
+ [[custom-rest-config]]
1747
+ === Custom REST API Client Configuration
1748
+
1749
+ // tag::custom-rest-config[]
1750
+
1751
+ ReleaseHx's API connections are extensible.
1752
+ As long as you can map the JSON payload returned by your preferred issue-management system provider, you are welcome to add it.
1753
+
1754
+ [NOTE]
1755
+ A new API client probably also means a new <<custom-source-rhyml-mapping,issue-mapping configuration>>.
1756
+
1757
+ [TIP]
1758
+ If you use a standard Jira, GitHub Issues, or GitLab Issues setup, you should NOT have to alter this file.
1759
+
1760
+ [NOTE.plea]
1761
+ If you add a non-standard API, please consider <<contributing,contributing it>> upstream to the ReleaseHx project.
1762
+
1763
+ ReleaseHx connects to all upstream REST APIs via YAML-based client configurations.
1764
+
1765
+ For reference, the official configs for the three supported REST APIs are at link:{this_prod_repo}/blob/lib/releasehx/rest/clients/jira.yml[jira.yml], link:{this_prod_repo}/blob/lib/releasehx/rest/clients/github.yml[github.yml], and link:{this_prod_repo}/blob/lib/releasehx/rest/clients/gitlab.yml[gitlab.yml].
1766
+
1767
+ To override any of these or to add your own, place a file at `.releasehx/rest/clients/<hostslug>.yml`.
1768
+ Make sure it conforms to the schema defined in `specs/data/api-client-schema.yaml`.
1769
+
1770
+ A custom API client configuration has a few main sections:
1771
+
1772
+ `parameters`::
1773
+ Defines the parameters that the client accepts, such as the project ID or the version number.
1774
+
1775
+ `headers`::
1776
+ Defines the HTTP headers to be sent with each request, such as the `Content-Type` or `Authorization` headers.
1777
+
1778
+ `requests`::
1779
+ Defines the API requests that the client can make.
1780
+ Each request has a `verb` (ex: `get`, `post`), a `path` (which can be a Liquid template), and a `params` section that maps the request parameters to the API parameters.
1781
+
1782
+ You can use Liquid templating in the `path` and `params` sections to create dynamic requests.
1783
+ For example, you can use `{{ version }}` to insert the release version into the request path.
1784
+
1785
+ // end::custom-rest-config[]
1786
+
1787
+ [[regex-patterns]]
1788
+ === Regular Expression Pattern Support
1789
+
1790
+ ReleaseHx supports two ways to specify regular expression patterns when called for in configuration and mapping files.
1791
+
1792
+ The traditional regular expression literal format:
1793
+ +
1794
+ [source,yaml]
1795
+ ----
1796
+ note_pattern: '/## Release Notes\n(?<note>.*?)(?=\n##|\z)/ms'
1797
+ ----
1798
+
1799
+ [[pattern-flags]]
1800
+ ==== Pattern Flags
1801
+
1802
+ Common flags used with ReleaseHx patterns:
1803
+
1804
+ `m` (multi-line)::
1805
+ Makes `^` and `$` match line boundaries instead of just start/end of string.
1806
+ Important for matching within paragraphs.
1807
+
1808
+ `s` (dotall)::
1809
+ Makes dot (`.`) match newlines.
1810
+ Often needed for note extraction across paragraphs.
1811
+
1812
+ `i` (case insensitive)::
1813
+ Makes pattern case-insensitive.
1814
+ Rarely needed in ReleaseHx patterns.
1815
+
1816
+ [[example-usage]]
1817
+ ==== Example Usage
1818
+
1819
+ All these are equivalent and will match a Release Note heading and capture its content:
1820
+
1821
+ .Example traditional /pattern/flags
1822
+ [source,yaml]
1823
+ note_pattern: '/## Release Notes?\n(?<note>.*?)(?=\n##|\z)/ms'
1824
+
1825
+ .Example %r{} syntax
1826
+ [source,yaml]
1827
+ note_pattern: '%r{## Release Notes?\n(?<note>.*?)(?=\n##|\z)}ms'
1828
+
1829
+ .Example plain pattern
1830
+ [source,yaml]
1831
+ note_pattern: '## Release Notes?\n(?<note>.*?)(?=\n##|\z)'
1832
+
1833
+ The RegexpUtils module will normalize any of these formats and apply the appropriate flags.
1834
+
1835
+ [[custom-source-rhyml-mapping]]
1836
+ === Custom Source-to-RHYML Mapping
1837
+
1838
+ Another YAML-based format introduced by ReleaseHx is the mapping between (1) the payload from any cloud-based issue-management system (IMS) API and (2) the universal RHYML format.
1839
+ This procedure turns remote _issues_ into local RHYML _changes_.
1840
+
1841
+ The data associated with _issues_ is translated, property-by-property, to its RHYML equivalent, all according to a YAML file.
1842
+
1843
+ Similarly to <<custom-rest-config,REST API client configs>>, initial/default files exist for the major platforms (Jira, GitHub, and GitLab), but these will almost certainly need some customization to suit your particular IMS setup.
1844
+
1845
+ [TIP]
1846
+ If you are just getting started with a project, you might consider using the default mapping to _Define_ how your issue management system is set up; they mostly hue to defaults from each cloud service.
1847
+
1848
+ [IMPORTANT]
1849
+ This mapping case is strictly between the cloud service's payload and the generic RHYML data model.
1850
+ Most configuration of output (for drafting or enriching), is handled in the main application config file.
1851
+
1852
+ For reference, the official mapping configs for the three supported REST APIs are at:
1853
+
1854
+ * link:{this_prod_repo}/blob/lib/releasehx/rest/mappings/jira.yaml[jira.yaml]
1855
+ * link:{this_prod_repo}/blob/lib/releasehx/rest/mappings/github.yaml[github.yaml]
1856
+ * link:{this_prod_repo}/blob/lib/releasehx/rest/mappings/gitlab.yaml[gitlab.yaml]
1857
+
1858
+ To override any of these or to add your own, place a file at `.releasehx/rest/mappings/<hostslug>.yml`.
1859
+
1860
+ A mapping file has two main parts: a `$config` block and a set of field mappings.
1861
+
1862
+ `$config`::
1863
+ This block defines the `path_lang` (either `jmespath` or `jsonpath`) used to traverse the API payload and a `changes_array_path` which is the path to the array of issues within the payload.
1864
+
1865
+ Field Mappings::
1866
+ Each subsequent top-level key in the mapping file corresponds to a field in the RHYML `change` object (ex: `tick`, `summ`, `note`).
1867
+ Each mapping specifies how to derive the value for that RHYML field from the source issue payload.
1868
+ This is done using a `path` and an optional `tplt` (template) or `ruby` script.
1869
+
1870
+ * `path`: An expression in the declared `path_lang` (`jmespath` or `jsonpath`) to extract the raw value from the issue payload.
1871
+
1872
+ * `tplt`: A Liquid template to format the extracted value.
1873
+ The extracted value is available as the `{{ path }}` variable.
1874
+
1875
+ * `ruby`: A Ruby script to perform more complex transformations.
1876
+ The extracted value is available in the `path` local variable.
1877
+
1878
+ [[sandboxed-ruby-transformations]]
1879
+ ==== Sandboxed Ruby Transformations
1880
+
1881
+ The `ruby` key provides a powerful way to perform complex data transformations using a secure, sandboxed Ruby environment.
1882
+ This sandbox is powered by the `SchemaGraphy::SafeTransform` class, which ensures that only an explicit allowlist of safe methods and language features can be used.
1883
+
1884
+ [[sandboxed-ruby-context]]
1885
+ ===== Execution Context
1886
+
1887
+ Within the `ruby` script, the following variables are available:
1888
+
1889
+ * `path`:: The value extracted by the corresponding `path` expression for the current field.
1890
+ * `issue`:: The full JSON object for the issue being processed.
1891
+ * `config`:: The complete application configuration hash.
1892
+
1893
+ [[sandboxed-ruby-helpers]]
1894
+ ===== Available Helper Methods
1895
+
1896
+ You can use a combination of standard Ruby methods and custom helpers within the script.
1897
+ All method calls are validated against a strict allowlist.
1898
+
1899
+ .Allowed Methods
1900
+ [cols="1,3"]
1901
+ |===
1902
+ | Method | Description
1903
+
1904
+ | `dig_path(obj, *keys)`
1905
+ | Safely traverses a nested Hash or Array using a dot-separated path string.
1906
+
1907
+ | `is_a?(obj, klass)`
1908
+ | Checks the class of an object. `klass` must be one of `Array`, `Hash`, `String`, `Integer`, etc.
1909
+
1910
+ | `inspect(obj)`
1911
+ | Returns a string representation of an object for debugging.
1912
+
1913
+ | `reduce(array, initial, &block)`
1914
+ | A safe wrapper around Ruby's `reduce` method.
1915
+
1916
+ | String Methods
1917
+ | `downcase`, `upcase`, `capitalize`, `strip`, `split`, `sub`, `gsub`, `start_with?`, `end_with?`
1918
+
1919
+ | Enumerable Methods
1920
+ | `map`, `select`, `reject`, `any?`, `uniq`, `compact`, `include?`, `empty?`, `size`
1921
+
1922
+ | Operators
1923
+ | `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `>`, `<=`, `>=`
1924
+ |===
1925
+
1926
+ [[sandboxed-ruby-example]]
1927
+ ===== Example
1928
+
1929
+ The following example demonstrates how to extract a "part" from a list of labels in the `path` variable.
1930
+
1931
+ [source,yaml]
1932
+ ----
1933
+ part:
1934
+ path: labels[].name
1935
+ ruby: |
1936
+ labels = is_a?(path, Array) ? path : [path]
1937
+ part_labels = labels.select { |label| label.downcase.start_with?('part:') }
1938
+ part_labels.map { |label| label.sub(/^part:/i, '') }.first
1939
+ ----
1940
+
1941
+ By creating a custom mapping file, you can adapt ReleaseHx to work with any issue tracker that provides a JSON-based REST API.
1942
+
1943
+ [[alternate-mappings-for-legacy-api-structures]]
1944
+ ==== Alternate Mappings for Legacy API Structures
1945
+
1946
+ In some cases, the default mappings for supported APIs may not match your particular issue management setup.
1947
+ This commonly occurs when:
1948
+
1949
+ * Your GitHub Issues don't use native issue types, relying instead on labels like `type:bug`, `type:feature`, or just `bug` and `feature`.
1950
+ * Your GitLab instance has a non-standard label taxonomy.
1951
+ * You need to extract data from different API response fields
1952
+
1953
+ ReleaseHx addresses this through *alternate mapping configurations* that override the default field extraction logic.
1954
+
1955
+ [[github-legacy-label-based-type-extraction]]
1956
+ ===== GitHub Legacy Label-based Type Extraction
1957
+
1958
+ The most common alternate mapping need is for GitHub repositories that don't use native issue types, instead relying on label-based type classification.
1959
+
1960
+ For example, if your GitHub issues use labels like:
1961
+
1962
+ * `type:bug` for bug fixes
1963
+ * `type:feature` for new features
1964
+ * `type:enhancement` for improvements
1965
+
1966
+ Your ReleaseHx application will need an alternate mapping because the default GitHub mapping expects native `issue_type.name` fields.
1967
+
1968
+ An example alternate mapping for label-based GitHub type extraction can be found at:
1969
+
1970
+ `link:{releasehx_demo_repo}/blob/main/_mappings_/legacy-labels/github.yaml[releasehx-demo/_mappings_/legacy-labels/github.yaml]`
1971
+
1972
+ This mapping includes Ruby logic to:
1973
+
1974
+ * Extract types from `labels[].name` instead of `issue_type.name`
1975
+ * Match label values against configured type definitions
1976
+ * Handle label prefixes (ex: `type:`, `kind:`) configured in your application
1977
+
1978
+ [[configuration-changes-for-alternate-mappings]]
1979
+ ===== Configuration Changes for Alternate Mappings
1980
+
1981
+ When using alternate mappings, you may also need to adjust your application configuration:
1982
+
1983
+ Label Prefixes::
1984
+ If your labels use prefixes like `type:bug`, configure the appropriate prefix in your config:
1985
+ +
1986
+ [source,yaml]
1987
+ ----
1988
+ types:
1989
+ label_prefix: 'type:' # Strip 'type:' from labels like 'type:bug'
1990
+ bug:
1991
+ slug: bug
1992
+ text: Bug Fix
1993
+ head: Bug Fixes
1994
+ ----
1995
+
1996
+ Parts Extraction::
1997
+ Similar configuration may be needed for parts/components:
1998
+ +
1999
+ [source,yaml]
2000
+ ----
2001
+ parts:
2002
+ label_prefix: 'part:' # Handle labels like 'part:api', 'part:ui'
2003
+ database:
2004
+ head: database
2005
+ text: Database
2006
+ ui:
2007
+ head: User Interface
2008
+ text: UI
2009
+ ----
2010
+
2011
+ [[using-alternate-mappings]]
2012
+ ===== Using Alternate Mappings
2013
+
2014
+ To use an alternate mapping:
2015
+
2016
+ . Place your custom mapping file in the appropriate directory (ex: `_mappings/github.yaml`) in your ReleaseHx application.
2017
+
2018
+ . Adjust your application configuration for any label prefixes or field differences
2019
+
2020
+ . Test with representative payload data to ensure proper extraction
2021
+
2022
+ The link:{releasehx_demo_repo}[demo repository] contains working examples of these alternate mappings alongside their corresponding configurations and test payloads.
2023
+
2024
+ [NOTE]
2025
+ ReleaseHx by default looks for a mapping file that matches the name of the API you are using.
2026
+ If <<conf_ppty_origin_source>> is set to `github`, ReleaseHx will first check if you have an override at `_mappings/github.yaml` before using the default `github.yaml` built into the application.
2027
+
2028
+ [NOTE]
2029
+ The custom mappings path can be set using <<conf_ppty_paths_mappings_dir>> setting.
2030
+
2031
+ [[templating-guide]]
2032
+ === Templating Guide
2033
+
2034
+ ReleaseHx generally uses enhanced *Liquid 4 templates* to generate new files and content from RHYML and configuration data.
2035
+
2036
+ Notably, it employs *link:https://jekyllrb.com/docs/liquid/[Jekyll's extended tags and filters]*, as well as some additional tag and several filters provided by Sourcerer.
2037
+
2038
+ Here we document the custom filters added by the Sourcerer module and ReleaseHx itself.
2039
+
2040
+ [[advanced-template-configuration]]
2041
+ ==== Advanced Template Configuration
2042
+
2043
+ Before messing with Liquid templates at all, try experimenting with the advanced configuration features available for manipulating the output of your drafts and enriched output.
2044
+
2045
+ Using the ReleaseHx config file, you can manipulate:
2046
+
2047
+ * the order in which Changelog and Release Notes sections appear, or if either does not appear at all
2048
+ * the inclusion or exclusion of internal changes, experimental features, or breaking changes
2049
+ * the formatting of section headers, entry headlines, and metadata fields
2050
+ * the sorting and grouping of entries by type, component, contributor, or tags
2051
+ * the presence and formatting of links to issues, commits, or external documentation
2052
+ * the use of custom "`frames`" for release notes and changelog entries
2053
+ * the display of contributor information, such as lead developer
2054
+ * the configuration of frontmatter
2055
+ * lots more!
2056
+
2057
+ Most of this can be manipulated using the following sections: <<conf_ppty_history>>, <<conf_ppty_changelog>>, <<conf_ppty_notes>>, <<conf_ppty_links>>, as well as within change-metadata config blocks, where you can alter labels, icons, and such: <<conf_ppty_types>>, <<conf_ppty_parts>>, <<conf_ppty_tags>>.
2058
+
2059
+ The various sample configurations found in the link:{releasehx_demo_repo}/blob/main/configs/[demo repository] illustrate many of these options.
2060
+
2061
+ A complete link:{default-config_www}[sample config] displays default values and commented descriptions of all available properties.
2062
+
2063
+ [[liquid-extensions]]
2064
+ [[custom-liquid-tags]]
2065
+ ==== Custom Liquid Tags
2066
+
2067
+ ReleaseHx uses Jekyll's version of the `include` tag, rather than Liquid's.
2068
+ It also supports Jekyll's `include_relative` tag.
2069
+
2070
+ link:https://jekyllrb.com/docs/includes/[See Jekyll's docs for more information.]
2071
+
2072
+ This works essentially like Liquid 5's `render` tag, which is not available in ReleaseHx.
2073
+
2074
+ ReleaseHx supports a tag called `embed` which takes no arguments and works exactly like Liquid's `include` tag.
2075
+ The embedded file has access to all the variables in the parent template and passes any newly created or modified variables back to affect any subsequent content in the parent template.
2076
+
2077
+ [[custom-liquid-filters]]
2078
+ ==== Custom Liquid Filters
2079
+
2080
+ These filters can be added to link:https://shopify.github.io/liquid/[Liquid's prime list of filters] and link:https://jekyllrb.com/docs/liquid/filters[Jekyll's extended filters].
2081
+ Jekyll filters always supercede same-named Liquid filters, including `where`.
2082
+
2083
+ plusify::
2084
+ Replace double line breaks (`+++\n\n+++`) with `+++\n+\n+++`.
2085
+ example:::
2086
+ `{{ note | plusify }}`
2087
+
2088
+ md_to_asciidoc::
2089
+ Uses Kramdown-AsciiDoc (Kramdoc) to convert Markdown to AsciiDoc.
2090
+ arguments:::
2091
+ wrap::::
2092
+ How to handle line wrapping.
2093
+ Can be 'preserve', 'ventilate', or 'none'.
2094
+ The `ventilate` option presents places all sentences on their own lines.
2095
+ example:::
2096
+ `{{ note | md_to_asciidoc: "ventilate" }}`
2097
+
2098
+ render::
2099
+ Renders a string as a Liquid template with the provided variables.
2100
+ arguments:::
2101
+ vars::::
2102
+ A Map (Hash) of variables to pass to the template.
2103
+ example:::
2104
+ `{{ note | render: vars }}`
2105
+
2106
+ indent::
2107
+ Indents each line of the input by the specified number of spaces.
2108
+ arguments:::
2109
+ spaces::::
2110
+ The number of spaces to indent by.
2111
+ line1::::
2112
+ If true, also indents the first line.
2113
+ example:::
2114
+ `{{ note | indent: 2, true }}`
2115
+
2116
+ sgyml_type::
2117
+ +
2118
+ --
2119
+ Returns a string representing the SGYML _kind_ and _class_ of the input, separated by a colon (`:`).
2120
+
2121
+ Response will be one of the following:
2122
+
2123
+ * `Null:nil`
2124
+ * `Scalar:String`
2125
+ * `Scalar:Number`
2126
+ * `Scalar:DateTime`
2127
+ * `Scalar:Boolean`
2128
+ * `Compound:Array`
2129
+ * `Compound:ArrayList`
2130
+ * `Compound:ArrayTable`
2131
+ * `Compound:Map`
2132
+ * `Compound:MapTable`
2133
+ * `unknown:unknown`
2134
+ --
2135
+
2136
+ example:::
2137
+ `{{ id | type_check }}`
2138
+
2139
+ ruby_class::
2140
+ Returns the Ruby class name of the input.
2141
+ example:::
2142
+ `{{ id | ruby_class }}`
2143
+
2144
+ demarkupify::
2145
+ Simplifies any Markdown and AsciiDoc syntax in the inline input.
2146
+ +
2147
+ Strips `*` and `_` quotes, simplifies `+++"`+++` and `+++'`+++` quotes and UTF-8 curly quotes, and removes all backticks.
2148
+ example:::
2149
+ `{{ note | demarkupify }}`
2150
+
2151
+ pasterize::
2152
+ Converts select verbs in the input from present/imperative to past tense.
2153
+ +
2154
+ Replaces common terms like `add`/`adds` with `added`, `fix`/`fixes` with `fixed`, `build`/`builds` with `built`, etc.
2155
+ example:::
2156
+ `{{ summary | pasterize }}`
2157
+
2158
+ inspect_yaml::
2159
+ Returns a YAML representation of the input for debugging purposes.
2160
+ example:::
2161
+ `{{ changes | inspect_yaml }}`
2162
+
2163
+
2164
+ [[troubleshooting]]
2165
+ == Troubleshooting
2166
+
2167
+ Common issues and solutions for ReleaseHx configuration and content generation problems.
2168
+
2169
+ [[empty-or-missing-content]]
2170
+ === Empty or Missing Content
2171
+
2172
+ [[transformed-n-changes-but-no-content-appears]]
2173
+ ==== "Transformed N changes" but no content appears
2174
+
2175
+ Symptoms::
2176
+ ReleaseHx reports successful data transformation (ex:, `INFO: Transformed 5 changes for release 1.1.0`) but generated files contain only headers and template text with no actual issue content.
2177
+
2178
+ Root Cause::
2179
+ Invalid sort configuration syntax in `notes:` or `changelog:` sections.
2180
+
2181
+ Solution::
2182
+ Check your config's `sort:` arrays for invalid `grouping1`/`grouping2`/`grouping3` syntax.
2183
+ +
2184
+ .Invalid sort configuration
2185
+ [source,yaml]
2186
+ ----
2187
+ # Will cause empty content
2188
+ sort:
2189
+ - 'part:grouping1'
2190
+ - 'type:grouping2'
2191
+ ----
2192
+ +
2193
+ .Correct sort configuration
2194
+ [source,yaml]
2195
+ ----
2196
+ sort:
2197
+ - 'part:group'
2198
+ - 'type:group'
2199
+ ----
2200
+
2201
+ [[all-mapped-changes-were-nil-after-transformation]]
2202
+ ==== "All mapped changes were nil after transformation"
2203
+
2204
+ Symptoms::
2205
+ ReleaseHx cannot transform any data from the API payload.
2206
+
2207
+ Root Cause::
2208
+ Incorrect tag filtering excluding all issues, or mapping/payload mismatch.
2209
+
2210
+ Solution::
2211
+ . Check `tags._exclude` lists - never exclude `release_note_needed` (workflow flag)
2212
+ . Verify the payload file exists and matches the expected API format
2213
+ . Ensure custom mappings are correctly specified with `--mapping` option
2214
+ . Test with a simpler config without complex tag filtering
2215
+
2216
+ [[template-processing-issues]]
2217
+ === Template Processing Issues
2218
+
2219
+ [[liquid-syntax-errors-during-template-rendering]]
2220
+ ==== Liquid syntax errors during template rendering
2221
+
2222
+ Symptoms::
2223
+ Errors like `Liquid::SyntaxError` or `Liquid::Error` when generating drafts or enriched output.
2224
+
2225
+ Root Cause::
2226
+ Syntax errors in custom Liquid templates.
2227
+
2228
+ Solution::
2229
+ . Validate Liquid syntax using online validators or IDE plugins
2230
+ . Test templates with minimal content to isolate issues
2231
+ . Review Jekyll's Liquid documentation for supported tags and filters
2232
+
2233
+
2234
+ ifdef::site-gen-jekyll[]
2235
+ [[apis]]
2236
+ == APIs
2237
+
2238
+ Documntation for th ReleaseHx, SchemaGraphy, and Sourcerer APIs is available at:
2239
+
2240
+ * link:/api/releasehx[ReleaseHx API]
2241
+ * link:/api/schemagraphy[SchemaGraphy API]
2242
+ * link:/api/sourcerer[Sourcerer API]
2243
+
2244
+ endif::[]
2245
+
2246
+
2247
+ ifndef::site-gen-jekyll[]
2248
+ // tag::releasehx-api[]
2249
+ [[releasehx-api]]
2250
+ == ReleaseHx API
2251
+
2252
+ While most users will interact with ReleaseHx via the `rhx` command-line tool, the gem can also be used as a library in your own Ruby projects.
2253
+ The full API reference will be available via RDoc comments in the source code.
2254
+
2255
+ Here is a high-level overview of the main components to get you started:
2256
+
2257
+ [[core-data-models-releasehx-rhyml]]
2258
+ === Core Data Models (`ReleaseHx::RHYML`)
2259
+
2260
+ The classes within the `ReleaseHx::RHYML` module are the core data objects for the application.
2261
+
2262
+ `ReleaseHx::RHYML::Release`::
2263
+ Represents a single product release, containing metadata (like version code and date) and a collection of `Change` objects.
2264
+
2265
+ `ReleaseHx::RHYML::Change`::
2266
+ Represents a single change within a release (ex: a bug fix or a new feature), containing properties like a summary, note, type, and tags.
2267
+
2268
+ You will typically create or receive a `Release` object to work with.
2269
+
2270
+ [[creating-a-release-releasehx-draftops]]
2271
+ === Creating a Release (`ReleaseHx::DraftOps`)
2272
+
2273
+ The `ReleaseHx::DraftOps` module provides methods for creating a `Release` object from a source.
2274
+
2275
+ * Use `DraftOps.from_payload` to take a raw JSON payload from an API (like GitHub or Jira) and convert it into a `Release` object, according to a mapping configuration.
2276
+
2277
+ [[generating-output-releasehx-enrichops-and-draftops]]
2278
+ === Generating Output (`ReleaseHx::EnrichOps` and `DraftOps`)
2279
+
2280
+ Once you have a `Release` object, you can generate output files.
2281
+
2282
+ * Use `DraftOps.process_template_content` to generate a lightweight draft (like Markdown, AsciiDoc, or RHYML) from a `Release` object.
2283
+
2284
+ * Use `EnrichOps.enrich_from_rhyml` to generate rich-text output (like HTML or PDF) from a `Release` object.
2285
+
2286
+ * Use `EnrichOps.enrich_from_file` to generate rich-text output directly from a source file (ex: converting `my-release.md` to `my-release.html`).
2287
+ // end::releasehx-api[]
2288
+
2289
+
2290
+ [[development]]
2291
+ == Development
2292
+
2293
+ ReleaseHx is free, open source, and *open for contributions*.
2294
+ Get in touch or open an issue to get involved.
2295
+
2296
+ [NOTE]
2297
+ The remainder of this document refers to _how ReleaseHx is made_ rather than how to use it for your own product.
2298
+
2299
+ [[quickstart]]
2300
+ === Quickstart
2301
+
2302
+ To work with ReleaseHx source, clone both repositories side by side for the most effective development workflow.
2303
+
2304
+ . Clone both repositories.
2305
+ +
2306
+ [.prompt]
2307
+ git clone {releasehx_prod_repo}
2308
+ git clone {releasehx_demo_repo}
2309
+ +
2310
+ This will give you `<source_dir>/releasehx` and `<source_dir>/releasehx-demo`, side by side.
2311
+
2312
+ [[building-the-releasehx-gem]]
2313
+ ==== Building the ReleaseHx Gem
2314
+
2315
+ From the `releasehx` repository:
2316
+
2317
+ . Install dependencies and build the gem locally.
2318
+ +
2319
+ [.prompt]
2320
+ cd releasehx
2321
+ bundle install
2322
+ bundle exec rake build
2323
+ +
2324
+ This creates the gem file in the `pkg/` directory.
2325
+
2326
+ . Install the locally built gem for testing.
2327
+ +
2328
+ [.prompt]
2329
+ gem install pkg/releasehx-*.gem
2330
+ +
2331
+ Alternatively, for development testing without installing:
2332
+ +
2333
+ [.prompt]
2334
+ bundle exec bin/rhx --version
2335
+
2336
+ . Run the test suite to verify functionality.
2337
+ +
2338
+ [.prompt]
2339
+ bundle exec rake spec
2340
+
2341
+ [[working-with-the-demo-repository]]
2342
+ ==== Working with the Demo Repository
2343
+
2344
+ From the `releasehx-demo` repository:
2345
+
2346
+ . Install the latest gem version (published or local).
2347
+ +
2348
+ [.prompt]
2349
+ cd releasehx-demo
2350
+ bundle install
2351
+ +
2352
+ If testing a local gem build, update the `Gemfile` to point to your local gem path.
2353
+
2354
+ . Execute `releasehx` commands against demo data.
2355
+ +
2356
+ [.prompt]
2357
+ bundle exec rhx <your arguments and options>
2358
+ +
2359
+ Replace `<your arguments and options>` with whatever you are testing.
2360
+ See the `releasehx-demo` repo's README for example commands.
2361
+
2362
+ . Generate sample outputs (for the `samples` branch).
2363
+ +
2364
+ .Example commands to generate outputs
2365
+ [.prompt]
2366
+ bundle exec rhx draft --source github --version v1.2.0
2367
+ bundle exec rhx enrich --input _drafts/v1.2.0.rhyml --format html
2368
+ +
2369
+ By convention/default, drafts are written to `_drafts/` and rich-text outputs to `_publish/`.
2370
+ These directories are ignored on the `main` branch but form the entire content of the `samples` branch.
2371
+
2372
+ [[background]]
2373
+ === Project Background
2374
+
2375
+ ReleaseHx is my fourth or fifth time tackling this problem, though in previous cases I had the misfortune (luxury?) of solving it for one company at a time, and never in such a robust way that the results would be worth open sourcing.
2376
+
2377
+ All of my employers and clients in the past 10 years needed a system like this, and some of them paid me to make one.
2378
+ But before all that, I inherited a Python script that converted Jira issue fields into AsciiDoc, for enriching to PDF and HTML.
2379
+
2380
+ [NOTE]
2381
+ All of the code in this repository is original to this instance of my work in the broader problem/solution space.
2382
+ The ReleaseHx codebase involves no licensing infringements whatsoever.
2383
+
2384
+ Using and hacking at that script for years of documenting GA releases for an entire enterprise software product made me appreciate the need for cloud sourcing and automation, for the benefit of all stakeholders.
2385
+
2386
+ I also spent years hanging in the #release-notes channel of the link:https:writethedocs.org/slack[Write the Docs Slack], over and over again advising technical writers on this broad problem space.
2387
+ "`How do you convert Jira tickets to release notes?`" or "`How do you automate a changelog from Git or GitHub Issues?`" are typical inquiries there.
2388
+
2389
+ The short answer is:
2390
+
2391
+ . Use your team's preferred scripting language to:
2392
+ [lowerroman]
2393
+ .. connect to the REST API, then
2394
+ .. download issues for the upcoming release, then
2395
+ .. extract release notes from some pre-designated part of the issue data.
2396
+ . Use your team's favorite template engine to enrich notes or log entries into your preferred lightweight markup:
2397
+ .. Markdown *or*
2398
+ .. AsciiDoc
2399
+ . Edit the content manually in Markdown/AsciiDoc, then:
2400
+ .. commit it to your existing docs SSG *or*
2401
+ .. push it to Confluence or the product's deployment pipeline
2402
+
2403
+ Easier said than done, especially for TWs working with scarce developer resources.
2404
+
2405
+ I am unaware of any utility that serves this need broadly and flexibly, and in all these years, nobody has ever recommended one in WTD Slack.
2406
+ Hopefully, ReleaseHx will fill much of this void in an adaptable and repeatable fashion.
2407
+
2408
+ [[ddd]]
2409
+ === Docs-driven Development
2410
+
2411
+ The ReleaseHx gem is an example of README-first development.
2412
+ Not only is the README written in AsciiDoc, and not only is documentation done first in the README during early development, but much of the documentation and product data is single-sourced in the README as AsciiDoc _attributes_.
2413
+
2414
+ This unorthodox approach requires some explanation.
2415
+ This method is probably better suited to large teams, but the point of DocOps Lab's broader approach is this unconventional means of coordinating docs and code.
2416
+
2417
+ At the very beginning of the build procedure for the application's Ruby gem, (1) data is ingested and (2) snippets are harvested from the `README.adoc` file for internal or user-facing purposes in the application.
2418
+
2419
+ For instance, the application version number is derived from the attribute `:this_prod_vrsn:` in the README.
2420
+ See, I can even place it here without fear that it will ever fall out of step:
2421
+ *{this_prod_vrsn}*.
2422
+
2423
+ Additionally, the help screen itself is sourced here in this README and included verbatim -- after converting to rich-text with link:https://asciidoctor.org[Asciidoctor] -- in the CLI's output.
2424
+
2425
+ The application help and manpage documentation is also sourced in this way.
2426
+ (Use `rhx --help` or `rhx --man` to reveal.)
2427
+
2428
+ This capability is provided by the Sourcerer module introduced in this gem but intended to be spun off into it own gem for use in all my (and any of your) Ruby projects in the future.
2429
+
2430
+ [[common-dev-tasks]]
2431
+ === Common Dev Tasks
2432
+
2433
+ Use `bundle exec rake --tasks` to list all available Rake tasks.
2434
+
2435
+ Use `bundle exec rake --tasks | grep -v labdev:` to see just local tasks.
2436
+
2437
+ Here is brief documentation for some key tasks.
2438
+
2439
+ [[add-cli-option]]
2440
+ ==== Add a new CLI Option
2441
+
2442
+ CLI options are not defined in the traditional way.
2443
+ To maintain DRY sourcing, make your changes in the following files:
2444
+
2445
+ . `README.adoc`: Descriptions are single sourced as AsciiDoc attributes:
2446
+ .. Add summary description to the `// tag::helpscreen_attrs[]` block.
2447
+ .. Add detailed description to the `cli-options-ref` section.
2448
+ . `lib/releasehx/cli.rb`
2449
+ .. Use the Thor DSL to define the option, referencing the AsciiDoc attributes for description.
2450
+ .. Add the handling code.
2451
+ . Add tests in `specs/tests/rspec/cli_spec.rb`.
2452
+
2453
+ [[build-the-docs]]
2454
+ ==== Build the Docs
2455
+
2456
+ To build the documentation locally, run the following command from the project root:
2457
+
2458
+ [.prompt]
2459
+ bundle exec rake docs
2460
+
2461
+ This will generate the documentation in the `build/docs` directory.
2462
+
2463
+ [[serve-the-docs]]
2464
+ ==== Serve the Docs
2465
+
2466
+ To serve the documentation locally, run the following command from the project root:
2467
+
2468
+ [.prompt]
2469
+ bundle exec rake serve
2470
+
2471
+ This will start a Jekyll server at http://localhost:8000 by default.
2472
+
2473
+ Use `PORT=NNNN` environment argument to specify a different port.
2474
+
2475
+ [.prompt]
2476
+ PORT=4000 bundle exec rake serve
2477
+
2478
+ ==== DocOps Lab Devtool (`docopslab-dev`)
2479
+
2480
+ Special dev Rake tasks and libraries are available via the `docopslab-dev` gem.
2481
+
2482
+ .List tasks from `docopslab-dev`
2483
+ [.prompt]
2484
+ bundle exec rake --tasks | grep labdev:
2485
+
2486
+ The link:{docopslab_git_www}/lab/tree/main/gems/docopslab-dev/README.adoc[DocOps Lab Devtool] or see `.agent/docs/topics/docpslab-devtool`.
2487
+
2488
+ // tag::releasehx-api[]
2489
+ [[issue-data-mapping]]
2490
+ === Issue-data Mapping
2491
+
2492
+ In designing a domain-specific data model, I had to mimic the logic of the domain, which is dominated by Jira and GitHub, for better or worse.
2493
+ Here is the way fields are mapped/adapated by default for converting _issue_ data to _change_ data.
2494
+
2495
+ // tag::mapping-table[]
2496
+ // tag::ai-prompt[]
2497
+ .Upstream/source issue data mapping table
2498
+ [cols="1a,1a,1a,1a,1a",options=header]
2499
+ |===
2500
+
2501
+ | Jira | GitHub | GitLab | RHYML | Ruby/Liquid
2502
+
2503
+ | N/A
2504
+ | N/A
2505
+ | N/A
2506
+ | `chid`
2507
+ | `chid`
2508
+
2509
+ | `key`
2510
+ | `number`
2511
+ | `iid`
2512
+ | `tick`
2513
+ | `tick`
2514
+
2515
+ | `commit` (custom field, if available)
2516
+ | associated commit hash (via PR merge or commit references)
2517
+ | commit hash from merge request or commit ref
2518
+ | `hash`
2519
+ | `hash`
2520
+
2521
+ | `issuetype` or label matching slug in `types`
2522
+ | `type` or label matching slug in `types`
2523
+ | `issue_type` or label matching slug in `types`
2524
+ | `type`
2525
+ | `type`
2526
+
2527
+ | `component`
2528
+ | label: `component:<component>`
2529
+ | label: `component::<component>` or scoped labels
2530
+ | `part`
2531
+ | `part`
2532
+
2533
+ | `summary`
2534
+ | `title`
2535
+ | `title`
2536
+ | `summ`
2537
+ | `summ`
2538
+
2539
+ | N/A
2540
+ | N/A
2541
+ | N/A
2542
+ | `head`
2543
+ | `head`
2544
+
2545
+ | _custom field_
2546
+ | `+++## Release Note+++` in body
2547
+ | `+++## Release Note+++` in body
2548
+ | `note`
2549
+ | `note`
2550
+
2551
+ | label: `deprecation`
2552
+ | label: `deprecation`
2553
+ | label: `deprecation`
2554
+ | `tags: [deprecation]`
2555
+ | `tags['deprecation']` / `deprecation` Boolean / `.deprecation?`
2556
+
2557
+ | label: `breaking`
2558
+ | label: `breaking`
2559
+ | label: `breaking`
2560
+ | `tags: [breaking]`
2561
+ | `tags['breaking']` / `breaking` Boolean / `.breaking?`
2562
+
2563
+ | label: `experimental`
2564
+ | label: `experimental`
2565
+ | label: `experimental`
2566
+ | `tags: [experimental]`
2567
+ | `tags['experimental']` / `experimental` Boolean / `.experimental?`
2568
+
2569
+ | label: `highlight`
2570
+ | label: `highlight`
2571
+ | label: `highlight`
2572
+ | `tags: [highlight]`
2573
+ | `tags['highlight']` / `highlight` Boolean / `.highlight?`
2574
+
2575
+ | label: `release_note_needed`
2576
+ | label: `release_note_needed`
2577
+ | label: `release_note_needed`
2578
+ | N/A
2579
+ | N/A
2580
+
2581
+ | label: `changelog`
2582
+ | label: `changelog`
2583
+ | label: `changelog`
2584
+ | N/A
2585
+ | N/A
2586
+
2587
+ | `fixVersions`
2588
+ | `milestone`
2589
+ | `milestone`
2590
+ | nested context
2591
+ | `version`
2592
+
2593
+ | `assignee`
2594
+ | `assignee`
2595
+ | `assignee`
2596
+ | `lead`
2597
+ | `lead`
2598
+
2599
+ |===
2600
+ // end::ai-prompt[]
2601
+ // end::mapping-table[]
2602
+
2603
+ Users are not beholden to these mappings.
2604
+ A powerful custom <<custom-source-rhyml-mapping,mapping system>> is available.
2605
+
2606
+ // end::releasehx-api[]
2607
+
2608
+ [[codebase-structure]]
2609
+ === Codebase Structure
2610
+
2611
+ Here is a model of the ReleaseHx gem's codebase.
2612
+ Only major files and directories are displayed, sorted in the order we find most instructive.
2613
+
2614
+ // tag::ai-prompt[]
2615
+ .File tree of key files
2616
+ [source,tree,line-comment=#]
2617
+ ----
2618
+ releasehx.gemspec # Gem definition
2619
+ Rakefile # Build tasks
2620
+ README.adoc # Single source of truth
2621
+ Dockerfile # Docker image definition
2622
+ build/ # Untracked, ephemeral path for generated assets
2623
+ docs/ # Documentation build source (Jekyll, YARD)
2624
+ .config/ # Config files for various tools
2625
+ ├── sourcerer.yml # Sourcerer prebuild manifest
2626
+ └── docopslab-dev.yml # DocOpsLab Devtool config
2627
+ specs/
2628
+ ├── data/ # Schema/definition files
2629
+ │ ├── config-def.yml # Configuration definition
2630
+ │ ├── rhyml-schema.yaml # RHYML schema definition
2631
+ │ ├── api-client-schema.yaml # API client schema definition
2632
+ │ ├── rhyml-mapping-schema.yaml # API -> RHYML schema definition
2633
+ │ └── mcp-manifest.yml # Asset registry for MCP server
2634
+ └── tests/
2635
+ ├── README.adoc
2636
+ ├── rspec/ # RSpec tests
2637
+ └── configs/ # Test configs
2638
+ lib/
2639
+ ├── releasehx.rb # Application core
2640
+ ├── schemagraphy.rb # Special YAML handling
2641
+ ├── sourcerer.rb # Single-sourcing tool
2642
+ ├── docopslab/
2643
+ │ ├── mcp/ # MCP assets and packaging
2644
+ │ └── mcp.rb # DocOpsLab MCP entrypoint
2645
+ ├── releasehx/
2646
+ │ ├── cli.rb # Thor CLI definition
2647
+ │ ├── configuration.rb # CFGYML parsing
2648
+ │ ├── generated.rb # Generated by prebuild (packaged)
2649
+ │ ├── helpers.rb # Utility helpers
2650
+ │ ├── mcp/ # MCP server assets
2651
+ │ ├── mcp.rb # MCP server entrypoint
2652
+ │ ├── README.adoc # Internal developer notes
2653
+ │ ├── rhyml.rb # RHYML entrypoint
2654
+ │ ├── sgyml/ # SGYML helpers
2655
+ │ │ └── helpers.rb # module SgymlHelpers
2656
+ │ ├── transforms/ # Input transformations (ADF, etc)
2657
+ │ ├── version.rb # Version constant
2658
+ │ ├── rest/ # module REST
2659
+ │ │ ├── yaml_client.rb # ReleaseHx::REST::YamlClient class
2660
+ │ │ └── clients/ # YAML files for API clients (jira.yaml, etc)
2661
+ │ ├── ops/ # Main ReleaseHx methods
2662
+ │ │ ├── check_ops.rb # ReleaseHx::CheckOps module
2663
+ │ │ ├── draft_ops.rb # ReleaseHx::DraftOps module
2664
+ │ │ ├── enrich_ops.rb # ReleaseHx::EnrichOps module
2665
+ │ │ ├── template_ops.rb # ReleaseHx::TemplateOps module
2666
+ │ │ └── write_ops.rb # ReleaseHx::WriteOps module
2667
+ │ ├── rhyml/ # module RHYML
2668
+ │ │ ├── adapter.rb # maps from JSON using a mapping file
2669
+ │ │ ├── change.rb # Change class
2670
+ │ │ ├── liquid.rb # Liquid filters for RHYML
2671
+ │ │ ├── release.rb # Release class
2672
+ │ │ ├── loaders.rb # loads RHYML YAML or JSON from disk
2673
+ │ │ ├── mappings/ # API -> RHYML mappings
2674
+ │ │ └── templates/ # RHYML output templates
2675
+ ├── schemagraphy/
2676
+ │ ├── cfgyml/ # CFGYML (OpenCFGY) parsing
2677
+ │ ├── attribute_resolver.rb # Resolves {attribute_name} placeholders
2678
+ │ ├── loader.rb # `SchemaGraphy::Loader`
2679
+ │ ├── regexp_utils.rb # Regular expression utilities
2680
+ │ ├── schema_utils.rb # `get_schema_defaults`, etc
2681
+ │ ├── tag_utils.rb # `detag`, `tag_of`, etc
2682
+ │ ├── templates/ # CFGYML documentation templates
2683
+ │ │ └── cfgyml/ # Config reference templates (+ sample gen)
2684
+ │ └── templating.rb # Defines handling of parsable YAML nodes
2685
+ └── sourcerer/
2686
+ ├── builder.rb # Writes snippets to files at build time
2687
+ ├── jekyll.rb # Jekyll and Liquid handling for Sourcerer
2688
+ ├── plaintext_converter.rb # Pre-processes AsciiDoc source files
2689
+ └── templating.rb # Liquid/ERB template handling
2690
+ ----
2691
+ // end::ai-prompt[]
2692
+
2693
+ [[docopslab]]
2694
+ === DocOpsLab (Module)
2695
+
2696
+ This code is intended to eventually make its way upstream to the `docopslab-dev` gem or more likely a `docopslab-mcp` gem, which is housed in the DocOps/lab monorepo and available to all DocOps Lab projects.
2697
+
2698
+ Either way, this gem will include a wrapper for the link:https://github.com/modelcontextprotocol/ruby-sdk[official Ruby SDK] for link:https://modelcontextprotocol.io/docs/getting-started/intro["`model context protocol`" (MCP)] integration.
2699
+ For now it's easier to test inside the one gem that is making immediate use of the protocol.
2700
+
2701
+ If the MVP pans out (which is uncertain given how weak MCP tech is and how frustrating it was to get it working with various clients), I will upstream it for use in any Ruby projects.
2702
+
2703
+ [[sourcerer]]
2704
+ === Sourcerer
2705
+ // tag::sourcerer[]
2706
+ This gem introduces a module called Sourcerer, by which AsciiDoc files can be parsed and their contents harvested for use in the application build.
2707
+ The module also handles Liquid template processing with enhanced attribute resolution capabilities.
2708
+
2709
+ [NOTE]
2710
+ Sourcerer is intended to be spun off as its own gem once it successfully proves the concept in this gem.
2711
+ It will probably be called _AsciiSourcerer_ and may replace an older and unmaintained utility of mine called LiquiDoc.
2712
+
2713
+ It is invoked in the Rakefile, establishing global namespaces:
2714
+
2715
+ * `ReleaseHx::ATTRIBUTES[:globals]` (derived from this `README.adoc` file)
2716
+ * `ReleaseHx.read_built_snippet(:<name>)` (such as `:helpscreen`)
2717
+
2718
+ The Sourcerer module also generates files like `build/docs/manpage.adoc`, which generates the formatted terminal manual, using content from `build/docs/config-reference.adoc` and this README (`tags="cli_options"`, for instance).
2719
+
2720
+ It also generates an AsciiDoc-formatted configuration reference, a machine-readable JSON reference, and a sample config using the `specs/data/config-def.yml` file.
2721
+ The Sourcerer system now supports *attribute resolution* from AsciiDoc source files, enabling templates to access README attributes during rendering, ensuring configuration documentation reflects actual default values.
2722
+
2723
+ Sourcerer also performs basic testing of select commands in the ASciiDoc file that have been assigned a `testable` role.
2724
+
2725
+ This is mostly just showing off what Sourcerer can do, and hopefully setting into habit some best practices for my more complicated apps.
2726
+
2727
+ Sourcerer is also where integration with Jekyll's extensions of Liquid occurs, bringing ReleaseHx's templating powers closely in line with how Jekyll's work, as described in <<custom-liquid>>.
2728
+ // end::sourcerer[]
2729
+
2730
+ [[schemagraphy]]
2731
+ === SchemaGraphy
2732
+
2733
+ This gem also introduces a module that derives from an unreleased gem I have been working on for some years: SchemaGraphy.
2734
+
2735
+ SchemaGraphy is basically an extension of YAML, enabling Ruby developers and end users more broadly to powerfully interpret and schematize YAML-based data.
2736
+ Most relevant to our case, as enabled by the `SchemaGraphy` module in this gem, is its handling of *YAML custom tags*, *attribute resolution*, and what I am calling *"`templated fields`"*, where the value of a YAML node is a String that is intended to be further processed by a templating engine like Liquid or ERB, either immediately upon ingest or later in the runtime stack, when it can be mixed with additional data.
2737
+
2738
+ SchemaGraphy facilitates handling these and other quirky power-ups we use with our fully valid YAML files, so low-code users can pass some dynamism along in their YAML configs and so forth.
2739
+
2740
+ [[attribute-resolution]]
2741
+ ==== Attribute Resolution
2742
+
2743
+ SchemaGraphy provides *attribute resolution* capabilities through the `AttributeResolver` component.
2744
+ This enables YAML files to reference external attributes using placeholder syntax like `{attribute_name}`.
2745
+
2746
+ When loading YAML with `.load_yaml_with_attributes(file_path, attributes)`, SchemaGraphy:
2747
+
2748
+ . Loads the YAML file normally
2749
+ . Searches for `{attribute_name}` patterns in String values
2750
+ . Replaces them with corresponding values from the provided attributes Hash
2751
+ . Returns the resolved YAML data structure
2752
+
2753
+ This is used extensively in ReleaseHx's configuration system to enable single-sourcing of defaults from README attributes.
2754
+
2755
+ [[custom-yaml-tag-handling]]
2756
+ ==== Custom YAML Tag Handling
2757
+
2758
+ To enable end users to pass meta-instructions along with their data, wherever it will make sense to do so, SchemaGraphy offers a straightforward handling system.
2759
+
2760
+ Wherever you parse YAML-formatted data using `.load_yaml_with_tags`, custom-tagged Scalar nodes are converted into Maps like so:
2761
+
2762
+ .User's YAML
2763
+ [source,yaml]
2764
+ ----
2765
+ some_property: !liquid "{{ some_value }}"
2766
+ ----
2767
+
2768
+ .Converted data TagMap
2769
+ [source,yaml]
2770
+ ----
2771
+ some_property:
2772
+ __tag__: liquid
2773
+ value: "{{ some_value }}"
2774
+ ----
2775
+
2776
+ Developers may therefore conditionally interpret ingested data based on user-defined classifications, wherever the developer supports such things.
2777
+
2778
+ Whether a Scalar has been transformed into a TagMap, you can resolve it using:
2779
+
2780
+ [source,ruby]
2781
+ ----
2782
+ SchemaGraphy::TagUtils.detag(some_property)
2783
+ # Or, with a local alias
2784
+ detag = ->(val) { SchemaGraphy::TagUtils.detag(val) }
2785
+ detag(some_property)
2786
+ ----
2787
+
2788
+ When tags are used this way, to convey a syntax/engine for processing a template or other dynamic content, SchemaGraphy can even help us handle the content in the manner designated by the tag.
2789
+ This will come up again in <<templated-fields,the next section>>.
2790
+
2791
+ [NOTE]
2792
+ This capability is only available on Scalar node values.
2793
+ For now, tags applied to other compound node types (Arrays/sequences, Maps/mappings) will be ignored by SchemaGraphy interpreters.
2794
+
2795
+ [WARNING]
2796
+ When you use `load_yaml_with_tags`, you will encounter errors downstream if a user places a tag on a node where you do not expect it.
2797
+
2798
+ [[templated-fields]]
2799
+ ==== Templated Property Values in YAML
2800
+
2801
+ We are calling these "`templated fields`" to specify that we are talking about enabling end users to use Liquid, ERB, or eventually other templating syntaxes in YAML node values.
2802
+
2803
+ In so doing, developer are able to designate that the value of certain YAML nodes should be handled by a templating engine, as well as when and how.
2804
+
2805
+ We'll look at how this is done in <<templated-fields-handling>>.
2806
+ For now, the point is that sometimes files like `specs/data/config-def.yml` or an API-mapping file call for a little more runtime dynamism than a low-code solution like pure YAML can support.
2807
+
2808
+ Therefore, when the value of a user-configurable or environment-deterimined "`setting`" is a string that must be generated from data defined outside that field, we parse and render the template at runtime, using data from the environment or elsewhere.
2809
+ For now, it is up to our calling code to provide the appropriate variables to the template depending on the context.
2810
+
2811
+ [[config-def]]
2812
+ ==== Configuration Definition (CFGYML)
2813
+
2814
+ All user-configurable settings have a definition, if not also a default value.
2815
+ For single-sourcing purposes, these are defined in a YAML format called CFGYML -- a configuration-file modeling language.
2816
+
2817
+ The file is at `{gem_config_definition_path}`.
2818
+ It is used to establish the literal default settings carried by the application, and also to document those settings for the user.
2819
+
2820
+ This practice lets developers give end users extremely detailed configurations, always well documented.
2821
+
2822
+ [[attribute-resolution-in-cfgyml]]
2823
+ ===== Attribute Resolution in CFGYML
2824
+
2825
+ CFGYML supports *attribute resolution* from AsciiDoc files (like this README) using placeholder syntax.
2826
+ Default values can reference README attributes using `{attribute_name}` syntax:
2827
+
2828
+ [source,yaml]
2829
+ ----
2830
+ properties:
2831
+ $meta:
2832
+ properties:
2833
+ markup:
2834
+ dflt: "{default_markup}" # Resolved from README.adoc :default_markup: attribute
2835
+ ----
2836
+
2837
+ This enables single-sourcing of configuration defaults from README attributes, ensuring that documentation and defaults stay synchronized.
2838
+
2839
+ [[cfgyml-schema-structure]]
2840
+ ===== CFGYML Schema Structure
2841
+
2842
+ The basic schema is somewhat straightforward.
2843
+ Essentially, you're nesting Map objects within a YAML key `properties`, and each property (setting) of the defined config file can be described and constrained.
2844
+
2845
+ Each setting can have a type, description (`desc`), default (`dflt`), and templated-field instructions (`templating`).
2846
+ If the setting is itself a of type `Map` (YAML "`mapping`", JSON "`object`"), its own nested parameters can be established with a `properties:` block.
2847
+
2848
+ For now, you can designate the type, which you will have to enforce in your code, as well as a default value.
2849
+
2850
+ [[sgyml-schemas]]
2851
+ ==== SGYML Schemas
2852
+
2853
+ Similar to but more complicated than CFGYML definition files are SchemaGraphy schema files.
2854
+ This is a partially specified, partially developed, and as-yet-incomplete syntax for designating and constraining YAML documents.
2855
+
2856
+ ReleaseHx at this time makes active use of only minimal aspects of these schemas, all of which are contained in the `specs/` directory at the root of the gem source.
2857
+
2858
+ Each of the YAML formats used by ReleaseHx has its own schema in the repo.
2859
+ The cfgyml-schema.yaml file will eventually be spun off, but the `specs/data/rhyml-schema.yaml` and `specs/data/rhyml-mapping-schema.yaml` files will stay here, defining valid formats for the types of files they apply to.
2860
+
2861
+ Since SchemaGraphy itself is still unreleased, CFGYML as introduced in this gem offers only a subset of what it will enable down the road.
2862
+
2863
+ Once SchemaGraphy is generally available, this gem will call it as a dependency.
2864
+ At that point, a file like `specs/data/config-def.yml` (CFGYML) will be able to impose a more detailed `$schema` for any property.
2865
+
2866
+ [[templated-fields-handling]]
2867
+ ==== Dynamic Templated-field Handling
2868
+
2869
+ The most powerful function of SchemaGraphy schemas that is now available in ReleaseHx is the ability to instruct how templated fields should be processed at different stages, and also to parse and render them as needed.
2870
+
2871
+ Templated-field handling can be established between a combination of (1) CFGYML definition files or SGYML schema files and (2) configuration files to be applied at runtime.
2872
+
2873
+ Developers can designate a given property to be `type: Template` in a schema or definition.
2874
+ This "`typing`" can be a trigger for downstream parsing/rendering of the template.
2875
+
2876
+ [NOTE]
2877
+ Liquid uses these two stages.
2878
+ The _parse_ operation compiles a template into a `Liquid::Template` object.
2879
+ The _render_ operation applies a dataset to the loaded template, generating a String with Liquid tags resolved.
2880
+
2881
+ [[nyi]]
2882
+ ==== Not Yet Implemented
2883
+
2884
+ Most aspects of SchemaGraphy/SGYML are not yet available in ReleaseHx, but some are worth pointing out.
2885
+
2886
+ data types::
2887
+ As of now, the `type` node of any property in `specs/data/config-def.yml` is not particularly functional.
2888
+ I do have a whole table of "`data types`" in SGYML, most of which are extremely self-explanatory and drawn from fairly platonic, cross-language terms.
2889
+ +
2890
+ However, these are entirely unenforced in ReleaseHx -- for now, data still has to be type checked explicitly in the Ruby code, and user configs are not validated against any kind of typing system.
2891
+
2892
+ schema docs::
2893
+ The schema files do not yet generate complete reference docs for the subject files that they govern.
2894
+ So for instance, you'll have to read files like `specs/data/rhyml-schema.yaml` and `specs/data/rhyml-mapping-schema.yaml` directly to understand the format of RHYML files and how they are mapped to REST response payloads.
2895
+ // end::schemagraphy[]
2896
+
2897
+ [[docs-deployment]]
2898
+ === Documentation Deployment
2899
+
2900
+ ReleaseHx end-user and developer documentation is primarily sourced in this README file.
2901
+
2902
+ Reference documentation is generated from YAML-formatted definition files (`specs/data/config-def.yml`, for instance) and from RDoc comments in Ruby files.
2903
+
2904
+ The documentation site is built using link:https://jekyllrb.com[Jekyll], with AsciiDoc source files processed by the link:https://github.com/asciidoctor/jekyll-asciidoc[jekyll-asciidoc plugin].
2905
+
2906
+ The `docs/` directory has its own resources, and there are docs-related operations in `.github/workflows`.
2907
+
2908
+ The docs are served at {releasehx_docs_www}.
2909
+
2910
+ Documentation deployment is fully automated via GitHub Actions.
2911
+ Every push to `main` triggers the `.github/workflows/gh-pages.yml` workflow
2912
+
2913
+ The site is served at `releasehx.docopslab.org` via the `docs/CNAME` file.
2914
+
2915
+ endif::[]