data_shifter 0.3.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ebcb5560026f1fcfda0f56953e6a3e139d5fd831c5bb935f352b214c526a7c9
4
- data.tar.gz: 7b8d142da33da3ead2adc2033a7ad6ab35b9d280da9b50704301d5f0ab093428
3
+ metadata.gz: 8f9ab924aaeb0638f2061907484bc7ba4f5e795a1ea58e96f1ae8b0a7542b150
4
+ data.tar.gz: 24a81ebe9a5e1f0d27d4cec1494fd26c4c8d1209ddca2aba6cd606dec14e4dda
5
5
  SHA512:
6
- metadata.gz: f104c5879fc422025eb752313da24db5a56af3ba2494adf47e7247e49cdcf3ddbd0d91129dafde8a911580e72dc4ae4229b90f7ff081fbd1c2dee20716672959
7
- data.tar.gz: df5cd362bbb77d66f6d555e5483471429ee1e2c9c089272d39a342ca0967e3de9165a482bc14d50618efc9061763fbac61faf6f14e16a44243a4cc8925aa76ea
6
+ metadata.gz: f5834ec7a2545de4342cc3f9205c8ce0f3a0b53fdfbebacd1452b7196c1b7cb606c4fa4d32e8e7d92532ff7e958f5537d2cba51e0176f9d760cdad9fa8b31498
7
+ data.tar.gz: cefd020aedd8a63f65f0bb507bcf8843a65fac12debfb78e47cd0e74b485e98746a8d3b805e0c2be6071254488308a1c10b47fb9e5280f13425d6eade6f4113d
data/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@
4
4
 
5
5
  * N/A
6
6
 
7
+ ## [0.3.3]
8
+
9
+ * [Bugfix] Dry-run net guard now allows loopback hosts (`127.0.0.1`, `::1`, `localhost`) by default. Previously, any tracing/metrics sidecar listening on loopback (Datadog agent on 8126, statsd on 8125, OTLP collectors, etc.) would trip `WebMock::NetConnectNotAllowedError` from a background tracer thread and abort the rake task — even when the shift itself made no HTTP calls. Opt out with `DataShifter.config.allow_loopback_requests = false` for strict net blocking.
10
+
11
+ ## [0.3.2.1]
12
+
13
+ * [Bugfix] Dry-run Sidekiq guard restores the previous `Sidekiq::Testing` mode (`fake!`, `inline!`, or `disable!`) instead of always calling `disable!`, which leaked global state and could leave later specs enqueueing work to real Redis.
14
+
7
15
  ## [0.3.2]
8
16
 
9
17
  * [Bugfix] Rake tasks exit quietly after a failed shift run when the shift already printed its failure summary; failures before that summary are still reported on stderr. Replaces rescuing only `Axn::Failure`, which missed most re-raised exceptions from `run!`.
data/README.md CHANGED
@@ -111,10 +111,10 @@ In **dry run** mode, DataShifter automatically blocks or fakes these side effect
111
111
 
112
112
  | Service | Behavior in dry run |
113
113
  |-------------|----------------------|
114
- | **HTTP** | Blocked via WebMock (`disable_net_connect!`). Allow specific hosts with `allow_external_requests [...]` or `DataShifter.config.allow_external_requests`. |
114
+ | **HTTP** | Blocked via WebMock (`disable_net_connect!`). Loopback (`127.0.0.1`, `::1`, `localhost`) is allowed by default so tracing/metrics sidecars (Datadog agent, statsd, OTLP collector, etc.) keep working; opt out with `DataShifter.config.allow_loopback_requests = false`. Allow other hosts with `allow_external_requests [...]` or `DataShifter.config.allow_external_requests`. |
115
115
  | **ActionMailer** | `perform_deliveries = false` (restored after run). |
116
116
  | **ActiveJob** | Queue adapter set to `:test` (restored after run). |
117
- | **Sidekiq** | `Sidekiq::Testing.fake!` (restored with `disable!` after run). Only applied if `Sidekiq::Testing` is already loaded. |
117
+ | **Sidekiq** | `Sidekiq::Testing.fake!` for the run; previous mode (`fake!`, `inline!`, or `disable!`) is restored after. Only applied if `Sidekiq::Testing` is already loaded. |
118
118
 
119
119
  **Guarding other side effects:** For anything we don't cover (e.g. another service, or allowed HTTP that mutates), use e.g. `return if dry_run?` in your shift. DB changes are always rolled back in dry run; only non-DB side effects need this.
120
120
 
@@ -222,6 +222,11 @@ DataShifter.configure do |config|
222
222
  # Hosts allowed for HTTP during dry run only (no effect in commit mode)
223
223
  config.allow_external_requests = ["api.readonly.example.com"]
224
224
 
225
+ # Allow loopback HTTP (127.0.0.1, ::1, localhost) during dry runs (default: true).
226
+ # Needed so tracing/metrics sidecars (Datadog agent on 8126, statsd on 8125, OTLP
227
+ # collector, etc.) keep working in dry-run mode.
228
+ config.allow_loopback_requests = true
229
+
225
230
  # Suppress repeated log messages during a shift run (default: true)
