pg_multitenant_schemas 0.1.3 → 0.2.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.actrc +17 -0
  3. data/.env.local.example +21 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +86 -0
  6. data/LOCAL_TESTING_SUMMARY.md +141 -0
  7. data/README.md +269 -16
  8. data/TESTING_LOCALLY.md +208 -0
  9. data/docs/README.md +81 -0
  10. data/docs/configuration.md +340 -0
  11. data/docs/context.md +292 -0
  12. data/docs/errors.md +498 -0
  13. data/docs/github_actions_permissions_fix.md +136 -0
  14. data/docs/github_actions_setup.md +181 -0
  15. data/docs/integration_testing.md +454 -0
  16. data/docs/local_workflow_testing.md +314 -0
  17. data/docs/migrator.md +291 -0
  18. data/docs/rails_integration.md +468 -0
  19. data/docs/schema_switcher.md +182 -0
  20. data/docs/tenant_resolver.md +394 -0
  21. data/docs/testing.md +358 -0
  22. data/examples/context_management.rb +198 -0
  23. data/examples/migration_workflow.rb +50 -0
  24. data/examples/rails_integration/controller_examples.rb +368 -0
  25. data/examples/schema_operations.rb +124 -0
  26. data/lib/pg_multitenant_schemas/configuration.rb +4 -4
  27. data/lib/pg_multitenant_schemas/migration_display_reporter.rb +30 -0
  28. data/lib/pg_multitenant_schemas/migration_executor.rb +81 -0
  29. data/lib/pg_multitenant_schemas/migration_schema_operations.rb +54 -0
  30. data/lib/pg_multitenant_schemas/migration_status_reporter.rb +65 -0
  31. data/lib/pg_multitenant_schemas/migrator.rb +89 -0
  32. data/lib/pg_multitenant_schemas/schema_switcher.rb +40 -66
  33. data/lib/pg_multitenant_schemas/tasks/advanced_tasks.rake +21 -0
  34. data/lib/pg_multitenant_schemas/tasks/basic_tasks.rake +20 -0
  35. data/lib/pg_multitenant_schemas/tasks/pg_multitenant_schemas.rake +53 -143
  36. data/lib/pg_multitenant_schemas/tasks/tenant_tasks.rake +65 -0
  37. data/lib/pg_multitenant_schemas/tenant_task_helpers.rb +102 -0
  38. data/lib/pg_multitenant_schemas/version.rb +1 -1
  39. data/lib/pg_multitenant_schemas.rb +10 -5
  40. data/pg_multitenant_schemas.gemspec +10 -9
  41. data/pre-push-check.sh +95 -0
  42. data/rails_integration/app/controllers/application_controller.rb +6 -0
  43. data/rails_integration/app/models/tenant.rb +6 -0
  44. data/test-github-setup.sh +85 -0
  45. data/validate-github-commands.sh +47 -0
  46. metadata +49 -17
