ros-apartment 3.4.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af86a04df8bf00d04859470cd76a8228d6b984da90e1324ed9eff43cbd0db0ac
4
- data.tar.gz: 905caaf498b70015ddccc9d8846ec18384fac0a98f6dd1010890a8fa2fb19e97
3
+ metadata.gz: 8c1a77f61c7ac94816e7f0a0d906435cf2f9f06d7efc979a7308ac41a99c4247
4
+ data.tar.gz: '08bdfedeaba0107f0931a2a1f438b2dffebcdd4df89381b5be97f7bd9de5b7d3'
5
5
  SHA512:
6
- metadata.gz: dfea9df160a8eb0e400f215eada4ecfb41852ab4d92123e1ee51bf2f1a25069c24a36a6b471048d70091a03af5efd420af6657e6bba38748630f285a5aa344cf
7
- data.tar.gz: 9a521c51af92800ac7b42a2f7f7ef48322d075095aed7868807caecc248958fc0667e3c0ae22b14e17d9df44ada1c325ca9804e03bdc9947a2f90bcf1a6bb27a
6
+ metadata.gz: c09415eddebce74732c14bf8f71ec3a4d8dab0e53f6df5d15439068964b2de79ac57c36253878456866e2021d6c8faf1a6f1a3ae12961b33d33a4118536128e3
7
+ data.tar.gz: db8413aa220b089dd0ab874051a5bf990e2f02b9a10da80e7e2356b8fbfd4a908346811ce6f8da0d9fc028c111fe9829ab495807e481a8b268353332d2e0c2bd
data/RELEASING.md ADDED
@@ -0,0 +1,106 @@
1
+ # Releasing ros-apartment
2
+
3
+ This document describes the release process for the `ros-apartment` gem.
4
+
5
+ ## Overview
6
+
7
+ Releases are automated via GitHub Actions. Pushing to `main` triggers the `gem-publish.yml` workflow, which publishes to RubyGems using trusted publishing (no API key required).
8
+
9
+ ## Prerequisites
10
+
11
+ - All changes merged to `development` branch
12
+ - CI passing on `development`
13
+ - Version number updated in `lib/apartment/version.rb`
14
+
15
+ ## Release Steps
16
+
17
+ ### 1. Bump the version
18
+
19
+ Update `lib/apartment/version.rb` on the `development` branch:
20
+
21
+ ```ruby
22
+ module Apartment
23
+ VERSION = 'X.Y.Z'
24
+ end
25
+ ```
26
+
27
+ Follow [Semantic Versioning](https://semver.org/):
28
+ - **MAJOR** (X): Breaking changes
29
+ - **MINOR** (Y): New features, backwards compatible
30
+ - **PATCH** (Z): Bug fixes, backwards compatible
31
+
32
+ ### 2. Create release PR
33
+
34
+ Create a PR from `development` to `main`:
35
+
36
+ ```bash
37
+ gh pr create --base main --head development --title "Release vX.Y.Z"
38
+ ```
39
+
40
+ Include a summary of changes in the PR description.
41
+
42
+ ### 3. Merge the release PR
43
+
44
+ Once CI passes and the PR is approved, merge it. This triggers the publish workflow.
45
+
46
+ **Important**: The workflow creates the git tag automatically. Do not create the tag manually beforehand or the workflow will fail.
47
+
48
+ ### 4. Verify the publish
49
+
50
+ Monitor the `gem-publish.yml` workflow run. It will:
51
+ 1. Build the gem
52
+ 2. Create and push the `vX.Y.Z` tag
53
+ 3. Publish to RubyGems
54
+ 4. Wait for RubyGems indexes to update
55
+
56
+ Verify at: https://rubygems.org/gems/ros-apartment
57
+
58
+ ### 5. Create GitHub Release
59
+
60
+ After the workflow completes:
61
+
62
+ 1. Go to https://github.com/rails-on-services/apartment/releases/new
63
+ 2. Select the `vX.Y.Z` tag (created by the workflow)
64
+ 3. Click "Generate release notes" for a starting point
65
+ 4. Edit the release notes to highlight key changes
66
+ 5. Publish the release
67
+
68
+ We use GitHub Releases as our changelog (no CHANGELOG.md file).
69
+
70
+ ### 6. Sync branches
71
+
72
+ Merge `main` back into `development` to keep them in sync:
73
+
74
+ ```bash
75
+ git checkout development
76
+ git pull origin development
77
+ git merge origin/main --no-edit
78
+ git push
79
+ ```
80
+
81
+ ## Workflow Details
82
+
83
+ The `gem-publish.yml` workflow uses:
84
+ - **Trusted publishing**: Configured via RubyGems.org OIDC, no API key needed
85
+ - **rubygems/release-gem@v1**: Official RubyGems action
86
+ - **rake release**: Builds gem, creates tag, pushes to RubyGems
87
+
88
+ ## Troubleshooting
89
+
90
+ ### Workflow fails with "tag already exists"
91
+
92
+ The tag was created manually before the workflow ran. Delete the tag and re-run:
93
+
94
+ ```bash
95
+ git push origin --delete vX.Y.Z
96
+ ```
97
+
98
+ Then re-trigger the workflow by pushing to main again (or re-run from GitHub Actions UI).
99
+
100
+ ### Gem published but GitHub Release missing
101
+
102
+ The GitHub Release is created manually (step 5). The gem is already available on RubyGems; the release is just for documentation.
103
+
104
+ ### RubyGems trusted publishing fails
105
+
106
+ Verify the GitHub environment `production` is configured correctly in repository settings, and that RubyGems.org has the trusted publisher configured for this repository.
data/context7.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "url": "https://context7.com/rails-on-services/apartment",
3
+ "public_key": "pk_EQhqzkh8FktmxBU0mbzmZ"
4
+ }
@@ -8,37 +8,47 @@ module Apartment
8
8
 
