releasehx 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/README.adoc +2915 -0
  3. data/bin/releasehx +7 -0
  4. data/bin/rhx +7 -0
  5. data/bin/rhx-mcp +7 -0
  6. data/bin/sourcerer +32 -0
  7. data/build/docs/CNAME +1 -0
  8. data/build/docs/Gemfile.lock +95 -0
  9. data/build/docs/_config.yml +36 -0
  10. data/build/docs/config-reference.adoc +4104 -0
  11. data/build/docs/config-reference.json +1546 -0
  12. data/build/docs/index.adoc +2915 -0
  13. data/build/docs/landing.adoc +21 -0
  14. data/build/docs/manpage.adoc +68 -0
  15. data/build/docs/releasehx.1 +281 -0
  16. data/build/docs/releasehx_readme.html +367 -0
  17. data/build/docs/sample-config.adoc +9 -0
  18. data/build/docs/sample-config.yml +251 -0
  19. data/build/docs/schemagraphy_readme.html +0 -0
  20. data/build/docs/sourcerer_readme.html +46 -0
  21. data/build/snippets/helpscreen.txt +29 -0
  22. data/lib/docopslab/mcp/asset_packager.rb +30 -0
  23. data/lib/docopslab/mcp/manifest.rb +67 -0
  24. data/lib/docopslab/mcp/resource_pack.rb +46 -0
  25. data/lib/docopslab/mcp/server.rb +92 -0
  26. data/lib/docopslab/mcp.rb +6 -0
  27. data/lib/releasehx/cli.rb +937 -0
  28. data/lib/releasehx/configuration.rb +215 -0
  29. data/lib/releasehx/generated.rb +17 -0
  30. data/lib/releasehx/helpers.rb +58 -0
  31. data/lib/releasehx/mcp/asset_packager.rb +21 -0
  32. data/lib/releasehx/mcp/assets/agent-config-guide.md +178 -0
  33. data/lib/releasehx/mcp/assets/config-def.yml +1426 -0
  34. data/lib/releasehx/mcp/assets/config-reference.adoc +4104 -0
  35. data/lib/releasehx/mcp/assets/config-reference.json +1546 -0
  36. data/lib/releasehx/mcp/assets/sample-config.yml +251 -0
  37. data/lib/releasehx/mcp/manifest.rb +18 -0
  38. data/lib/releasehx/mcp/resource_pack.rb +26 -0
  39. data/lib/releasehx/mcp/server.rb +57 -0
  40. data/lib/releasehx/mcp.rb +7 -0
  41. data/lib/releasehx/ops/check_ops.rb +136 -0
  42. data/lib/releasehx/ops/draft_ops.rb +173 -0
  43. data/lib/releasehx/ops/enrich_ops.rb +221 -0
  44. data/lib/releasehx/ops/template_ops.rb +61 -0
  45. data/lib/releasehx/ops/write_ops.rb +124 -0
  46. data/lib/releasehx/rest/clients/github.yml +46 -0
  47. data/lib/releasehx/rest/clients/gitlab.yml +31 -0
  48. data/lib/releasehx/rest/clients/jira.yml +31 -0
  49. data/lib/releasehx/rest/yaml_client.rb +418 -0
  50. data/lib/releasehx/rhyml/adapter.rb +740 -0
  51. data/lib/releasehx/rhyml/change.rb +167 -0
  52. data/lib/releasehx/rhyml/liquid.rb +13 -0
  53. data/lib/releasehx/rhyml/loaders.rb +37 -0
  54. data/lib/releasehx/rhyml/mappings/github.yaml +60 -0
  55. data/lib/releasehx/rhyml/mappings/gitlab.yaml +73 -0
  56. data/lib/releasehx/rhyml/mappings/jira.yaml +29 -0
  57. data/lib/releasehx/rhyml/mappings/verb_past_tenses.yml +98 -0
  58. data/lib/releasehx/rhyml/release.rb +144 -0
  59. data/lib/releasehx/rhyml.rb +15 -0
  60. data/lib/releasehx/sgyml/helpers.rb +45 -0
  61. data/lib/releasehx/transforms/adf_to_markdown.rb +307 -0
  62. data/lib/releasehx/version.rb +7 -0
  63. data/lib/releasehx.rb +69 -0
  64. data/lib/schemagraphy/attribute_resolver.rb +48 -0
  65. data/lib/schemagraphy/cfgyml/definition.rb +90 -0
  66. data/lib/schemagraphy/cfgyml/doc_builder.rb +52 -0
  67. data/lib/schemagraphy/cfgyml/path_reference.rb +24 -0
  68. data/lib/schemagraphy/data_query/json_pointer.rb +42 -0
  69. data/lib/schemagraphy/loader.rb +59 -0
  70. data/lib/schemagraphy/regexp_utils.rb +215 -0
  71. data/lib/schemagraphy/safe_expression.rb +189 -0
  72. data/lib/schemagraphy/schema_utils.rb +124 -0
  73. data/lib/schemagraphy/tag_utils.rb +32 -0
  74. data/lib/schemagraphy/templating.rb +104 -0
  75. data/lib/schemagraphy.rb +17 -0
  76. data/lib/sourcerer/builder.rb +120 -0
  77. data/lib/sourcerer/jekyll/bootstrapper.rb +78 -0
  78. data/lib/sourcerer/jekyll/liquid/file_system.rb +74 -0
  79. data/lib/sourcerer/jekyll/liquid/filters.rb +215 -0
  80. data/lib/sourcerer/jekyll/liquid/tags.rb +44 -0
  81. data/lib/sourcerer/jekyll/monkeypatches.rb +73 -0
  82. data/lib/sourcerer/jekyll.rb +26 -0
  83. data/lib/sourcerer/plaintext_converter.rb +75 -0
  84. data/lib/sourcerer/templating.rb +190 -0
  85. data/lib/sourcerer.rb +322 -0
  86. data/specs/data/api-client-schema.yaml +160 -0
  87. data/specs/data/config-def.yml +1426 -0
  88. data/specs/data/mcp-manifest.yml +50 -0
  89. data/specs/data/rhyml-mapping-schema.yaml +410 -0
  90. data/specs/data/rhyml-schema.yaml +152 -0
  91. metadata +376 -0
