diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index c23e4ea3..ecf5c1bf 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -33,23 +33,31 @@ jobs: git config --local user.name "$ACTION_USERNAME" git add CHANGELOG.md && git commit -m 'Updated CHANGELOG.md' && echo ::set-env name=push::1 || echo "No changes to CHANGELOG.md" - - name: Push changelog to master - if: env.push == 1 - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.CHANGELOG_GITHUB_TOKEN }} - branch: master - - - name: Cherry-pick changelog to development + - name: Push changes if: env.push == 1 env: - ACTION_EMAIL: action@github.com - ACTION_USERNAME: GitHub Action + # CI_USER: ${{ secrets.YOUR_GITHUB_USER }} + CI_TOKEN: ${{ secrets.CHANGELOG_GITHUB_TOKEN }} run: | - git config --local user.email "$ACTION_EMAIL" - git config --local user.name "$ACTION_USERNAME" - commit_hash=`git show HEAD | egrep commit\ .+$ | cut -d' ' -f2` - git checkout development - git pull - git cherry-pick $commit_hash - git push + git push "https://$GITHUB_ACTOR:$CI_TOKEN@github.com/$GITHUB_REPOSITORY.git" HEAD:master + + # - name: Push changelog to master + # if: env.push == 1 + # uses: ad-m/github-push-action@master + # with: + # github_token: ${{ secrets.CHANGELOG_GITHUB_TOKEN }} + # branch: master + + # - name: Cherry-pick changelog to development + # if: env.push == 1 + # env: + # ACTION_EMAIL: action@github.com + # ACTION_USERNAME: GitHub Action + # run: | + # git config --local user.email "$ACTION_EMAIL" + # git config --local user.name "$ACTION_USERNAME" + # commit_hash=`git show HEAD | egrep commit\ .+$ | cut -d' ' -f2` + # git checkout development + # git pull + # git cherry-pick $commit_hash + # git push diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a0b7741..345ae68e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,25 @@ [Full Changelog](https://github.com/rails-on-services/apartment/compare/v2.7.2...HEAD) +**Implemented enhancements:** + +- Uses a transaction to create a tenant [\#66](https://github.com/rails-on-services/apartment/issues/66) + +**Fixed bugs:** + +- Fix seeding errors [\#86](https://github.com/rails-on-services/apartment/issues/86) +- When tests run in a transaction, new tenants in tests fail to create [\#123](https://github.com/rails-on-services/apartment/issues/123) +- Reverted unsafe initializer - introduces the possibility of disabling the initial connection to the database via +environment variable. Relates to the following tickets/PRs: + - [#113](https://github.com/rails-on-services/apartment/issues/113) + - [#39](https://github.com/rails-on-services/apartment/pull/39) + - [#53](https://github.com/rails-on-services/apartment/pull/53) + - [#118](https://github.com/rails-on-services/apartment/pull/118) + **Closed issues:** - Improve changelog automatic generation [\#98](https://github.com/rails-on-services/apartment/issues/98) +- Relaxes dependencies to allow rails 6.1 [\#121](https://github.com/rails-on-services/apartment/issues/121) ## [v2.7.2](https://github.com/rails-on-services/apartment/tree/v2.7.2) (2020-07-17) diff --git a/README.md b/README.md index f296892c..5704b97e 100644 --- a/README.md +++ b/README.md @@ -594,11 +594,10 @@ module Apartment end ``` -## Running rails console without a connection +## Running rails console without a connection to the database -Before this fork, running rails with the gem installed would connect to the database -which is different than the default behavior. To disable this initial -connection, just run with `APARTMENT_DISABLE_INIT` set to something: +By default, once apartment starts, it establishes a connection to the database. It is possible to +disable this initial connection, by running with `APARTMENT_DISABLE_INIT` set to something: ```shell $ APARTMENT_DISABLE_INIT=true DATABASE_URL=postgresql://localhost:1234/buk_development bin/rails runner 'puts 1' diff --git a/lib/apartment.rb b/lib/apartment.rb index 6bca1cc8..59a61cd1 100644 --- a/lib/apartment.rb +++ b/lib/apartment.rb @@ -6,7 +6,7 @@ require 'active_record' require 'apartment/tenant' -require_relative 'apartment/active_record/log_subscriber' +require_relative 'apartment/log_subscriber' if ActiveRecord.version.release >= Gem::Version.new('6.0') require_relative 'apartment/active_record/connection_handling' diff --git a/lib/apartment/active_record/log_subscriber.rb b/lib/apartment/active_record/log_subscriber.rb deleted file mode 100644 index 45d3772d..00000000 --- a/lib/apartment/active_record/log_subscriber.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -module ActiveRecord - # Supports the logging configuration to prepend the database and schema in the ActiveRecord log - class LogSubscriber < ActiveSupport::LogSubscriber - def apartment_log - return unless Apartment.active_record_log - - database = color("[#{Apartment.connection.current_database}] ", ActiveSupport::LogSubscriber::MAGENTA, true) - schema = nil - unless Apartment.connection.schema_search_path.nil? - schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ", - ActiveSupport::LogSubscriber::YELLOW, true) - end - "#{database}#{schema}" - end - - def payload_binds(binds, type_casted_binds) - return unless (binds || []).empty? - - casted_params = type_casted_binds(type_casted_binds) - ' ' + binds.zip(casted_params).map { |attr, value| render_bind(attr, value) }.inspect - end - - def sql(event) - self.class.runtime += event.duration - return unless logger.debug? - - payload = event.payload - - return if IGNORE_PAYLOAD_NAMES.include?(payload[:name]) - - name = "#{payload[:name]} (#{event.duration.round(1)}ms)" - name = "CACHE #{name}" if payload[:cached] - sql = payload[:sql] - binds = payload_binds(payload[:binds], payload[:type_casted_binds]) - - name = colorize_payload_name(name, payload[:name]) - sql = color(sql, sql_color(sql), true) if colorize_logging - - debug " #{apartment_log}#{name} #{sql}#{binds}" - end - end -end diff --git a/lib/apartment/adapters/postgresql_adapter.rb b/lib/apartment/adapters/postgresql_adapter.rb index 17cbb892..fd2ea683 100644 --- a/lib/apartment/adapters/postgresql_adapter.rb +++ b/lib/apartment/adapters/postgresql_adapter.rb @@ -97,7 +97,23 @@ def tenant_exists?(tenant) end def create_tenant_command(conn, tenant) - conn.execute(%(CREATE SCHEMA "#{tenant}")) + # NOTE: This was causing some tests to fail because of the database strategy for rspec + if ActiveRecord::Base.connection.open_transactions > 0 + conn.execute(%(CREATE SCHEMA "#{tenant}")) + else + schema = %(BEGIN; + CREATE SCHEMA "#{tenant}"; + COMMIT;) + + conn.execute(schema) + end + rescue *rescuable_exceptions => e + rollback_transaction(conn) + raise e + end + + def rollback_transaction(conn) + conn.execute("ROLLBACK;") end # Generate the final search path to set including persistent_schemas diff --git a/lib/apartment/log_subscriber.rb b/lib/apartment/log_subscriber.rb new file mode 100644 index 00000000..cb733f3c --- /dev/null +++ b/lib/apartment/log_subscriber.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Apartment + class LogSubscriber < ActiveRecord::LogSubscriber + def sql(event) + super(event) + end + + private + + def debug(progname = nil, &block) + progname = " #{apartment_log}#{progname}" unless progname.nil? + + super(progname, &block) + end + + def apartment_log + database = color("[#{Apartment.connection.current_database}] ", ActiveSupport::LogSubscriber::MAGENTA, true) + schema = nil + unless Apartment.connection.schema_search_path.nil? + schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ", + ActiveSupport::LogSubscriber::YELLOW, true) + end + "#{database}#{schema}" + end + end +end diff --git a/lib/apartment/railtie.rb b/lib/apartment/railtie.rb index c7d8f6b5..18b47644 100644 --- a/lib/apartment/railtie.rb +++ b/lib/apartment/railtie.rb @@ -45,6 +45,14 @@ class Railtie < Rails::Railtie end end + config.after_initialize do |app| + # NOTE: Load the custom log subscriber if enabled + if Apartment.active_record_log + ActiveSupport::Notifications.unsubscribe 'sql.active_record' + Apartment::LogSubscriber.attach_to :active_record + end + end + # # Ensure rake tasks are loaded # diff --git a/lib/apartment/tasks/task_helper.rb b/lib/apartment/tasks/task_helper.rb index 84257b9a..6065c953 100644 --- a/lib/apartment/tasks/task_helper.rb +++ b/lib/apartment/tasks/task_helper.rb @@ -29,5 +29,12 @@ def self.warn_if_tenants_empty Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this. WARNING end + + def self.create_tenant(tenant_name) + puts("Creating #{tenant_name} tenant") + Apartment::Tenant.create(tenant_name) + rescue Apartment::TenantExists => e + puts "Tried to create already existing tenant: #{e}" + end end end diff --git a/lib/apartment/version.rb b/lib/apartment/version.rb index 8191b485..398dd80a 100644 --- a/lib/apartment/version.rb +++ b/lib/apartment/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Apartment - VERSION = '2.7.2' + VERSION = '2.8.0' end diff --git a/lib/tasks/apartment.rake b/lib/tasks/apartment.rake index f4583074..1ea98fed 100644 --- a/lib/tasks/apartment.rake +++ b/lib/tasks/apartment.rake @@ -10,12 +10,7 @@ apartment_namespace = namespace :apartment do Apartment::TaskHelper.warn_if_tenants_empty Apartment::TaskHelper.tenants.each do |tenant| - begin - puts("Creating #{tenant} tenant") - Apartment::Tenant.create(tenant) - rescue Apartment::TenantExists => e - puts e.message - end + Apartment::TaskHelper.create_tenant(tenant) end end @@ -36,6 +31,7 @@ apartment_namespace = namespace :apartment do Apartment::TaskHelper.warn_if_tenants_empty Apartment::TaskHelper.each_tenant do |tenant| begin + Apartment::TaskHelper.create_tenant(tenant) puts("Migrating #{tenant} tenant") Apartment::Migrator.migrate tenant rescue Apartment::TenantNotFound => e @@ -45,11 +41,12 @@ apartment_namespace = namespace :apartment do end desc 'Seed all tenants' - task seed: :create do + task :seed do Apartment::TaskHelper.warn_if_tenants_empty Apartment::TaskHelper.each_tenant do |tenant| begin + Apartment::TaskHelper.create_tenant(tenant) puts("Seeding #{tenant} tenant") Apartment::Tenant.switch(tenant) do Apartment::Tenant.seed diff --git a/ros-apartment.gemspec b/ros-apartment.gemspec index 5c01be69..7c59a6ba 100644 --- a/ros-apartment.gemspec +++ b/ros-apartment.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/rails-on-services/apartment' s.licenses = ['MIT'] - s.add_dependency 'activerecord', '>= 5.0.0', '< 6.1' + s.add_dependency 'activerecord', '>= 5.0.0', '< 6.2' s.add_dependency 'parallel', '< 2.0' s.add_dependency 'public_suffix', '>= 2.0.5', '< 5.0' s.add_dependency 'rack', '>= 1.3.6', '< 3.0' diff --git a/spec/examples/generic_adapter_custom_configuration_example.rb b/spec/examples/generic_adapter_custom_configuration_example.rb index 5abe5029..2ad7ee20 100644 --- a/spec/examples/generic_adapter_custom_configuration_example.rb +++ b/spec/examples/generic_adapter_custom_configuration_example.rb @@ -29,7 +29,7 @@ receive(:establish_connection).with(expected_args).and_call_original ) - # because we dont have another server to connect to it errors + # because we don't have another server to connect to it errors # what matters is establish_connection receives proper args expect { subject.create(custom_tenant_name) }.to raise_error(Apartment::TenantExists) end