schema_reaper 1.0.16 → 2.0.1
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/CHANGELOG.md +98 -0
- data/PRO.md +11 -6
- data/README.md +368 -71
- data/lib/generators/schema_reaper/install/install_generator.rb +194 -0
- data/lib/generators/schema_reaper/install/templates/initializer.rb.tt +18 -0
- data/lib/generators/schema_reaper/install/templates/schema_reaper_controller.rb.tt +69 -0
- data/lib/schema_reaper/alert_config.rb +55 -0
- data/lib/schema_reaper/analyzers/dead_column.rb +10 -4
- data/lib/schema_reaper/introspect/postgres.rb +22 -4
- data/lib/schema_reaper/mailer.rb +31 -0
- data/lib/schema_reaper/notifier.rb +106 -0
- data/lib/schema_reaper/scan_job.rb +39 -0
- data/lib/schema_reaper/tasks/schema_reaper.rake +5 -0
- data/lib/schema_reaper/version.rb +1 -1
- data/lib/schema_reaper.rb +14 -0
- data/schema_reaper.gemspec +5 -1
- metadata +83 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 89431a69d7cd997b743e0a7996ce1bae64244946dbea4d0683f8beb477ad1498
|
|
4
|
+
data.tar.gz: d43309fe35f2f6b4c669e21413c300997fdabf03f3d77f3295a6742de5f3cea2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d2c527fc15a64ce62680a96a989c1ba0fbda445fd216afe590dd95e3344b1a8c2ef271a102eed01626b1cac1b0e9400874c8cc177f71d1d27efa32fda79e6fb
|
|
7
|
+
data.tar.gz: 777a1561b89af7d5795a326d9c30d6764190b14f6a3dbb1af5f22d2fb525f3959d73e2f3beaa25262a9508f94958a1c1cad42d908f879855f1643f0206bc1208
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,103 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.1] - 2026-09-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Report emails now use the app's `ApplicationMailer`.** `SchemaReaper::Mailer`
|
|
7
|
+
was defined while the gem loaded (`Bundler.require`), before the app's
|
|
8
|
+
autoloader could see `app/mailers/application_mailer.rb`, so it always
|
|
9
|
+
inherited `ActionMailer::Base` and sent from the `schema_reaper@localhost`
|
|
10
|
+
placeholder -- which most SMTP relays reject. It is now autoloaded on first
|
|
11
|
+
use, after boot. The install generator's `from:` check now also accepts
|
|
12
|
+
`config.action_mailer.default_options` for apps without an
|
|
13
|
+
`ApplicationMailer`. 2.0.0 workaround: add
|
|
14
|
+
`SchemaReaper::Mailer.default from: "..."` to the initializer.
|
|
15
|
+
- **`rake schema_reaper:alert` no longer silently drops the scan on the
|
|
16
|
+
`:async` ActiveJob adapter** (the default before Rails 8). The job ran on a
|
|
17
|
+
thread inside the rake process, which exited first -- so the whenever and
|
|
18
|
+
plain-cron schedules never scanned. The task now runs the scan inline (with
|
|
19
|
+
email delivered immediately) when the adapter is `:async`, and enqueues as
|
|
20
|
+
before otherwise.
|
|
21
|
+
- **A missing `pg` gem now gives a clear error.** `pg` is deliberately not a
|
|
22
|
+
runtime dependency (the gem uses the host app's own), but without it the
|
|
23
|
+
scan failed with `NameError: uninitialized constant ...::PG` from the
|
|
24
|
+
connection rescue. It now says to add `gem "pg"`.
|
|
25
|
+
- **`min_age_days` in `.schema_reaper.yml` now takes effect.** It was defined
|
|
26
|
+
and documented since 1.0.0 but never read -- `dead_column` used its own
|
|
27
|
+
hardcoded 14-day threshold for trusting runtime data. The analyzer now reads
|
|
28
|
+
the config key (default still 14, so nothing changes unless you set it).
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- README rewritten around a quickstart, with animated SVG illustrations
|
|
32
|
+
(`docs/assets/`, excluded from the packaged gem) and corrected details on
|
|
33
|
+
scheduling, the manual trigger's cooldown, CI and gem awareness. Diagrams
|
|
34
|
+
for each major section; animations loop with a long hold on the finished
|
|
35
|
+
frame, since GitHub can't start a README image's animation on scroll.
|
|
36
|
+
Documents the `pg` requirement, that only the `public` schema is scanned, and
|
|
37
|
+
that lists in `.schema_reaper.yml` replace their defaults, and what
|
|
38
|
+
`min_age_days` controls.
|
|
39
|
+
- The `automation`, `safety` and `ci` section diagrams carry label text meant
|
|
40
|
+
to be read, so they no longer loop a fade in/out -- the reveal plays once
|
|
41
|
+
and holds the finished frame, instead of pulling attention away from the
|
|
42
|
+
text every 12s. The safety timeline's progress line keeps a continuous
|
|
43
|
+
moving-dash accent once grown in, since that's motion, not text.
|
|
44
|
+
|
|
45
|
+
## [2.0.0] - 2026-09-23
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
- **`rails generate schema_reaper:install`** — one-time setup for running
|
|
49
|
+
`schema_reaper` unattended in production, with zero ongoing DevOps
|
|
50
|
+
dependency: a scheduled scan, results delivered automatically, and an
|
|
51
|
+
on-demand manual trigger, none of it gated behind infrastructure a given
|
|
52
|
+
project may not have (Slack, a CI pipeline with prod network access,
|
|
53
|
+
etc.).
|
|
54
|
+
- `SchemaReaper::AlertConfig` / `config/initializers/schema_reaper.rb` —
|
|
55
|
+
where reports go (`emails`, `webhook_url`). Plain committed config, not
|
|
56
|
+
secrets; commented out by default so an unfilled-in initializer is a
|
|
57
|
+
safe no-op.
|
|
58
|
+
- `SchemaReaper::Notifier` — delivers a scan's findings through whichever
|
|
59
|
+
channels are configured. Both fire when both are set (two audiences —
|
|
60
|
+
a dev-facing chat channel and a formal inbox record — not a fallback
|
|
61
|
+
chain). Webhook: a Slack-compatible `{"text": ...}` POST, with a 10s
|
|
62
|
+
timeout so a dead host can't hang a queue worker indefinitely. Email:
|
|
63
|
+
reuses the host app's own ActionMailer setup via `SchemaReaper::Mailer`
|
|
64
|
+
(inherits `ApplicationMailer` when the host app defines one, falls back
|
|
65
|
+
to a placeholder `default from:` otherwise so delivery degrades to a
|
|
66
|
+
normal SMTP rejection instead of a hard crash). Delivery failures are
|
|
67
|
+
logged, never raised, so a flaky endpoint can't fail the scan job.
|
|
68
|
+
- `SchemaReaper::ScanJob` / `rake schema_reaper:alert` — the one job both
|
|
69
|
+
the schedule and the manual trigger enqueue.
|
|
70
|
+
- Generated `app/controllers/schema_reaper_controller.rb` + a route for
|
|
71
|
+
the manual trigger — bearer-token protected via
|
|
72
|
+
`Rails.application.credentials` (decrypted with the `RAILS_MASTER_KEY`
|
|
73
|
+
every Rails app already has, so this introduces zero new production
|
|
74
|
+
configuration), checked with `ActiveSupport::SecurityUtils
|
|
75
|
+
.secure_compare`, and a shared 5-minute cooldown via `Rails.cache` so a
|
|
76
|
+
valid or leaked token can't be POSTed repeatedly to stack up scans
|
|
77
|
+
against production.
|
|
78
|
+
- A schedule entry in whichever of `config/schedule.rb` (`whenever`) or
|
|
79
|
+
`config/schedule.yml` (`sidekiq-cron`) the app's `Gemfile.lock` says it
|
|
80
|
+
has; prints manual instructions instead of guessing when neither gem is
|
|
81
|
+
present. Warns at install time if the Gemfile scopes `schema_reaper` to
|
|
82
|
+
`group: :development` (most production deploy pipelines strip dev/test
|
|
83
|
+
groups) or if no `ApplicationMailer` `default from:` is detected (email
|
|
84
|
+
reports would otherwise silently never arrive).
|
|
85
|
+
- Re-running the generator is safe — every step checks for its own
|
|
86
|
+
marker before writing, so nothing gets duplicated.
|
|
87
|
+
|
|
88
|
+
CI/SARIF stays a separate, already-documented path for PR/staging checks
|
|
89
|
+
— this is for production, where GitHub-hosted runners don't have prod
|
|
90
|
+
network access by default.
|
|
91
|
+
|
|
92
|
+
Verified against a real booted `Rails::Application` (not just specs):
|
|
93
|
+
the manual-trigger endpoint correctly rejects requests without hitting
|
|
94
|
+
Rails' CSRF protection, a valid token enqueues and a second one within
|
|
95
|
+
the cooldown 429s without enqueuing twice, and wrong-token requests
|
|
96
|
+
during the cooldown still 401 rather than being masked by the lock.
|
|
97
|
+
Reviewed by @aksshatt; three follow-up findings (a stale doc comment, the
|
|
98
|
+
mailer `from:` gap, and the missing rate limit) addressed and verified
|
|
99
|
+
the same way. (#20, mitkush)
|
|
100
|
+
|
|
3
101
|
## [1.0.16] - 2026-09-22
|
|
4
102
|
|
|
5
103
|
### Fixed
|
data/PRO.md
CHANGED
|
@@ -24,7 +24,7 @@ work that only pays off at scale and that individuals rarely need.
|
|
|
24
24
|
| History / trend | local JSONL + `trend` | hosted timeline, burndown charts, per-team dashboards |
|
|
25
25
|
| Baseline gate | one file | per-branch baselines, ownership routing (CODEOWNERS) |
|
|
26
26
|
| Multi-database / shards | one DB per run | fan-out across N databases, divergence report |
|
|
27
|
-
| Scheduled scans + alerts |
|
|
27
|
+
| Scheduled scans + alerts | ✅ self-hosted (`rails g schema_reaper:install`: whenever/sidekiq-cron + webhook/email) | ✅ hosted, zero-install + native Slack/Jira routing + per-team alert rules |
|
|
28
28
|
| Mountable dashboard engine | — | ✅ `mount SchemaReaper::Pro::Engine` |
|
|
29
29
|
| SSO, audit log, RBAC | — | ✅ (Enterprise) |
|
|
30
30
|
| Support | GitHub issues, best effort | private issues, SLA |
|
|
@@ -59,7 +59,7 @@ team-scale.
|
|
|
59
59
|
| Tier | Who | Price | Limits |
|
|
60
60
|
|---|---|---|---|
|
|
61
61
|
| **Solo Pro** | 1 dev, unlimited personal/side projects | $9 / mo ($90 / yr) | 3 databases |
|
|
62
|
-
| **Team** | up to 10 devs | $49 / mo ($490 / yr) | 15 databases, Slack/Jira, scheduled scans |
|
|
62
|
+
| **Team** | up to 10 devs | $49 / mo ($490 / yr) | 15 databases, Slack/Jira, hosted scheduled scans |
|
|
63
63
|
| **Business** | up to 50 devs | $199 / mo | unlimited databases, dashboard engine, priority support |
|
|
64
64
|
| **Enterprise** | 50+ / regulated | custom (from ~$12k / yr) | SSO, audit log, RBAC, on-prem license server, SLA |
|
|
65
65
|
|
|
@@ -82,10 +82,15 @@ scheduler + a web app.
|
|
|
82
82
|
1. **Now**: Sponsor button, `PRO.md`, "Pro" section in README (waitlist link).
|
|
83
83
|
2. **v1.1 (OSS)**: MySQL adapter groundwork, real size math — proves demand,
|
|
84
84
|
some lands free.
|
|
85
|
-
3. **
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
3. **v2.0 (OSS, shipped)**: self-hosted scheduled scans + webhook/email alerts
|
|
86
|
+
(`rails g schema_reaper:install`) — this landed free rather than Pro; it's
|
|
87
|
+
the kind of single-app automation the "anything a single app genuinely
|
|
88
|
+
needs stays free" principle below is about.
|
|
89
|
+
4. **Pro 0.1**: private gem = MySQL + Slack/Jira reporters + hosted scan
|
|
90
|
+
runner + license key. Sell to the first 10 teams at half price for
|
|
91
|
+
feedback.
|
|
92
|
+
5. **Pro 0.2**: dashboard engine, multi-DB fan-out, per-branch baselines.
|
|
93
|
+
6. **SaaS beta**: once ~25 paying teams self-host.
|
|
89
94
|
|
|
90
95
|
---
|
|
91
96
|
|