record_store 6.6.0 → 6.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae84b7bdb21213316b302d424f3eb6bb9810281b92febc84120f450b9aacfd68
4
- data.tar.gz: 468fe78980844d8141d1f348a3a0bad8f91284cd4cb22071b89b5bc07ad55241
3
+ metadata.gz: 02e832c94076da4058146c7bfad4d822c475ded9dd1bd33a1fe30fd8d3089d8a
4
+ data.tar.gz: 2488528b4db3555c5b3885ff12896e5a2079e7f3252ec6a333f16bfebc7fab04
5
5
  SHA512:
6
- metadata.gz: 230e44b71ac9d44479220c8bfada189a6543be1fca3d59deb5b1821923b0475fb222b7def68aa9df4291ca3a0b5c221ada4c990fa6e02d08beb66d870a77a749
7
- data.tar.gz: d6392925d011317884762dff640c1ce57205c8bf9ebb954797faaf3d26641db52f24d4b7041848530a6758304d92914eae5ed9c267eb324f584b7503f622d768
6
+ metadata.gz: 6d36d6ca7aefdcc839f454ccfb5c90ad92ed6998a9034065a0655aed66d6c3a04bde138d11d2852ae56799f8a1ffaa329b87024b7bcab10cd95b724278f24495
7
+ data.tar.gz: a7b3c47a1d85221509f7a3a75d863086ee53c7f400d4508e679d7c683d5f05c42f8636a9bc145797992137995a38213682866e149d8007eccbf0e28aea5fbaeb
@@ -0,0 +1,17 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: bundler
5
+ directory: "/"
6
+ schedule:
7
+ interval: weekly
8
+ open-pull-requests-limit: 100
9
+ groups:
10
+ minor_versions:
11
+ update-types:
12
+ - 'minor'
13
+ - 'patch'
14
+ - package-ecosystem: github-actions
15
+ directory: '/'
16
+ schedule:
17
+ interval: weekly
@@ -14,7 +14,7 @@ jobs:
14
14
  ruby: [ 2.7.1, 3.2.1 ]
15
15
  name: Test Ruby ${{ matrix.ruby }}
16
16
  steps:
17
- - uses: actions/checkout@v2
17
+ - uses: actions/checkout@v4
18
18
  - name: Install dependencies
19
19
  run: |
20
20
  sudo apt-get update && sudo apt-get install build-essential libcurl4-openssl-dev
@@ -0,0 +1,31 @@
1
+ # Configuration for stale action https://github.com/actions/stale
2
+ name: 'Close stale issues and PRs'
3
+ on:
4
+ schedule:
5
+ - cron: '0 14 * * *'
6
+
7
+ jobs:
8
+ stale:
9
+ runs-on: ubuntu-latest
10
+
11
+ permissions:
12
+ issues: write
13
+ pull-requests: write
14
+
15
+ steps:
16
+ - uses: actions/stale@v9
17
+ with:
18
+ ascending: true
19
+ operations-per-run: 100
20
+ stale-pr-message: 'As of today this PR is stale. If you want to keep it apply an update otherwise it will be closed in 7 days.'
21
+ close-pr-message: 'PR was closed because of missing activity.'
22
+ days-before-pr-stale: 90
23
+ days-before-pr-close: 7
24
+ stale-issue-message: >
25
+ This issue is stale because it has been open for 90 days with no activity. It will be closed if no further action occurs in 7 days.
26
+ close-issue-message: |
27
+ We are closing this issue because it has been inactive for a few months.
28
+ This probably means that it is not reproducible or it has been fixed in a newer version.
29
+ If it's an enhancement and hasn't been taken on since it was submitted, then it seems other issues have taken priority.
30
+ days-before-issue-stale: 90
31
+ days-before-issue-close: 7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 6.7.0
4
+ - Update dependencies like dnsimple, thor, ruby-limiter
5
+
3
6
  ## 6.6.0
4
7
  - Update ruby version
5
8
 
data/README.md CHANGED
@@ -20,6 +20,12 @@ record-store validate_initial_state # Validates state hasn't diverged since t
20
20
  record-store validate_records # Validates that all DNS records have valid definitions
