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.
- checksums.yaml +7 -0
- data/README.adoc +2915 -0
- data/bin/releasehx +7 -0
- data/bin/rhx +7 -0
- data/bin/rhx-mcp +7 -0
- data/bin/sourcerer +32 -0
- data/build/docs/CNAME +1 -0
- data/build/docs/Gemfile.lock +95 -0
- data/build/docs/_config.yml +36 -0
- data/build/docs/config-reference.adoc +4104 -0
- data/build/docs/config-reference.json +1546 -0
- data/build/docs/index.adoc +2915 -0
- data/build/docs/landing.adoc +21 -0
- data/build/docs/manpage.adoc +68 -0
- data/build/docs/releasehx.1 +281 -0
- data/build/docs/releasehx_readme.html +367 -0
- data/build/docs/sample-config.adoc +9 -0
- data/build/docs/sample-config.yml +251 -0
- data/build/docs/schemagraphy_readme.html +0 -0
- data/build/docs/sourcerer_readme.html +46 -0
- data/build/snippets/helpscreen.txt +29 -0
- data/lib/docopslab/mcp/asset_packager.rb +30 -0
- data/lib/docopslab/mcp/manifest.rb +67 -0
- data/lib/docopslab/mcp/resource_pack.rb +46 -0
- data/lib/docopslab/mcp/server.rb +92 -0
- data/lib/docopslab/mcp.rb +6 -0
- data/lib/releasehx/cli.rb +937 -0
- data/lib/releasehx/configuration.rb +215 -0
- data/lib/releasehx/generated.rb +17 -0
- data/lib/releasehx/helpers.rb +58 -0
- data/lib/releasehx/mcp/asset_packager.rb +21 -0
- data/lib/releasehx/mcp/assets/agent-config-guide.md +178 -0
- data/lib/releasehx/mcp/assets/config-def.yml +1426 -0
- data/lib/releasehx/mcp/assets/config-reference.adoc +4104 -0
- data/lib/releasehx/mcp/assets/config-reference.json +1546 -0
- data/lib/releasehx/mcp/assets/sample-config.yml +251 -0
- data/lib/releasehx/mcp/manifest.rb +18 -0
- data/lib/releasehx/mcp/resource_pack.rb +26 -0
- data/lib/releasehx/mcp/server.rb +57 -0
- data/lib/releasehx/mcp.rb +7 -0
- data/lib/releasehx/ops/check_ops.rb +136 -0
- data/lib/releasehx/ops/draft_ops.rb +173 -0
- data/lib/releasehx/ops/enrich_ops.rb +221 -0
- data/lib/releasehx/ops/template_ops.rb +61 -0
- data/lib/releasehx/ops/write_ops.rb +124 -0
- data/lib/releasehx/rest/clients/github.yml +46 -0
- data/lib/releasehx/rest/clients/gitlab.yml +31 -0
- data/lib/releasehx/rest/clients/jira.yml +31 -0
- data/lib/releasehx/rest/yaml_client.rb +418 -0
- data/lib/releasehx/rhyml/adapter.rb +740 -0
- data/lib/releasehx/rhyml/change.rb +167 -0
- data/lib/releasehx/rhyml/liquid.rb +13 -0
- data/lib/releasehx/rhyml/loaders.rb +37 -0
- data/lib/releasehx/rhyml/mappings/github.yaml +60 -0
- data/lib/releasehx/rhyml/mappings/gitlab.yaml +73 -0
- data/lib/releasehx/rhyml/mappings/jira.yaml +29 -0
- data/lib/releasehx/rhyml/mappings/verb_past_tenses.yml +98 -0
- data/lib/releasehx/rhyml/release.rb +144 -0
- data/lib/releasehx/rhyml.rb +15 -0
- data/lib/releasehx/sgyml/helpers.rb +45 -0
- data/lib/releasehx/transforms/adf_to_markdown.rb +307 -0
- data/lib/releasehx/version.rb +7 -0
- data/lib/releasehx.rb +69 -0
- data/lib/schemagraphy/attribute_resolver.rb +48 -0
- data/lib/schemagraphy/cfgyml/definition.rb +90 -0
- data/lib/schemagraphy/cfgyml/doc_builder.rb +52 -0
- data/lib/schemagraphy/cfgyml/path_reference.rb +24 -0
- data/lib/schemagraphy/data_query/json_pointer.rb +42 -0
- data/lib/schemagraphy/loader.rb +59 -0
- data/lib/schemagraphy/regexp_utils.rb +215 -0
- data/lib/schemagraphy/safe_expression.rb +189 -0
- data/lib/schemagraphy/schema_utils.rb +124 -0
- data/lib/schemagraphy/tag_utils.rb +32 -0
- data/lib/schemagraphy/templating.rb +104 -0
- data/lib/schemagraphy.rb +17 -0
- data/lib/sourcerer/builder.rb +120 -0
- data/lib/sourcerer/jekyll/bootstrapper.rb +78 -0
- data/lib/sourcerer/jekyll/liquid/file_system.rb +74 -0
- data/lib/sourcerer/jekyll/liquid/filters.rb +215 -0
- data/lib/sourcerer/jekyll/liquid/tags.rb +44 -0
- data/lib/sourcerer/jekyll/monkeypatches.rb +73 -0
- data/lib/sourcerer/jekyll.rb +26 -0
- data/lib/sourcerer/plaintext_converter.rb +75 -0
- data/lib/sourcerer/templating.rb +190 -0
- data/lib/sourcerer.rb +322 -0
- data/specs/data/api-client-schema.yaml +160 -0
- data/specs/data/config-def.yml +1426 -0
- data/specs/data/mcp-manifest.yml +50 -0
- data/specs/data/rhyml-mapping-schema.yaml +410 -0
- data/specs/data/rhyml-schema.yaml +152 -0
- 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 <v.r.sn> --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 <v.r.sn> --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 `<drafts_dir>` is the value of `paths.drafts_dir` in the config, and `<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::[]
|