metanorma-release 0.2.24 → 0.2.25

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +21 -319
  3. data/README.adoc +306 -91
  4. data/lib/metanorma/release/aggregation_pipeline.rb +65 -40
  5. data/lib/metanorma/release/asset_processor.rb +0 -2
  6. data/lib/metanorma/release/cache_store.rb +1 -0
  7. data/lib/metanorma/release/change_detector.rb +3 -2
  8. data/lib/metanorma/release/cli.rb +26 -2
  9. data/lib/metanorma/release/commands/aggregate.rb +0 -16
  10. data/lib/metanorma/release/commands/package.rb +9 -17
  11. data/lib/metanorma/release/commands/release_command.rb +19 -14
  12. data/lib/metanorma/release/config.rb +16 -7
  13. data/lib/metanorma/release/dependency_validation.rb +19 -0
  14. data/lib/metanorma/release/document_flattener.rb +173 -0
  15. data/lib/metanorma/release/index.rb +1 -1
  16. data/lib/metanorma/release/interfaces.rb +12 -0
  17. data/lib/metanorma/release/platform/github/manifest_reader.rb +3 -1
  18. data/lib/metanorma/release/platform/github/release_fetcher.rb +4 -10
  19. data/lib/metanorma/release/platform/github/topic_discoverer.rb +1 -1
  20. data/lib/metanorma/release/platform/github.rb +0 -4
  21. data/lib/metanorma/release/platform/local/fetcher.rb +5 -17
  22. data/lib/metanorma/release/platform/null/manifest_reader.rb +15 -0
  23. data/lib/metanorma/release/platform/null/publisher.rb +1 -1
  24. data/lib/metanorma/release/platform/null.rb +2 -0
  25. data/lib/metanorma/release/platform/static_discoverer.rb +19 -0
  26. data/lib/metanorma/release/platform.rb +1 -0
  27. data/lib/metanorma/release/platform_factory.rb +6 -21
  28. data/lib/metanorma/release/publication.rb +23 -161
  29. data/lib/metanorma/release/publication_serializer.rb +59 -0
  30. data/lib/metanorma/release/release_pipeline.rb +7 -15
  31. data/lib/metanorma/release/rxl_extractor.rb +106 -0
  32. data/lib/metanorma/release/site.rb +4 -164
  33. data/lib/metanorma/release/slug_strategy.rb +30 -15
  34. data/lib/metanorma/release/version.rb +1 -1
  35. data/lib/metanorma/release.rb +36 -19
  36. metadata +8 -2
@@ -8,12 +8,13 @@ module Metanorma
8
8
  class ContentHashChangeDetector
9
9
  include ChangeDetector
10
10
 
11
- def initialize(previous_releases:)
11
+ def initialize(previous_releases:, output_dir: ".")
12
12
  @previous_releases = previous_releases
13
+ @output_dir = output_dir
13
14
  end
14
15
 
15
16
  def detect(publication, tag, force: false)
16
- current = publication.content_hash
17
+ current = publication.content_hash(from_directory: @output_dir)
17
18
  previous = @previous_releases[tag.to_s]
18
19
  changed = force || previous.nil? || !current.eql?(previous)
