metanorma-release 0.2.1
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/.rspec +3 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +504 -0
- data/CHANGELOG.md +15 -0
- data/PROMPT.md +282 -0
- data/README.adoc +430 -0
- data/Rakefile +8 -0
- data/exe/mn-release +6 -0
- data/lib/metanorma/release/aggregation_interfaces.rb +33 -0
- data/lib/metanorma/release/aggregation_pipeline.rb +155 -0
- data/lib/metanorma/release/asset_processor.rb +58 -0
- data/lib/metanorma/release/cache_store.rb +86 -0
- data/lib/metanorma/release/change_detector.rb +20 -0
- data/lib/metanorma/release/channel.rb +64 -0
- data/lib/metanorma/release/channel_audience.rb +24 -0
- data/lib/metanorma/release/channel_config.rb +55 -0
- data/lib/metanorma/release/channel_filter.rb +26 -0
- data/lib/metanorma/release/channel_manifest.rb +192 -0
- data/lib/metanorma/release/channel_registry.rb +60 -0
- data/lib/metanorma/release/cli.rb +129 -0
- data/lib/metanorma/release/commands/aggregate.rb +126 -0
- data/lib/metanorma/release/commands/package.rb +46 -0
- data/lib/metanorma/release/commands/publish.rb +51 -0
- data/lib/metanorma/release/config_fetcher.rb +11 -0
- data/lib/metanorma/release/config_locator.rb +37 -0
- data/lib/metanorma/release/config_resolver.rb +37 -0
- data/lib/metanorma/release/content_hash.rb +51 -0
- data/lib/metanorma/release/delta_state.rb +108 -0
- data/lib/metanorma/release/document_id.rb +45 -0
- data/lib/metanorma/release/document_index.rb +183 -0
- data/lib/metanorma/release/document_metadata.rb +39 -0
- data/lib/metanorma/release/document_stage.rb +86 -0
- data/lib/metanorma/release/document_type.rb +55 -0
- data/lib/metanorma/release/document_version.rb +50 -0
- data/lib/metanorma/release/file_routing.rb +51 -0
- data/lib/metanorma/release/interfaces.rb +47 -0
- data/lib/metanorma/release/naming_strategy.rb +158 -0
- data/lib/metanorma/release/platform/github/config_fetcher.rb +40 -0
- data/lib/metanorma/release/platform/github/manifest_reader.rb +32 -0
- data/lib/metanorma/release/platform/github/publisher.rb +73 -0
- data/lib/metanorma/release/platform/github/release_fetcher.rb +52 -0
- data/lib/metanorma/release/platform/github/topic_discoverer.rb +29 -0
- data/lib/metanorma/release/platform/github.rb +25 -0
- data/lib/metanorma/release/platform/local/config_fetcher.rb +20 -0
- data/lib/metanorma/release/platform/local/directory_discoverer.rb +26 -0
- data/lib/metanorma/release/platform/local/fetcher.rb +76 -0
- data/lib/metanorma/release/platform/local/publisher.rb +44 -0
- data/lib/metanorma/release/platform/local.rb +14 -0
- data/lib/metanorma/release/platform/null/publisher.rb +17 -0
- data/lib/metanorma/release/platform/null.rb +11 -0
- data/lib/metanorma/release/platform.rb +11 -0
- data/lib/metanorma/release/platform_factory.rb +78 -0
- data/lib/metanorma/release/rake_tasks.rb +71 -0
- data/lib/metanorma/release/relaton_enricher.rb +138 -0
- data/lib/metanorma/release/release_metadata.rb +79 -0
- data/lib/metanorma/release/release_pipeline.rb +115 -0
- data/lib/metanorma/release/release_tag.rb +49 -0
- data/lib/metanorma/release/repo_ref.rb +34 -0
- data/lib/metanorma/release/rxl_extractor.rb +115 -0
- data/lib/metanorma/release/stage_filter.rb +18 -0
- data/lib/metanorma/release/version.rb +7 -0
- data/lib/metanorma/release/zip_packager.rb +37 -0
- data/lib/metanorma/release.rb +116 -0
- metadata +156 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Release
|
|
5
|
+
class ReleasePipeline
|
|
6
|
+
Dependencies = Struct.new(
|
|
7
|
+
:extractor, :filters, :change_detector,
|
|
8
|
+
:packager, :publisher, :naming_registry,
|
|
9
|
+
:manifest, :channel_override, :channel_config,
|
|
10
|
+
keyword_init: true
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
Config = Struct.new(
|
|
14
|
+
:output_dir, :manifest_path, :force, :force_replace_patterns,
|
|
15
|
+
:concurrency, :default_visibility,
|
|
16
|
+
keyword_init: true
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
def initialize(deps)
|
|
20
|
+
@deps = deps
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run(config)
|
|
24
|
+
documents = @deps.extractor.discover(config.output_dir)
|
|
25
|
+
filtered = apply_filters(documents)
|
|
26
|
+
results = phase_one(filtered, config)
|
|
27
|
+
phase_two(results, config)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def apply_filters(documents)
|
|
33
|
+
return documents unless @deps.filters && !@deps.filters.empty?
|
|
34
|
+
|
|
35
|
+
@deps.filters.reduce(documents) { |docs, filter| filter.apply(docs) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def phase_one(documents, config)
|
|
39
|
+
documents.map do |doc|
|
|
40
|
+
strategy = @deps.naming_registry.resolve(doc.document_type)
|
|
41
|
+
tag = strategy.compute_tag(doc.id.to_s, doc.version)
|
|
42
|
+
canonical_base = strategy.compute_canonical_base(doc.id.to_s, doc.version)
|
|
43
|
+
change = @deps.change_detector.detect(doc, tag, force: config.force)
|
|
44
|
+
|
|
45
|
+
{ document: doc, tag: tag, canonical_base: canonical_base,
|
|
46
|
+
changed: change.changed?, change_result: change }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def phase_two(candidates, config)
|
|
51
|
+
released = []
|
|
52
|
+
skipped = []
|
|
53
|
+
failed = []
|
|
54
|
+
released_artifacts = []
|
|
55
|
+
|
|
56
|
+
candidates.each do |candidate|
|
|
57
|
+
doc = candidate[:document]
|
|
58
|
+
tag = candidate[:tag]
|
|
59
|
+
|
|
60
|
+
unless candidate[:changed]
|
|
61
|
+
skipped << doc
|
|
62
|
+
next
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
begin
|
|
66
|
+
policy = resolve_policy(doc, config)
|
|
67
|
+
unless policy.release?
|
|
68
|
+
skipped << doc
|
|
69
|
+
next
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
artifact = @deps.packager.package(doc, canonical_base: candidate[:canonical_base])
|
|
73
|
+
channels = resolve_channels(doc, policy)
|
|
74
|
+
metadata_json = ReleaseMetadata.from_document(doc, channels: channels)
|
|
75
|
+
force = config.force_replace_patterns&.any? { |p| File.fnmatch?(p, doc.id.to_s) } || false
|
|
76
|
+
|
|
77
|
+
result = @deps.publisher.publish(tag, artifact, metadata_json, channels: channels, force_replace: force)
|
|
78
|
+
released << doc
|
|
79
|
+
released_artifacts << ReleasedArtifact.new(
|
|
80
|
+
id: doc.id.to_s, tag: tag.to_s,
|
|
81
|
+
url: result.url, channels: channels.map(&:to_s)
|
|
82
|
+
)
|
|
83
|
+
rescue StandardError => e
|
|
84
|
+
failed << { document: doc, error: e.message }
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
ReleaseResult.new(released: released, skipped: skipped, failed: failed,
|
|
89
|
+
released_artifacts: released_artifacts)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def resolve_policy(doc, _config)
|
|
93
|
+
return @deps.manifest.resolve(doc) if @deps.manifest
|
|
94
|
+
|
|
95
|
+
DocumentReleasePolicy.from_defaults('public', [Channel.public('default')])
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def resolve_channels(_doc, policy)
|
|
99
|
+
channels = if @deps.channel_override && !@deps.channel_override.empty?
|
|
100
|
+
@deps.channel_override
|
|
101
|
+
else
|
|
102
|
+
policy.channels
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
validate_channels(channels)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def validate_channels(channels)
|
|
109
|
+
return channels unless @deps.channel_config
|
|
110
|
+
|
|
111
|
+
channels.select { |ch| @deps.channel_config.registry.valid?(ch) }
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Release
|
|
5
|
+
class ReleaseTag
|
|
6
|
+
PRE_RELEASE_SUFFIXES = %w[-wd -cd -ds -fd -proposal].freeze
|
|
7
|
+
|
|
8
|
+
def self.from(doc_id, version)
|
|
9
|
+
tag = "#{doc_id}/#{version.tag_component}"
|
|
10
|
+
new(tag: tag, pre_release: version.pre_release?)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.create(tag, pre_release:)
|
|
14
|
+
raise ArgumentError, 'Tag must contain a slash separator' unless tag.include?('/')
|
|
15
|
+
|
|
16
|
+
new(tag: tag, pre_release: pre_release)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.parse(tag)
|
|
20
|
+
raise ArgumentError, 'Tag must contain a slash separator' unless tag.include?('/')
|
|
21
|
+
|
|
22
|
+
pre = PRE_RELEASE_SUFFIXES.any? { |s| tag.include?(s) }
|
|
23
|
+
new(tag: tag, pre_release: pre)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(tag:, pre_release:)
|
|
27
|
+
@tag = tag
|
|
28
|
+
@pre_release = pre_release
|
|
29
|
+
freeze
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_s
|
|
33
|
+
@tag
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def pre_release?
|
|
37
|
+
@pre_release
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def eql?(other)
|
|
41
|
+
other.is_a?(self.class) && @tag == other.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def hash
|
|
45
|
+
@tag.hash
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Release
|
|
5
|
+
class RepoRef
|
|
6
|
+
attr_reader :owner, :repo
|
|
7
|
+
|
|
8
|
+
def self.from_string(str)
|
|
9
|
+
parts = str.split('/', 2)
|
|
10
|
+
raise ArgumentError, "Invalid repo reference: #{str}" unless parts.length == 2
|
|
11
|
+
|
|
12
|
+
new(owner: parts[0], repo: parts[1])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(owner:, repo:)
|
|
16
|
+
@owner = owner
|
|
17
|
+
@repo = repo
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
"#{owner}/#{repo}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def eql?(other)
|
|
26
|
+
other.is_a?(self.class) && owner == other.owner && repo == other.repo
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def hash
|
|
30
|
+
[owner, repo].hash
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
raise LoadError, "The nokogiri gem is required for RxlExtractor. Add `gem 'nokogiri'` to your Gemfile."
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module Metanorma
|
|
10
|
+
module Release
|
|
11
|
+
class RxlExtractor
|
|
12
|
+
def initialize(fallback_flavor: nil)
|
|
13
|
+
@fallback_flavor = fallback_flavor
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def discover(output_dir)
|
|
17
|
+
rxl_files = Dir.glob(File.join(output_dir, '**', '*.rxl'))
|
|
18
|
+
rxl_files.filter_map do |path|
|
|
19
|
+
extract(path)
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
warn "Warning: Skipping #{path}: #{e.message}"
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def extract(rxl_path)
|
|
27
|
+
raise ArgumentError, "RXL file not found: #{rxl_path}" unless File.exist?(rxl_path)
|
|
28
|
+
|
|
29
|
+
content = File.read(rxl_path)
|
|
30
|
+
doc = Nokogiri::XML(content, nil, 'UTF-8', Nokogiri::XML::ParseOptions::STRICT)
|
|
31
|
+
extract_from_xml(doc, rxl_path)
|
|
32
|
+
rescue Nokogiri::XML::SyntaxError => e
|
|
33
|
+
warn "Warning: Failed to parse RXL #{rxl_path}: #{e.message}"
|
|
34
|
+
fallback_metadata(rxl_path)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def extract_from_xml(xml, rxl_path)
|
|
40
|
+
bibdata = xml.at_xpath('/bibdata') || xml.root
|
|
41
|
+
raw_id = text_of(bibdata, 'docidentifier') || derive_id_from_path(rxl_path)
|
|
42
|
+
id = DocumentId.from_raw(raw_id)
|
|
43
|
+
title = text_of(bibdata, 'title') || ''
|
|
44
|
+
edition = text_of(bibdata, 'edition') || '1'
|
|
45
|
+
stage_node = bibdata.at_xpath('status/stage')
|
|
46
|
+
stage = if stage_node
|
|
47
|
+
DocumentStage.from_iso_stage(stage_node.text.to_i)
|
|
48
|
+
else
|
|
49
|
+
DocumentStage.published
|
|
50
|
+
end
|
|
51
|
+
version = DocumentVersion.from(edition, stage)
|
|
52
|
+
doctype = text_of(bibdata, 'ext/doctype') || ''
|
|
53
|
+
revdate = extract_revdate(bibdata)
|
|
54
|
+
flavor = @fallback_flavor || detect_flavor(raw_id)
|
|
55
|
+
output_dir = File.dirname(rxl_path)
|
|
56
|
+
file_base_name = File.basename(rxl_path, '.rxl')
|
|
57
|
+
formats = detect_formats(output_dir, file_base_name)
|
|
58
|
+
document_type = DocumentType.from_identifier(raw_id)
|
|
59
|
+
|
|
60
|
+
DocumentMetadata.new(
|
|
61
|
+
id: id, title: title, version: version, doctype: doctype,
|
|
62
|
+
document_type: document_type, flavor: flavor, revdate: revdate,
|
|
63
|
+
source_path: derive_source_path(rxl_path), output_dir: output_dir,
|
|
64
|
+
formats: formats, file_base_name: file_base_name
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def fallback_metadata(rxl_path)
|
|
69
|
+
file_base_name = File.basename(rxl_path, '.rxl')
|
|
70
|
+
id = DocumentId.from_raw(file_base_name)
|
|
71
|
+
DocumentMetadata.new(
|
|
72
|
+
id: id, title: '', version: DocumentVersion.published(edition: '0'),
|
|
73
|
+
doctype: '', document_type: 'standard', flavor: nil, revdate: nil,
|
|
74
|
+
source_path: rxl_path, output_dir: File.dirname(rxl_path),
|
|
75
|
+
formats: [], file_base_name: file_base_name
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def text_of(node, xpath)
|
|
80
|
+
n = node.at_xpath(xpath)
|
|
81
|
+
n&.text&.strip
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def extract_revdate(bibdata)
|
|
85
|
+
date_node = bibdata.at_xpath("date[@type='published']/on") ||
|
|
86
|
+
bibdata.at_xpath('date/on')
|
|
87
|
+
date_node&.text&.strip
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def detect_formats(output_dir, base_name)
|
|
91
|
+
extensions = []
|
|
92
|
+
%w[html pdf xml rxl doc].each do |ext|
|
|
93
|
+
path = File.join(output_dir, "#{base_name}.#{ext}")
|
|
94
|
+
extensions << ext if File.exist?(path)
|
|
95
|
+
end
|
|
96
|
+
extensions
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def detect_flavor(raw_id)
|
|
100
|
+
return nil if raw_id.nil?
|
|
101
|
+
|
|
102
|
+
parts = raw_id.split(/\s|-/)
|
|
103
|
+
parts.first&.downcase
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def derive_id_from_path(rxl_path)
|
|
107
|
+
File.basename(rxl_path, '.rxl')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def derive_source_path(rxl_path)
|
|
111
|
+
rxl_path.sub(/\.rxl$/, '.adoc')
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Release
|
|
5
|
+
class StageFilter
|
|
6
|
+
def initialize(stages)
|
|
7
|
+
@stages = Set.new(stages.map(&:downcase))
|
|
8
|
+
@all = @stages.empty?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def matches?(release_metadata)
|
|
12
|
+
return true if @all
|
|
13
|
+
|
|
14
|
+
@stages.include?(release_metadata['stage'].to_s.downcase)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'zip'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
raise LoadError, "The rubyzip gem is required for ZipPackager. Add `gem 'rubyzip'` to your Gemfile."
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module Metanorma
|
|
10
|
+
module Release
|
|
11
|
+
class ZipPackager
|
|
12
|
+
include Packager
|
|
13
|
+
|
|
14
|
+
def package(metadata, canonical_base:)
|
|
15
|
+
dir = metadata.output_dir
|
|
16
|
+
base = metadata.file_base_name
|
|
17
|
+
files = Dir.glob(File.join(dir, "#{base}.*")).reject { |f| File.directory?(f) }
|
|
18
|
+
|
|
19
|
+
zip_path = File.join(dir, "#{canonical_base}.zip")
|
|
20
|
+
File.delete(zip_path) if File.exist?(zip_path)
|
|
21
|
+
Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile|
|
|
22
|
+
files.each do |file|
|
|
23
|
+
ext = File.extname(file)
|
|
24
|
+
entry_name = "#{canonical_base}#{ext}"
|
|
25
|
+
zipfile.add(entry_name, file)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Artifact.new(
|
|
30
|
+
zip_path: zip_path,
|
|
31
|
+
asset_name: "#{canonical_base}.zip",
|
|
32
|
+
size: File.size(zip_path)
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Release
|
|
5
|
+
require_relative 'release/version'
|
|
6
|
+
|
|
7
|
+
# Domain value objects
|
|
8
|
+
autoload :ChannelAudience, 'metanorma/release/channel_audience'
|
|
9
|
+
autoload :Channel, 'metanorma/release/channel'
|
|
10
|
+
autoload :ChannelRegistry, 'metanorma/release/channel_registry'
|
|
11
|
+
autoload :ChannelConfig, 'metanorma/release/channel_config'
|
|
12
|
+
autoload :ConfigLocator, 'metanorma/release/config_locator'
|
|
13
|
+
autoload :ContentHash, 'metanorma/release/content_hash'
|
|
14
|
+
autoload :DocumentId, 'metanorma/release/document_id'
|
|
15
|
+
autoload :DocumentStage, 'metanorma/release/document_stage'
|
|
16
|
+
autoload :DocumentType, 'metanorma/release/document_type'
|
|
17
|
+
autoload :DocumentVersion, 'metanorma/release/document_version'
|
|
18
|
+
autoload :ReleaseTag, 'metanorma/release/release_tag'
|
|
19
|
+
autoload :RepoRef, 'metanorma/release/repo_ref'
|
|
20
|
+
|
|
21
|
+
# Domain strategies
|
|
22
|
+
autoload :NamingStrategy, 'metanorma/release/naming_strategy'
|
|
23
|
+
autoload :EditionNaming, 'metanorma/release/naming_strategy'
|
|
24
|
+
autoload :VersionNaming, 'metanorma/release/naming_strategy'
|
|
25
|
+
autoload :InternetDraftNaming, 'metanorma/release/naming_strategy'
|
|
26
|
+
autoload :RfcNaming, 'metanorma/release/naming_strategy'
|
|
27
|
+
autoload :DraftSuffixNaming, 'metanorma/release/naming_strategy'
|
|
28
|
+
autoload :NamingRegistry, 'metanorma/release/naming_strategy'
|
|
29
|
+
|
|
30
|
+
# Manifest & policy
|
|
31
|
+
autoload :ChannelManifest, 'metanorma/release/channel_manifest'
|
|
32
|
+
autoload :DocumentReleasePolicy, 'metanorma/release/channel_manifest'
|
|
33
|
+
autoload :ManifestEntry, 'metanorma/release/channel_manifest'
|
|
34
|
+
|
|
35
|
+
# Metadata
|
|
36
|
+
autoload :DocumentMetadata, 'metanorma/release/document_metadata'
|
|
37
|
+
autoload :ReleaseMetadata, 'metanorma/release/release_metadata'
|
|
38
|
+
autoload :RxlExtractor, 'metanorma/release/rxl_extractor'
|
|
39
|
+
|
|
40
|
+
# Interfaces
|
|
41
|
+
autoload :Extractor, 'metanorma/release/interfaces'
|
|
42
|
+
autoload :Filter, 'metanorma/release/interfaces'
|
|
43
|
+
autoload :ChangeDetector, 'metanorma/release/interfaces'
|
|
44
|
+
autoload :Packager, 'metanorma/release/interfaces'
|
|
45
|
+
autoload :Publisher, 'metanorma/release/interfaces'
|
|
46
|
+
|
|
47
|
+
# Pipeline components
|
|
48
|
+
autoload :ChangeResult, 'metanorma/release/interfaces'
|
|
49
|
+
autoload :Artifact, 'metanorma/release/interfaces'
|
|
50
|
+
autoload :PublishResult, 'metanorma/release/interfaces'
|
|
51
|
+
autoload :ReleasedArtifact, 'metanorma/release/interfaces'
|
|
52
|
+
autoload :ReleaseResult, 'metanorma/release/interfaces'
|
|
53
|
+
autoload :ContentHashChangeDetector, 'metanorma/release/change_detector'
|
|
54
|
+
autoload :ZipPackager, 'metanorma/release/zip_packager'
|
|
55
|
+
autoload :ReleasePipeline, 'metanorma/release/release_pipeline'
|
|
56
|
+
|
|
57
|
+
# Cache
|
|
58
|
+
autoload :CacheStore, 'metanorma/release/cache_store'
|
|
59
|
+
autoload :FileCacheStore, 'metanorma/release/cache_store'
|
|
60
|
+
autoload :NullCacheStore, 'metanorma/release/cache_store'
|
|
61
|
+
|
|
62
|
+
# Aggregation filters
|
|
63
|
+
autoload :ChannelFilter, 'metanorma/release/channel_filter'
|
|
64
|
+
autoload :ConfigFetcher, 'metanorma/release/config_fetcher'
|
|
65
|
+
autoload :StageFilter, 'metanorma/release/stage_filter'
|
|
66
|
+
autoload :DeltaState, 'metanorma/release/delta_state'
|
|
67
|
+
autoload :NullDeltaState, 'metanorma/release/delta_state'
|
|
68
|
+
|
|
69
|
+
# Document index
|
|
70
|
+
autoload :DocumentFile, 'metanorma/release/document_index'
|
|
71
|
+
autoload :DocumentSource, 'metanorma/release/document_index'
|
|
72
|
+
autoload :IndexParameters, 'metanorma/release/document_index'
|
|
73
|
+
autoload :IndexSummary, 'metanorma/release/document_index'
|
|
74
|
+
autoload :AggregatedDocument, 'metanorma/release/document_index'
|
|
75
|
+
autoload :DocumentIndex, 'metanorma/release/document_index'
|
|
76
|
+
|
|
77
|
+
# Asset processing
|
|
78
|
+
autoload :FileRouting, 'metanorma/release/file_routing'
|
|
79
|
+
autoload :ByDocument, 'metanorma/release/file_routing'
|
|
80
|
+
autoload :Flat, 'metanorma/release/file_routing'
|
|
81
|
+
autoload :ByFormat, 'metanorma/release/file_routing'
|
|
82
|
+
autoload :FileRoutingFactory, 'metanorma/release/file_routing'
|
|
83
|
+
autoload :AssetProcessor, 'metanorma/release/asset_processor'
|
|
84
|
+
|
|
85
|
+
# Aggregation
|
|
86
|
+
autoload :RepoDiscoverer, 'metanorma/release/aggregation_interfaces'
|
|
87
|
+
autoload :ReleaseFetcher, 'metanorma/release/aggregation_interfaces'
|
|
88
|
+
autoload :ManifestReader, 'metanorma/release/aggregation_interfaces'
|
|
89
|
+
autoload :IndexGenerator, 'metanorma/release/aggregation_interfaces'
|
|
90
|
+
autoload :FetchResult, 'metanorma/release/aggregation_interfaces'
|
|
91
|
+
autoload :RepoReport, 'metanorma/release/aggregation_interfaces'
|
|
92
|
+
autoload :RepoError, 'metanorma/release/aggregation_interfaces'
|
|
93
|
+
autoload :AggregationPipeline, 'metanorma/release/aggregation_pipeline'
|
|
94
|
+
|
|
95
|
+
# Platform namespace
|
|
96
|
+
autoload :Platform, 'metanorma/release/platform'
|
|
97
|
+
|
|
98
|
+
# Platform factory
|
|
99
|
+
autoload :PlatformFactory, 'metanorma/release/platform_factory'
|
|
100
|
+
|
|
101
|
+
# Relaton enrichment
|
|
102
|
+
autoload :RelatonEnricher, 'metanorma/release/relaton_enricher'
|
|
103
|
+
|
|
104
|
+
# CLI & Rake
|
|
105
|
+
autoload :CLI, 'metanorma/release/cli'
|
|
106
|
+
autoload :RakeTasks, 'metanorma/release/rake_tasks'
|
|
107
|
+
|
|
108
|
+
# Commands
|
|
109
|
+
autoload :PackageCommand, 'metanorma/release/commands/package'
|
|
110
|
+
autoload :PublishCommand, 'metanorma/release/commands/publish'
|
|
111
|
+
autoload :AggregateCommand, 'metanorma/release/commands/aggregate'
|
|
112
|
+
|
|
113
|
+
# Config resolution
|
|
114
|
+
autoload :ConfigResolver, 'metanorma/release/config_resolver'
|
|
115
|
+
end
|
|
116
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: metanorma-release
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ribose Inc.
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: relaton-bib
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '13.2'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '13.2'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.13'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.13'
|
|
55
|
+
description: 'Manages the full release lifecycle of Metanorma documents: discover
|
|
56
|
+
compiled documents, extract metadata, detect changes, package as zip, publish to
|
|
57
|
+
platforms (GitHub Releases, GitLab, local filesystem), and aggregate published releases
|
|
58
|
+
into index.json with a file tree for any site generator.'
|
|
59
|
+
email:
|
|
60
|
+
- open.source@ribose.com
|
|
61
|
+
executables:
|
|
62
|
+
- mn-release
|
|
63
|
+
extensions: []
|
|
64
|
+
extra_rdoc_files: []
|
|
65
|
+
files:
|
|
66
|
+
- ".rspec"
|
|
67
|
+
- ".rubocop.yml"
|
|
68
|
+
- ".rubocop_todo.yml"
|
|
69
|
+
- CHANGELOG.md
|
|
70
|
+
- PROMPT.md
|
|
71
|
+
- README.adoc
|
|
72
|
+
- Rakefile
|
|
73
|
+
- exe/mn-release
|
|
74
|
+
- lib/metanorma/release.rb
|
|
75
|
+
- lib/metanorma/release/aggregation_interfaces.rb
|
|
76
|
+
- lib/metanorma/release/aggregation_pipeline.rb
|
|
77
|
+
- lib/metanorma/release/asset_processor.rb
|
|
78
|
+
- lib/metanorma/release/cache_store.rb
|
|
79
|
+
- lib/metanorma/release/change_detector.rb
|
|
80
|
+
- lib/metanorma/release/channel.rb
|
|
81
|
+
- lib/metanorma/release/channel_audience.rb
|
|
82
|
+
- lib/metanorma/release/channel_config.rb
|
|
83
|
+
- lib/metanorma/release/channel_filter.rb
|
|
84
|
+
- lib/metanorma/release/channel_manifest.rb
|
|
85
|
+
- lib/metanorma/release/channel_registry.rb
|
|
86
|
+
- lib/metanorma/release/cli.rb
|
|
87
|
+
- lib/metanorma/release/commands/aggregate.rb
|
|
88
|
+
- lib/metanorma/release/commands/package.rb
|
|
89
|
+
- lib/metanorma/release/commands/publish.rb
|
|
90
|
+
- lib/metanorma/release/config_fetcher.rb
|
|
91
|
+
- lib/metanorma/release/config_locator.rb
|
|
92
|
+
- lib/metanorma/release/config_resolver.rb
|
|
93
|
+
- lib/metanorma/release/content_hash.rb
|
|
94
|
+
- lib/metanorma/release/delta_state.rb
|
|
95
|
+
- lib/metanorma/release/document_id.rb
|
|
96
|
+
- lib/metanorma/release/document_index.rb
|
|
97
|
+
- lib/metanorma/release/document_metadata.rb
|
|
98
|
+
- lib/metanorma/release/document_stage.rb
|
|
99
|
+
- lib/metanorma/release/document_type.rb
|
|
100
|
+
- lib/metanorma/release/document_version.rb
|
|
101
|
+
- lib/metanorma/release/file_routing.rb
|
|
102
|
+
- lib/metanorma/release/interfaces.rb
|
|
103
|
+
- lib/metanorma/release/naming_strategy.rb
|
|
104
|
+
- lib/metanorma/release/platform.rb
|
|
105
|
+
- lib/metanorma/release/platform/github.rb
|
|
106
|
+
- lib/metanorma/release/platform/github/config_fetcher.rb
|
|
107
|
+
- lib/metanorma/release/platform/github/manifest_reader.rb
|
|
108
|
+
- lib/metanorma/release/platform/github/publisher.rb
|
|
109
|
+
- lib/metanorma/release/platform/github/release_fetcher.rb
|
|
110
|
+
- lib/metanorma/release/platform/github/topic_discoverer.rb
|
|
111
|
+
- lib/metanorma/release/platform/local.rb
|
|
112
|
+
- lib/metanorma/release/platform/local/config_fetcher.rb
|
|
113
|
+
- lib/metanorma/release/platform/local/directory_discoverer.rb
|
|
114
|
+
- lib/metanorma/release/platform/local/fetcher.rb
|
|
115
|
+
- lib/metanorma/release/platform/local/publisher.rb
|
|
116
|
+
- lib/metanorma/release/platform/null.rb
|
|
117
|
+
- lib/metanorma/release/platform/null/publisher.rb
|
|
118
|
+
- lib/metanorma/release/platform_factory.rb
|
|
119
|
+
- lib/metanorma/release/rake_tasks.rb
|
|
120
|
+
- lib/metanorma/release/relaton_enricher.rb
|
|
121
|
+
- lib/metanorma/release/release_metadata.rb
|
|
122
|
+
- lib/metanorma/release/release_pipeline.rb
|
|
123
|
+
- lib/metanorma/release/release_tag.rb
|
|
124
|
+
- lib/metanorma/release/repo_ref.rb
|
|
125
|
+
- lib/metanorma/release/rxl_extractor.rb
|
|
126
|
+
- lib/metanorma/release/stage_filter.rb
|
|
127
|
+
- lib/metanorma/release/version.rb
|
|
128
|
+
- lib/metanorma/release/zip_packager.rb
|
|
129
|
+
homepage: https://github.com/metanorma/metanorma-release
|
|
130
|
+
licenses:
|
|
131
|
+
- BSD-2-Clause
|
|
132
|
+
metadata:
|
|
133
|
+
homepage_uri: https://github.com/metanorma/metanorma-release
|
|
134
|
+
source_code_uri: https://github.com/metanorma/metanorma-release
|
|
135
|
+
changelog_uri: https://github.com/metanorma/metanorma-release/blob/main/CHANGELOG.md
|
|
136
|
+
rubygems_mfa_required: 'true'
|
|
137
|
+
post_install_message:
|
|
138
|
+
rdoc_options: []
|
|
139
|
+
require_paths:
|
|
140
|
+
- lib
|
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '3.2'
|
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
|
+
requirements:
|
|
148
|
+
- - ">="
|
|
149
|
+
- !ruby/object:Gem::Version
|
|
150
|
+
version: '0'
|
|
151
|
+
requirements: []
|
|
152
|
+
rubygems_version: 3.5.22
|
|
153
|
+
signing_key:
|
|
154
|
+
specification_version: 4
|
|
155
|
+
summary: Release lifecycle management for Metanorma documents
|
|
156
|
+
test_files: []
|