record_store 6.6.0 → 6.7.0

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 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