9
9
  # Migrate to latest
10
10
  def migrate(database)
11
- Tenant.switch(database) do
12
- version = ENV['VERSION']&.to_i
11
+ # Pin a connection for the entire migration to ensure Tenant.switch
12
+ # sets search_path on the same connection used by migration_context.
13
+ # Without this, connection pool may return different connections
14
+ # for the switch vs the actual migration operations.
15
+ ActiveRecord::Base.connection_pool.with_connection do
16
+ Tenant.switch(database) do
17
+ version = ENV['VERSION']&.to_i
13
18
 
14
- migration_scope_block = ->(migration) { ENV['SCOPE'].blank? || (ENV['SCOPE'] == migration.scope) }
19
+ migration_scope_block = ->(migration) { ENV['SCOPE'].blank? || (ENV['SCOPE'] == migration.scope) }
15
20
 
16
- if ActiveRecord.version >= Gem::Version.new('7.2.0')
17
- ActiveRecord::Base.connection_pool.migration_context.migrate(version, &migration_scope_block)
18
- else
19
- ActiveRecord::Base.connection.migration_context.migrate(version, &migration_scope_block)
21
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
22
+ ActiveRecord::Base.connection_pool.migration_context.migrate(version, &migration_scope_block)
23
+ else
24
+ ActiveRecord::Base.connection.migration_context.migrate(version, &migration_scope_block)
25
+ end
20
26
  end
21
27
  end
22
28
  end
23
29
 
24
30
  # Migrate up/down to a specific version
25
31
  def run(direction, database, version)
26
- Tenant.switch(database) do
27
- if ActiveRecord.version >= Gem::Version.new('7.2.0')
28
- ActiveRecord::Base.connection_pool.migration_context.run(direction, version)
29
- else
30
- ActiveRecord::Base.connection.migration_context.run(direction, version)
32
+ ActiveRecord::Base.connection_pool.with_connection do
33
+ Tenant.switch(database) do
34
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
35
+ ActiveRecord::Base.connection_pool.migration_context.run(direction, version)
36
+ else
37
+ ActiveRecord::Base.connection.migration_context.run(direction, version)
38
+ end
31
39
  end
32
40
  end
33
41
  end
34
42
 
35
43
  # rollback latest migration `step` number of times
36
44
  def rollback(database, step = 1)
37
- Tenant.switch(database) do
38
- if ActiveRecord.version >= Gem::Version.new('7.2.0')
39
- ActiveRecord::Base.connection_pool.migration_context.rollback(step)
40
- else
41
- ActiveRecord::Base.connection.migration_context.rollback(step)
45
+ ActiveRecord::Base.connection_pool.with_connection do
46
+ Tenant.switch(database) do
47
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
48
+ ActiveRecord::Base.connection_pool.migration_context.rollback(step)
49
+ else
50
+ ActiveRecord::Base.connection.migration_context.rollback(step)
51
+ end
42
52
  end
43
53
  end
44
54
  end
@@ -2,12 +2,26 @@
2
2
 
3
3
  # Require this file to append Apartment rake tasks to ActiveRecord db rake tasks
4
4
  # Enabled by default in the initializer
5
+ #
6
+ # ## Multi-Database Support (Rails 7+)
7
+ #
8
+ # When a Rails app has multiple databases configured in database.yml, Rails creates
9
+ # namespaced rake tasks like `db:migrate:primary`, `db:rollback:primary`, etc.
10
+ # This enhancer automatically detects databases with `database_tasks: true` and
11
+ # enhances their namespaced tasks to also run the corresponding apartment task.
12
+ #
13
+ # Example: Running `rails db:rollback:primary` will also invoke `apartment:rollback`
14
+ # to rollback all tenant schemas.
5
15
 
