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
|
@@ -2,13 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
module Metanorma
|
|
4
4
|
module Release
|
|
5
|
-
|
|
5
|
+
FetchResult = Struct.new(:releases, :etag, :unchanged?, keyword_init: true)
|
|
6
|
+
RepoReport = Struct.new(:releases, :included, :skipped, :reason, :errors,
|
|
7
|
+
keyword_init: true)
|
|
8
|
+
RepoError = Struct.new(:tag, :message, keyword_init: true)
|
|
9
|
+
|
|
10
|
+
class AggregationPipeline # rubocop:disable Metrics/ClassLength
|
|
6
11
|
Dependencies = Struct.new(
|
|
7
12
|
:discoverer, :fetcher, :manifest_reader,
|
|
8
|
-
:
|
|
9
|
-
:asset_processor, :delta_state,
|
|
13
|
+
:metadata_filter, :asset_processor, :delta_state,
|
|
10
14
|
keyword_init: true
|
|
11
|
-
)
|
|
15
|
+
) do
|
|
16
|
+
def initialize(**kwargs)
|
|
17
|
+
super
|
|
18
|
+
validate_types!
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def validate_types!
|
|
24
|
+
validate_interface!(discoverer, RepoDiscoverer, "discoverer")
|
|
25
|
+
validate_interface!(fetcher, ReleaseFetcher, "fetcher")
|
|
26
|
+
validate_interface!(manifest_reader, ManifestReader,
|
|
27
|
+
"manifest_reader")
|
|
28
|
+
validate_interface!(delta_state, DeltaStateManager, "delta_state")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def validate_interface!(obj, mod, name)
|
|
32
|
+
return if obj.is_a?(mod) || begin
|
|
33
|
+
obj.class.ancestors.include?(mod)
|
|
34
|
+
rescue StandardError
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
raise ArgumentError, "#{name} must include #{mod}, got #{obj.class}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
12
41
|
|
|
13
42
|
Config = Struct.new(
|
|
14
43
|
:organizations, :channels, :topic,
|
|
@@ -17,7 +46,7 @@ module Metanorma
|
|
|
17
46
|
)
|
|
18
47
|
|
|
19
48
|
Result = Struct.new(
|
|
20
|
-
:
|
|
49
|
+
:publications, :repo_count, :channels_found,
|
|
21
50
|
:report, :failed_repos,
|
|
22
51
|
keyword_init: true
|
|
23
52
|
)
|
|
@@ -29,13 +58,13 @@ module Metanorma
|
|
|
29
58
|
def run(config, output_dir)
|
|
30
59
|
@deps.delta_state.load
|
|
31
60
|
repos = @deps.discoverer.discover
|
|
32
|
-
|
|
61
|
+
publications = []
|
|
33
62
|
reports = []
|
|
34
63
|
failed_repos = []
|
|
35
64
|
|
|
36
65
|
repos.each do |repo|
|
|
37
66
|
repo_docs, report = process_repo(repo, output_dir, config)
|
|
38
|
-
|
|
67
|
+
publications.concat(repo_docs)
|
|
39
68
|
reports << report
|
|
40
69
|
rescue StandardError => e
|
|
41
70
|
failed_repos << RepoError.new(tag: repo.to_s, message: e.message)
|
|
@@ -45,11 +74,11 @@ module Metanorma
|
|
|
45
74
|
@deps.delta_state.save
|
|
46
75
|
|
|
47
76
|
Result.new(
|
|
48
|
-
|
|
77
|
+
publications: publications,
|
|
49
78
|
repo_count: repos.length,
|
|
50
|
-
channels_found:
|
|
79
|
+
channels_found: publications.flat_map(&:channels).uniq.sort,
|
|
51
80
|
report: reports,
|
|
52
|
-
failed_repos: failed_repos
|
|
81
|
+
failed_repos: failed_repos,
|
|
53
82
|
)
|
|
54
83
|
end
|
|
55
84
|
|
|
@@ -59,9 +88,9 @@ module Metanorma
|
|
|
59
88
|
repo_key = repo.to_s
|
|
60
89
|
|
|
61
90
|
manifest_channels = @deps.manifest_reader.read(repo)
|
|
62
|
-
if manifest_channels && !@deps.
|
|
91
|
+
if manifest_channels && !@deps.metadata_filter.overlaps?(manifest_channels)
|
|
63
92
|
return [], RepoReport.new(releases: 0, included: 0, skipped: 0,
|
|
64
|
-
reason:
|
|
93
|
+
reason: "channel manifest", errors: [])
|
|
65
94
|
end
|
|
66
95
|
|
|
67
96
|
etag = @deps.delta_state.etag(repo_key)
|
|
@@ -69,19 +98,19 @@ module Metanorma
|
|
|
69
98
|
|
|
70
99
|
if fetch_result.unchanged?
|
|
71
100
|
return [], RepoReport.new(releases: 0, included: 0, skipped: 0,
|
|
72
|
-
reason:
|
|
101
|
+
reason: "etag unchanged", errors: [])
|
|
73
102
|
end
|
|
74
103
|
|
|
75
104
|
current_tags = []
|
|
76
|
-
|
|
105
|
+
publications = []
|
|
77
106
|
errors = []
|
|
78
107
|
|
|
79
108
|
fetch_result.releases.each do |release|
|
|
80
|
-
metadata =
|
|
109
|
+
metadata = Publication.from_release_body(release.body)
|
|
81
110
|
next if metadata.nil?
|
|
82
111
|
|
|
83
|
-
|
|
84
|
-
next unless @deps.
|
|
112
|
+
metadata_h = metadata.to_h
|
|
113
|
+
next unless @deps.metadata_filter.matches?(metadata_h)
|
|
85
114
|
next if release.prerelease && !config.include_drafts
|
|
86
115
|
|
|
87
116
|
tag = release.tag_name
|
|
@@ -91,16 +120,19 @@ module Metanorma
|
|
|
91
120
|
|
|
92
121
|
if @deps.delta_state.processed?(repo_key, tag, content_hash)
|
|
93
122
|
files = @deps.delta_state.release_files(repo_key, tag)
|
|
94
|
-
|
|
123
|
+
publications << build_publication(metadata, files, content_hash,
|
|
124
|
+
release, repo)
|
|
95
125
|
next
|
|
96
126
|
end
|
|
97
127
|
|
|
98
128
|
zip_asset = find_zip_asset(release)
|
|
99
129
|
next unless zip_asset
|
|
100
130
|
|
|
101
|
-
result = @deps.asset_processor.process(zip_asset.data,
|
|
102
|
-
@deps.delta_state.mark_processed(repo_key, tag, content_hash,
|
|
103
|
-
|
|
131
|
+
result = @deps.asset_processor.process(zip_asset.data, metadata_h)
|
|
132
|
+
@deps.delta_state.mark_processed(repo_key, tag, content_hash,
|
|
133
|
+
result.files.map(&:path))
|
|
134
|
+
publications << build_publication(metadata, result.files.map(&:path),
|
|
135
|
+
content_hash, release, repo)
|
|
104
136
|
rescue StandardError => e
|
|
105
137
|
errors << RepoError.new(tag: release.tag_name, message: e.message)
|
|
106
138
|
end
|
|
@@ -108,34 +140,16 @@ module Metanorma
|
|
|
108
140
|
@deps.delta_state.cleanup_stale(repo_key, current_tags)
|
|
109
141
|
@deps.delta_state.set_etag(repo_key, fetch_result.etag)
|
|
110
142
|
|
|
111
|
-
[
|
|
143
|
+
[publications, RepoReport.new(
|
|
112
144
|
releases: fetch_result.releases.length,
|
|
113
|
-
included:
|
|
114
|
-
skipped: fetch_result.releases.length -
|
|
145
|
+
included: publications.length,
|
|
146
|
+
skipped: fetch_result.releases.length - publications.length,
|
|
115
147
|
reason: nil, errors: errors
|
|
116
148
|
)]
|
|
117
149
|
end
|
|
118
150
|
|
|
119
|
-
def
|
|
120
|
-
|
|
121
|
-
owner: repo.owner, repo: repo.repo,
|
|
122
|
-
tag: release.tag_name,
|
|
123
|
-
release_url: release.html_url,
|
|
124
|
-
release_date: release.published_at
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
file_structs = files.map { |f| DocumentFile.new(name: File.basename(f), path: f) }
|
|
128
|
-
|
|
129
|
-
AggregatedDocument.new(
|
|
130
|
-
id: metadata.id, title: metadata.title,
|
|
131
|
-
edition: metadata.edition, stage: metadata.stage,
|
|
132
|
-
doctype: metadata.doctype,
|
|
133
|
-
channels: metadata.channels,
|
|
134
|
-
formats: metadata.formats,
|
|
135
|
-
flavor: metadata.flavor,
|
|
136
|
-
content_hash: content_hash.to_s,
|
|
137
|
-
source: source, files: file_structs
|
|
138
|
-
)
|
|
151
|
+
def build_publication(metadata, files, _content_hash, release, repo)
|
|
152
|
+
metadata.with_files_and_source(files, release, repo)
|
|
139
153
|
end
|
|
140
154
|
|
|
141
155
|
def extract_content_hash(body)
|
|
@@ -148,7 +162,7 @@ module Metanorma
|
|
|
148
162
|
def find_zip_asset(release)
|
|
149
163
|
return nil unless release.assets
|
|
150
164
|
|
|
151
|
-
release.assets.find { |a| a.name.end_with?(
|
|
165
|
+
release.assets.find { |a| a.name.end_with?(".zip") }
|
|
152
166
|
end
|
|
153
167
|
end
|
|
154
168
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
begin
|
|
4
|
-
require
|
|
4
|
+
require "zip"
|
|
5
5
|
rescue LoadError
|
|
6
|
-
raise LoadError,
|
|
6
|
+
raise LoadError,
|
|
7
|
+
"The rubyzip gem is required for AssetProcessor. Add `gem 'rubyzip'` to your Gemfile."
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
module Metanorma
|
|
@@ -23,7 +24,7 @@ module Metanorma
|
|
|
23
24
|
files = []
|
|
24
25
|
|
|
25
26
|
Dir.mktmpdir do |tmp_dir|
|
|
26
|
-
zip_path = File.join(tmp_dir,
|
|
27
|
+
zip_path = File.join(tmp_dir, "archive.zip")
|
|
27
28
|
File.binwrite(zip_path, zip_data)
|
|
28
29
|
|
|
29
30
|
Zip::File.open(zip_path) do |zip_file|
|
|
@@ -38,20 +39,21 @@ module Metanorma
|
|
|
38
39
|
FileUtils.mkdir_p(File.dirname(dest_path))
|
|
39
40
|
entry.extract(dest_path) { true }
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
ext = File.extname(file_name).delete_prefix(".")
|
|
43
|
+
files << PublicationFile.new(format: ext, name: file_name,
|
|
44
|
+
path: relative_path)
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
end
|
|
45
48
|
|
|
46
|
-
ProcessResult.new(files: files, channels: metadata[
|
|
49
|
+
ProcessResult.new(files: files, channels: metadata["channels"])
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
private
|
|
50
53
|
|
|
51
54
|
def canonicalize_name(name)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.sub(/-ed\d+(\.\d+)?\./, '.')
|
|
55
|
+
name.sub(/-ed\d+(\.\d+)?-(?=[a-z0-9])/, "-")
|
|
56
|
+
.sub(/-ed\d+(\.\d+)?\./, ".")
|
|
55
57
|
end
|
|
56
58
|
end
|
|
57
59
|
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
|
|
@@ -47,13 +47,13 @@ module Metanorma
|
|
|
47
47
|
|
|
48
48
|
def delete(key)
|
|
49
49
|
path = file_path(key)
|
|
50
|
-
|
|
50
|
+
FileUtils.rm_f(path)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def clear
|
|
54
54
|
return unless Dir.exist?(@directory)
|
|
55
55
|
|
|
56
|
-
Dir.glob(File.join(@directory,
|
|
56
|
+
Dir.glob(File.join(@directory, "*")).each do |f|
|
|
57
57
|
File.delete(f) if File.file?(f)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -61,14 +61,14 @@ module Metanorma
|
|
|
61
61
|
def keys
|
|
62
62
|
return [] unless Dir.exist?(@directory)
|
|
63
63
|
|
|
64
|
-
Dir.glob(File.join(@directory,
|
|
65
|
-
|
|
64
|
+
Dir.glob(File.join(@directory, "*")).select { |f| File.file?(f) }
|
|
65
|
+
.map { |f| File.basename(f) }
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
private
|
|
69
69
|
|
|
70
70
|
def file_path(key)
|
|
71
|
-
sanitized = key.gsub(/[^a-zA-Z0-9._-]/,
|
|
71
|
+
sanitized = key.gsub(/[^a-zA-Z0-9._-]/, "_")
|
|
72
72
|
File.join(@directory, sanitized)
|
|
73
73
|
end
|
|
74
74
|
end
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Metanorma
|
|
4
4
|
module Release
|
|
5
|
+
ChangeResult = Struct.new(:changed?, :current_hash, :previous_hash,
|
|
6
|
+
keyword_init: true)
|
|
7
|
+
|
|
5
8
|
class ContentHashChangeDetector
|
|
6
9
|
include ChangeDetector
|
|
7
10
|
|
|
@@ -9,11 +12,12 @@ module Metanorma
|
|
|
9
12
|
@previous_releases = previous_releases
|
|
10
13
|
end
|
|
11
14
|
|
|
12
|
-
def detect(
|
|
13
|
-
current =
|
|
15
|
+
def detect(publication, tag, force: false)
|
|
16
|
+
current = publication.content_hash
|
|
14
17
|
previous = @previous_releases[tag.to_s]
|
|
15
18
|
changed = force || previous.nil? || !current.eql?(previous)
|
|
16
|
-
ChangeResult.new(changed?: changed, current_hash: current,
|
|
19
|
+
ChangeResult.new(changed?: changed, current_hash: current,
|
|
20
|
+
previous_hash: previous)
|
|
17
21
|
end
|
|
18
22
|
end
|
|
19
23
|
end
|
|
@@ -3,61 +3,35 @@
|
|
|
3
3
|
module Metanorma
|
|
4
4
|
module Release
|
|
5
5
|
class Channel
|
|
6
|
-
|
|
7
|
-
parts = channel_string.to_s.strip.split('/', 2)
|
|
8
|
-
if ChannelAudience.values.include?(parts[0])
|
|
9
|
-
new(audience: parts[0], category: parts[1] || 'default')
|
|
10
|
-
else
|
|
11
|
-
new(audience: ChannelAudience::PUBLIC, category: parts[0])
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.parse_list(strings)
|
|
16
|
-
(strings || []).map { |s| parse(s) }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def self.public(category)
|
|
20
|
-
new(audience: ChannelAudience::PUBLIC, category: category)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.members(category)
|
|
24
|
-
new(audience: ChannelAudience::MEMBERS, category: category)
|
|
25
|
-
end
|
|
6
|
+
attr_reader :name
|
|
26
7
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
attr_reader :audience, :category
|
|
32
|
-
|
|
33
|
-
def initialize(audience:, category:)
|
|
34
|
-
@audience = audience
|
|
35
|
-
@category = category
|
|
8
|
+
def initialize(name)
|
|
9
|
+
@name = name.to_s.strip
|
|
36
10
|
freeze
|
|
37
11
|
end
|
|
38
12
|
|
|
39
13
|
def to_s
|
|
40
|
-
|
|
14
|
+
@name
|
|
41
15
|
end
|
|
42
16
|
|
|
43
|
-
def
|
|
44
|
-
|
|
17
|
+
def eql?(other)
|
|
18
|
+
other.is_a?(self.class) && @name == other.name
|
|
45
19
|
end
|
|
46
20
|
|
|
47
|
-
def
|
|
48
|
-
|
|
21
|
+
def hash
|
|
22
|
+
@name.hash
|
|
49
23
|
end
|
|
50
24
|
|
|
51
25
|
def matches?(filter_channels)
|
|
52
|
-
filter_channels.any? { |c| eql?(Channel.
|
|
26
|
+
filter_channels.any? { |c| eql?(Channel.new(c)) }
|
|
53
27
|
end
|
|
54
28
|
|
|
55
|
-
def
|
|
56
|
-
|
|
29
|
+
def self.parse(channel_string)
|
|
30
|
+
new(channel_string.to_s.strip)
|
|
57
31
|
end
|
|
58
32
|
|
|
59
|
-
def
|
|
60
|
-
[
|
|
33
|
+
def self.parse_list(strings)
|
|
34
|
+
(strings || []).map { |s| parse(s) }
|
|
61
35
|
end
|
|
62
36
|
end
|
|
63
37
|
end
|
|
@@ -2,25 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
module Metanorma
|
|
4
4
|
module Release
|
|
5
|
-
class
|
|
6
|
-
def initialize(channels)
|
|
7
|
-
@channels = channels.map { |c| Channel.
|
|
8
|
-
@
|
|
5
|
+
class MetadataFilter
|
|
6
|
+
def initialize(channels: [], stages: [])
|
|
7
|
+
@channels = channels.map { |c| Channel.new(c) }
|
|
8
|
+
@stages = Set.new(stages.map(&:downcase))
|
|
9
|
+
@all_channels = @channels.empty?
|
|
10
|
+
@all_stages = @stages.empty?
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
def matches?(release_metadata)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
release_channels = (release_metadata['channels'] || []).map { |c| Channel.parse(c) }
|
|
15
|
-
release_channels.any? { |rc| @channels.any? { |fc| fc.eql?(rc) } }
|
|
14
|
+
channel_match?(release_metadata) && stage_match?(release_metadata)
|
|
16
15
|
end
|
|
17
16
|
|
|
18
17
|
def overlaps?(manifest_channels)
|
|
19
|
-
return true if @
|
|
18
|
+
return true if @all_channels
|
|
20
19
|
|
|
21
|
-
parsed = manifest_channels.map { |c| Channel.
|
|
20
|
+
parsed = manifest_channels.map { |c| Channel.new(c) }
|
|
22
21
|
parsed.any? { |mc| @channels.any? { |fc| fc.eql?(mc) } }
|
|
23
22
|
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def channel_match?(release_metadata)
|
|
27
|
+
return true if @all_channels
|
|
28
|
+
|
|
29
|
+
release_channels = (release_metadata["channels"] || []).map do |c|
|
|
30
|
+
Channel.new(c)
|
|
31
|
+
end
|
|
32
|
+
release_channels.any? { |rc| @channels.any? { |fc| fc.eql?(rc) } }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def stage_match?(release_metadata)
|
|
36
|
+
return true if @all_stages
|
|
37
|
+
|
|
38
|
+
@stages.include?(release_metadata["stage"].to_s.downcase)
|
|
39
|
+
end
|
|
24
40
|
end
|
|
25
41
|
end
|
|
26
42
|
end
|