pg_sql_triggers 1.0.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +120 -0
- data/CHANGELOG.md +52 -0
- data/Goal.md +294 -0
- data/LICENSE +21 -0
- data/README.md +294 -0
- data/RELEASE.md +270 -0
- data/Rakefile +16 -0
- data/app/assets/javascripts/pg_sql_triggers/application.js +5 -0
- data/app/assets/stylesheets/pg_sql_triggers/application.css +179 -0
- data/app/controllers/pg_sql_triggers/application_controller.rb +35 -0
- data/app/controllers/pg_sql_triggers/dashboard_controller.rb +42 -0
- data/app/controllers/pg_sql_triggers/generator_controller.rb +145 -0
- data/app/controllers/pg_sql_triggers/migrations_controller.rb +84 -0
- data/app/controllers/pg_sql_triggers/tables_controller.rb +44 -0
- data/app/models/pg_sql_triggers/application_record.rb +7 -0
- data/app/models/pg_sql_triggers/trigger_registry.rb +93 -0
- data/app/views/layouts/pg_sql_triggers/application.html.erb +72 -0
- data/app/views/pg_sql_triggers/dashboard/index.html.erb +225 -0
- data/app/views/pg_sql_triggers/generator/new.html.erb +370 -0
- data/app/views/pg_sql_triggers/generator/preview.html.erb +77 -0
- data/app/views/pg_sql_triggers/tables/index.html.erb +105 -0
- data/app/views/pg_sql_triggers/tables/show.html.erb +126 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20251222000001_create_pg_sql_triggers_tables.rb +29 -0
- data/lib/generators/pg_sql_triggers/install_generator.rb +36 -0
- data/lib/generators/pg_sql_triggers/templates/README +36 -0
- data/lib/generators/pg_sql_triggers/templates/create_pg_sql_triggers_tables.rb +36 -0
- data/lib/generators/pg_sql_triggers/templates/initializer.rb +27 -0
- data/lib/generators/pg_sql_triggers/templates/trigger_migration.rb.erb +32 -0
- data/lib/generators/pg_sql_triggers/trigger_migration_generator.rb +60 -0
- data/lib/generators/trigger/migration_generator.rb +60 -0
- data/lib/pg_sql_triggers/database_introspection.rb +251 -0
- data/lib/pg_sql_triggers/drift.rb +24 -0
- data/lib/pg_sql_triggers/dsl/trigger_definition.rb +67 -0
- data/lib/pg_sql_triggers/dsl.rb +15 -0
- data/lib/pg_sql_triggers/engine.rb +29 -0
- data/lib/pg_sql_triggers/generator/form.rb +78 -0
- data/lib/pg_sql_triggers/generator/service.rb +251 -0
- data/lib/pg_sql_triggers/generator.rb +8 -0
- data/lib/pg_sql_triggers/migration.rb +15 -0
- data/lib/pg_sql_triggers/migrator.rb +237 -0
- data/lib/pg_sql_triggers/permissions/checker.rb +33 -0
- data/lib/pg_sql_triggers/permissions.rb +35 -0
- data/lib/pg_sql_triggers/registry/manager.rb +47 -0
- data/lib/pg_sql_triggers/registry/validator.rb +15 -0
- data/lib/pg_sql_triggers/registry.rb +36 -0
- data/lib/pg_sql_triggers/sql.rb +21 -0
- data/lib/pg_sql_triggers/testing/dry_run.rb +74 -0
- data/lib/pg_sql_triggers/testing/function_tester.rb +118 -0
- data/lib/pg_sql_triggers/testing/safe_executor.rb +66 -0
- data/lib/pg_sql_triggers/testing/syntax_validator.rb +124 -0
- data/lib/pg_sql_triggers/testing.rb +10 -0
- data/lib/pg_sql_triggers/version.rb +15 -0
- data/lib/pg_sql_triggers.rb +41 -0
- data/lib/tasks/trigger_migrations.rake +254 -0
- data/sig/pg_sql_triggers.rbs +4 -0
- metadata +260 -0
data/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# PgSqlTriggers
|
|
2
|
+
|
|
3
|
+
> **A PostgreSQL Trigger Control Plane for Rails**
|
|
4
|
+
|
|
5
|
+
Production-grade PostgreSQL trigger management for Rails with lifecycle management, safe deploys, versioning, drift detection, and a mountable UI.
|
|
6
|
+
|
|
7
|
+
## Why PgSqlTriggers?
|
|
8
|
+
|
|
9
|
+
Rails teams use PostgreSQL triggers for data integrity, performance, and billing logic. But triggers today are:
|
|
10
|
+
|
|
11
|
+
- Managed manually
|
|
12
|
+
- Invisible to Rails
|
|
13
|
+
- Unsafe to deploy
|
|
14
|
+
- Easy to drift
|
|
15
|
+
|
|
16
|
+
**PgSqlTriggers** brings triggers into the Rails ecosystem with:
|
|
17
|
+
|
|
18
|
+
- Lifecycle management
|
|
19
|
+
- Safe deploys
|
|
20
|
+
- Versioning
|
|
21
|
+
- UI control
|
|
22
|
+
- Emergency SQL escape hatches
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
Add this line to your application's Gemfile:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
gem 'pg_sql_triggers'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
And then execute:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
$ bundle install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Run the installer:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
$ rails generate pg_sql_triggers:install
|
|
42
|
+
$ rails db:migrate
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This will:
|
|
46
|
+
1. Create an initializer at `config/initializers/pg_sql_triggers.rb`
|
|
47
|
+
2. Create migrations for registry table
|
|
48
|
+
3. Mount the engine at `/pg_sql_triggers`
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### 1. Declaring Triggers
|
|
53
|
+
|
|
54
|
+
Create trigger definitions using the Ruby DSL:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
# app/triggers/users_email_validation.rb
|
|
58
|
+
PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
|
|
59
|
+
table :users
|
|
60
|
+
on :insert, :update
|
|
61
|
+
function :validate_user_email
|
|
62
|
+
|
|
63
|
+
version 1
|
|
64
|
+
enabled false
|
|
65
|
+
|
|
66
|
+
when_env :production
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 2. Trigger Migrations
|
|
71
|
+
|
|
72
|
+
Generate and run trigger migrations similar to Rails schema migrations:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Generate a new trigger migration
|
|
76
|
+
rails generate trigger:migration add_validation_trigger
|
|
77
|
+
|
|
78
|
+
# Run pending trigger migrations
|
|
79
|
+
rake trigger:migrate
|
|
80
|
+
|
|
81
|
+
# Rollback last trigger migration
|
|
82
|
+
rake trigger:rollback
|
|
83
|
+
|
|
84
|
+
# Rollback multiple steps
|
|
85
|
+
rake trigger:rollback STEP=3
|
|
86
|
+
|
|
87
|
+
# Check migration status
|
|
88
|
+
rake trigger:migrate:status
|
|
89
|
+
|
|
90
|
+
# Run a specific migration up
|
|
91
|
+
rake trigger:migrate:up VERSION=20231215120000
|
|
92
|
+
|
|
93
|
+
# Run a specific migration down
|
|
94
|
+
rake trigger:migrate:down VERSION=20231215120000
|
|
95
|
+
|
|
96
|
+
# Redo last migration
|
|
97
|
+
rake trigger:migrate:redo
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Web UI Migration Management:**
|
|
101
|
+
|
|
102
|
+
You can also manage migrations directly from the web dashboard:
|
|
103
|
+
|
|
104
|
+
- **Apply All Pending Migrations**: Click the "Apply All Pending Migrations" button to run all pending migrations at once
|
|
105
|
+
- **Rollback Last Migration**: Use the "Rollback Last Migration" button to undo the most recent migration
|
|
106
|
+
- **Redo Last Migration**: Click "Redo Last Migration" to rollback and re-apply the last migration
|
|
107
|
+
- **Individual Migration Actions**: Each migration in the status table has individual "Up", "Down", or "Redo" buttons for granular control
|
|
108
|
+
|
|
109
|
+
All migration actions include confirmation dialogs and provide feedback via flash messages.
|
|
110
|
+
|
|
111
|
+
Trigger migrations are stored in `db/triggers/` and follow the same naming convention as Rails migrations (`YYYYMMDDHHMMSS_name.rb`).
|
|
112
|
+
|
|
113
|
+
Example trigger migration:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
# db/triggers/20231215120000_add_validation_trigger.rb
|
|
117
|
+
class AddValidationTrigger < PgSqlTriggers::Migration
|
|
118
|
+
def up
|
|
119
|
+
execute <<-SQL
|
|
120
|
+
CREATE OR REPLACE FUNCTION validate_user_email()
|
|
121
|
+
RETURNS TRIGGER AS $$
|
|
122
|
+
BEGIN
|
|
123
|
+
IF NEW.email !~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$' THEN
|
|
124
|
+
RAISE EXCEPTION 'Invalid email format';
|
|
125
|
+
END IF;
|
|
126
|
+
RETURN NEW;
|
|
127
|
+
END;
|
|
128
|
+
$$ LANGUAGE plpgsql;
|
|
129
|
+
|
|
130
|
+
CREATE TRIGGER user_email_validation
|
|
131
|
+
BEFORE INSERT OR UPDATE ON users
|
|
132
|
+
FOR EACH ROW
|
|
133
|
+
EXECUTE FUNCTION validate_user_email();
|
|
134
|
+
SQL
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def down
|
|
138
|
+
execute <<-SQL
|
|
139
|
+
DROP TRIGGER IF EXISTS user_email_validation ON users;
|
|
140
|
+
DROP FUNCTION IF EXISTS validate_user_email();
|
|
141
|
+
SQL
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. Combined Schema and Trigger Migrations
|
|
147
|
+
|
|
148
|
+
Run both schema and trigger migrations together:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Run both schema and trigger migrations
|
|
152
|
+
rake db:migrate:with_triggers
|
|
153
|
+
|
|
154
|
+
# Rollback both (rolls back the most recent migration)
|
|
155
|
+
rake db:rollback:with_triggers
|
|
156
|
+
|
|
157
|
+
# Check status of both
|
|
158
|
+
rake db:migrate:status:with_triggers
|
|
159
|
+
|
|
160
|
+
# Get versions of both
|
|
161
|
+
rake db:version:with_triggers
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 4. Console Introspection
|
|
165
|
+
|
|
166
|
+
Access trigger information from the Rails console:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
# List all triggers
|
|
170
|
+
PgSqlTriggers::Registry.list
|
|
171
|
+
|
|
172
|
+
# List enabled triggers
|
|
173
|
+
PgSqlTriggers::Registry.enabled
|
|
174
|
+
|
|
175
|
+
# List disabled triggers
|
|
176
|
+
PgSqlTriggers::Registry.disabled
|
|
177
|
+
|
|
178
|
+
# Get triggers for a specific table
|
|
179
|
+
PgSqlTriggers::Registry.for_table(:users)
|
|
180
|
+
|
|
181
|
+
# Check for drift
|
|
182
|
+
PgSqlTriggers::Registry.diff
|
|
183
|
+
|
|
184
|
+
# Validate all triggers
|
|
185
|
+
PgSqlTriggers::Registry.validate!
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 5. Web UI
|
|
189
|
+
|
|
190
|
+
Access the web UI at `http://localhost:3000/pg_sql_triggers` to:
|
|
191
|
+
|
|
192
|
+
- View all triggers and their status
|
|
193
|
+
- Enable/disable triggers
|
|
194
|
+
- View drift states
|
|
195
|
+
- Execute SQL capsules
|
|
196
|
+
- Manage trigger lifecycle
|
|
197
|
+
- **Run trigger migrations** (up/down/redo) directly from the dashboard
|
|
198
|
+
- Apply all pending migrations with a single click
|
|
199
|
+
- Rollback the last migration
|
|
200
|
+
- Redo the last migration
|
|
201
|
+
- Individual migration controls for each migration in the status table
|
|
202
|
+
|
|
203
|
+
<img width="3360" height="2506" alt="screencapture-localhost-3000-pg-triggers-2025-12-27-17_04_29" src="https://github.com/user-attachments/assets/a7f5904b-1172-41fc-ba3f-c05587cb1fe8" />
|
|
204
|
+
|
|
205
|
+
<img width="3360" height="3420" alt="screencapture-localhost-3000-pg-triggers-generator-new-2025-12-27-17_04_49" src="https://github.com/user-attachments/assets/fc9e53f2-f540-489d-8e41-6075dab8d731" />
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
### 6. Permissions
|
|
209
|
+
|
|
210
|
+
PgSqlTriggers supports three permission levels:
|
|
211
|
+
|
|
212
|
+
- **Viewer**: Read-only access (view triggers, diffs)
|
|
213
|
+
- **Operator**: Can enable/disable triggers, apply generated triggers
|
|
214
|
+
- **Admin**: Full access including dropping triggers and executing SQL
|
|
215
|
+
|
|
216
|
+
Configure custom permission checking:
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
# config/initializers/pg_sql_triggers.rb
|
|
220
|
+
PgSqlTriggers.configure do |config|
|
|
221
|
+
config.permission_checker = ->(actor, action, environment) {
|
|
222
|
+
# Your custom permission logic
|
|
223
|
+
user = User.find(actor[:id])
|
|
224
|
+
user.has_permission?(action)
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 7. Drift Detection
|
|
230
|
+
|
|
231
|
+
PgSqlTriggers automatically detects drift between your DSL definitions and the actual database state:
|
|
232
|
+
|
|
233
|
+
- **Managed & In Sync**: Trigger matches DSL definition
|
|
234
|
+
- **Managed & Drifted**: Trigger exists but doesn't match DSL
|
|
235
|
+
- **Manual Override**: Trigger was modified outside of PgSqlTriggers
|
|
236
|
+
- **Disabled**: Trigger is disabled
|
|
237
|
+
- **Dropped**: Trigger was dropped but still in registry
|
|
238
|
+
- **Unknown**: Trigger exists in DB but not in registry
|
|
239
|
+
|
|
240
|
+
### 8. Production Kill Switch
|
|
241
|
+
|
|
242
|
+
By default, PgSqlTriggers blocks destructive operations in production:
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
# config/initializers/pg_sql_triggers.rb
|
|
246
|
+
PgSqlTriggers.configure do |config|
|
|
247
|
+
# Enable production kill switch (default: true)
|
|
248
|
+
config.kill_switch_enabled = true
|
|
249
|
+
end
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Override for specific operations:
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
PgSqlTriggers::SQL.override_kill_switch do
|
|
256
|
+
# Dangerous operation here
|
|
257
|
+
end
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Configuration
|
|
261
|
+
|
|
262
|
+
```ruby
|
|
263
|
+
# config/initializers/pg_sql_triggers.rb
|
|
264
|
+
PgSqlTriggers.configure do |config|
|
|
265
|
+
# Kill switch for production (default: true)
|
|
266
|
+
config.kill_switch_enabled = true
|
|
267
|
+
|
|
268
|
+
# Environment detection (default: -> { Rails.env })
|
|
269
|
+
config.default_environment = -> { Rails.env }
|
|
270
|
+
|
|
271
|
+
# Custom permission checker
|
|
272
|
+
config.permission_checker = ->(actor, action, environment) {
|
|
273
|
+
# Return true/false based on your authorization logic
|
|
274
|
+
true
|
|
275
|
+
}
|
|
276
|
+
end
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Core Principles
|
|
280
|
+
|
|
281
|
+
- **Rails-native**: Works seamlessly with Rails conventions
|
|
282
|
+
- **Explicit over magic**: No automatic execution
|
|
283
|
+
- **Safe by default**: Requires explicit confirmation for destructive actions
|
|
284
|
+
- **Power with guardrails**: Emergency SQL escape hatches with safety checks
|
|
285
|
+
|
|
286
|
+
## Development
|
|
287
|
+
|
|
288
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
289
|
+
|
|
290
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
291
|
+
|
|
292
|
+
## Contributing
|
|
293
|
+
|
|
294
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/samaswin87/pg_sql_triggers.
|
data/RELEASE.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Gem Release Guide
|
|
2
|
+
|
|
3
|
+
This guide walks you through the process of releasing a new version of `pg_sql_triggers` to RubyGems.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before releasing, ensure you have:
|
|
8
|
+
|
|
9
|
+
1. **RubyGems account**: You need an account at https://rubygems.org
|
|
10
|
+
2. **API key**: Generate one at https://rubygems.org/api_keys
|
|
11
|
+
3. **MFA enabled**: Your gemspec requires MFA (`rubygems_mfa_required = "true"`), so ensure MFA is enabled on your RubyGems account
|
|
12
|
+
4. **Git access**: You need push access to the repository
|
|
13
|
+
|
|
14
|
+
## Release Checklist
|
|
15
|
+
|
|
16
|
+
### 1. Update Version Number
|
|
17
|
+
|
|
18
|
+
Update the version in `lib/pg_sql_triggers/version.rb` following [Semantic Versioning](https://semver.org/):
|
|
19
|
+
|
|
20
|
+
- **MAJOR** (1.0.0 → 2.0.0): Breaking changes
|
|
21
|
+
- **MINOR** (1.0.0 → 1.1.0): New features, backward compatible
|
|
22
|
+
- **PATCH** (1.0.0 → 1.0.1): Bug fixes, backward compatible
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# lib/pg_sql_triggers/version.rb
|
|
26
|
+
module PgSqlTriggers
|
|
27
|
+
VERSION = "1.0.1" # Update this
|
|
28
|
+
end
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Update CHANGELOG.md
|
|
32
|
+
|
|
33
|
+
Add a new entry to `CHANGELOG.md` following the existing format:
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
## [1.0.1] - 2025-12-28
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- New feature description
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- Change description
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
- Bug fix description
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Important**: Update the date to today's date and ensure all changes since the last release are documented.
|
|
49
|
+
|
|
50
|
+
### 3. Run Tests
|
|
51
|
+
|
|
52
|
+
Ensure all tests pass before releasing:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Run the full test suite
|
|
56
|
+
bundle exec rspec
|
|
57
|
+
|
|
58
|
+
# Or use the rake task
|
|
59
|
+
bundle exec rake spec
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4. Check for Linting Issues
|
|
63
|
+
|
|
64
|
+
Run RuboCop to ensure code quality:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bundle exec rubocop
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Fix any issues before proceeding.
|
|
71
|
+
|
|
72
|
+
### 5. Build the Gem Locally (Optional but Recommended)
|
|
73
|
+
|
|
74
|
+
Build the gem locally to verify it works:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Build the gem
|
|
78
|
+
gem build pg_sql_triggers.gemspec
|
|
79
|
+
|
|
80
|
+
# This creates pg_sql_triggers-1.0.1.gem
|
|
81
|
+
# You can inspect it or test install it locally
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 6. Commit Your Changes
|
|
85
|
+
|
|
86
|
+
Commit the version bump and CHANGELOG updates:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Stage your changes
|
|
90
|
+
git add lib/pg_sql_triggers/version.rb CHANGELOG.md
|
|
91
|
+
|
|
92
|
+
# Commit with a descriptive message
|
|
93
|
+
git commit -m "Bump version to 1.0.1"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 7. Create a Git Tag
|
|
97
|
+
|
|
98
|
+
The release process will create a tag automatically, but you can also create it manually:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Create an annotated tag
|
|
102
|
+
git tag -a v1.0.1 -m "Release version 1.0.1"
|
|
103
|
+
|
|
104
|
+
# Or let the release task handle it (recommended)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 8. Push to Git Repository
|
|
108
|
+
|
|
109
|
+
Push your commits and tags:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Push commits
|
|
113
|
+
git push origin main # or master, depending on your default branch
|
|
114
|
+
|
|
115
|
+
# Push tags (if created manually)
|
|
116
|
+
git push origin v1.0.1
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 9. Release to RubyGems
|
|
120
|
+
|
|
121
|
+
Use the built-in Rake task to release:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# This will:
|
|
125
|
+
# 1. Build the gem
|
|
126
|
+
# 2. Create a git tag
|
|
127
|
+
# 3. Push commits and tags to git
|
|
128
|
+
# 4. Push the gem to RubyGems.org
|
|
129
|
+
bundle exec rake release
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Note**: This command will:
|
|
133
|
+
- Build the gem file
|
|
134
|
+
- Create a git tag for the version
|
|
135
|
+
- Push git commits and tags to the remote repository
|
|
136
|
+
- Push the `.gem` file to RubyGems.org
|
|
137
|
+
|
|
138
|
+
You'll be prompted for:
|
|
139
|
+
- Your RubyGems credentials (username and password)
|
|
140
|
+
- Your MFA code (if MFA is enabled, which it should be)
|
|
141
|
+
|
|
142
|
+
### 10. Verify the Release
|
|
143
|
+
|
|
144
|
+
After releasing, verify the gem is available:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Check if the gem is available
|
|
148
|
+
gem search pg_sql_triggers
|
|
149
|
+
|
|
150
|
+
# Or visit https://rubygems.org/gems/pg_sql_triggers
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 11. Create a GitHub Release (Optional but Recommended)
|
|
154
|
+
|
|
155
|
+
1. Go to https://github.com/samaswin87/pg_sql_triggers/releases
|
|
156
|
+
2. Click "Draft a new release"
|
|
157
|
+
3. Select the tag you just created (e.g., `v1.0.1`)
|
|
158
|
+
4. Use the CHANGELOG entry as the release notes
|
|
159
|
+
5. Publish the release
|
|
160
|
+
|
|
161
|
+
## Quick Release Script
|
|
162
|
+
|
|
163
|
+
For convenience, here's a quick release script you can run:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
#!/bin/bash
|
|
167
|
+
# release.sh
|
|
168
|
+
|
|
169
|
+
set -e # Exit on error
|
|
170
|
+
|
|
171
|
+
VERSION=$1
|
|
172
|
+
|
|
173
|
+
if [ -z "$VERSION" ]; then
|
|
174
|
+
echo "Usage: ./release.sh <version>"
|
|
175
|
+
echo "Example: ./release.sh 1.0.1"
|
|
176
|
+
exit 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
echo "Releasing version $VERSION..."
|
|
180
|
+
|
|
181
|
+
# Update version
|
|
182
|
+
sed -i '' "s/VERSION = \".*\"/VERSION = \"$VERSION\"/" lib/pg_sql_triggers/version.rb
|
|
183
|
+
|
|
184
|
+
# Run tests
|
|
185
|
+
echo "Running tests..."
|
|
186
|
+
bundle exec rspec
|
|
187
|
+
|
|
188
|
+
# Run linter
|
|
189
|
+
echo "Running linter..."
|
|
190
|
+
bundle exec rubocop
|
|
191
|
+
|
|
192
|
+
# Build gem
|
|
193
|
+
echo "Building gem..."
|
|
194
|
+
gem build pg_sql_triggers.gemspec
|
|
195
|
+
|
|
196
|
+
# Commit changes
|
|
197
|
+
echo "Committing changes..."
|
|
198
|
+
git add lib/pg_sql_triggers/version.rb CHANGELOG.md
|
|
199
|
+
git commit -m "Bump version to $VERSION"
|
|
200
|
+
|
|
201
|
+
# Create tag
|
|
202
|
+
echo "Creating tag..."
|
|
203
|
+
git tag -a v$VERSION -m "Release version $VERSION"
|
|
204
|
+
|
|
205
|
+
# Push
|
|
206
|
+
echo "Pushing to git..."
|
|
207
|
+
git push origin main
|
|
208
|
+
git push origin v$VERSION
|
|
209
|
+
|
|
210
|
+
# Release
|
|
211
|
+
echo "Releasing to RubyGems..."
|
|
212
|
+
bundle exec rake release
|
|
213
|
+
|
|
214
|
+
echo "Release $VERSION complete!"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Troubleshooting
|
|
218
|
+
|
|
219
|
+
### MFA Required Error
|
|
220
|
+
|
|
221
|
+
If you get an MFA error, ensure:
|
|
222
|
+
1. MFA is enabled on your RubyGems account
|
|
223
|
+
2. You're using the correct API key
|
|
224
|
+
3. You have the latest version of the `gem` command
|
|
225
|
+
|
|
226
|
+
### Authentication Issues
|
|
227
|
+
|
|
228
|
+
If authentication fails:
|
|
229
|
+
1. Check your RubyGems credentials: `gem credentials list`
|
|
230
|
+
2. Update credentials: `gem signin`
|
|
231
|
+
3. Verify your API key at https://rubygems.org/api_keys
|
|
232
|
+
|
|
233
|
+
### Tag Already Exists
|
|
234
|
+
|
|
235
|
+
If the tag already exists:
|
|
236
|
+
```bash
|
|
237
|
+
# Delete local tag
|
|
238
|
+
git tag -d v1.0.1
|
|
239
|
+
|
|
240
|
+
# Delete remote tag
|
|
241
|
+
git push origin :refs/tags/v1.0.1
|
|
242
|
+
|
|
243
|
+
# Then retry the release
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Gem Already Exists
|
|
247
|
+
|
|
248
|
+
If the version already exists on RubyGems:
|
|
249
|
+
1. You cannot overwrite a published gem version
|
|
250
|
+
2. You must bump to a new version number
|
|
251
|
+
3. Update the version in `version.rb` and try again
|
|
252
|
+
|
|
253
|
+
## Best Practices
|
|
254
|
+
|
|
255
|
+
1. **Always test before releasing**: Run the full test suite
|
|
256
|
+
2. **Update CHANGELOG**: Document all changes for users
|
|
257
|
+
3. **Follow semantic versioning**: Be consistent with version numbers
|
|
258
|
+
4. **Create GitHub releases**: Helps with documentation and announcements
|
|
259
|
+
5. **Release during business hours**: Easier to monitor and fix issues
|
|
260
|
+
6. **Test the gem after release**: Install it in a test project to verify
|
|
261
|
+
|
|
262
|
+
## Post-Release
|
|
263
|
+
|
|
264
|
+
After a successful release:
|
|
265
|
+
|
|
266
|
+
1. ✅ Verify the gem is installable: `gem install pg_sql_triggers -v 1.0.1`
|
|
267
|
+
2. ✅ Check the RubyGems page: https://rubygems.org/gems/pg_sql_triggers
|
|
268
|
+
3. ✅ Update any documentation that references version numbers
|
|
269
|
+
4. ✅ Announce the release (if applicable) via blog, Twitter, etc.
|
|
270
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Bundler gem tasks provide:
|
|
4
|
+
# - rake build: Build the gem file (creates pg_sql_triggers-X.X.X.gem)
|
|
5
|
+
# - rake install: Build and install the gem locally
|
|
6
|
+
# - rake release: Build, tag, push to git, and publish to RubyGems.org
|
|
7
|
+
require "bundler/gem_tasks"
|
|
8
|
+
|
|
9
|
+
# RSpec tasks:
|
|
10
|
+
# - rake spec: Run the test suite
|
|
11
|
+
require "rspec/core/rake_task"
|
|
12
|
+
|
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
14
|
+
|
|
15
|
+
# Default task runs the test suite
|
|
16
|
+
task default: :spec
|