19
20
  ChangeResult.new(changed?: changed, current_hash: current,
@@ -11,6 +11,17 @@ module Metanorma
11
11
 
12
12
  class PipelineError < Thor::Error; end
13
13
 
14
+ desc "version", "Print version"
15
+ def version
16
+ puts "metanorma-release #{VERSION}"
17
+ end
18
+ map %w[--version -v] => :version
19
+
20
+ class_option :verbose, type: :boolean, default: false,
21
+ desc: "Verbose output"
22
+ class_option :quiet, type: :boolean, default: false,
23
+ desc: "Suppress warnings"
24
+
14
25
  desc "package", "Package compiled documents"
15
26
  option :output_dir, type: :string, default: "_site",
16
27
  desc: "Compiled docs directory"
@@ -21,6 +32,7 @@ module Metanorma
21
32
  option :config, type: :string, desc: "Config file"
22
33
 
23
34
  def package
35
+ configure_logging
24
36
  config = PackageCommand::Config.new(
25
37
  output_dir: options[:output_dir],
26
38
  dest: options[:dest],
@@ -49,6 +61,7 @@ module Metanorma
49
61
  option :config, type: :string, desc: "Config file"
50
62
 
51
63
  def release
64
+ configure_logging
52
65
  config = ReleaseCommand::Config.new(
53
66
  output_dir: options[:output_dir],
54
67
  platform: options[:platform],
@@ -80,16 +93,19 @@ module Metanorma
80
93
  option :file_routing, type: :string,
81
94
  desc: "File routing (by-document|flat|by-format)"
82
95
  option :cache_dir, type: :string, desc: "Cache directory"
83
- option :data_dir, type: :string, desc: "Write flattened documents.json for site generators"
96
+ option :data_dir, type: :string,
97
+ desc: "Write flattened documents.json for site generators"
84
98
  option :include_drafts, type: :boolean, default: false,
85
99
  desc: "Include draft releases"
86
100
  option :concurrency, type: :numeric, default: 4
87
101
  option :min_documents, type: :numeric, default: 0,
88
102
  desc: "Minimum required documents"
89
103
  option :token, type: :string, desc: "Platform auth token"
90
- option :config, type: :string, desc: "Config file (default: metanorma.aggregate.yml)"
104
+ option :config, type: :string,
105
+ desc: "Config file (default: metanorma.aggregate.yml)"
91
106
 
92
107
  def aggregate
108
+ configure_logging
93
109
  config = AggregateCommand.build_config(
94
110
  source: options[:source],
95
111
  organizations: options[:organizations],
@@ -123,6 +139,14 @@ module Metanorma
123
139
 
124
140
  private
125
141
 
142
+ def configure_logging
143
+ if options[:verbose]
144
+ Metanorma::Release.logger.level = Logger::DEBUG
145
+ elsif options[:quiet]
146
+ Metanorma::Release.logger.level = Logger::ERROR
147
+ end
148
+ end
149
+
126
150
  def print_package_result(result, dest)
127
151
  released = result.released
128
152
  puts "Packaged #{released.length} documents → #{dest}/"
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
3
  require "yaml"
5
4
 
6
5
  module Metanorma
@@ -33,7 +32,6 @@ module Metanorma
33
32
  site.enrich!
34
33
  site.package! if @config.create_zip
35
34
 
36
- stamp_primary_identifiers(index)
37
35
  result
38
36
  end
39
37
 
@@ -151,20 +149,6 @@ module Metanorma
151
149
  output_dir: @config.output_dir,
152
150
  )
153
151
  end
154
-
155
- def stamp_primary_identifiers(index)
156
- index.publications.each do |pub|
157
- next unless pub.to_h["bibliographic"]
158
-
159
- ids = pub.to_h.dig("bibliographic", "docidentifier")
160
- next unless ids&.any?
161
-
162
- primary = ids.find { |di| di["primary"] == true } || ids.first
163
- pub.to_h.merge("primary_identifier" => primary["content"])
164
- end
165
- rescue LoadError
166
- warn " (relaton gem not available — bibliography skipped)"
167
- end
168
152
  end
169
153
  end
170
154
  end
@@ -3,6 +3,8 @@
3
3
  module Metanorma
4
4
  module Release
5
5
  class PackageCommand
6
+ extend ConfigLoader
7
+
6
8
  Config = Struct.new(
7
9
  :output_dir, :dest, :manifest, :config_source,
8
10
  keyword_init: true
@@ -13,11 +15,15 @@ module Metanorma
13
15
  end
14
16
 
15
17
  def call
16
- config = load_config
18
+ config = self.class.load_config(
19
+ config_source: @config.config_source,
20
+ manifest: @config.manifest,
21
+ )
17
22
  deps = ReleasePipeline::Dependencies.new(
18
- extractor: Publication,
23
+ extractor: RxlExtractor,
19
24
  filters: [],
20
- change_detector: ContentHashChangeDetector.new(previous_releases: {}),
25
+ change_detector: ContentHashChangeDetector.new(previous_releases: {},
26
+ output_dir: @config.output_dir),
21
27
  packager: ZipPackager.new(output_dir: @config.output_dir),
22
28
  publisher: PlatformFactory.build_publisher("null", {}),
23
29
  slug_registry: SlugRegistry.from_config(config),
@@ -28,27 +34,13 @@ module Metanorma
28
34
 
29
35
  pipeline_config = ReleasePipeline::Config.new(
30
36
  output_dir: @config.output_dir,
31
- manifest_path: @config.manifest,
32
37
  force: false,
33
38
  force_replace_patterns: nil,
34
39
  concurrency: 4,
35
- default_visibility: "public",
36
40
  )
37
41
 
38
42
  ReleasePipeline.new(deps).run(pipeline_config)
39
43
  end
40
-
41
- private
42
-
43
- def load_config
44
- if @config.config_source && File.exist?(@config.config_source)
45
- Metanorma::Release::Config.from_file(@config.config_source)
46
- elsif @config.manifest && File.exist?(@config.manifest)
47
- Metanorma::Release::Config.from_file(@config.manifest)
48
- else
49
- Metanorma::Release::Config.defaults
50
- end
51
- end
52
44
  end
53
45
  end
54
46
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
-
5
3
  module Metanorma
6
4
  module Release
7
5
  class ReleaseCommand
6
+ extend ConfigLoader
7
+
8
8
  Config = Struct.new(
9
9
  :output_dir, :platform, :manifest, :force,
10
10
  :force_replace, :channels, :concurrency, :token, :config_source,
@@ -16,15 +16,20 @@ module Metanorma
16
16
  end
17
17
 
18
18
  def call
19
- config = load_config
19
+ config = self.class.load_config(
20
+ config_source: @config.config_source,
21
+ manifest: @config.manifest,
22
+ )
20
23
  options = { token: @config.token }
21
24
  publisher = PlatformFactory.build_publisher(@config.platform, options)
22
25
  channel_override = Channel.parse_list(@config.channels) if @config.channels
23
26
 
27
+ previous_releases = build_previous_releases
24
28
  deps = ReleasePipeline::Dependencies.new(
25
- extractor: Publication,
29
+ extractor: RxlExtractor,
26
30
  filters: [],
27
- change_detector: ContentHashChangeDetector.new(previous_releases: {}),
31
+ change_detector: ContentHashChangeDetector.new(previous_releases: previous_releases,
32
+ output_dir: @config.output_dir),
28
33
  packager: ZipPackager.new(output_dir: @config.output_dir),
29
34
  publisher: publisher,
30
35
  slug_registry: SlugRegistry.from_config(config),
@@ -35,11 +40,9 @@ module Metanorma
35
40
 
36
41
  pipeline_config = ReleasePipeline::Config.new(
37
42
  output_dir: @config.output_dir,
38
- manifest_path: @config.manifest,
39
43
  force: @config.force,
40
44
  force_replace_patterns: @config.force_replace && !@config.force_replace.empty? ? @config.force_replace : nil,
41
45
  concurrency: @config.concurrency,
42
- default_visibility: "public",
43
46
  )
44
47
 
45
48
  ReleasePipeline.new(deps).run(pipeline_config)
@@ -47,13 +50,15 @@ module Metanorma
47
50
 
48
51
  private
49
52
 
50
- def load_config
51
- if @config.config_source && File.exist?(@config.config_source)
52
- Metanorma::Release::Config.from_file(@config.config_source)
53
- elsif @config.manifest && File.exist?(@config.manifest)
54
- Metanorma::Release::Config.from_file(@config.manifest)
55
- else
56
- Metanorma::Release::Config.defaults
53
+ def build_previous_releases
54
+ pubs = RxlExtractor.discover(@config.output_dir)
55
+ pubs.each_with_object({}) do |pub, map|
56
+ pub.slug
57
+ registry = SlugRegistry.default
58
+ strategy = registry.resolve(SlugStrategy.publisher_from_identifier(pub.identifier))
59
+ tag_info = strategy.compute_tag(pub)
60
+ content_hash = pub.content_hash(from_directory: @config.output_dir)
61
+ map[tag_info[:tag]] = content_hash if content_hash
57
62
  end
58
63
  end
59
64
  end
@@ -60,13 +60,26 @@ module Metanorma
60
60
  end
61
61
  end
62
62
 
63
- # Single routing entry matches by any combination of pattern, source,
63
+ # Shared config resolution logic for CLI commands.
64
+ module ConfigLoader
65
+ def load_config(config_source:, manifest:)
66
+ if config_source && File.exist?(config_source)
67
+ Config.from_file(config_source)
68
+ elsif manifest && File.exist?(manifest)
69
+ Config.from_file(manifest)
70
+ else
71
+ Config.defaults
72
+ end
73
+ end
74
+ end
75
+
76
+ # Single routing entry — matches by any combination of pattern,
64
77
  # stage, and doctype. An entry with no criteria matches everything (catch-all).
65
- DocumentEntry = Struct.new(:pattern, :source, :stages, :doctypes, :channels, keyword_init: true) do
78
+ DocumentEntry = Struct.new(:pattern, :stages, :doctypes,
79
+ :channels, keyword_init: true) do
66
80
  def initialize(data)
67
81
  super(
68
82
  pattern: data["pattern"],
69
- source: data["source"],
70
83
  stages: Array(data["stage"]).map(&:to_s),
71
84
  doctypes: Array(data["doctype"]).map(&:to_s),
72
85
  channels: Array(data["channels"]).map(&:to_s),
@@ -80,10 +93,6 @@ module Metanorma
80
93
  return false
81
94
  end
82
95
 
83
- if source && !(publication.source_path&.end_with?(source) || false)
84
- return false
85
- end
86
-
87
96
  if !stages.empty? && !stages.include?(publication.stage.to_s)
88
97
  return false
89
98
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Release
5
+ module DependencyValidation
6
+ private
7
+
8
+ def validate_interface!(obj, mod, name)
9
+ return if obj.is_a?(mod) || begin
10
+ obj.class.ancestors.include?(mod)
11
+ rescue StandardError
12
+ false
13
+ end
14
+
15
+ raise ArgumentError, "#{name} must include #{mod}, got #{obj.class}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Release
5
+ class DocumentFlattener
6
+ def initialize(display_categories: [])
7
+ @display_categories = display_categories || []
8
+ end
9
+
10
+ def flatten(doc)
11
+ bib = doc["bibliographic"] || {}
12
+ doctype = extract_doctype(bib) || doc.fetch("doctype", "")
13
+ formats = doc["formats"] || []
14
+ base = {
15
+ "slug" => doc["id"],
16
+ "id" => resolve_doc_id(bib, doc),
17
+ "title" => doc["title"].to_s,
18
+ "abstract" => extract_abstract(bib),
19
+ "stage" => (doc["stage"] || "published").to_s.downcase,
20
+ "doctype" => doctype,
21
+ "edition" => doc["edition"],
22
+ "date" => extract_date(doc),
23
+ "channels" => doc["channels"] || [],
24
+ "formats" => formats,
25
+ "files" => doc["files"] || [],
26
+ "bibliographic" => bib,
27
+ }
28
+ add_format_flags(base, formats)
29
+ add_display_category(base, doctype)
30
+ add_contributors(base, bib)
31
+ base
32
+ end
33
+
34
+ private
35
+
36
+ def add_format_flags(hash, formats)
37
+ hash["has_html"] = formats.include?("html")
38
+ hash["has_pdf"] = formats.include?("pdf")
39
+ hash["has_xml"] = formats.include?("xml")
40
+ hash["has_rxl"] = formats.include?("rxl")
41
+
42
+ files = hash["files"]
43
+ %w[html pdf xml rxl].each do |fmt|
44
+ file = files.find { |f| f["format"] == fmt }
45
+ hash["#{fmt}_path"] = file["path"] if file
46
+ end
47
+ end
48
+
49
+ def add_display_category(hash, doctype)
50
+ cat = resolve_display_category(doctype)
51
+ hash["stage_css"] = hash["stage"].gsub(/\s+/, "-")
52
+ hash["doctype_class"] = "type-#{doctype.downcase}"
53
+ hash["display_category"] = cat&.fetch("name", nil)
54
+ hash["display_category_slug"] = cat&.fetch("slug", nil)
55
+ end
56
+
57
+ def resolve_display_category(doctype)
58
+ return nil if doctype.nil? || doctype.empty?
59
+
60
+ @display_categories.each do |cat|
61
+ doctypes = cat["doctypes"] || []
62
+ if doctypes.include?(doctype)
63
+ return { "name" => cat["name"],
64
+ "slug" => cat["slug"] }
65
+ end
66
+ end
67
+ nil
68
+ end
69
+
70
+ def resolve_doc_id(bib, doc)
71
+ extract_primary_id(bib) || doc["identifier"] || doc["id"]
72
+ end
73
+
74
+ def extract_primary_id(bib)
75
+ ids = bib["docidentifier"]
76
+ return nil unless ids&.any?
77
+
78
+ primary = ids.find { |di| di["primary"] == true } || ids.first
79
+ primary["content"]
80
+ end
81
+
82
+ def extract_doctype(bib)
83
+ bib.dig("ext", "doctype", "content")
84
+ end
85
+
86
+ def extract_abstract(bib)
87
+ abstracts = bib["abstract"]
88
+ return nil unless abstracts&.any?
89
+
90
+ abstracts.first["content"]
91
+ end
92
+
93
+ def extract_date(doc)
94
+ bib_date = extract_bib_date(doc["bibliographic"])
95
+ return bib_date if bib_date
96
+
97
+ release_date = doc.dig("source", "releaseDate")
98
+ return nil unless release_date
99
+
100
+ release_date.to_s.split(/[T ]/).first
101
+ end
102
+
103
+ def extract_bib_date(bib)
104
+ return nil unless bib
105
+
106
+ dates = bib["date"]
107
+ return nil if dates.nil? || dates.empty?
108
+
109
+ published = dates.find { |d| d["type"] == "published" }
110
+ entry = published || dates.first
111
+ at = entry["at"]
112
+ at ? at.to_s.split(/[T ]/).first : nil
113
+ end
114
+
115
+ def add_contributors(hash, bib)
116
+ contribs = bib["contributor"] || []
117
+ persons, committees = partition_contributors(contribs)
118
+ hash["authors"] = persons
119
+ hash["committee"] = committees.first
120
+ end
121
+
122
+ def partition_contributors(contribs)
123
+ persons = contribs.filter_map { |c| parse_person(c) }
124
+ committees = contribs.filter_map { |c| parse_committee(c) }
125
+ [persons, committees]
126
+ end
127
+
128
+ def parse_person(contrib)
129
+ return nil unless contrib["person"]
130
+
131
+ name = extract_person_name(contrib["person"])
132
+ return nil unless name
133
+
134
+ role = (contrib["role"] || []).first&.fetch("type", nil)
135
+ { "name" => name, "role" => role }
136
+ end
137
+
138
+ def parse_committee(contrib)
139
+ return nil unless contrib["organization"]
140
+
141
+ extract_org_subdivision(contrib["organization"])
142
+ end
143
+
144
+ def extract_person_name(person)
145
+ n = person["name"] || {}
146
+ complete = n["completename"]
147
+ return complete["content"] if complete.is_a?(Hash) && complete["content"]
148
+ return complete if complete.is_a?(String)
149
+
150
+ surname = n["surname"]
151
+ given = n["given"]
152
+ given_str = given.is_a?(Hash) ? given["content"].to_s : given.to_s
153
+ parts = [given_str, surname].compact
154
+ parts.empty? ? nil : parts.join(" ")
155
+ end
156
+
157
+ def extract_org_subdivision(org)
158
+ subs = org["subdivision"]
159
+ return nil unless subs&.any?
160
+
161
+ sd = subs.first
162
+ sd_name = sd["name"]
163
+ if sd_name.is_a?(Array)
164
+ sd_name.first&.dig("content")
165
+ elsif sd_name.is_a?(Hash)
166
+ sd_name["content"]
167
+ else
168
+ sd_name.to_s
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -51,7 +51,7 @@ module Metanorma
51
51
  end
52
52
 
53
53
  def to_json(*_args)
54
- JSON.generate(to_h)
54
+ JSON.pretty_generate(to_h)
55
55
  end
56
56
 
57
57
  def write(path)
@@ -2,6 +2,18 @@
2
2
 
3
3
  module Metanorma
4
4
  module Release
5
+ module Extractor
6
+ def discover(output_dir)
7
+ raise NotImplementedError, "#{self} must implement .discover"
8
+ end
9
+ end
10
+
11
+ Release = Struct.new(:tag_name, :body, :prerelease, :draft,
12
+ :html_url, :published_at, :created_at,
13
+ :assets, keyword_init: true)
14
+ Asset = Struct.new(:name, :browser_download_url, :size, :data,
15
+ keyword_init: true)
16
+
5
17
  module Filter
6
18
  def apply(documents)
7
19
  raise NotImplementedError, "#{self.class} must implement #apply"
@@ -22,7 +22,9 @@ module Metanorma
22
22
  return nil unless parsed.is_a?(Hash)
23
23
 
24
24
  channels = Array(parsed["channels"])
25
- Array(parsed["documents"]).each { |doc| channels.concat(Array(doc["channels"])) }
25
+ Array(parsed["documents"]).each do |doc|
26
+ channels.concat(Array(doc["channels"]))
27
+ end
26
28
  channels.map(&:to_s).uniq
27
29
  rescue StandardError
28
30
  nil
@@ -6,12 +6,6 @@ module Metanorma
6
6
  module Release
7
7
  module Platform
8
8
  module GitHub
9
- GitHubRelease = Struct.new(:tag_name, :body, :prerelease, :draft,
10
- :html_url, :published_at, :created_at,
11
- :assets, keyword_init: true)
12
- GitHubAsset = Struct.new(:name, :browser_download_url, :size, :data,
13
- keyword_init: true)
14
-
15
9
  class ReleaseFetcher
16
10
  include Metanorma::Release::ReleaseFetcher
17
11
 
@@ -43,21 +37,21 @@ module Metanorma
43
37
  end
44
38
  all
45
39
  rescue StandardError => e
46
- warn "Warning: Failed to fetch releases for #{repo_slug}: #{e.message}"
40
+ Metanorma::Release.logger.warn "Failed to fetch releases for #{repo_slug}: #{e.message}"
47
41
  []
48
42
  end
49
43
 
50
44
  def parse_release(r)
51
45
  assets = (r[:assets] || []).map do |a|
52
46
  data = download_asset(a[:url]) if a[:name].end_with?(".zip")
53
- GitHubAsset.new(
47
+ Asset.new(
54
48
  name: a[:name],
55
49
  browser_download_url: a[:browser_download_url],
56
50
  size: a[:size],
57
51
  data: data,
58
52
  )
59
53
  end
60
- GitHubRelease.new(
54
+ Release.new(
61
55
  tag_name: r[:tag_name],
62
56
  body: r[:body],
63
57
  prerelease: r[:prerelease],
@@ -82,7 +76,7 @@ module Metanorma
82
76
  end
83
77
  data
84
78
  rescue StandardError => e
85
- warn "Warning: Failed to download asset #{url}: #{e.message}"
79
+ Metanorma::Release.logger.warn "Failed to download asset #{url}: #{e.message}"
86
80
  nil
87
81
  end
88
82
 
@@ -20,7 +20,7 @@ module Metanorma
20
20
  page = 1
21
21
  loop do
22
22
  results = @client.search_repositories(query, per_page: 100,
23
- page: page)
23
+ page: page)
24
24
  items = results[:items]
25
25
  break if items.nil? || items.empty?
26
26
 
@@ -18,10 +18,6 @@ module Metanorma
18
18
  "metanorma/release/platform/github/release_fetcher"
19
19
  autoload :ManifestReader,
20
20
  "metanorma/release/platform/github/manifest_reader"
21
-
22
- def self.cache_store(cache_dir:)
23
- FileCacheStore.new(cache_dir)
24
- end
25
21
  end
26
22
  end
27
23
  end
@@ -6,12 +6,6 @@ module Metanorma
6
6
  module Release
7
7
  module Platform
8
8
  module Local
9
- LocalRelease = Struct.new(:tag_name, :body, :prerelease, :draft,
10
- :html_url, :published_at, :created_at,
11
- :assets, keyword_init: true)
12
- LocalAsset = Struct.new(:name, :browser_download_url, :size, :data,
13
- keyword_init: true)
14
-
15
9
  class Fetcher
16
10
  include Metanorma::Release::ReleaseFetcher
17
11
 
@@ -42,22 +36,22 @@ module Metanorma
42
36
  zip_path = File.join(dir, "#{base}.zip")
43
37
 
44
38
  unless File.exist?(zip_path)
45
- warn "Warning: Missing zip for #{meta_path}, skipping"
39
+ Metanorma::Release.logger.warn "Missing zip for #{meta_path}, skipping"
46
40
  return nil
47
41
  end
48
42
 
49
43
  metadata = Publication.from_metadata_hash(data)
50
- asset = LocalAsset.new(
44
+ asset = Asset.new(
51
45
  name: "#{base}.zip",
52
46
  browser_download_url: "file://#{File.expand_path(zip_path)}",
53
47
  size: File.size(zip_path),
54
48
  data: File.binread(zip_path),
55
49
  )
56
50
 
57
- LocalRelease.new(
51
+ Release.new(
58
52
  tag_name: "#{metadata.slug}/#{metadata.edition || '1'}",
59
53
  body: metadata.to_release_body,
60
- prerelease: prerelease?(metadata),
54
+ prerelease: metadata.draft?,
61
55
  draft: false,
62
56
  html_url: "file://#{File.expand_path(dir)}",
63
57
  published_at: File.mtime(zip_path).iso8601,
@@ -65,15 +59,9 @@ module Metanorma
65
59
  assets: [asset],
66
60
  )
67
61
  rescue JSON::ParserError
68
- warn "Warning: Invalid metadata JSON in #{meta_path}, skipping"
62
+ Metanorma::Release.logger.warn "Invalid metadata JSON in #{meta_path}, skipping"
69
63
  nil
70
64
  end
71
-
72
- def prerelease?(metadata)
73
- stage = metadata.stage.to_s
74
- %w[working-draft committee-draft draft-standard
75
- final-draft].include?(stage)
76
- end
77
65
  end
78
66
  end
79
67
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Release
5
+ module Platform
6
+ module Null
7
+ class ManifestReader
8
+ include Metanorma::Release::ManifestReader
9
+
10
+ def read(_repo) = nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,7 +8,7 @@ module Metanorma
8
8
  include Metanorma::Release::Publisher
9
9
 
10
10
  def publish(tag, _artifact, _metadata, channels:,
11
- force_replace: false)
11
+ force_replace: false)
12
12
  PublishResult.new(tag: tag.to_s, url: "null://", created?: true)
13
13
  end
14
14
  end