6
16
  module Apartment
7
17
  class RakeTaskEnhancer
8
18
  module TASKS
9
19
  ENHANCE_BEFORE = %w[db:drop].freeze
10
20
  ENHANCE_AFTER = %w[db:migrate db:rollback db:migrate:up db:migrate:down db:migrate:redo db:seed].freeze
21
+
22
+ # Base tasks that have namespaced variants in multi-database setups
23
+ # db:seed is excluded because Rails doesn't create db:seed:primary
24
+ NAMESPACED_AFTER = %w[db:migrate db:rollback db:migrate:up db:migrate:down db:migrate:redo].freeze
11
25
  freeze
12
26
  end
13
27
 
@@ -18,36 +32,89 @@ module Apartment
18
32
  def enhance!
19
33
  return unless should_enhance?
20
34
 
21
- # insert task before
35
+ enhance_base_tasks!
36
+ enhance_namespaced_tasks!
37
+ end
38
+
39
+ def should_enhance?
40
+ Apartment.db_migrate_tenants
41
+ end
42
+
43
+ private
44
+
45
+ # Enhance standard db:* tasks (backward compatible behavior)
46
+ def enhance_base_tasks!
22
47
  TASKS::ENHANCE_BEFORE.each do |name|
23
- task = Rake::Task[name]
24
- enhance_before_task(task)
48
+ enhance_task_before(name)
25
49
  end
26
50
 
27
- # insert task after
28
51
  TASKS::ENHANCE_AFTER.each do |name|
29
- task = Rake::Task[name]
30
- enhance_after_task(task)
52
+ enhance_task_after(name)
31
53
  end
32
54
  end
33
55
 
34
- def should_enhance?
35
- Apartment.db_migrate_tenants
56
+ # Enhance namespaced db:*:database_name tasks for multi-database setups
57
+ # Maps namespaced tasks to base apartment tasks:
58
+ # db:migrate:primary -> apartment:migrate
59
+ # db:rollback:primary -> apartment:rollback
60
+ # db:migrate:up:primary -> apartment:migrate:up
61
+ def enhance_namespaced_tasks!
62
+ database_names_with_tasks.each do |db_name|
63
+ TASKS::NAMESPACED_AFTER.each do |base_task|
64
+ namespaced_task = "#{base_task}:#{db_name}"
65
+ next unless task_defined?(namespaced_task)
66
+
67
+ apartment_task = base_task.sub('db:', 'apartment:')
68
+ enhance_namespaced_task_after(namespaced_task, apartment_task)
69
+ end
70
+ end
36
71
  end
37
72
 
38
- def enhance_before_task(task)
73
+ def enhance_task_before(name)
74
+ return unless task_defined?(name)
75
+
76
+ task = Rake::Task[name]
39
77
  task.enhance([inserted_task_name(task)])
40
78
  end
41
79
 
42
- def enhance_after_task(task)
80
+ def enhance_task_after(name)
81
+ return unless task_defined?(name)
82
+
83
+ task = Rake::Task[name]
43
84
  task.enhance do
44
85
  Rake::Task[inserted_task_name(task)].invoke
45
86
  end
46
87
  end
47
88
 
89
+ def enhance_namespaced_task_after(namespaced_task_name, apartment_task_name)
90
+ Rake::Task[namespaced_task_name].enhance do
91
+ Rake::Task[apartment_task_name].invoke
92
+ end
93
+ end
94
+
48
95
  def inserted_task_name(task)
49
96
  task.name.sub('db:', 'apartment:')
50
97
  end
98
+
99
+ def task_defined?(name)
100
+ Rake::Task.task_defined?(name)
101
+ end
102
+
103
+ # Returns database names that have database_tasks enabled and are not replicas.
104
+ # These are the databases for which Rails creates namespaced rake tasks.
105
+ #
106
+ # @return [Array<String>] database names (e.g., ['primary', 'secondary'])
107
+ def database_names_with_tasks
108
+ return [] unless defined?(Rails) && Rails.respond_to?(:env)
109
+
110
+ configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
111
+ configs
112
+ .select { |c| c.database_tasks? && !c.replica? }
113
+ .map(&:name)
114
+ rescue StandardError
115
+ # Fail gracefully if configurations unavailable (e.g., during early boot)
116
+ []
117
+ end
51
118
  end
52
119
  end
53
120
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Apartment
4
- VERSION = '3.4.0'
4
+ VERSION = '3.4.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ros-apartment
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Brunner
@@ -129,7 +129,9 @@ files:
129
129
  - Gemfile
130
130
  - Guardfile
131
131
  - README.md
132
+ - RELEASING.md
132
133
  - Rakefile
134
+ - context7.json
133
135
  - docs/adapters.md
134
136
  - docs/architecture.md
135
137
  - docs/elevators.md