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
|
@@ -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(:<name>)</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’s extensions of Liquid occurs, bringing ReleaseHx’s templating powers closely in line with how Jekyll’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
|