@@ -0,0 +1,314 @@
1
+ # Testing GitHub Workflows Locally
2
+
3
+ This guide shows you how to test GitHub Actions workflows locally before pushing to GitHub.
4
+
5
+ ## 🚀 Method 1: Using `act` (Recommended)
6
+
7
+ `act` is the most popular tool for running GitHub Actions locally using Docker.
8
+
9
+ ### Installation
10
+
11
+ ```bash
12
+ # macOS (using Homebrew)
13
+ brew install act
14
+
15
+ # Linux (using curl)
16
+ curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
17
+
18
+ # Windows (using Chocolatey)
19
+ choco install act-cli
20
+ ```
21
+
22
+ ### Basic Usage
23
+
24
+ ```bash
25
+ # List all workflows
26
+ act -l
27
+
28
+ # Run all workflows
29
+ act
30
+
31
+ # Run specific workflow
32
+ act push
33
+
34
+ # Run specific job
35
+ act -j test
36
+
37
+ # Run with specific event
38
+ act pull_request
39
+
40
+ # Dry run (show what would be executed)
41
+ act -n
42
+ ```
43
+
44
+ ### Testing Our Workflows
45
+
46
+ ```bash
47
+ # Test the main CI workflow
48
+ act push
49
+
50
+ # Test the release workflow (simulates a push to main)
51
+ act push --env GITHUB_REF=refs/heads/main
52
+
53
+ # Test pull request workflow
54
+ act pull_request
55
+ ```
56
+
57
+ ### Configuration
58
+
59
+ Create `.actrc` file in project root for default settings:
60
+
61
+ ```bash
62
+ # .actrc
63
+ --container-architecture linux/amd64
64
+ --artifact-server-path /tmp/act-artifacts
65
+ --env-file .env.local
66
+ ```
67
+
68
+ ### Environment Variables
69
+
70
+ Create `.env.local` for local testing:
71
+
72
+ ```bash
73
+ # .env.local
74
+ GITHUB_TOKEN=your_github_token_here
75
+ RUBYGEMS_API_KEY=your_rubygems_key_here
76
+ GITHUB_REPOSITORY=rubenpazch/pg_multitenant_schemas
77
+ GITHUB_ACTOR=your_username
78
+ ```
79
+
80
+ ## 🔧 Method 2: Manual Testing Components
81
+
82
+ ### Test RuboCop Locally
83
+
84
+ ```bash
85
+ # Run RuboCop (same as in CI)
86
+ bundle exec rubocop
87
+
88
+ # Auto-fix issues
89
+ bundle exec rubocop -A
90
+
91
+ # Check specific files
92
+ bundle exec rubocop lib/ spec/
93
+ ```
94
+
95
+ ### Test RSpec Locally
96
+
97
+ ```bash
98
+ # Run all tests
99
+ bundle exec rspec
100
+
101
+ # Run with coverage (if configured)
102
+ COVERAGE=true bundle exec rspec
103
+
104
+ # Run integration tests
105
+ bundle exec rspec --tag integration
106
+
107
+ # Run tests with different Ruby versions (using rbenv/rvm)
108
+ rbenv shell 3.2.0 && bundle exec rspec
109
+ rbenv shell 3.3.0 && bundle exec rspec
110
+ ```
111
+
112
+ ### Test Gem Building
113
+
114
+ ```bash
115
+ # Build gem locally
116
+ gem build pg_multitenant_schemas.gemspec
117
+
118
+ # Install locally built gem
119
+ gem install pg_multitenant_schemas-*.gem
120
+
121
+ # Test gem installation
122
+ gem list | grep pg_multitenant_schemas
123
+ ```
124
+
125
+ ### Test PostgreSQL Setup
126
+
127
+ ```bash
128
+ # Start PostgreSQL (macOS with Homebrew)
129
+ brew services start postgresql@15
130
+
131
+ # Create test database
132
+ createdb pg_multitenant_test
133
+
134
+ # Run integration tests
135
+ PGDATABASE=pg_multitenant_test bundle exec rspec --tag integration
136
+ ```
137
+
138
+ ## 🐳 Method 3: Docker-based Testing
139
+
140
+ Create a local testing environment that mirrors CI:
141
+
142
+ ```bash
143
+ # Create Dockerfile.test
144
+ cat > Dockerfile.test << 'EOF'
145
+ FROM ruby:3.3
146
+
147
+ # Install PostgreSQL client
148
+ RUN apt-get update && apt-get install -y postgresql-client
149
+
150
+ # Set working directory
151
+ WORKDIR /app
152
+
153
+ # Copy Gemfile
154
+ COPY Gemfile* ./
155
+ RUN bundle install
156
+
157
+ # Copy source code
158
+ COPY . .
159
+
160
+ # Run tests
161
+ CMD ["bundle", "exec", "rspec"]
162
+ EOF
163
+
164
+ # Build and run
165
+ docker build -f Dockerfile.test -t pg_multitenant_test .
166
+ docker run --rm pg_multitenant_test
167
+ ```
168
+
169
+ ## 🔍 Method 4: GitHub CLI for Remote Testing
170
+
171
+ Use GitHub CLI to trigger workflows manually:
172
+
173
+ ```bash
174
+ # Install GitHub CLI
175
+ brew install gh
176
+
177
+ # Authenticate
178
+ gh auth login
179
+
180
+ # Trigger workflow manually
181
+ gh workflow run main.yml
182
+
183
+ # Check workflow status
184
+ gh run list
185
+
186
+ # View workflow logs
187
+ gh run view --log
188
+ ```
189
+
190
+ ## 📋 Pre-Push Checklist
191
+
192
+ Before pushing to GitHub, run these commands locally:
193
+
194
+ ```bash
195
+ #!/bin/bash
196
+ # pre-push-check.sh
197
+
198
+ echo "🔍 Running pre-push checks..."
199
+
200
+ # 1. RuboCop
201
+ echo "Running RuboCop..."
202
+ bundle exec rubocop || exit 1
203
+
204
+ # 2. RSpec
205
+ echo "Running RSpec..."
206
+ bundle exec rspec || exit 1
207
+
208
+ # 3. Security audit
209
+ echo "Running security audit..."
210
+ bundle audit || exit 1
211
+
212
+ # 4. Gem build test
213
+ echo "Testing gem build..."
214
+ gem build pg_multitenant_schemas.gemspec || exit 1
215
+
216
+ # 5. Integration tests (if PostgreSQL available)
217
+ if command -v psql &> /dev/null; then
218
+ echo "Running integration tests..."
219
+ bundle exec rspec --tag integration || exit 1
220
+ fi
221
+
222
+ echo "✅ All checks passed! Ready to push."
223
+ ```
224
+
225
+ Make it executable:
226
+
227
+ ```bash
228
+ chmod +x pre-push-check.sh
229
+ ./pre-push-check.sh
230
+ ```
231
+
232
+ ## 🎯 Specific Workflow Testing
233
+
234
+ ### Testing CI Workflow (main.yml)
235
+
236
+ ```bash
237
+ # Using act
238
+ act push -W .github/workflows/main.yml
239
+
240
+ ```bash
241
+ # Manual simulation
242
+ bundle install
243
+ bundle exec rubocop
244
+ bundle exec rspec --exclude-pattern '**/integration/**/*_spec.rb'
245
+ bundle audit
246
+ ```
247
+ ```
248
+
249
+ ### Testing Release Workflow (release.yml)
250
+
251
+ ```bash
252
+ # Simulate version bump
253
+ # 1. Update version in lib/pg_multitenant_schemas/version.rb
254
+ # 2. Test locally
255
+ act push -W .github/workflows/release.yml --env GITHUB_REF=refs/heads/main
256
+
257
+ # Manual simulation (without actual publishing)
258
+ gem build pg_multitenant_schemas.gemspec
259
+ # Note: Don't run 'gem push' in testing
260
+ ```
261
+
262
+ ## 🛠️ Troubleshooting
263
+
264
+ ### Common Issues with `act`
265
+
266
+ 1. **Docker not running**: Start Docker Desktop
267
+ 2. **Permission issues**: Run with `sudo` or fix Docker permissions
268
+ 3. **Platform issues**: Use `--container-architecture linux/amd64`
269
+ 4. **Secret errors**: Provide secrets via `.env.local` file
270
+
271
+ ### PostgreSQL Issues
272
+
273
+ ```bash
274
+ # Check if PostgreSQL is running
275
+ pg_isready
276
+
277
+ # Start PostgreSQL service
278
+ brew services start postgresql@15
279
+
280
+ # Create test database
281
+ createdb pg_multitenant_test
282
+ ```
283
+
284
+ ### Ruby Version Issues
285
+
286
+ ```bash
287
+ # Install required Ruby versions
288
+ rbenv install 3.2.0
289
+ rbenv install 3.3.0
290
+ rbenv install 3.4.0
291
+
292
+ # Test with specific version
293
+ rbenv shell 3.3.0
294
+ bundle install
295
+ bundle exec rspec
296
+ ```
297
+
298
+ ## 📚 Additional Resources
299
+
300
+ - [act Documentation](https://github.com/nektos/act)
301
+ - [GitHub Actions Documentation](https://docs.github.com/en/actions)
302
+ - [Local Development Best Practices](https://docs.github.com/en/actions/using-workflows/about-workflows#best-practices)
303
+
304
+ ## 🔗 Integration with Git Hooks
305
+
306
+ Add to `.git/hooks/pre-push`:
307
+
308
+ ```bash
309
+ #!/bin/bash
310
+ ./pre-push-check.sh
311
+ exit $?
312
+ ```
313
+
314
+ This ensures checks run automatically before every push.
data/docs/migrator.md ADDED
@@ -0,0 +1,291 @@
1
+ # Migrator - Automated Migration Management
2
+
3
+ **File**: `lib/pg_multitenant_schemas/migrator.rb`
4
+
5
+ ## 📋 Overview
6
+
7
+ The `Migrator` class provides comprehensive automated migration management for multi-tenant applications. It handles running migrations across all tenant schemas, setting up new tenants, and tracking migration status.
8
+
9
+ ## 🎯 Purpose
10
+
11
+ - **Bulk Migration**: Run migrations across all tenant schemas with single command
12
+ - **Tenant Setup**: Automated tenant creation with schema and migrations
13
+ - **Status Tracking**: Monitor migration status across all tenants
14
+ - **Error Resilience**: Handle migration failures gracefully per tenant
15
+ - **Progress Reporting**: Detailed feedback during migration operations
16
+
17
+ ## 🔧 Key Methods
18
+
19
+ ### Core Migration Operations
20
+
21
+ ```ruby
22
+ # Migrate all tenant schemas
23
+ Migrator.migrate_all
24
+
25
+ # Migrate specific tenant
26
+ Migrator.migrate_tenant('acme_corp')
27
+
28
+ # Check migration status across all tenants
29
+ Migrator.migration_status
30
+
31
+ # Setup new tenant (create schema + run migrations)
32
+ Migrator.setup_tenant('new_tenant')
33
+ ```
34
+
35
+ ### Tenant Management
36
+
37
+ ```ruby
38
+ # Setup all existing tenants
39
+ Migrator.setup_all_tenants
40
+
41
+ # Create tenant with attributes and schema
42
+ Migrator.create_tenant_with_schema({
43
+ subdomain: 'acme',
44
+ name: 'ACME Corporation'
45
+ })
46
+
47
+ # Rollback specific tenant
48
+ Migrator.rollback_tenant('tenant_name', steps: 2)
49
+ ```
50
+
51
+ ## 🏗️ Implementation Details
52
+
53
+ ### Migration Execution Flow
54
+
55
+ ```ruby
56
+ def migrate_all
57
+ puts "🚀 Starting migration for all tenant schemas..."
58
+
59
+ tenant_schemas.each do |schema|
60
+ puts "📦 Migrating schema: #{schema}"
61
+
62
+ migrate_tenant(schema)
63
+ end
64
+
65
+ puts "✅ Migration completed for all schemas"
66
+ end
67
+ ```
68
+
69
+ ### Error Handling Strategy
70
+
71
+ The Migrator implements robust error handling:
72
+
73
+ - **Per-Tenant Isolation**: Failures in one tenant don't affect others
74
+ - **Detailed Error Reporting**: Specific error messages per tenant
75
+ - **Continue on Error**: Migration continues for remaining tenants
76
+ - **Transaction Safety**: Each tenant migration is self-contained
77
+
78
+ ### Progress Tracking
79
+
80
+ ```ruby
81
+ def migration_status
82
+ puts "📊 Migration Status Report"
83
+
84
+ tenant_schemas.each do |schema|
85
+ pending = pending_migrations_for_schema(schema)
86
+
87
+ if pending.empty?
88
+ puts "▸ #{schema}: ✅ Up to date"
89
+ else
90
+ puts "▸ #{schema}: ⚠️ #{pending.count} pending migrations"
91
+ end
92
+ end
93
+ end
94
+ ```
95
+
96
+ ## 🔄 Usage Patterns
97
+
98
+ ### Daily Operations
99
+
100
+ ```ruby
101
+ # Check what needs migration
102
+ PgMultitenantSchemas::Migrator.migration_status
103
+
104
+ # Run migrations across all tenants
105
+ PgMultitenantSchemas::Migrator.migrate_all
106
+
107
+ # Setup new tenant
108
+ PgMultitenantSchemas::Migrator.setup_tenant('new_client')
109
+ ```
110
+
111
+ ### Deployment Workflow
112
+
113
+ ```ruby
114
+ # In deployment script
115
+ namespace :deploy do
116
+ task :migrate_tenants do
117
+ PgMultitenantSchemas::Migrator.migrate_all
118
+ end
119
+ end
120
+ ```
121
+
122
+ ### New Tenant Onboarding
123
+
124
+ ```ruby
125
+ # Complete tenant setup
126
+ tenant_attributes = {
127
+ subdomain: 'newco',
128
+ name: 'New Company Ltd',
129
+ domain: 'newco.com'
130
+ }
131
+
132
+ tenant = PgMultitenantSchemas::Migrator.create_tenant_with_schema(tenant_attributes)
133
+ puts "✅ Tenant #{tenant.subdomain} ready for use"
134
+ ```
135
+
136
+ ### Rollback Operations
137
+
138
+ ```ruby
139
+ # Rollback specific tenant
140
+ PgMultitenantSchemas::Migrator.rollback_tenant('acme_corp', steps: 1)
141
+
142
+ # Check status after rollback
143
+ PgMultitenantSchemas::Migrator.migration_status
144
+ ```
145
+
146
+ ## 🎛️ Configuration Integration
147
+
148
+ The Migrator respects global configuration:
149
+
150
+ ```ruby
151
+ PgMultitenantSchemas.configure do |config|
152
+ config.default_schema = 'public'
153
+ config.tenant_model = 'Tenant'
154
+ config.connection_class = 'ApplicationRecord'
155
+ end
156
+ ```
157
+
158
+ ## 📊 Status Reporting
159
+
160
+ ### Migration Status Output
161
+
162
+ ```
163
+ 📊 Migration Status Report
164
+ ▸ acme_corp: ✅ Up to date (5 migrations)
165
+ ▸ beta_corp: ⚠️ 2 pending migrations
166
+ - 20241201120000_add_feature_flags
167
+ - 20241202100000_update_user_fields
168
+ ▸ demo_corp: ✅ Up to date (5 migrations)
169
+
170
+ 📈 Overall: 2/3 tenants current, 2 migrations pending
171
+ ```
172
+
173
+ ### Migration Progress Output
174
+
175
+ ```
176
+ 🚀 Starting migration for all tenant schemas...
177
+
178
+ 📦 Migrating schema: acme_corp
179
+ ✓ Running migration 20241201120000_add_feature_flags
180
+ ✓ Running migration 20241202100000_update_user_fields
181
+ ✅ Completed migration for acme_corp
182
+
183
+ 📦 Migrating schema: beta_corp
184
+ ✓ Running migration 20241201120000_add_feature_flags
185
+ ✗ Error in migration 20241202100000_update_user_fields: column already exists
186
+ ⚠️ Continuing with next tenant...
187
+
188
+ ✅ Migration completed for all schemas
189
+ 📊 Summary: 1/2 tenants migrated successfully
190
+ ```
191
+
192
+ ## 🔍 Advanced Features
193
+
194
+ ### Custom Migration Paths
195
+
196
+ ```ruby
197
+ # Override migration paths if needed
198
+ class CustomMigrator < PgMultitenantSchemas::Migrator
199
+ private
200
+
201
+ def migration_paths
202
+ [
203
+ Rails.root.join('db', 'migrate'),
204
+ Rails.root.join('db', 'tenant_migrations')
205
+ ]
206
+ end
207
+ end
208
+ ```
209
+
210
+ ### Migration Callbacks
211
+
212
+ ```ruby
213
+ # Add hooks for migration events
214
+ module MigrationHooks
215
+ def self.before_tenant_migration(schema_name)
216
+ Rails.logger.info "Starting migration for #{schema_name}"
217
+ end
218
+
219
+ def self.after_tenant_migration(schema_name, success)
220
+ status = success ? "SUCCESS" : "FAILED"
221
+ Rails.logger.info "Migration for #{schema_name}: #{status}"
222
+ end
223
+ end
224
+ ```
225
+
226
+ ### Batch Processing
227
+
228
+ ```ruby
229
+ # Process tenants in batches for large installations
230
+ def migrate_all_batched(batch_size: 10)
231
+ tenant_schemas.each_slice(batch_size) do |batch|
232
+ batch.each { |schema| migrate_tenant(schema) }
233
+ sleep(1) # Brief pause between batches
234
+ end
235
+ end
236
+ ```
237
+
238
+ ## 🚨 Important Considerations
239
+
240
+ ### Performance
241
+
242
+ - **Parallel Processing**: Consider parallelization for large tenant counts
243
+ - **Resource Usage**: Monitor database connections during bulk operations
244
+ - **Timing**: Run during low-traffic periods for production
245
+
246
+ ### Data Integrity
247
+
248
+ - **Backup Strategy**: Ensure proper backups before major migrations
249
+ - **Testing**: Test migrations on staging environment with production data
250
+ - **Rollback Plan**: Have rollback procedures for failed migrations
251
+
252
+ ### Monitoring
253
+
254
+ - **Log Analysis**: Monitor migration logs for patterns and issues
255
+ - **Alert Setup**: Set up alerts for migration failures
256
+ - **Performance Metrics**: Track migration duration and resource usage
257
+
258
+ ## 🔧 Troubleshooting
259
+
260
+ ### Common Issues
261
+
262
+ **Migration Stuck**
263
+ ```ruby
264
+ # Check for long-running queries
265
+ ActiveRecord::Base.connection.execute("SELECT * FROM pg_stat_activity WHERE state = 'active'")
266
+ ```
267
+
268
+ **Schema Not Found**
269
+ ```ruby
270
+ # Verify schema exists
271
+ if !PgMultitenantSchemas::SchemaSwitcher.schema_exists?('tenant_name')
272
+ PgMultitenantSchemas::Migrator.setup_tenant('tenant_name')
273
+ end
274
+ ```
275
+
276
+ **Permission Errors**
277
+ ```ruby
278
+ # Check database permissions
279
+ ActiveRecord::Base.connection.execute("SELECT has_schema_privilege('tenant_schema', 'USAGE')")
280
+ ```
281
+
282
+ ## 🔗 Related Components
283
+
284
+ - **[SchemaSwitcher](schema_switcher.md)**: Core schema operations used by Migrator
285
+ - **[Context](context.md)**: Tenant context management during migrations
286
+ - **[Configuration](configuration.md)**: Migrator configuration options
287
+ - **[Rails Integration](rails_integration.md)**: Framework integration features
288
+
289
+ ## 📝 Examples
290
+
291
+ See [examples/migration_workflow.rb](../examples/) for complete usage examples and [rake tasks documentation](../lib/pg_multitenant_schemas/tasks/) for command-line usage.