@@ -0,0 +1,46 @@
1
+ <div class="paragraph">
2
+ <p>This gem introduces a module called Sourcerer, by which AsciiDoc files can be parsed and their contents harvested for use in the application build.
3
+ The module also handles Liquid template processing with enhanced attribute resolution capabilities.</p>
4
+ </div>
5
+ <div class="admonitionblock note">
6
+ <table>
7
+ <tr>
8
+ <td class="icon">
9
+ <div class="title">Note</div>
10
+ </td>
11
+ <td class="content">
12
+ Sourcerer is intended to be spun off as its own gem once it successfully proves the concept in this gem.
13
+ It will probably be called <em>AsciiSourcerer</em> and may replace an older and unmaintained utility of mine called LiquiDoc.
14
+ </td>
15
+ </tr>
16
+ </table>
17
+ </div>
18
+ <div class="paragraph">
19
+ <p>It is invoked in the Rakefile, establishing global namespaces:</p>
20
+ </div>
21
+ <div class="ulist">
22
+ <ul>
23
+ <li>
24
+ <p><code>ReleaseHx::ATTRIBUTES[:globals]</code> (derived from this <code>README.adoc</code> file)</p>
25
+ </li>
26
+ <li>
27
+ <p><code>ReleaseHx.read_built_snippet(:&lt;name&gt;)</code> (such as <code>:helpscreen</code>)</p>
28
+ </li>
29
+ </ul>
30
+ </div>
31
+ <div class="paragraph">
32
+ <p>The Sourcerer module also generates files like <code>build/docs/manpage.adoc</code>, which generates the formatted terminal manual, using content from <code>build/docs/config-reference.adoc</code> and this README (<code>tags="cli_options"</code>, for instance).</p>
33
+ </div>
34
+ <div class="paragraph">
35
+ <p>It also generates an AsciiDoc-formatted configuration reference, a machine-readable JSON reference, and a sample config using the <code>specs/data/config-def.yml</code> file.
36
+ The Sourcerer system now supports <strong>attribute resolution</strong> from AsciiDoc source files, enabling templates to access README attributes during rendering, ensuring configuration documentation reflects actual default values.</p>
37
+ </div>
38
+ <div class="paragraph">
39
+ <p>Sourcerer also performs basic testing of select commands in the ASciiDoc file that have been assigned a <code>testable</code> role.</p>
40
+ </div>
41
+ <div class="paragraph">
42
+ <p>This is mostly just showing off what Sourcerer can do, and hopefully setting into habit some best practices for my more complicated apps.</p>
43
+ </div>
44
+ <div class="paragraph">
45
+ <p>Sourcerer is also where integration with Jekyll&#8217;s extensions of Liquid occurs, bringing ReleaseHx&#8217;s templating powers closely in line with how Jekyll&#8217;s work, as described in <a href="#custom-liquid">[custom-liquid]</a>.</p>
46
+ </div>
@@ -0,0 +1,29 @@
1
+ Usage: rhx VERSION|FILE [options]
2
+
3
+ Options:
4
+ --md [PATH] Draft to Markdown
5
+ --adoc, --ad [PATH] Draft to AsciiDoc
6
+ --yaml, --yml [PATH] Draft to YAML
7
+ --html [PATH] Enrich to HTML
8
+ --pdf [PATH] Enrich to PDF
9
+ --output-dir PATH Establish base target path for generated files
10
+ --api-data PATH Ingest from a JSON file instead of REST response
11
+
12
+ --config PATH Config location (default: ./{app_default_config_path})
13
+ --mapping PATH Alternate API mapping location
14
+ --payload PATH Store payload as JSON file at PATH or default
15
+ --fetch Refresh data from source
16
+ --append Add any new issues to the end of local YAML source
17
+ --over, --force Overwrite any existing files without prompting
18
+ --check, --scan Find issues with missing release note
19
+ --empty, -e [RULE] Set/reverse policy on issues "awaiting notes"
20
+ --internal Include issues marked internal or likewise
21
+ --[no-]wrap Enrich HTML with/out head and body tags
22
+ --[no-]frontmatter Enrich or draft with/out frontmatter
23
+
24
+ --manpage, --man Show the full manpage documentation
25
+ --verbose Express each step to console
26
+ --debug Express each step and show inferred states
27
+ --debug-dump Complete debugging with raw data
28
+ --quiet Suppress all output, including warnings
29
+ --version Display the ReleaseHx version code
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module DocOpsLab
6
+ module MCP
7
+ # Copies MCP resource assets into a packaged location for runtime access.
8
+ class AssetPackager
9
+ def initialize manifest:, asset_root:
10
+ raise ArgumentError, 'asset_root is required' if asset_root.nil? || asset_root == ''
11
+
12
+ @manifest = manifest
13
+ @asset_root = asset_root
14
+ end
15
+
16
+ def package!
17
+ FileUtils.mkdir_p(@asset_root)
18
+ @manifest.resources.each do |entry|
19
+ normalized = @manifest.normalize_resource(entry)
20
+ source_path = normalized[:source_path]
21
+ target_path = File.join(@asset_root, normalized[:packaged_name])
22
+ raise Errno::ENOENT, "Missing MCP resource source: #{source_path}" unless File.exist?(source_path)
23
+
24
+ FileUtils.mkdir_p(File.dirname(target_path))
25
+ FileUtils.cp(source_path, target_path)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module DocOpsLab
6
+ module MCP
7
+ # Loads MCP resource and tool definitions from a YAML manifest.
8
+ class Manifest
9
+ def initialize data
10
+ @data = data
11
+ end
12
+
13
+ def self.load path
14
+ raise ArgumentError, 'Manifest path is required' if path.nil? || path == ''
15
+
16
+ new(YAML.safe_load_file(path, symbolize_names: true, aliases: true))
17
+ end
18
+
19
+ def resources
20
+ Array(@data[:resources])
21
+ end
22
+
23
+ def tools
24
+ Array(@data[:tools])
25
+ end
26
+
27
+ def normalize_resource entry
28
+ {
29
+ uri: entry[:href],
30
+ name: entry[:name],
31
+ description: entry[:desc],
32
+ mime_type: entry[:mime],
33
+ source_path: entry[:path],
34
+ packaged_name: entry[:file]
35
+ }
36
+ end
37
+
38
+ def normalize_tool entry
39
+ {
40
+ name: entry[:name],
41
+ # Convert dots to spaces, capitalize initials
42
+ title: entry[:title] || entry[:name].tr('.', ' ').split.map(&:capitalize).join(' '),
43
+ description: entry[:desc],
44
+ input_schema: normalize_schema(entry[:input_schema]),
45
+ annotations: entry[:annotations]
46
+ }
47
+ end
48
+
49
+ private
50
+
51
+ # Recursively normalize schema keys (ex: :desc to :description)
52
+ def normalize_schema value
53
+ case value
54
+ when Hash
55
+ value.each_with_object({}) do |(key, inner), acc|
56
+ mapped_key = key == :desc ? :description : key
57
+ acc[mapped_key] = normalize_schema(inner)
58
+ end
59
+ when Array
60
+ value.map { |item| normalize_schema(item) }
61
+ else
62
+ value
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DocOpsLab
4
+ module MCP
5
+ # Resolves MCP resources from a YAML manifest and packaged assets.
6
+ class ResourcePack
7
+ Resource = Struct.new(:uri, :name, :description, :mime_type, :path, keyword_init: true)
8
+
9
+ def initialize manifest:, asset_root:
10
+ raise ArgumentError, 'asset_root is required' if asset_root.nil? || asset_root == ''
11
+
12
+ @manifest = manifest
13
+ @asset_root = asset_root
14
+ end
15
+
16
+ def resources
17
+ @manifest.resources.map do |entry|
18
+ normalized = @manifest.normalize_resource(entry)
19
+ Resource.new(
20
+ uri: normalized[:uri],
21
+ name: normalized[:name],
22
+ description: normalized[:description],
23
+ mime_type: normalized[:mime_type],
24
+ path: File.join(@asset_root, normalized[:packaged_name]))
25
+ end
26
+ end
27
+
28
+ def list
29
+ resources.map(&:uri)
30
+ end
31
+
32
+ def find uri
33
+ resources.find { |entry| entry.uri == uri }
34
+ end
35
+
36
+ def read uri
37
+ resource = find(uri)
38
+ raise ArgumentError, "Unknown MCP resource: #{uri}" unless resource
39
+
40
+ raise Errno::ENOENT, "Missing MCP resource file: #{resource.path}" unless File.exist?(resource.path)
41
+
42
+ File.read(resource.path)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mcp'
4
+
5
+ module DocOpsLab
6
+ module MCP
7
+ # Hosts MCP resources and tools from a manifest-driven resource pack.
8
+ class Server
9
+ def initialize name:, manifest:, resource_pack:, tool_handler: nil
10
+ raise ArgumentError, 'name is required' if name.nil? || name == ''
11
+
12
+ @manifest = manifest
13
+ @resource_pack = resource_pack
14
+ @tool_handler = tool_handler
15
+ @server = ::MCP::Server.new(
16
+ name: name,
17
+ resources: mcp_resources,
18
+ tools: mcp_tools)
19
+
20
+ register_resource_reader
21
+ end
22
+
23
+ def start_stdio
24
+ transport = ::MCP::Server::Transports::StdioTransport.new(@server)
25
+ transport.open
26
+ end
27
+
28
+ def list_resources
29
+ @resource_pack.list
30
+ end
31
+
32
+ def get_resource uri
33
+ @resource_pack.read(uri)
34
+ end
35
+
36
+ private
37
+
38
+ def register_resource_reader
39
+ @server.resources_read_handler do |params|
40
+ uri = params[:uri]
41
+ resource = @resource_pack.find(uri)
42
+ raise ArgumentError, "Unknown MCP resource: #{uri}" unless resource
43
+
44
+ [{
45
+ uri:,
46
+ mimeType: resource.mime_type,
47
+ text: @resource_pack.read(uri)
48
+ }]
49
+ end
50
+ end
51
+
52
+ def mcp_resources
53
+ @resource_pack.resources.map do |entry|
54
+ ::MCP::Resource.new(
55
+ uri: entry.uri,
56
+ name: entry.name,
57
+ title: entry.name,
58
+ description: entry.description,
59
+ mime_type: entry.mime_type)
60
+ end
61
+ end
62
+
63
+ def mcp_tools
64
+ @manifest.tools.map do |tool|
65
+ normalized = @manifest.normalize_tool(tool)
66
+ build_tool(normalized)
67
+ end
68
+ end
69
+
70
+ def build_tool tool
71
+ tool_handler = @tool_handler
72
+ ::MCP::Tool.define(
73
+ name: tool[:name],
74
+ title: tool[:title],
75
+ description: tool[:description],
76
+ input_schema: tool[:input_schema],
77
+ annotations: tool[:annotations]) do |**args|
78
+ server_context = args.delete(:server_context)
79
+ raise ArgumentError, "No MCP tool handler configured for: #{tool[:name]}" unless tool_handler
80
+
81
+ tool_handler.call(tool[:name], args, server_context)
82
+ end
83
+ end
84
+
85
+ def handle_tool name, args, server_context
86
+ raise ArgumentError, "No MCP tool handler configured for: #{name}" unless @tool_handler
87
+
88
+ @tool_handler.call(name, args, server_context)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'mcp/manifest'
4
+ require_relative 'mcp/resource_pack'
5
+ require_relative 'mcp/asset_packager'
6
+ require_relative 'mcp/server'