226
231
  config.suppress_repeated_logs = true
227
232
 
@@ -16,6 +16,11 @@ module DataShifter
16
16
  # Has no effect in commit mode — HTTP is unrestricted when dry_run is false.
17
17
  attr_accessor :allow_external_requests
18
18
 
19
+ # Whether to allow loopback HTTP (127.0.0.1, ::1, localhost) during dry runs. Default: true.
20
+ # Loopback is rarely "external" and is needed for tracing/metrics sidecars (Datadog agent on
21
+ # 8126, statsd on 8125, OTLP collector, etc.). Set to false if you want strict net blocking.
22
+ attr_accessor :allow_loopback_requests
23
+
19
24
  # Whether to suppress repeated log messages during a shift run. Default: true.
20
25
  # Can be overridden per shift with `suppress_repeated_logs true/false`.
21
26
  attr_accessor :suppress_repeated_logs
@@ -33,6 +38,7 @@ module DataShifter
33
38
 
34
39
  def initialize
35
40
  @allow_external_requests = []
41
+ @allow_loopback_requests = true
36
42
  @suppress_repeated_logs = true
37
43
  @repeated_log_cap = 1000
38
44
  @progress_enabled = true
@@ -12,8 +12,15 @@ module DataShifter
12
12
  # production runs never load WebMock. On restore we revert to the previous state (enable!
13
13
  # or disable!) so e.g. specs that had WebMock enabled are not left with it disabled.
14
14
  # - ActionMailer / ActiveJob / Sidekiq: no extra loading; we only toggle existing config
15
- # for the duration of the block and restore in ensure, so impact is scoped to the run.
15
+ # for the duration of the block and restore in ensure (Sidekiq restores prior fake/inline/disable).
16
16
  module SideEffectGuards
17
+ # Loopback hosts allowed by default during dry-run net blocking (unless opted out via
18
+ # DataShifter.config.allow_loopback_requests = false). Localhost is by definition local —
19
+ # the guard's purpose is to prevent accidental *external* state mutations, not to fight
20
+ # tracing/metrics sidecars (Datadog agent on 8126, statsd on 8125, OTLP collector, etc.)
21
+ # which commonly listen on these hosts.
22
+ DEFAULT_LOOPBACK_HOSTS = %w[127.0.0.1 ::1 localhost].freeze
23
+
17
24
  class << self
18
25
  # Applies side-effect guards, yields, then restores. Call only when running in dry run.
19
26
  def with_guards(shift_class:, &block)
@@ -62,7 +69,8 @@ module DataShifter
62
69
  def allowed_net_hosts(shift_class)
63
70
  per_shift = shift_class.respond_to?(:_allow_external_requests) ? shift_class._allow_external_requests : []
64
71
  global = DataShifter.config.allow_external_requests
65
- Array(per_shift) + Array(global)
72
+ loopback = DataShifter.config.allow_loopback_requests ? DEFAULT_LOOPBACK_HOSTS : []
73
+ Array(per_shift) + Array(global) + loopback
66
74
  end
67
75
 
68
76
  def webmock_net_connect_error
@@ -97,10 +105,23 @@ module DataShifter
97
105
  def apply_sidekiq(saved)
98
106
  return unless Sidekiq::Testing.respond_to?(:fake!)
99
107
 
108
+ saved[:sidekiq_testing_mode] = capture_sidekiq_testing_mode
100
109
  Sidekiq::Testing.fake!
101
110
  saved[:sidekiq] = true
102
111
  end
103
112
 
113
+ def capture_sidekiq_testing_mode
114
+ if Sidekiq::Testing.respond_to?(:__test_mode)
115
+ Sidekiq::Testing.__test_mode
116
+ elsif Sidekiq::Testing.fake?
117
+ :fake
118
+ elsif Sidekiq::Testing.inline?
119
+ :inline
120
+ else
121
+ :disable
122
+ end
123
+ end
124
+
104
125
  def restore_guards(saved)
105
126
  if saved.delete(:webmock)
106
127
  (saved.delete(:webmock_was_enabled) ? WebMock.enable! : WebMock.disable!)
@@ -112,7 +133,18 @@ module DataShifter
112
133
 
113
134
  return unless saved.delete(:sidekiq)
114
135
 
115
- Sidekiq::Testing.disable!
136
+ restore_sidekiq_testing_mode(saved.delete(:sidekiq_testing_mode))
137
+ end
138
+
139
+ def restore_sidekiq_testing_mode(mode)
140
+ case mode
141
+ when :fake
142
+ Sidekiq::Testing.fake!
143
+ when :inline
144
+ Sidekiq::Testing.inline!
145
+ else
146
+ Sidekiq::Testing.disable!
147
+ end
116
148
  end
117
149
  end
118
150
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DataShifter
4
- VERSION = "0.3.2"
4
+ VERSION = "0.3.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_shifter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kali Donovan