schema_reaper 1.0.0 → 1.0.2
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 +1 -1
- data/CHANGELOG.md +18 -0
- data/PRO.md +98 -0
- data/README.md +15 -0
- data/lib/schema_reaper/analyzers/base.rb +25 -7
- data/lib/schema_reaper/analyzers/dead_table.rb +3 -1
- data/lib/schema_reaper/analyzers/registry.rb +3 -1
- data/lib/schema_reaper/cli.rb +12 -4
- data/lib/schema_reaper/config.rb +35 -9
- data/lib/schema_reaper/finding.rb +3 -1
- data/lib/schema_reaper/gem_awareness.rb +2 -0
- data/lib/schema_reaper/migration_generator.rb +7 -2
- data/lib/schema_reaper/reporters/markdown.rb +3 -1
- data/lib/schema_reaper/reporters/sarif.rb +3 -1
- data/lib/schema_reaper/reporters/table.rb +3 -1
- data/lib/schema_reaper/runner.rb +2 -0
- data/lib/schema_reaper/runtime.rb +14 -4
- data/lib/schema_reaper/schema.rb +23 -7
- data/lib/schema_reaper/static/scanner.rb +1 -1
- data/lib/schema_reaper/version.rb +1 -1
- data/lib/schema_reaper.rb +3 -1
- data/schema_reaper.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f26fed85dd152f6d3f64a45e34d2741f9ec065000267b02ff0f1f0dec05de4e0
|
|
4
|
+
data.tar.gz: 6d11813b5fa9d27468479b60ffd20e86109cfc3d620c9ee0394f96525c2d0e43
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9a743c7b541a5c82a80eef34b623faa83f22636bd5195cb7278921fe6772baefc75c6ce9cb87643f6ac1ebdd47d400706b9c17dd03004be5d5fbd267355170ca
|
|
7
|
+
data.tar.gz: db87b48312c071ef3013e0a550cabe43196d68536d0dc4249f67cac5455c03360b8609c827a2785efccb55722a7c6912298bc347902e16bd10eda6b3b69107ca
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.2] - 2026-09-04
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Lowered `required_ruby_version` to `>= 2.7.0` (was `>= 3.1.0`).
|
|
7
|
+
- Rewrote all 40 endless method definitions (`def x = ...`, a Ruby 3.0
|
|
8
|
+
feature) as classic `def ... end`.
|
|
9
|
+
- Added explicit `require "set"` where `Set` / `to_set` are used (autoloaded
|
|
10
|
+
only on Ruby 3.2+).
|
|
11
|
+
- `rubocop` `TargetRubyVersion` set to 2.7; CI matrix now 2.7–3.3.
|
|
12
|
+
- Every `lib/`, `spec/` and `exe/` file verified to parse under Ruby 2.7.0;
|
|
13
|
+
dependency-free modules exercised on a real 2.7 runtime. Runtime deps
|
|
14
|
+
(`prism` >= 2.7, `thor` >= 2.6, `pg`) all support 2.7.
|
|
15
|
+
- No behaviour change; 29 specs unchanged.
|
|
16
|
+
|
|
17
|
+
## [1.0.1] - 2026-09-04
|
|
18
|
+
|
|
19
|
+
Superseded by 1.0.2 before release. Lowered the floor to `>= 3.0.0` only.
|
|
20
|
+
|
|
3
21
|
## [1.0.0] - 2026-09-04
|
|
4
22
|
|
|
5
23
|
First stable release.
|
data/PRO.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# schema_reaper Pro — open-core plan
|
|
2
|
+
|
|
3
|
+
The `schema_reaper` gem stays **MIT, free, and complete for its job**: schema
|
|
4
|
+
introspection, the seven analyzers, static + runtime signal, staged migrations,
|
|
5
|
+
`table`/`json`/`markdown`/`sarif` output, the CI baseline gate. Everything a
|
|
6
|
+
solo developer or single app needs.
|
|
7
|
+
|
|
8
|
+
**Pro** is a separate paid layer for *teams and multi-database estates* — the
|
|
9
|
+
work that only pays off at scale and that individuals rarely need.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Free vs Pro
|
|
14
|
+
|
|
15
|
+
| Capability | Free (`schema_reaper`) | Pro (`schema_reaper-pro`) |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| PostgreSQL adapter | ✅ | ✅ |
|
|
18
|
+
| MySQL / MariaDB adapter | — | ✅ |
|
|
19
|
+
| 7 core analyzers | ✅ | ✅ |
|
|
20
|
+
| Orphan-row + schema-drift analyzers | — | ✅ |
|
|
21
|
+
| Runtime attribute tracker | ✅ (file sink) | ✅ + Redis / StatsD / OTLP sinks |
|
|
22
|
+
| Reporters | table / json / markdown / sarif | + HTML, Slack, Jira, PR review comments |
|
|
23
|
+
| Reclaimable estimate | bytes/row × est. rows | real `pg_total_relation_size`, index bloat, $ per cloud plan |
|
|
24
|
+
| History / trend | local JSONL + `trend` | hosted timeline, burndown charts, per-team dashboards |
|
|
25
|
+
| Baseline gate | one file | per-branch baselines, ownership routing (CODEOWNERS) |
|
|
26
|
+
| Multi-database / shards | one DB per run | fan-out across N databases, divergence report |
|
|
27
|
+
| Scheduled scans + alerts | — | ✅ (cron runner, "queue breached", "new dead column in `billing`") |
|
|
28
|
+
| Mountable dashboard engine | — | ✅ `mount SchemaReaper::Pro::Engine` |
|
|
29
|
+
| SSO, audit log, RBAC | — | ✅ (Enterprise) |
|
|
30
|
+
| Support | GitHub issues, best effort | private issues, SLA |
|
|
31
|
+
|
|
32
|
+
Pro depends on the OSS gem and reuses its analyzer registry — no fork, no
|
|
33
|
+
divergence. New analyzers land in Free first unless they are inherently
|
|
34
|
+
team-scale.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Delivery & licensing
|
|
39
|
+
|
|
40
|
+
- **Distribution**: private gem on a Gemfury / GitHub Packages source, installed
|
|
41
|
+
with a license-key-scoped token.
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
source "https://pro.schema-reaper.dev" do
|
|
45
|
+
gem "schema_reaper-pro"
|
|
46
|
+
end
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- **License check**: offline-friendly signed key (Ed25519), 30-day grace if the
|
|
50
|
+
license server is unreachable. No phone-home of schema content — ever.
|
|
51
|
+
- **License**: commercial EULA, per-organization. Source-available to
|
|
52
|
+
subscribers (read + patch), not redistributable.
|
|
53
|
+
- **Trial**: 21-day full-feature key, no card.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Pricing (draft)
|
|
58
|
+
|
|
59
|
+
| Tier | Who | Price | Limits |
|
|
60
|
+
|---|---|---|---|
|
|
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 |
|
|
63
|
+
| **Business** | up to 50 devs | $199 / mo | unlimited databases, dashboard engine, priority support |
|
|
64
|
+
| **Enterprise** | 50+ / regulated | custom (from ~$12k / yr) | SSO, audit log, RBAC, on-prem license server, SLA |
|
|
65
|
+
|
|
66
|
+
Free forever for: OSS projects, students, and any single non-commercial
|
|
67
|
+
database. Charity/edu 50% off.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Hosted option (later — biggest ceiling)
|
|
72
|
+
|
|
73
|
+
`schema-reaper.dev` SaaS: point it at a read-replica, get weekly reports, trend
|
|
74
|
+
dashboards, PR comments, and alerts with zero gem install. Same tiers, +$X for
|
|
75
|
+
the managed runner. Ship the self-hosted Pro gem first; the SaaS is Pro + a
|
|
76
|
+
scheduler + a web app.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Rollout order
|
|
81
|
+
|
|
82
|
+
1. **Now**: Sponsor button, `PRO.md`, "Pro" section in README (waitlist link).
|
|
83
|
+
2. **v1.1 (OSS)**: MySQL adapter groundwork, real size math — proves demand,
|
|
84
|
+
some lands free.
|
|
85
|
+
3. **Pro 0.1**: private gem = MySQL + Slack reporter + scheduled scans + license
|
|
86
|
+
key. Sell to the first 10 teams at half price for feedback.
|
|
87
|
+
4. **Pro 0.2**: dashboard engine, multi-DB fan-out, per-branch baselines.
|
|
88
|
+
5. **SaaS beta**: once ~25 paying teams self-host.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Principles
|
|
93
|
+
|
|
94
|
+
- Free tier never gets *worse* to sell Pro. No crippling, no nag screens.
|
|
95
|
+
- Anything a single app genuinely needs stays free.
|
|
96
|
+
- Never transmit schema, data, or query text without explicit opt-in.
|
|
97
|
+
- Pro features are the ones a 2-person team can't be bothered to build and a
|
|
98
|
+
50-person org will happily expense.
|
data/README.md
CHANGED
|
@@ -124,6 +124,21 @@ require:
|
|
|
124
124
|
- Mountable dashboard engine, trend charts
|
|
125
125
|
- MySQL adapter
|
|
126
126
|
|
|
127
|
+
## Pro (for teams)
|
|
128
|
+
|
|
129
|
+
The gem is free and complete for a single app. **schema_reaper Pro** adds the
|
|
130
|
+
team-scale layer: MySQL adapter, multi-database fan-out, orphan-row and
|
|
131
|
+
schema-drift analyzers, Slack/Jira/PR-comment reporters, real
|
|
132
|
+
`pg_total_relation_size` + $ estimates, scheduled scans with alerts, and a
|
|
133
|
+
mountable dashboard engine. See [PRO.md](PRO.md). Waitlist / early access:
|
|
134
|
+
open an issue tagged `pro`.
|
|
135
|
+
|
|
136
|
+
## Sponsor
|
|
137
|
+
|
|
138
|
+
`schema_reaper` is MIT and maintained in the open. If it saved you disk, money,
|
|
139
|
+
or a nasty migration, sponsor its development via the **Sponsor** button on the
|
|
140
|
+
repo.
|
|
141
|
+
|
|
127
142
|
## Development
|
|
128
143
|
|
|
129
144
|
```
|
|
@@ -9,8 +9,13 @@ module SchemaReaper
|
|
|
9
9
|
# gem_columns - Hash{table_name => Set<column_name>} reserved by gems
|
|
10
10
|
# config - Config
|
|
11
11
|
Context = Struct.new(:schema, :used_tokens, :runtime, :gem_columns, :config, keyword_init: true) do
|
|
12
|
-
def runtime
|
|
13
|
-
|
|
12
|
+
def runtime
|
|
13
|
+
self[:runtime] || Runtime::Report.empty
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def gem_columns
|
|
17
|
+
self[:gem_columns] || {}
|
|
18
|
+
end
|
|
14
19
|
end
|
|
15
20
|
|
|
16
21
|
# Shared plumbing for analyzers: schema access and token lookup helpers.
|
|
@@ -24,16 +29,29 @@ module SchemaReaper
|
|
|
24
29
|
end
|
|
25
30
|
|
|
26
31
|
# @return [Array<Finding>]
|
|
27
|
-
def call
|
|
32
|
+
def call
|
|
33
|
+
raise(NotImplementedError)
|
|
34
|
+
end
|
|
28
35
|
|
|
29
36
|
private
|
|
30
37
|
|
|
31
38
|
attr_reader :ctx
|
|
32
39
|
|
|
33
|
-
def schema
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
def schema
|
|
41
|
+
ctx.schema
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def config
|
|
45
|
+
ctx.config
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def runtime
|
|
49
|
+
ctx.runtime
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def used?(token)
|
|
53
|
+
ctx.used_tokens.include?(token.to_s.downcase)
|
|
54
|
+
end
|
|
37
55
|
|
|
38
56
|
def gem_reserved?(table, column)
|
|
39
57
|
ctx.gem_columns.fetch(table, []).include?(column)
|
data/lib/schema_reaper/cli.rb
CHANGED
|
@@ -6,7 +6,9 @@ require_relative "../schema_reaper"
|
|
|
6
6
|
module SchemaReaper
|
|
7
7
|
# Command-line entry point. See `exe/schema_reaper`.
|
|
8
8
|
class CLI < Thor
|
|
9
|
-
def self.exit_on_failure?
|
|
9
|
+
def self.exit_on_failure?
|
|
10
|
+
true
|
|
11
|
+
end
|
|
10
12
|
|
|
11
13
|
class_option :config, type: :string, default: ".schema_reaper.yml",
|
|
12
14
|
desc: "path to config file"
|
|
@@ -48,13 +50,19 @@ module SchemaReaper
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
desc "version", "Print version"
|
|
51
|
-
def version
|
|
53
|
+
def version
|
|
54
|
+
say(SchemaReaper::VERSION)
|
|
55
|
+
end
|
|
52
56
|
|
|
53
57
|
private
|
|
54
58
|
|
|
55
|
-
def config
|
|
59
|
+
def config
|
|
60
|
+
@config ||= Config.load(options[:config])
|
|
61
|
+
end
|
|
56
62
|
|
|
57
|
-
def run
|
|
63
|
+
def run
|
|
64
|
+
Runner.new(config: config).run
|
|
65
|
+
end
|
|
58
66
|
|
|
59
67
|
def enforce_baseline(findings)
|
|
60
68
|
new_ones = Baseline.new(config.baseline_path).new_among(findings)
|
data/lib/schema_reaper/config.rb
CHANGED
|
@@ -44,15 +44,41 @@ module SchemaReaper
|
|
|
44
44
|
@data["database_url"] || ENV.fetch("DATABASE_URL", nil)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def scan_paths
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def
|
|
47
|
+
def scan_paths
|
|
48
|
+
@data["scan_paths"]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def view_globs
|
|
52
|
+
@data["view_globs"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def ignore_tables
|
|
56
|
+
@data.dig("ignore", "tables").to_a
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def min_age_days
|
|
60
|
+
@data["min_age_days"]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def baseline_path
|
|
64
|
+
@data["baseline"]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def runtime_log
|
|
68
|
+
@data["runtime_log"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def history_log
|
|
72
|
+
@data["history_log"]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def gem_awareness?
|
|
76
|
+
@data["gem_awareness"] != false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def require_paths
|
|
80
|
+
@data["require"].to_a
|
|
81
|
+
end
|
|
56
82
|
|
|
57
83
|
def always_keep_columns
|
|
58
84
|
@data["always_keep_columns"].to_a
|
|
@@ -19,7 +19,9 @@ module SchemaReaper
|
|
|
19
19
|
[type, table, column, index].compact.join("/")
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def reclaimable_bytes
|
|
22
|
+
def reclaimable_bytes
|
|
23
|
+
self[:reclaimable_bytes] || 0
|
|
24
|
+
end
|
|
23
25
|
|
|
24
26
|
def to_h
|
|
25
27
|
super.merge(id: id, reclaimable_bytes: reclaimable_bytes)
|
|
@@ -61,7 +61,12 @@ module SchemaReaper
|
|
|
61
61
|
path
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def camel
|
|
65
|
-
|
|
64
|
+
def camel
|
|
65
|
+
"#{@table}_#{@column}".split("_").map(&:capitalize).join
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def model
|
|
69
|
+
@table.split("_").map(&:capitalize).join.sub(/s$/, "")
|
|
70
|
+
end
|
|
66
71
|
end
|
|
67
72
|
end
|
|
@@ -39,7 +39,9 @@ module SchemaReaper
|
|
|
39
39
|
@findings.sort_by { |f| [-f.confidence, SEV_ORDER.fetch(f.severity, 9)] }
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def total_reclaimable
|
|
42
|
+
def total_reclaimable
|
|
43
|
+
@findings.sum(&:reclaimable_bytes)
|
|
44
|
+
end
|
|
43
45
|
end
|
|
44
46
|
end
|
|
45
47
|
end
|
data/lib/schema_reaper/runner.rb
CHANGED
|
@@ -11,7 +11,9 @@ module SchemaReaper
|
|
|
11
11
|
module Runtime
|
|
12
12
|
# Aggregated view of a usage log, consumed by analyzers.
|
|
13
13
|
Report = Struct.new(:accessed, :observed_days, keyword_init: true) do
|
|
14
|
-
def self.empty
|
|
14
|
+
def self.empty
|
|
15
|
+
new(accessed: Set.new, observed_days: 0)
|
|
16
|
+
end
|
|
15
17
|
|
|
16
18
|
def self.load(path)
|
|
17
19
|
return empty unless path && File.exist?(path)
|
|
@@ -36,9 +38,17 @@ module SchemaReaper
|
|
|
36
38
|
((Time.parse(last) - Time.parse(first)) / 86_400).ceil
|
|
37
39
|
end
|
|
38
40
|
|
|
39
|
-
def empty?
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
def empty?
|
|
42
|
+
accessed.empty?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def present?
|
|
46
|
+
!empty?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def read?(table, column)
|
|
50
|
+
accessed.include?("#{table}.#{column}")
|
|
51
|
+
end
|
|
42
52
|
end
|
|
43
53
|
|
|
44
54
|
# Buffered writer for the usage log. Thread-safe append of JSON lines.
|
data/lib/schema_reaper/schema.rb
CHANGED
|
@@ -9,26 +9,42 @@ module SchemaReaper
|
|
|
9
9
|
keyword_init: true
|
|
10
10
|
) do
|
|
11
11
|
# true when every row holds NULL (pg_stats null_frac == 1)
|
|
12
|
-
def always_null?
|
|
12
|
+
def always_null?
|
|
13
|
+
null_fraction && null_fraction >= 1.0
|
|
14
|
+
end
|
|
13
15
|
|
|
14
16
|
# true when the column holds exactly one distinct non-null value
|
|
15
|
-
def single_value?
|
|
17
|
+
def single_value?
|
|
18
|
+
distinct_values == 1
|
|
19
|
+
end
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
Index = Struct.new(:name, :columns, :unique, :primary, :scans, keyword_init: true) do
|
|
19
|
-
def covers?(other)
|
|
23
|
+
def covers?(other)
|
|
24
|
+
columns.first(other.columns.length) == other.columns
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
Table = Struct.new(
|
|
23
29
|
:name, :columns, :indexes, :primary_key, :foreign_keys, :row_count,
|
|
24
30
|
keyword_init: true
|
|
25
31
|
) do
|
|
26
|
-
def column_names
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
def column_names
|
|
33
|
+
columns.map(&:name)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def column(name)
|
|
37
|
+
columns.find { |c| c.name == name }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def index_on(cols)
|
|
41
|
+
indexes.find { |i| i.columns == Array(cols) }
|
|
42
|
+
end
|
|
29
43
|
end
|
|
30
44
|
|
|
31
45
|
DatabaseSchema = Struct.new(:tables, keyword_init: true) do
|
|
32
|
-
def table(name)
|
|
46
|
+
def table(name)
|
|
47
|
+
tables.find { |t| t.name == name }
|
|
48
|
+
end
|
|
33
49
|
end
|
|
34
50
|
end
|
|
@@ -10,7 +10,7 @@ module SchemaReaper
|
|
|
10
10
|
# safe, a false "dead" is not.
|
|
11
11
|
class Scanner
|
|
12
12
|
RUBY_GLOB = "**/*.rb"
|
|
13
|
-
WORD_RE = /[a-z_][a-z0-9_]*/i
|
|
13
|
+
WORD_RE = /[a-z_][a-z0-9_]*/i.freeze
|
|
14
14
|
|
|
15
15
|
# Node classes whose #name (or #unescaped) is a bare identifier we treat
|
|
16
16
|
# as a possible column/table reference.
|
data/lib/schema_reaper.rb
CHANGED
data/schema_reaper.gemspec
CHANGED
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
DESC
|
|
22
22
|
spec.homepage = "https://github.com/aksshatt/schema_reaper"
|
|
23
23
|
spec.license = "MIT"
|
|
24
|
-
spec.required_ruby_version = ">=
|
|
24
|
+
spec.required_ruby_version = ">= 2.7.0"
|
|
25
25
|
|
|
26
26
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
27
27
|
spec.metadata["homepage_uri"] = spec.homepage
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schema_reaper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aksshatt
|
|
@@ -100,6 +100,7 @@ files:
|
|
|
100
100
|
- CHANGELOG.md
|
|
101
101
|
- CODE_OF_CONDUCT.md
|
|
102
102
|
- LICENSE.txt
|
|
103
|
+
- PRO.md
|
|
103
104
|
- README.md
|
|
104
105
|
- Rakefile
|
|
105
106
|
- exe/schema_reaper
|
|
@@ -152,7 +153,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
152
153
|
requirements:
|
|
153
154
|
- - ">="
|
|
154
155
|
- !ruby/object:Gem::Version
|
|
155
|
-
version:
|
|
156
|
+
version: 2.7.0
|
|
156
157
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
158
|
requirements:
|
|
158
159
|
- - ">="
|