metanorma-release 0.2.2 → 0.2.3
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 +4 -4
- data/.rubocop.yml +19 -1
- data/.rubocop_todo.yml +250 -319
- data/README.adoc +120 -233
- data/Rakefile +2 -2
- data/exe/metanorma-release +2 -2
- data/lib/metanorma/release/aggregation_pipeline.rb +59 -45
- data/lib/metanorma/release/asset_processor.rb +10 -8
- data/lib/metanorma/release/cache_store.rb +6 -6
- data/lib/metanorma/release/change_detector.rb +7 -3
- data/lib/metanorma/release/channel.rb +13 -39
- data/lib/metanorma/release/channel_filter.rb +26 -10
- data/lib/metanorma/release/cli.rb +129 -100
- data/lib/metanorma/release/commands/aggregate.rb +39 -54
- data/lib/metanorma/release/commands/package.rb +20 -12
- data/lib/metanorma/release/commands/{publish.rb → release_command.rb} +20 -12
- data/lib/metanorma/release/config.rb +104 -0
- data/lib/metanorma/release/content_hash.rb +11 -3
- data/lib/metanorma/release/delta_state.rb +55 -18
- data/lib/metanorma/release/file_routing.rb +8 -5
- data/lib/metanorma/release/index.rb +132 -0
- data/lib/metanorma/release/interfaces.rb +15 -15
- data/lib/metanorma/release/platform/github/manifest_reader.rb +4 -4
- data/lib/metanorma/release/platform/github/publisher.rb +23 -11
- data/lib/metanorma/release/platform/github/release_fetcher.rb +12 -3
- data/lib/metanorma/release/platform/github.rb +10 -7
- data/lib/metanorma/release/platform/local/directory_discoverer.rb +1 -1
- data/lib/metanorma/release/platform/local/fetcher.rb +17 -12
- data/lib/metanorma/release/platform/local/publisher.rb +9 -7
- data/lib/metanorma/release/platform/local.rb +4 -4
- data/lib/metanorma/release/platform/null/publisher.rb +3 -2
- data/lib/metanorma/release/platform/null.rb +1 -1
- data/lib/metanorma/release/platform.rb +3 -3
- data/lib/metanorma/release/platform_factory.rb +48 -29
- data/lib/metanorma/release/publication.rb +335 -0
- data/lib/metanorma/release/release_pipeline.rb +85 -52
- data/lib/metanorma/release/repo_ref.rb +5 -2
- data/lib/metanorma/release/site.rb +66 -0
- data/lib/metanorma/release/slug_strategy.rb +163 -0
- data/lib/metanorma/release/version.rb +1 -1
- data/lib/metanorma/release/zip_packager.rb +31 -8
- data/lib/metanorma/release.rb +68 -94
- metadata +22 -26
- data/lib/metanorma/release/aggregation_interfaces.rb +0 -27
- data/lib/metanorma/release/channel_audience.rb +0 -24
- data/lib/metanorma/release/channel_config.rb +0 -55
- data/lib/metanorma/release/channel_manifest.rb +0 -192
- data/lib/metanorma/release/channel_registry.rb +0 -60
- data/lib/metanorma/release/config_fetcher.rb +0 -11
- data/lib/metanorma/release/config_locator.rb +0 -37
- data/lib/metanorma/release/config_resolver.rb +0 -37
- data/lib/metanorma/release/document_id.rb +0 -45
- data/lib/metanorma/release/document_index.rb +0 -183
- data/lib/metanorma/release/document_metadata.rb +0 -39
- data/lib/metanorma/release/document_stage.rb +0 -86
- data/lib/metanorma/release/document_type.rb +0 -55
- data/lib/metanorma/release/document_version.rb +0 -50
- data/lib/metanorma/release/naming_strategy.rb +0 -158
- data/lib/metanorma/release/platform/github/config_fetcher.rb +0 -40
- data/lib/metanorma/release/platform/local/config_fetcher.rb +0 -20
- data/lib/metanorma/release/rake_tasks.rb +0 -71
- data/lib/metanorma/release/relaton_enricher.rb +0 -138
- data/lib/metanorma/release/release_metadata.rb +0 -79
- data/lib/metanorma/release/release_tag.rb +0 -49
- data/lib/metanorma/release/rxl_extractor.rb +0 -115
- data/lib/metanorma/release/stage_filter.rb +0 -18
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "json"
|
|
4
4
|
|
|
5
5
|
module Metanorma
|
|
6
6
|
module Release
|
|
7
|
+
module DeltaStateManager
|
|
8
|
+
def load
|
|
9
|
+
raise NotImplementedError, "#{self.class} must implement #load"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def save
|
|
13
|
+
raise NotImplementedError, "#{self.class} must implement #save"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def etag(repo_key)
|
|
17
|
+
raise NotImplementedError, "#{self.class} must implement #etag"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def set_etag(repo_key, etag_value)
|
|
21
|
+
raise NotImplementedError, "#{self.class} must implement #set_etag"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def processed?(repo_key, tag, content_hash)
|
|
25
|
+
raise NotImplementedError, "#{self.class} must implement #processed?"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def release_files(repo_key, tag)
|
|
29
|
+
raise NotImplementedError, "#{self.class} must implement #release_files"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def mark_processed(repo_key, tag, content_hash, files)
|
|
33
|
+
raise NotImplementedError,
|
|
34
|
+
"#{self.class} must implement #mark_processed"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cleanup_stale(repo_key, current_tags)
|
|
38
|
+
raise NotImplementedError, "#{self.class} must implement #cleanup_stale"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
7
42
|
class DeltaState
|
|
43
|
+
include DeltaStateManager
|
|
44
|
+
|
|
8
45
|
def initialize(cache_store:, output_dir:)
|
|
9
46
|
@cache = cache_store
|
|
10
47
|
@output_dir = output_dir
|
|
@@ -12,7 +49,7 @@ module Metanorma
|
|
|
12
49
|
end
|
|
13
50
|
|
|
14
51
|
def load
|
|
15
|
-
raw = @cache.get(
|
|
52
|
+
raw = @cache.get("delta_state")
|
|
16
53
|
return if raw.nil?
|
|
17
54
|
|
|
18
55
|
@state = JSON.parse(raw)
|
|
@@ -21,50 +58,50 @@ module Metanorma
|
|
|
21
58
|
end
|
|
22
59
|
|
|
23
60
|
def save
|
|
24
|
-
@cache.set(
|
|
61
|
+
@cache.set("delta_state", JSON.generate(@state))
|
|
25
62
|
end
|
|
26
63
|
|
|
27
64
|
def etag(repo_key)
|
|
28
|
-
repo_state(repo_key)[
|
|
65
|
+
repo_state(repo_key)["etag"]
|
|
29
66
|
end
|
|
30
67
|
|
|
31
68
|
def set_etag(repo_key, etag_value)
|
|
32
69
|
repo = ensure_repo(repo_key)
|
|
33
|
-
repo[
|
|
70
|
+
repo["etag"] = etag_value
|
|
34
71
|
end
|
|
35
72
|
|
|
36
73
|
def processed?(repo_key, tag, content_hash)
|
|
37
|
-
releases = repo_state(repo_key)[
|
|
74
|
+
releases = repo_state(repo_key)["releases"]
|
|
38
75
|
return false unless releases.key?(tag)
|
|
39
76
|
return false if content_hash.nil?
|
|
40
77
|
|
|
41
|
-
releases[tag][
|
|
78
|
+
releases[tag]["content_hash"] == content_hash.to_s
|
|
42
79
|
end
|
|
43
80
|
|
|
44
81
|
def release_files(repo_key, tag)
|
|
45
|
-
releases = repo_state(repo_key)[
|
|
82
|
+
releases = repo_state(repo_key)["releases"]
|
|
46
83
|
return [] unless releases.key?(tag)
|
|
47
84
|
|
|
48
|
-
releases[tag][
|
|
85
|
+
releases[tag]["files"] || []
|
|
49
86
|
end
|
|
50
87
|
|
|
51
88
|
def mark_processed(repo_key, tag, content_hash, files)
|
|
52
89
|
repo = ensure_repo(repo_key)
|
|
53
|
-
repo[
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
repo["releases"][tag] = {
|
|
91
|
+
"content_hash" => content_hash.to_s,
|
|
92
|
+
"files" => files,
|
|
56
93
|
}
|
|
57
94
|
end
|
|
58
95
|
|
|
59
96
|
def cleanup_stale(repo_key, current_tags)
|
|
60
97
|
repo = repo_state(repo_key)
|
|
61
|
-
releases = repo[
|
|
98
|
+
releases = repo["releases"]
|
|
62
99
|
removed = 0
|
|
63
100
|
|
|
64
101
|
releases.each do |tag, entry|
|
|
65
102
|
next if current_tags.include?(tag)
|
|
66
103
|
|
|
67
|
-
(entry[
|
|
104
|
+
(entry["files"] || []).each do |file|
|
|
68
105
|
path = File.join(@output_dir, file)
|
|
69
106
|
if File.exist?(path)
|
|
70
107
|
File.delete(path)
|
|
@@ -80,20 +117,20 @@ module Metanorma
|
|
|
80
117
|
private
|
|
81
118
|
|
|
82
119
|
def empty_state
|
|
83
|
-
{
|
|
120
|
+
{ "last_run" => Time.now.utc.iso8601, "repos" => {} }
|
|
84
121
|
end
|
|
85
122
|
|
|
86
123
|
def repo_state(repo_key)
|
|
87
|
-
@state[
|
|
124
|
+
@state["repos"][repo_key] || { "etag" => nil, "releases" => {} }
|
|
88
125
|
end
|
|
89
126
|
|
|
90
127
|
def ensure_repo(repo_key)
|
|
91
|
-
@state[
|
|
128
|
+
@state["repos"][repo_key] ||= { "etag" => nil, "releases" => {} }
|
|
92
129
|
end
|
|
93
130
|
end
|
|
94
131
|
|
|
95
132
|
class NullDeltaState
|
|
96
|
-
|
|
133
|
+
include DeltaStateManager
|
|
97
134
|
|
|
98
135
|
def load; end
|
|
99
136
|
def save; end
|
|
@@ -28,21 +28,24 @@ module Metanorma
|
|
|
28
28
|
include FileRouting
|
|
29
29
|
|
|
30
30
|
def compute_path(file_name, _metadata)
|
|
31
|
-
ext = File.extname(file_name).delete_prefix(
|
|
31
|
+
ext = File.extname(file_name).delete_prefix(".")
|
|
32
32
|
"#{ext}/#{file_name}"
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
module FileRoutingFactory
|
|
37
37
|
ROUTING_MAP = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
"by-document" => ByDocument,
|
|
39
|
+
"flat" => Flat,
|
|
40
|
+
"by-format" => ByFormat,
|
|
41
41
|
}.freeze
|
|
42
42
|
|
|
43
43
|
def self.from_name(name)
|
|
44
44
|
klass = ROUTING_MAP[name]
|
|
45
|
-
|
|
45
|
+
unless klass
|
|
46
|
+
raise ArgumentError,
|
|
47
|
+
"Unknown routing mode: #{name}. Available: #{ROUTING_MAP.keys.join(', ')}"
|
|
48
|
+
end
|
|
46
49
|
|
|
47
50
|
klass.new
|
|
48
51
|
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Metanorma
|
|
6
|
+
module Release
|
|
7
|
+
class Index
|
|
8
|
+
SCHEMA_VERSION = 1
|
|
9
|
+
|
|
10
|
+
class SchemaError < StandardError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :publications, :parameters, :generated_at
|
|
14
|
+
|
|
15
|
+
def initialize(publications:, parameters:, generated_at: nil)
|
|
16
|
+
@publications = publications.freeze
|
|
17
|
+
@parameters = parameters
|
|
18
|
+
@generated_at = generated_at || Time.now.utc.iso8601
|
|
19
|
+
freeze
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def channels
|
|
23
|
+
@publications.flat_map(&:channels).uniq.sort
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def publication_count
|
|
27
|
+
@publications.length
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def empty?
|
|
31
|
+
@publications.empty?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_h
|
|
35
|
+
{
|
|
36
|
+
"version" => SCHEMA_VERSION,
|
|
37
|
+
"generatedAt" => @generated_at,
|
|
38
|
+
"parameters" => {
|
|
39
|
+
"organizations" => @parameters[:organizations] || [],
|
|
40
|
+
"channels" => @parameters[:channels] || [],
|
|
41
|
+
"topic" => @parameters[:topic],
|
|
42
|
+
"repoCount" => @parameters[:repo_count] || 0,
|
|
43
|
+
},
|
|
44
|
+
"summary" => {
|
|
45
|
+
"repoCount" => @parameters[:repo_count] || 0,
|
|
46
|
+
"documentCount" => publication_count,
|
|
47
|
+
"channelsFound" => channels,
|
|
48
|
+
},
|
|
49
|
+
"documents" => @publications.map(&:to_h),
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_json(*_args)
|
|
54
|
+
JSON.generate(to_h)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def write(path)
|
|
58
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
59
|
+
File.write(path, to_json)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.from_documents(publications, parameters:)
|
|
63
|
+
new(publications: publications, parameters: parameters)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.from_json(json_string)
|
|
67
|
+
data = JSON.parse(json_string)
|
|
68
|
+
validate!(data)
|
|
69
|
+
publications = (data["documents"] || []).map do |d|
|
|
70
|
+
publication_from_h(d)
|
|
71
|
+
end
|
|
72
|
+
new(
|
|
73
|
+
publications: publications,
|
|
74
|
+
parameters: {
|
|
75
|
+
organizations: data.dig("parameters", "organizations") || [],
|
|
76
|
+
channels: data.dig("parameters", "channels") || [],
|
|
77
|
+
topic: data.dig("parameters", "topic"),
|
|
78
|
+
repo_count: data.dig("parameters", "repoCount") || 0,
|
|
79
|
+
},
|
|
80
|
+
generated_at: data["generatedAt"],
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.validate!(data)
|
|
85
|
+
raise SchemaError, "Missing 'version' field" unless data.key?("version")
|
|
86
|
+
unless data["version"] == SCHEMA_VERSION
|
|
87
|
+
raise SchemaError,
|
|
88
|
+
"Unsupported schema version: #{data['version']}. Expected #{SCHEMA_VERSION}"
|
|
89
|
+
end
|
|
90
|
+
unless data.key?("documents")
|
|
91
|
+
raise SchemaError,
|
|
92
|
+
"Missing 'documents' field"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
data["documents"].each do |doc|
|
|
96
|
+
unless doc.key?("id")
|
|
97
|
+
raise SchemaError,
|
|
98
|
+
"Document missing required field 'id'"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.publication_from_h(hash)
|
|
104
|
+
files = (hash["files"] || []).map do |f|
|
|
105
|
+
PublicationFile.new(format: f["format"], name: f["name"],
|
|
106
|
+
path: f["path"])
|
|
107
|
+
end
|
|
108
|
+
source = if hash["source"]
|
|
109
|
+
PublicationSource.new(
|
|
110
|
+
owner: hash["source"]["owner"],
|
|
111
|
+
repo: hash["source"]["repo"],
|
|
112
|
+
tag: hash["source"]["tag"],
|
|
113
|
+
url: hash["source"]["releaseUrl"],
|
|
114
|
+
date: hash["source"]["releaseDate"],
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
Publication.new(
|
|
118
|
+
identifier: hash["identifier"] || hash["id"],
|
|
119
|
+
slug: hash["id"],
|
|
120
|
+
title: hash["title"],
|
|
121
|
+
edition: hash["edition"],
|
|
122
|
+
stage: hash["stage"],
|
|
123
|
+
doctype: hash.fetch("doctype", ""),
|
|
124
|
+
revdate: hash["revdate"],
|
|
125
|
+
channels: hash["channels"] || [],
|
|
126
|
+
files: files,
|
|
127
|
+
source: source,
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -2,16 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Metanorma
|
|
4
4
|
module Release
|
|
5
|
-
module Extractor
|
|
6
|
-
def discover(output_dir)
|
|
7
|
-
raise NotImplementedError, "#{self.class} must implement #discover"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def extract(rxl_path)
|
|
11
|
-
raise NotImplementedError, "#{self.class} must implement #extract"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
5
|
module Filter
|
|
16
6
|
def apply(documents)
|
|
17
7
|
raise NotImplementedError, "#{self.class} must implement #apply"
|
|
@@ -36,12 +26,22 @@ module Metanorma
|
|
|
36
26
|
end
|
|
37
27
|
end
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
module RepoDiscoverer
|
|
30
|
+
def discover
|
|
31
|
+
raise NotImplementedError, "#{self.class} must implement #discover"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
42
34
|
|
|
43
|
-
|
|
35
|
+
module ReleaseFetcher
|
|
36
|
+
def fetch(repo, etag: nil)
|
|
37
|
+
raise NotImplementedError, "#{self.class} must implement #fetch"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
44
40
|
|
|
45
|
-
|
|
41
|
+
module ManifestReader
|
|
42
|
+
def read(repo)
|
|
43
|
+
raise NotImplementedError, "#{self.class} must implement #read"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "yaml"
|
|
4
4
|
|
|
5
5
|
module Metanorma
|
|
6
6
|
module Release
|
|
@@ -14,14 +14,14 @@ module Metanorma
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def read(repo)
|
|
17
|
-
content = @client.contents(repo.to_s, path:
|
|
17
|
+
content = @client.contents(repo.to_s, path: "metanorma.release.yml")
|
|
18
18
|
return nil unless content
|
|
19
19
|
|
|
20
|
-
yaml = content[
|
|
20
|
+
yaml = content["content"].unpack1("m0")
|
|
21
21
|
parsed = YAML.safe_load(yaml, permitted_classes: [Symbol])
|
|
22
22
|
return nil unless parsed.is_a?(Hash)
|
|
23
23
|
|
|
24
|
-
(parsed[
|
|
24
|
+
(parsed["channels"] || []).map(&:to_s)
|
|
25
25
|
rescue StandardError
|
|
26
26
|
nil
|
|
27
27
|
end
|
|
@@ -17,7 +17,8 @@ module Metanorma
|
|
|
17
17
|
|
|
18
18
|
if force_replace
|
|
19
19
|
delete_existing_release(tag_name)
|
|
20
|
-
return create_release(tag_name, metadata, artifact
|
|
20
|
+
return create_release(tag_name, metadata, artifact,
|
|
21
|
+
prerelease: channels_pre_release?(channels))
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
existing = find_release(tag_name)
|
|
@@ -25,41 +26,52 @@ module Metanorma
|
|
|
25
26
|
if existing
|
|
26
27
|
update_release(existing, metadata)
|
|
27
28
|
else
|
|
28
|
-
create_release(tag_name, metadata, artifact
|
|
29
|
+
create_release(tag_name, metadata, artifact,
|
|
30
|
+
prerelease: channels_pre_release?(channels))
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
private
|
|
33
35
|
|
|
36
|
+
def channels_pre_release?(channels)
|
|
37
|
+
channels.any? do |c|
|
|
38
|
+
c.to_s.include?("draft") || c.to_s.include?("internal")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
def find_release(tag_name)
|
|
35
|
-
@client.releases(@repo).find { |r| r[
|
|
43
|
+
@client.releases(@repo).find { |r| r["tag_name"] == tag_name }
|
|
36
44
|
rescue StandardError
|
|
37
45
|
nil
|
|
38
46
|
end
|
|
39
47
|
|
|
40
|
-
def create_release(tag_name, metadata, artifact)
|
|
48
|
+
def create_release(tag_name, metadata, artifact, prerelease: false)
|
|
41
49
|
release = @client.create_release(
|
|
42
50
|
@repo, tag_name,
|
|
43
51
|
name: tag_name,
|
|
44
52
|
body: metadata.to_release_body,
|
|
45
|
-
prerelease:
|
|
53
|
+
prerelease: prerelease
|
|
46
54
|
)
|
|
47
|
-
upload_asset(release[
|
|
48
|
-
PublishResult.new(tag: tag_name, url: release[
|
|
55
|
+
upload_asset(release["id"], artifact)
|
|
56
|
+
PublishResult.new(tag: tag_name, url: release["html_url"],
|
|
57
|
+
created?: true)
|
|
49
58
|
end
|
|
50
59
|
|
|
51
60
|
def update_release(release, metadata)
|
|
52
|
-
@client.update_release(release[
|
|
53
|
-
|
|
61
|
+
@client.update_release(release["url"],
|
|
62
|
+
body: metadata.to_release_body)
|
|
63
|
+
PublishResult.new(tag: release["tag_name"],
|
|
64
|
+
url: release["html_url"], created?: false)
|
|
54
65
|
end
|
|
55
66
|
|
|
56
67
|
def upload_asset(release_id, artifact)
|
|
57
|
-
@client.upload_asset(release_id, artifact.zip_path,
|
|
68
|
+
@client.upload_asset(release_id, artifact.zip_path,
|
|
69
|
+
content_type: "application/zip")
|
|
58
70
|
end
|
|
59
71
|
|
|
60
72
|
def delete_existing_release(tag_name)
|
|
61
73
|
release = find_release(tag_name)
|
|
62
|
-
@client.delete_release(release[
|
|
74
|
+
@client.delete_release(release["url"]) if release
|
|
63
75
|
begin
|
|
64
76
|
@client.delete_ref(@repo, "tags/#{tag_name}")
|
|
65
77
|
rescue StandardError
|
|
@@ -20,18 +20,20 @@ module Metanorma
|
|
|
20
20
|
def fetch(repo, etag: nil)
|
|
21
21
|
releases = @client.releases(repo.to_s)
|
|
22
22
|
parsed = releases.map { |r| parse_release(r) }
|
|
23
|
-
FetchResult.new(releases: parsed, etag: "etag-#{repo}",
|
|
23
|
+
FetchResult.new(releases: parsed, etag: "etag-#{repo}",
|
|
24
|
+
unchanged?: false)
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
private
|
|
27
28
|
|
|
28
29
|
def parse_release(r)
|
|
29
30
|
assets = (r[:assets] || []).map do |a|
|
|
31
|
+
data = download_asset(a[:url]) if a[:name].end_with?(".zip")
|
|
30
32
|
GitHubAsset.new(
|
|
31
33
|
name: a[:name],
|
|
32
34
|
browser_download_url: a[:browser_download_url],
|
|
33
35
|
size: a[:size],
|
|
34
|
-
data:
|
|
36
|
+
data: data,
|
|
35
37
|
)
|
|
36
38
|
end
|
|
37
39
|
GitHubRelease.new(
|
|
@@ -42,9 +44,16 @@ module Metanorma
|
|
|
42
44
|
html_url: r[:html_url],
|
|
43
45
|
published_at: r[:published_at],
|
|
44
46
|
created_at: r[:created_at],
|
|
45
|
-
assets: assets
|
|
47
|
+
assets: assets,
|
|
46
48
|
)
|
|
47
49
|
end
|
|
50
|
+
|
|
51
|
+
def download_asset(url)
|
|
52
|
+
@client.get(url, accept: "application/octet-stream")
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
warn "Warning: Failed to download asset #{url}: #{e.message}"
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
48
57
|
end
|
|
49
58
|
end
|
|
50
59
|
end
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
begin
|
|
4
|
-
require
|
|
4
|
+
require "octokit"
|
|
5
5
|
rescue LoadError
|
|
6
|
-
raise LoadError,
|
|
6
|
+
raise LoadError,
|
|
7
|
+
"The octokit gem is required for GitHub adapters. Add `gem 'octokit'` to your Gemfile."
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
module Metanorma
|
|
10
11
|
module Release
|
|
11
12
|
module Platform
|
|
12
13
|
module GitHub
|
|
13
|
-
autoload :Publisher,
|
|
14
|
-
autoload :TopicDiscoverer,
|
|
15
|
-
|
|
16
|
-
autoload :
|
|
17
|
-
|
|
14
|
+
autoload :Publisher, "metanorma/release/platform/github/publisher"
|
|
15
|
+
autoload :TopicDiscoverer,
|
|
16
|
+
"metanorma/release/platform/github/topic_discoverer"
|
|
17
|
+
autoload :ReleaseFetcher,
|
|
18
|
+
"metanorma/release/platform/github/release_fetcher"
|
|
19
|
+
autoload :ManifestReader,
|
|
20
|
+
"metanorma/release/platform/github/manifest_reader"
|
|
18
21
|
|
|
19
22
|
def self.cache_store(cache_dir:)
|
|
20
23
|
FileCacheStore.new(cache_dir)
|
|
@@ -16,7 +16,7 @@ module Metanorma
|
|
|
16
16
|
|
|
17
17
|
Dir.children(@base_path).filter_map do |entry|
|
|
18
18
|
full = File.join(@base_path, entry)
|
|
19
|
-
RepoRef.new(owner:
|
|
19
|
+
RepoRef.new(owner: "local", repo: entry) if File.directory?(full)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "json"
|
|
4
4
|
|
|
5
5
|
module Metanorma
|
|
6
6
|
module Release
|
|
@@ -21,9 +21,13 @@ module Metanorma
|
|
|
21
21
|
|
|
22
22
|
def fetch(repo, etag: nil)
|
|
23
23
|
dir = File.join(@base_path, repo.repo)
|
|
24
|
-
|
|
24
|
+
unless Dir.exist?(dir)
|
|
25
|
+
return FetchResult.new(releases: [], etag: nil,
|
|
26
|
+
unchanged?: false)
|
|
27
|
+
end
|
|
25
28
|
|
|
26
|
-
releases = Dir.glob(File.join(dir,
|
|
29
|
+
releases = Dir.glob(File.join(dir,
|
|
30
|
+
"*.meta.json")).filter_map do |meta_path|
|
|
27
31
|
build_release(dir, meta_path)
|
|
28
32
|
end
|
|
29
33
|
|
|
@@ -34,7 +38,7 @@ module Metanorma
|
|
|
34
38
|
|
|
35
39
|
def build_release(dir, meta_path)
|
|
36
40
|
data = JSON.parse(File.read(meta_path))
|
|
37
|
-
base = File.basename(meta_path,
|
|
41
|
+
base = File.basename(meta_path, ".meta.json")
|
|
38
42
|
zip_path = File.join(dir, "#{base}.zip")
|
|
39
43
|
|
|
40
44
|
unless File.exist?(zip_path)
|
|
@@ -42,32 +46,33 @@ module Metanorma
|
|
|
42
46
|
return nil
|
|
43
47
|
end
|
|
44
48
|
|
|
45
|
-
metadata =
|
|
49
|
+
metadata = Publication.from_metadata_hash(data)
|
|
46
50
|
asset = LocalAsset.new(
|
|
47
51
|
name: "#{base}.zip",
|
|
48
52
|
browser_download_url: "file://#{File.expand_path(zip_path)}",
|
|
49
53
|
size: File.size(zip_path),
|
|
50
|
-
data: File.binread(zip_path)
|
|
54
|
+
data: File.binread(zip_path),
|
|
51
55
|
)
|
|
52
56
|
|
|
53
57
|
LocalRelease.new(
|
|
54
|
-
tag_name: "#{
|
|
58
|
+
tag_name: "#{metadata.slug}/#{metadata.edition || '1'}",
|
|
55
59
|
body: metadata.to_release_body,
|
|
56
|
-
prerelease: prerelease?(
|
|
60
|
+
prerelease: prerelease?(metadata),
|
|
57
61
|
draft: false,
|
|
58
62
|
html_url: "file://#{File.expand_path(dir)}",
|
|
59
63
|
published_at: File.mtime(zip_path).iso8601,
|
|
60
64
|
created_at: File.mtime(zip_path).iso8601,
|
|
61
|
-
assets: [asset]
|
|
65
|
+
assets: [asset],
|
|
62
66
|
)
|
|
63
67
|
rescue JSON::ParserError
|
|
64
68
|
warn "Warning: Invalid metadata JSON in #{meta_path}, skipping"
|
|
65
69
|
nil
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
def prerelease?(
|
|
69
|
-
stage =
|
|
70
|
-
%w[working-draft committee-draft draft-standard
|
|
72
|
+
def prerelease?(metadata)
|
|
73
|
+
stage = metadata.stage.to_s
|
|
74
|
+
%w[working-draft committee-draft draft-standard
|
|
75
|
+
final-draft].include?(stage)
|
|
71
76
|
end
|
|
72
77
|
end
|
|
73
78
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "json"
|
|
4
|
+
require "fileutils"
|
|
5
5
|
|
|
6
6
|
module Metanorma
|
|
7
7
|
module Release
|
|
@@ -18,23 +18,25 @@ module Metanorma
|
|
|
18
18
|
FileUtils.mkdir_p(@output_dir)
|
|
19
19
|
|
|
20
20
|
zip_dest = File.join(@output_dir, artifact.asset_name)
|
|
21
|
-
meta_dest = File.join(@output_dir,
|
|
21
|
+
meta_dest = File.join(@output_dir,
|
|
22
|
+
meta_file_name(artifact.asset_name))
|
|
22
23
|
|
|
23
24
|
if force_replace
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
FileUtils.rm_f(zip_dest)
|
|
26
|
+
FileUtils.rm_f(meta_dest)
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
FileUtils.cp(artifact.zip_path, zip_dest)
|
|
29
30
|
File.write(meta_dest, metadata.to_json)
|
|
30
31
|
|
|
31
|
-
PublishResult.new(tag: tag.to_s,
|
|
32
|
+
PublishResult.new(tag: tag.to_s,
|
|
33
|
+
url: "file://#{File.expand_path(zip_dest)}", created?: true)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
private
|
|
35
37
|
|
|
36
38
|
def meta_file_name(asset_name)
|
|
37
|
-
base = asset_name.sub(/\.zip$/,
|
|
39
|
+
base = asset_name.sub(/\.zip$/, "")
|
|
38
40
|
"#{base}.meta.json"
|
|
39
41
|
end
|
|
40
42
|
end
|
|
@@ -4,10 +4,10 @@ module Metanorma
|
|
|
4
4
|
module Release
|
|
5
5
|
module Platform
|
|
6
6
|
module Local
|
|
7
|
-
autoload :Publisher,
|
|
8
|
-
autoload :DirectoryDiscoverer,
|
|
9
|
-
|
|
10
|
-
autoload :
|
|
7
|
+
autoload :Publisher, "metanorma/release/platform/local/publisher"
|
|
8
|
+
autoload :DirectoryDiscoverer,
|
|
9
|
+
"metanorma/release/platform/local/directory_discoverer"
|
|
10
|
+
autoload :Fetcher, "metanorma/release/platform/local/fetcher"
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|