21
21
  ```
22
22
 
23
+ ## Releasing a new version
24
+ * Bump the version [here](https://github.com/Shopify/record_store/blob/main/lib/record_store/version.rb).
25
+ * Add to CHANGELOG [here](https://github.com/Shopify/record_store/blob/main/CHANGELOG.md).
26
+ * PR, merge and shipit [here](https://shipit.shopify.io/shopify/record_store/production).
27
+
28
+
23
29
  ## Providers
24
30
 
25
31
  Below is the list of DNS providers supported by Record Store. PRs [adding more](#adding-new-providers) are welcome.
data/bin/rubocop CHANGED
@@ -9,8 +9,10 @@
9
9
  #
10
10
 
11
11
  require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
13
+ "../../Gemfile",
14
+ Pathname.new(__FILE__).realpath,
15
+ )
14
16
 
15
17
  bundle_binstub = File.expand_path("../bundle", __FILE__)
16
18
 
@@ -9,16 +9,18 @@ module RecordStore
9
9
  @id = id
10
10
  end
11
11
 
12
- def self.addition(record)
13
- new(type: :addition, record: record)
14
- end
12
+ class << self
13
+ def addition(record)
14
+ new(type: :addition, record: record)
15
+ end
15
16
 
16
- def self.removal(record)
17
- new(type: :removal, record: record)
18
- end
17
+ def removal(record)
18
+ new(type: :removal, record: record)
19
+ end
19
20
 
20
- def self.update(id, record)
21
- new(type: :update, record: record, id: id)
21
+ def update(id, record)
22
+ new(type: :update, record: record, id: id)
23
+ end
22
24
  end
23
25
 
24
26
  def removal?
@@ -36,18 +38,20 @@ module RecordStore
36
38
 
37
39
  attr_reader :current_records, :desired_records, :removals, :additions, :updates, :provider, :zone
38
40
 
39
- def self.build_from(provider:, zone:, all: false)
40
- current_zone = provider.build_zone(zone_name: zone.unrooted_name, config: zone.config)
41
+ class << self
42
+ def build_from(provider:, zone:, all: false)
43
+ current_zone = provider.build_zone(zone_name: zone.unrooted_name, config: zone.config)
41
44
 
42
- current_records = all ? current_zone.all : current_zone.records
43
- desired_records = all ? zone.all : zone.records
45
+ current_records = all ? current_zone.all : current_zone.records
46
+ desired_records = all ? zone.all : zone.records
44
47
 
45
- new(
46
- current_records: current_records,
47
- desired_records: desired_records,
48
- provider: provider,
49
- zone: zone.unrooted_name
50
- )
48
+ new(
49
+ current_records: current_records,
50
+ desired_records: desired_records,
51
+ provider: provider,
52
+ zone: zone.unrooted_name,
53
+ )
54
+ end
51
55
  end
52
56
 
53
57
  def initialize(current_records: [], desired_records: [], provider:, zone:)
@@ -10,8 +10,10 @@ module RecordStore
10
10
  RecordStore.config_path = options.fetch('config', "#{Dir.pwd}/config.yml")
11
11
  end
12
12
 
13
- def self.exit_on_failure?
14
- true
13
+ class << self
14
+ def exit_on_failure?
15
+ true
16
+ end
15
17
  end
16
18
 
17
19
  desc 'thaw', 'Thaws all zones under management to allow manual edits'
@@ -108,6 +110,7 @@ module RecordStore
108
110
  end
109
111
 
110
112
  next unless options.fetch('verbose')
113
+
111
114
  puts "Unchanged:"
112
115
  changeset.unchanged.each do |record|
113
116
  puts " - #{record}"
@@ -147,7 +150,7 @@ module RecordStore
147
150
  option :name, desc: 'Zone to download', aliases: '-n', type: :string, required: true
148
151
  option :provider, desc: 'Provider in which this zone exists', aliases: '-p', type: :string
149
152
  desc 'download', 'Downloads all records from zone and creates YAML zone definition in zones/ '\
150
- 'e.g. record-store download --name=shopify.io'
153
+ 'e.g. record-store download --name=shopify.io'
151
154
  def download
152
155
  name = options.fetch('name')
153
156
  abort('Please omit the period at the end of the zone') if name.ends_with?('.')
@@ -20,7 +20,7 @@ module RecordStore
20
20
  # returns an array of Record objects that match the records which exist in the provider
21
21
  def retrieve_current_records(zone:, stdout: $stdout)
22
22
  retry_on_connection_errors do
23
- session.zones.all_records(account_id, zone).data.map do |record|
23
+ session.zones.all_zone_records(account_id, zone).data.map do |record|
24
24
  build_from_api(record, zone)
25
25
  rescue StandardError
26
26
  stdout.puts "Cannot build record: #{record}"
@@ -40,7 +40,7 @@ module RecordStore
40
40
 
41
41
  def add(record, zone)
42
42
  record_hash = api_hash(record, zone)
43
- res = session.zones.create_record(account_id, zone, record_hash)
43
+ res = session.zones.create_zone_record(account_id, zone, record_hash)
44
44
 
45
45
  if record.type == 'ALIAS'
46
46
  txt_alias = retrieve_current_records(zone: zone).detect do |rr|
@@ -53,7 +53,7 @@ module RecordStore
53
53
  end
54
54
 
55
55
  def remove(record, zone)
56
- session.zones.delete_record(account_id, zone, record.id)
56
+ session.zones.delete_zone_record(account_id, zone, record.id)
57
57
  end
58
58
 
59
59
  def update(id, record, zone)
@@ -63,7 +63,7 @@ module RecordStore
63
63
  def session
64
64
  @dns ||= Dnsimple::Client.new(
65
65
  base_url: secrets.fetch('base_url'),
66
- access_token: secrets.fetch('api_token')
66
+ access_token: secrets.fetch('api_token'),
67
67
  )
68
68
  end
69
69
 
@@ -1,8 +1,8 @@
1
1
  require 'fog/dynect'
2
2
  require 'limiter'
3
3
 
4
- Fog::DNS::Dynect::Real.extend(Limiter::Mixin)
5
- Fog::DNS::Dynect::Real.limit_method(:request, rate: 5, interval: 1) # 5 RPS == 300 RPM
4
+ Fog::Dynect::DNS::Real.extend(Limiter::Mixin)
5
+ Fog::Dynect::DNS::Real.limit_method(:request, rate: 5, interval: 1) # 5 RPS == 300 RPM
6
6
 
7
7
  module RecordStore
8
8
  class Provider::DynECT < Provider
@@ -23,7 +23,8 @@ module RecordStore
23
23
  def record(zone:, fqdn:, type:, must_exist: false)
24
24
  result = super(zone, fqdn, type)
25
25
  raise_if_error!(result) if must_exist
26
- return nil if result.is_a?(NS1::Response::Error)
26
+ return if result.is_a?(NS1::Response::Error)
27
+
27
28
  result
28
29
  end
29
30
 
@@ -52,6 +53,7 @@ module RecordStore
52
53
  if result.is_a?(NS1::Response::UnparsableBodyError)
53
54
  raise RecordStore::Provider::UnparseableBodyError, result.to_s
54
55
  end
56
+
55
57
  raise RecordStore::Provider::Error, result.to_s
56
58
  end
57
59
  end
@@ -19,7 +19,7 @@ module NS1::Transport
19
19
 
20
20
  if response_hash.key?(X_RATELIMIT_PERIOD) && response_hash.key?(X_RATELIMIT_REMAINING)
21
21
  sleep_time = response_hash[X_RATELIMIT_PERIOD].first.to_i /
22
- [1, response_hash[X_RATELIMIT_REMAINING].first.to_i].max.to_f
22
+ [1, response_hash[X_RATELIMIT_REMAINING].first.to_i].max.to_f
23
23
 
24
24
  rate_limit = RateLimitWaiter.new('NS1')
25
25
  rate_limit.wait(sleep_time)
@@ -87,7 +87,7 @@ module RecordStore
87
87
  existing_record = client.record(
88
88
  zone: zone,
89
89
  fqdn: record_fqdn,
90
- type: record.type
90
+ type: record.type,
91
91
  )
92
92
 
93
93
  if existing_record.nil?
@@ -99,7 +99,7 @@ module RecordStore
99
99
  answers: new_answers,
100
100
  ttl: record.ttl,
101
101
  use_client_subnet: false, # only required for filter chains that are not supported by record_store
102
- }
102
+ },
103
103
  )
104
104
  return
105
105
  end
@@ -109,7 +109,7 @@ module RecordStore
109
109
  zone: zone,
110
110
  fqdn: record_fqdn,
111
111
  type: record.type,
112
- params: { answers: existing_answers + new_answers, ttl: record.ttl }
112
+ params: { answers: existing_answers + new_answers, ttl: record.ttl },
113
113
  )
114
114
  end
115
115
 
@@ -123,7 +123,7 @@ module RecordStore
123
123
  existing_record = client.record(
124
124
  zone: zone,
125
125
  fqdn: record_fqdn,
126
- type: record.type
126
+ type: record.type,
127
127
  )
128
128
  return if existing_record.nil?
129
129
 
@@ -135,7 +135,7 @@ module RecordStore
135
135
  client.delete_record(
136
136
  zone: zone,
137
137
  fqdn: record_fqdn,
138
- type: record.type
138
+ type: record.type,
139
139
  )
140
140
  return
141
141
  end
@@ -144,7 +144,7 @@ module RecordStore
144
144
  zone: zone,
145
145
  fqdn: record_fqdn,
146
146
  type: record.type,
147
- params: { answers: pruned_answers }
147
+ params: { answers: pruned_answers },
148
148
  )
149
149
  end
150
150
 
@@ -188,7 +188,7 @@ module RecordStore
188
188
  zone: zone,
189
189
  fqdn: record_fqdn,
190
190
  type: record.type,
191
- params: { answers: existing_record['answers'], ttl: record.ttl }
191
+ params: { answers: existing_record['answers'], ttl: record.ttl },
192
192
  )
193
193
  end
194
194
 
@@ -55,7 +55,7 @@ module RecordStore
55
55
 
56
56
  client.patch_zone_records(
57
57
  zone,
58
- OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_add_record)
58
+ OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_add_record),
59
59
  )
60
60
  end
61
61
 
@@ -72,6 +72,7 @@ module RecordStore
72
72
  ).data.items.select { |r| r.rdata == record.rdata_txt }
73
73
 
74
74
  return unless found_record
75
+
75
76
  begin
76
77
  record_hash = found_record.first.record_hash if found_record.length == 1
77
78
  rescue NoMethodError
@@ -90,7 +91,7 @@ module RecordStore
90
91
 
91
92
  client.patch_zone_records(
92
93
  zone,
93
- OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_remove_record)
94
+ OCI::Dns::Models::PatchZoneRecordsDetails.new(items: patch_remove_record),
94
95
  )
95
96
  end
96
97
  end
@@ -122,7 +123,7 @@ module RecordStore
122
123
  domain: record_fqdn,
123
124
  ttl: record.ttl,
124
125
  rtype: record.type,
125
- rdata: record.rdata_txt
126
+ rdata: record.rdata_txt,
126
127
  )
127
128
  update_zone_record_items.delete_if { |r| id == r.record_hash }
128
129
 
@@ -8,6 +8,7 @@ module RecordStore
8
8
 
9
9
  class << self
10
10
  def provider_for(object)
11
+ lookup_error = false
11
12
  ns_server =
12
13
  case object
13
14
  when Record::NS
@@ -17,9 +18,10 @@ module RecordStore
17
18
  master_nameserver_for(object)
18
19
  rescue Resolv::ResolvError
19
20
  $stderr.puts "Domain doesn't exist (#{object})"
20
- return
21
+ lookup_error = true
21
22
  end
22
23
  end
24
+ return if lookup_error
23
25
 
24
26
  case ns_server
25
27
  when /\.dnsimple\.com\z/
@@ -156,16 +158,19 @@ module RecordStore
156
158
  return yield
157
159
  rescue UnparseableBodyError
158
160
  raise if max_retries <= 0
161
+
159
162
  max_retries -= 1
160
163
 
161
164
  waiter.wait(message: 'Waiting to retry after receiving an unparseable response')
162
165
  rescue Net::OpenTimeout, Errno::ETIMEDOUT
163
166
  raise if max_timeouts <= 0
167
+
164
168
  max_timeouts -= 1
165
169
 
166
170
  $stderr.puts('Retrying after a connection timeout')
167
171
  rescue Errno::ECONNRESET
168
172
  raise if max_conn_resets <= 0
173
+
169
174
  max_conn_resets -= 1
170
175
 
171
176
  waiter.wait
@@ -23,7 +23,7 @@ module RecordStore
23
23
  end
24
24
 
25
25
  def validate_circular_reference
26
- errors.add(:fqdn, 'An ALIAS should not point to itself') unless fqdn != @alias
26
+ errors.add(:fqdn, 'An ALIAS should not point to itself') if fqdn == @alias
27
27
  end
28
28
  end
29
29
  end
@@ -7,7 +7,8 @@ module RecordStore
7
7
 
8
8
  validates :flags, presence: true, numericality:
9
9
  {
10
- only_integer: true, greater_than_or_equal_to: 0,
10
+ only_integer: true,
11
+ greater_than_or_equal_to: 0,
11
12
  less_than_or_equal_to: 255
12
13
  }
13
14
  validates :tag, inclusion: { in: %w(issue issuewild iodef) }, presence: true
@@ -42,6 +43,7 @@ module RecordStore
42
43
  def validate_uri_value
43
44
  uri = URI(value)
44
45
  return if uri.is_a?(URI::MailTo) || uri.is_a?(URI::HTTP)
46
+
45
47
  errors.add(:value, "URL scheme should be mailto, http, or https")
46
48
  rescue URI::Error
47
49
  errors.add(:value, "Value should be a valid URI")
@@ -23,7 +23,7 @@ module RecordStore
23
23
  end
24
24
 
25
25
  def validate_circular_reference
26
- errors.add(:fqdn, 'A CNAME should not point to itself') unless fqdn != cname
26
+ errors.add(:fqdn, 'A CNAME should not point to itself') if fqdn == cname
27
27
  end
28
28
  end
29
29
  end
@@ -61,12 +61,14 @@ module RecordStore
61
61
  @id = record.fetch(:record_id, nil)
62
62
  end
63
63
 
64
- def self.build_from_yaml_definition(yaml_definition)
65
- record_type = yaml_definition.fetch(:type)
66
- Record.const_get(record_type).new(yaml_definition)
64
+ class << self
65
+ def build_from_yaml_definition(yaml_definition)
66
+ record_type = yaml_definition.fetch(:type)
67
+ Record.const_get(record_type).new(yaml_definition)
68
+ end
67
69
  end
68
70
 
69
- def log!(logger = STDOUT)
71
+ def log!(logger = $stdout)
70
72
  logger.puts to_s
71
73
  end
72
74
 
@@ -1,3 +1,3 @@
1
1
  module RecordStore
2
- VERSION = '6.6.0'.freeze
2
+ VERSION = '6.7.0'.freeze
3
3
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module RecordStore
3
4
  class Zone
4
5
  class Config
5
6
  class TemplateContext
6
- def self.build(record:, current_records:)
7
- new(record: record, current_records: current_records)
7
+ class << self
8
+ def build(record:, current_records:)
9
+ new(record: record, current_records: current_records)
10
+ end
8
11
  end
9
12
 
10
13
  def initialize(record:, current_records:)
@@ -31,9 +34,11 @@ module RecordStore
31
34
  filters_for_records_to_template = template_file_yaml[:each_record]
32
35
  filters_for_records_to_exclude = template_file_yaml[:except_record] || []
33
36
 
34
- new(template: ERB.new(template_file),
37
+ new(
38
+ template: ERB.new(template_file),
35
39
  filters_for_records_to_template: filters_for_records_to_template,
36
- filters_for_records_to_exclude: filters_for_records_to_exclude)
40
+ filters_for_records_to_exclude: filters_for_records_to_exclude,
41
+ )
37
42
  end
38
43
 
39
44
  private
@@ -56,11 +61,11 @@ module RecordStore
56
61
  .each_with_object([]) do |template_records, records_to_inject|
57
62
  next unless should_inject?(
58
63
  template_records: template_records,
59
- current_records: current_records + records_to_inject
64
+ current_records: current_records + records_to_inject,
60
65
  )
61
66
 
62
67
  records_to_inject.push(
63
- *template_records.fetch(:injected_records, []).map { |r_yml| Record.build_from_yaml_definition(r_yml) }
68
+ *template_records.fetch(:injected_records, []).map { |r_yml| Record.build_from_yaml_definition(r_yml) },
64
69
  )
65
70
  end
66
71
  end
@@ -79,7 +84,7 @@ module RecordStore
79
84
  end
80
85
 
81
86
  def should_template?(record:)
82
- filters_for_records_to_template.any? { |filter| record_match?(record: record, filter: filter) } && \
87
+ filters_for_records_to_template.any? { |filter| record_match?(record: record, filter: filter) } &&
83
88
  filters_for_records_to_exclude.none? { |filter| record_match?(record: record, filter: filter) }
84
89
  end
85
90
 
@@ -32,6 +32,7 @@ module RecordStore
32
32
 
33
33
  def write(name, config:, records:, format: :file)
34
34
  raise ArgumentError, "format must be :directory or :file" unless [:file, :directory].include?(format)
35
+
35
36
  name = name.chomp('.')
36
37
  zone_file = "#{RecordStore.zones_path}/#{name}.yml"
37
38
  zone = { name => { config: config.to_hash } }
@@ -60,6 +61,7 @@ module RecordStore
60
61
  dir = File.dirname(filename)
61
62
  data = YAML.load_file(filename)
62
63
  raise 'more than one zone in file' if data.size > 1
64
+
63
65
  name, definition = data.first
64
66
  definition['records'] ||= []
65
67
  definition['records'] = definition['records'].map(&:deep_symbolize_keys)
@@ -33,7 +33,7 @@ module RecordStore
33
33
  zone.config = Zone::Config.new(
34
34
  providers: [provider_name],
35
35
  ignore_patterns: [{ type: "NS", fqdn: "#{name}." }],
36
- supports_alias: (zone.records.map(&:type).include?('ALIAS') || nil)
36
+ supports_alias: zone.records.map(&:type).include?('ALIAS') || nil,
37
37
  )
38
38
 
39
39
  zone.write(**write_options)
@@ -144,24 +144,22 @@ module RecordStore
144
144
  authority = fetch_soa(nameserver) do |reply, _name|
145
145
  break if reply.answer.any?
146
146
 
147
- raise "No authority found (#{name})" unless reply.authority.any?
147
+ raise "No authority found (#{name})" if reply.authority.none?
148
148
 
149
149
  break extract_authority(reply.authority)
150
150
  end
151
151
 
152
152
  # candidate DNS name is returned instead when NXDomain or other error
153
- return nil if unrooted_name.casecmp?(Array(authority).first.to_s)
153
+ return if unrooted_name.casecmp?(Array(authority).first.to_s)
154
154
 
155
155
  authority
156
156
  end
157
157
 
158
158
  private
159
159
 
160
- def fetch_soa(nameserver)
160
+ def fetch_soa(nameserver, &block)
161
161
  Resolv::DNS.open(nameserver: nameserver) do |resolv|
162
- resolv.fetch_resource(name, Resolv::DNS::Resource::IN::SOA) do |reply, name|
163
- yield reply, name
164
- end
162
+ resolv.fetch_resource(name, Resolv::DNS::Resource::IN::SOA, &block)
165
163
  end
166
164
  end
167
165
 
@@ -174,6 +172,7 @@ module RecordStore
174
172
  rescue Errno::EHOSTUNREACH => e
175
173
  $stderr.puts "Warning: #{e} [host=#{nameserver}]"
176
174
  raise if nameservers.empty?
175
+
177
176
  retry
178
177
  end
179
178
  end
@@ -244,6 +243,7 @@ module RecordStore
244
243
  cname_records.each do |cname_record|
245
244
  records.each do |record|
246
245
  next unless record.fqdn == cname_record.fqdn && record != cname_record
246
+
247
247
  case record.type
248
248
  when 'SIG', 'NXT', 'KEY'
249
249
  # this is fine
@@ -284,12 +284,13 @@ module RecordStore
284
284
 
285
285
  nameserver_fqdns.each do |ns_record|
286
286
  selected_records = records.reject do |record|
287
- record.is_a?(Record::NS) && \
287
+ record.is_a?(Record::NS) &&
288
288
  record.fqdn.delete_suffix(".") == ns_record
289
289
  end
290
290
  selected_records.each do |record|
291
291
  normalized_record = record.fqdn.delete_suffix(".")
292
292
  next unless normalized_record.end_with?(".#{ns_record}") || normalized_record == ns_record
293
+
293
294
  errors.add(:records, "Record #{record.fqdn} #{record.type} in Zone #{name} " \
294
295
  "is shadowed by #{ns_record} and will be ignored")
295
296
  end
@@ -305,14 +306,14 @@ module RecordStore
305
306
 
306
307
  terminal_records = records.map(&:fqdn)
307
308
  .select { |record| record.match?(/^([a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_])#{Regexp.escape(suffix)}$/) }
308
- next unless terminal_records.any?
309
+ next if terminal_records.none?
309
310
 
310
311
  intermediate_records = records.map(&:fqdn)
311
312
  .select { |record| record.match?(/^([a-zA-Z0-9\-_]+)#{Regexp.escape(suffix)}$/) }
312
313
  terminal_records.each do |terminal_record|
313
314
  non_terminal = terminal_record.partition('.').last
314
315
  errors.add(:records, "found empty non-terminal #{non_terminal} "\
315
- "(caused by existing records #{wildcard} and #{terminal_record})")\
316
+ "(caused by existing records #{wildcard} and #{terminal_record})")\
316
317
  unless intermediate_records.include?(non_terminal)
317
318
  end
318
319
  end
data/lib/record_store.rb CHANGED
@@ -52,8 +52,10 @@ module RecordStore
52
52
 
53
53
  def zones_path
54
54
  @zones_path ||= Pathname.new(
55
- File.expand_path(config.fetch('zones_path'),
56
- File.dirname(config_path)),
55
+ File.expand_path(
56
+ config.fetch('zones_path'),
57
+ File.dirname(config_path),
58
+ ),
57
59
  ).realpath.to_s
58
60
  end
59
61
 
@@ -63,8 +65,10 @@ module RecordStore
63
65
 
64
66
  def implicit_records_templates_path
65
67
  @implicit_records_templates_path ||= Pathname.new(
66
- File.expand_path(config.fetch('implicit_records_templates_path'),
67
- File.dirname(config_path)),
68
+ File.expand_path(
69
+ config.fetch('implicit_records_templates_path'),
70
+ File.dirname(config_path),
71
+ ),
68
72
  ).realpath.to_s
69
73
  end
70
74
 
data/record_store.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Manage DNS using git'
12
12
  spec.description = "Manage DNS through a git-based workflow. If you're looking for the original 'record_store',"\
13
- " that has been renamed to 'sequel_record_store'."
13
+ " that has been renamed to 'sequel_record_store'."
14
14
  spec.homepage = 'https://github.com/Shopify/record_store'
15
15
  spec.license = 'MIT'
16
16
 
@@ -26,28 +26,28 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '>= 2.0'
28
28
 
29
- spec.add_runtime_dependency 'thor', '~> 0.20.3'
30
- spec.add_runtime_dependency 'activesupport', '>= 4.2'
31
29
  spec.add_runtime_dependency 'activemodel', '>= 4.2'
30
+ spec.add_runtime_dependency 'activesupport', '>= 4.2'
32
31
  spec.add_runtime_dependency 'ejson'
32
+ spec.add_runtime_dependency 'thor', '>= 0.20.3', '< 1.4.0'
33
33
 
34
+ spec.add_runtime_dependency 'dnsimple', '>= 4.4', '< 8.8'
35
+ spec.add_runtime_dependency 'fog-dynect', '>= 0.4', '< 0.6'
34
36
  spec.add_runtime_dependency 'fog-json'
35
37
  spec.add_runtime_dependency 'fog-xml'
36
- spec.add_runtime_dependency 'fog-dynect', '~> 0.4.0'
37
- spec.add_runtime_dependency 'dnsimple', '~> 4.4.0'
38
38
  spec.add_runtime_dependency 'google-cloud-dns', '~> 0.31'
39
- spec.add_runtime_dependency 'ruby-limiter', '~> 1.0', '>= 1.0.1'
40
39
  spec.add_runtime_dependency 'ns1'
41
40
  spec.add_runtime_dependency 'oci', '~> 2.14.0'
41
+ spec.add_runtime_dependency 'ruby-limiter', '>= 1.0.1', '< 3'
42
42
 
43
- spec.add_development_dependency 'byebug'
44
- spec.add_development_dependency 'rake'
45
43
  spec.add_development_dependency 'bundler'
44
+ spec.add_development_dependency 'byebug'
45
+ spec.add_development_dependency 'minitest-focus'
46
46
  spec.add_development_dependency 'mocha'
47
- spec.add_development_dependency 'vcr'
48
47
  spec.add_development_dependency 'pry'
48
+ spec.add_development_dependency 'rake'
49
+ spec.add_development_dependency 'rubocop', '~> 1.59.0'
50
+ spec.add_development_dependency 'rubocop-shopify', '~> 2.14.0'
51
+ spec.add_development_dependency 'vcr'
49
52
  spec.add_development_dependency 'webmock'
50
- spec.add_development_dependency 'rubocop', '~> 1.18.0'
51
- spec.add_development_dependency 'rubocop-shopify', '~> 2.2.0'
52
- spec.add_development_dependency 'minitest-focus'
53
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: record_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.6.0
4
+ version: 6.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -9,24 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-07-07 00:00:00.000000000 Z
12
+ date: 2024-01-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: thor
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: 0.20.3
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: 0.20.3
28
- - !ruby/object:Gem::Dependency
29
- name: activesupport
15
+ name: activemodel
30
16
  requirement: !ruby/object:Gem::Requirement
31
17
  requirements:
32
18
  - - ">="
@@ -40,7 +26,7 @@ dependencies:
40
26
  - !ruby/object:Gem::Version
41
27
  version: '4.2'
42
28
  - !ruby/object:Gem::Dependency
43
- name: activemodel
29
+ name: activesupport
44
30
  requirement: !ruby/object:Gem::Requirement
45
31
  requirements:
46
32
  - - ">="
@@ -68,95 +54,107 @@ dependencies:
68
54
  - !ruby/object:Gem::Version
69
55
  version: '0'
70
56
  - !ruby/object:Gem::Dependency
71
- name: fog-json
57
+ name: thor
72
58
  requirement: !ruby/object:Gem::Requirement
73
59
  requirements:
74
60
  - - ">="
75
61
  - !ruby/object:Gem::Version
76
- version: '0'
62
+ version: 0.20.3
63
+ - - "<"
64
+ - !ruby/object:Gem::Version
65
+ version: 1.4.0
77
66
  type: :runtime
78
67
  prerelease: false
79
68
  version_requirements: !ruby/object:Gem::Requirement
80
69
  requirements:
81
70
  - - ">="
82
71
  - !ruby/object:Gem::Version
83
- version: '0'
72
+ version: 0.20.3
73
+ - - "<"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.4.0
84
76
  - !ruby/object:Gem::Dependency
85
- name: fog-xml
77
+ name: dnsimple
86
78
  requirement: !ruby/object:Gem::Requirement
87
79
  requirements:
88
80
  - - ">="
89
81
  - !ruby/object:Gem::Version
90
- version: '0'
82
+ version: '4.4'
83
+ - - "<"
84
+ - !ruby/object:Gem::Version
85
+ version: '8.8'
91
86
  type: :runtime
92
87
  prerelease: false
93
88
  version_requirements: !ruby/object:Gem::Requirement
94
89
  requirements:
95
90
  - - ">="
96
91
  - !ruby/object:Gem::Version
97
- version: '0'
92
+ version: '4.4'
93
+ - - "<"
94
+ - !ruby/object:Gem::Version
95
+ version: '8.8'
98
96
  - !ruby/object:Gem::Dependency
99
97
  name: fog-dynect
100
98
  requirement: !ruby/object:Gem::Requirement
101
99
  requirements:
102
- - - "~>"
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0.4'
103
+ - - "<"
103
104
  - !ruby/object:Gem::Version
104
- version: 0.4.0
105
+ version: '0.6'
105
106
  type: :runtime
106
107
  prerelease: false
107
108
  version_requirements: !ruby/object:Gem::Requirement
108
109
  requirements:
109
- - - "~>"
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0.4'
113
+ - - "<"
110
114
  - !ruby/object:Gem::Version
111
- version: 0.4.0
115
+ version: '0.6'
112
116
  - !ruby/object:Gem::Dependency
113
- name: dnsimple
117
+ name: fog-json
114
118
  requirement: !ruby/object:Gem::Requirement
115
119
  requirements:
116
- - - "~>"
120
+ - - ">="
117
121
  - !ruby/object:Gem::Version
118
- version: 4.4.0
122
+ version: '0'
119
123
  type: :runtime
120
124
  prerelease: false
121
125
  version_requirements: !ruby/object:Gem::Requirement
122
126
  requirements:
123
- - - "~>"
127
+ - - ">="
124
128
  - !ruby/object:Gem::Version
125
- version: 4.4.0
129
+ version: '0'
126
130
  - !ruby/object:Gem::Dependency
127
- name: google-cloud-dns
131
+ name: fog-xml
128
132
  requirement: !ruby/object:Gem::Requirement
129
133
  requirements:
130
- - - "~>"
134
+ - - ">="
131
135
  - !ruby/object:Gem::Version
132
- version: '0.31'
136
+ version: '0'
133
137
  type: :runtime
134
138
  prerelease: false
135
139
  version_requirements: !ruby/object:Gem::Requirement
136
140
  requirements:
137
- - - "~>"
141
+ - - ">="
138
142
  - !ruby/object:Gem::Version
139
- version: '0.31'
143
+ version: '0'
140
144
  - !ruby/object:Gem::Dependency
141
- name: ruby-limiter
145
+ name: google-cloud-dns
142
146
  requirement: !ruby/object:Gem::Requirement
143
147
  requirements:
144
148
  - - "~>"
145
149
  - !ruby/object:Gem::Version
146
- version: '1.0'
147
- - - ">="
148
- - !ruby/object:Gem::Version
149
- version: 1.0.1
150
+ version: '0.31'
150
151
  type: :runtime
151
152
  prerelease: false
152
153
  version_requirements: !ruby/object:Gem::Requirement
153
154
  requirements:
154
155
  - - "~>"
155
156
  - !ruby/object:Gem::Version
156
- version: '1.0'
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: 1.0.1
157
+ version: '0.31'
160
158
  - !ruby/object:Gem::Dependency
161
159
  name: ns1
162
160
  requirement: !ruby/object:Gem::Requirement
@@ -186,21 +184,27 @@ dependencies:
186
184
  - !ruby/object:Gem::Version
187
185
  version: 2.14.0
188
186
  - !ruby/object:Gem::Dependency
189
- name: byebug
187
+ name: ruby-limiter
190
188
  requirement: !ruby/object:Gem::Requirement
191
189
  requirements:
192
190
  - - ">="
193
191
  - !ruby/object:Gem::Version
194
- version: '0'
195
- type: :development
192
+ version: 1.0.1
193
+ - - "<"
194
+ - !ruby/object:Gem::Version
195
+ version: '3'
196
+ type: :runtime
196
197
  prerelease: false
197
198
  version_requirements: !ruby/object:Gem::Requirement
198
199
  requirements:
199
200
  - - ">="
200
201
  - !ruby/object:Gem::Version
201
- version: '0'
202
+ version: 1.0.1
203
+ - - "<"
204
+ - !ruby/object:Gem::Version
205
+ version: '3'
202
206
  - !ruby/object:Gem::Dependency
203
- name: rake
207
+ name: bundler
204
208
  requirement: !ruby/object:Gem::Requirement
205
209
  requirements:
206
210
  - - ">="
@@ -214,7 +218,7 @@ dependencies:
214
218
  - !ruby/object:Gem::Version
215
219
  version: '0'
216
220
  - !ruby/object:Gem::Dependency
217
- name: bundler
221
+ name: byebug
218
222
  requirement: !ruby/object:Gem::Requirement
219
223
  requirements:
220
224
  - - ">="
@@ -228,7 +232,7 @@ dependencies:
228
232
  - !ruby/object:Gem::Version
229
233
  version: '0'
230
234
  - !ruby/object:Gem::Dependency
231
- name: mocha
235
+ name: minitest-focus
232
236
  requirement: !ruby/object:Gem::Requirement
233
237
  requirements:
234
238
  - - ">="
@@ -242,7 +246,7 @@ dependencies:
242
246
  - !ruby/object:Gem::Version
243
247
  version: '0'
244
248
  - !ruby/object:Gem::Dependency
245
- name: vcr
249
+ name: mocha
246
250
  requirement: !ruby/object:Gem::Requirement
247
251
  requirements:
248
252
  - - ">="
@@ -270,7 +274,7 @@ dependencies:
270
274
  - !ruby/object:Gem::Version
271
275
  version: '0'
272
276
  - !ruby/object:Gem::Dependency
273
- name: webmock
277
+ name: rake
274
278
  requirement: !ruby/object:Gem::Requirement
275
279
  requirements:
276
280
  - - ">="
@@ -289,30 +293,44 @@ dependencies:
289
293
  requirements:
290
294
  - - "~>"
291
295
  - !ruby/object:Gem::Version
292
- version: 1.18.0
296
+ version: 1.59.0
293
297
  type: :development
294
298
  prerelease: false
295
299
  version_requirements: !ruby/object:Gem::Requirement
296
300
  requirements:
297
301
  - - "~>"
298
302
  - !ruby/object:Gem::Version
299
- version: 1.18.0
303
+ version: 1.59.0
300
304
  - !ruby/object:Gem::Dependency
301
305
  name: rubocop-shopify
302
306
  requirement: !ruby/object:Gem::Requirement
303
307
  requirements:
304
308
  - - "~>"
305
309
  - !ruby/object:Gem::Version
306
- version: 2.2.0
310
+ version: 2.14.0
307
311
  type: :development
308
312
  prerelease: false
309
313
  version_requirements: !ruby/object:Gem::Requirement
310
314
  requirements:
311
315
  - - "~>"
312
316
  - !ruby/object:Gem::Version
313
- version: 2.2.0
317
+ version: 2.14.0
314
318
  - !ruby/object:Gem::Dependency
315
- name: minitest-focus
319
+ name: vcr
320
+ requirement: !ruby/object:Gem::Requirement
321
+ requirements:
322
+ - - ">="
323
+ - !ruby/object:Gem::Version
324
+ version: '0'
325
+ type: :development
326
+ prerelease: false
327
+ version_requirements: !ruby/object:Gem::Requirement
328
+ requirements:
329
+ - - ">="
330
+ - !ruby/object:Gem::Version
331
+ version: '0'
332
+ - !ruby/object:Gem::Dependency
333
+ name: webmock
316
334
  requirement: !ruby/object:Gem::Requirement
317
335
  requirements:
318
336
  - - ">="
@@ -335,8 +353,10 @@ executables:
335
353
  extensions: []
336
354
  extra_rdoc_files: []
337
355
  files:
356
+ - ".github/dependabot.yml"
338
357
  - ".github/workflows/ci.yml"
339
358
  - ".github/workflows/cla.yml"
359
+ - ".github/workflows/stale-action-handling.yml"
340
360
  - ".gitignore"
341
361
  - ".rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml"
342
362
  - ".rubocop.yml"
@@ -419,7 +439,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
419
439
  - !ruby/object:Gem::Version
420
440
  version: '0'
421
441
  requirements: []
422
- rubygems_version: 3.4.14
442
+ rubygems_version: 3.5.4
423
443
  signing_key:
424
444
  specification_version: 4
425
445
  summary: Manage DNS using git