Skip to content

Commit

Permalink
Compability, Versioning and Upgrading Penthouse and Using Docker & Ci…
Browse files Browse the repository at this point in the history
…rcleCI for Developer Experience (#16)

This change adds the standard linter, it adds support for testing multiple ruby versions in CI
  • Loading branch information
Simon authored Jul 21, 2020
1 parent 8b81c90 commit 721f390
Show file tree
Hide file tree
Showing 42 changed files with 405 additions and 199 deletions.
39 changes: 39 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
version: 2
jobs:
build:
docker:
- image: circleci/ruby:2.4.1

- image: circleci/postgres:9.6.2-alpine
name: postgres

steps:
- checkout

- run: bundle install
- run: bundle exec standardrb
- run: rm Gemfile.lock

- run: RUBY_VERSION=2.4.1 RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 bundle install
- run: RUBY_VERSION=2.4.1 RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 bundle exec rspec
- run: rm Gemfile.lock

- run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.1.6.2 PG_VERSION=0.21.0 bundle install
- run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.1.6.2 PG_VERSION=0.21.0 bundle exec rspec
- run: rm Gemfile.lock

- run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.1.7 PG_VERSION=0.21.0 bundle install
- run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.1.7 PG_VERSION=0.21.0 bundle exec rspec
- run: rm Gemfile.lock
#
#
# - run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.2.3 PG_VERSION=1.1.4 bundle install
# - run: RUBY_VERSION=2.4.1 RAILS_VERSION=5.2.3 PG_VERSION=1.1.4 bundle exec rspec
# - run: rm Gemfile.lock
#
# Fails with `NameError: undefined method `migrate' for class `#<Class:ActiveRecord::Migrator>'`
#
# Uncomment when adding support for greater rails versions
#
# - run: RUBY_VERSION=2.4.1 RAILS_VERSION=6.0.0 PG_VERSION=0.21.0 bundle install
# - run: RUBY_VERSION=2.4.1 RAILS_VERSION=6.0.0 PG_VERSION=0.21.0 bundle exec rspec
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Gemfile.lock
1 change: 0 additions & 1 deletion .ruby-version

This file was deleted.

22 changes: 22 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
ARG RUBY_VERSION="2.5"

FROM ruby:$RUBY_VERSION-alpine

ARG RUBY_VERSION="2.5"
ARG RAILS_VERSION="5.1.4"
ARG PG_VERSION="1.1.4"

RUN apk add --update build-base postgresql-dev tzdata git

WORKDIR /app
ADD ./ /app/

RUN gem install bundler -v '1.17'

ENV RUBY_VERSION=$RUBY_VERSION
ENV RAILS_VERSION=$RAILS_VERSION
ENV PG_VERSION=$PG_VERSION

RUN RUBY_VERSION=$RUBY_VERSION RAILS_VERSION=$RAILS_VERSION PG_VERSION=$PG_VERSION bundle install --jobs=4 --no-cache

ENTRYPOINT ["bundle", "exec", "rspec"]
11 changes: 9 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
source 'https://rubygems.org'
ruby '2.5.7'
source "https://rubygems.org"
ruby ENV.fetch("RUBY_VERSION", "2.3.0")

group :test do
gem "activesupport", ENV.fetch("RAILS_VERSION", "4.2.2").to_s
gem "activerecord", ENV.fetch("RAILS_VERSION", "4.2.2").to_s
gem "pg", ENV.fetch("PG_VERSION", "0.19.0").to_s
end

gemspec
18 changes: 9 additions & 9 deletions Guardfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,26 @@ guard :rspec, cmd: "bundle exec rspec", failed_mode: :focus do
dsl.watch_spec_files_for(ruby.lib_files)

# Rails files
rails = dsl.rails(view_extensions: %w(erb haml slim))
rails = dsl.rails(view_extensions: %w[erb haml slim])
dsl.watch_spec_files_for(rails.app_files)
dsl.watch_spec_files_for(rails.views)

watch(rails.controllers) do |m|
[
rspec.spec.("routing/#{m[1]}_routing"),
rspec.spec.("controllers/#{m[1]}_controller"),
rspec.spec.("acceptance/#{m[1]}")
rspec.spec.call("routing/#{m[1]}_routing"),
rspec.spec.call("controllers/#{m[1]}_controller"),
rspec.spec.call("acceptance/#{m[1]}")
]
end

# Rails config changes
watch(rails.spec_helper) { rspec.spec_dir }
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
watch(rails.spec_helper) { rspec.spec_dir }
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }

# Capybara features specs
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
watch(rails.layouts) { |m| rspec.spec.("features/#{m[1]}") }
watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }

# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
Expand Down
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
test-4.2.11.1: # Test rails 4 LTS
RUBY_VERSION=2.3.0 RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 docker-compose build
RUBY_VERSION=2.3.0 RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 docker-compose run penthouse

test-5.1.7: # Test rails 5 before migration context
RUBY_VERSION=2.4.0 RAILS_VERSION=5.1.7 PG_VERSION=0.21.0 docker-compose build
RUBY_VERSION=2.4.0 RAILS_VERSION=5.1.7 PG_VERSION=0.21.0 docker-compose run penthouse

test-5.2.3: # Test rails 5 with migration context
RUBY_VERSION=2.5.0 RAILS_VERSION=5.2.3 PG_VERSION=1.1.4 docker-compose build
RUBY_VERSION=2.5.0 RAILS_VERSION=5.2.3 PG_VERSION=1.1.4 docker-compose run penthouse

test-6.0.0: # Test rails 6
RUBY_VERSION=2.6.0 RAILS_VERSION=6.0.0 PG_VERSION=1.1.4 docker-compose build
RUBY_VERSION=2.6.0 RAILS_VERSION=6.0.0 PG_VERSION=1.1.4 docker-compose run penthouse

test:
make test-4.2.11.1
make test-5.1.7
make test-5.2.3
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
# Penthouse

[![Codeship Status](https://codeship.com/projects/c6513ab0-cc05-0133-94c6-0666c337ff82/status?branch=master)](https://codeship.com/projects/140114) [![Code Climate](https://codeclimate.com/github/ryantownsend/penthouse/badges/gpa.svg)](https://codeclimate.com/github/ryantownsend/penthouse) [![RubyDocs](https://img.shields.io/badge/rubydocs-click_here-blue.svg)](http://www.rubydoc.info/github/ryantownsend/penthouse)

Penthouse is an alternative to the excellent [Apartment gem](https://github.com/influitive/apartment) – however Penthouse is more of a framework for multi-tenancy than a library, in that it provides less out-of-the-box functionality, but should make for easier customisation.

- [Penthouse](#penthouse)
- [Installation](#installation)
- [Basic Usage](#basic-usage)
- [Octopus (shard) Usage](#octopus-shard-usage)
- [ActiveJob](#activejob)
- [Sidekiq](#sidekiq)
- [Dictionary](#dictionary)
- [Contributing](#contributing)
- [Testing](#testing)
- [CI/Local](#cilocal)
- [Without Circle](#without-circle)

## Installation

Add this line to your application's Gemfile:
Expand Down Expand Up @@ -80,3 +94,39 @@ require 'penthouse/sidekiq'
## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ryantownsend/penthouse.

## Testing

### CI/Local

We use circle,a dn it can be used locally with docker. See:

- [running circle locally](https://circleci.com/docs/2.0/local-cli/)
- [Using postgres with circle](https://circleci.com/docs/2.0/postgres-config/)

```bash
echo <circle-api-token> | circleci setup
circleci local execute
```

### Without Circle

Docker is used for isolated testing. To test all supported versions run:

```bash
make test
```

For specific versions see the `Makefile`.

Alternatively you can tets any version locally with:

```
export RUBY_VERSION=2.5.0
rbenv local $RUBY_VERSION
RUBY_VERSION=$RUBY_VERSION RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 bundle install
RUBY_VERSION=$RUBY_VERSION RAILS_VERSION=4.2.11.1 PG_VERSION=0.21.0 bundle exec rsepc
```


30 changes: 30 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: '3.5'

services:
postgres:
image: postgres:10.5-alpine
ports:
- 5432
networks:
penthouse:
default:

penthouse:
build:
context: .
dockerfile: Dockerfile.test
args:
RUBY_VERSION: ${RUBY_VERSION:-2.5.0}
RAILS_VERSION: ${RAILS_VERSION:-5.1.7}
PG_VERSION: ${PG_VERSION:-1.1.4}
RAILS_ENV: test
networks:
penthouse:
default:
depends_on:
- postgres

networks:
penthouse:
driver: bridge
name: penthouse
16 changes: 8 additions & 8 deletions lib/penthouse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

module Penthouse
class TenantNotFound < RuntimeError; end
CURRENT_TENANT_KEY = 'penthouse_tenant'.freeze
CURRENT_TENANT_KEY = "penthouse_tenant".freeze

class << self
# Retrieves the currently active tenant identifier
Expand All @@ -29,7 +29,7 @@ def tenant=(tenant_identifier)
# @param block [Block] the code to execute
# @yield [String, Symbol] the identifier for the tenant
# @return [void]
def with_tenant(tenant_identifier:, default_tenant: self.tenant, &block)
def with_tenant(tenant_identifier:, default_tenant: tenant, &block)
self.tenant = tenant_identifier
block.yield(tenant_identifier)
ensure
Expand All @@ -43,7 +43,7 @@ def with_tenant(tenant_identifier:, default_tenant: self.tenant, &block)
# @param block [Block] the code to execute
# @yield [String, Symbol] the identifier for the tenant
# @return [void]
def each_tenant(tenant_identifiers: self.tenant_identifiers, runner: self.configuration.runner, &block)
def each_tenant(tenant_identifiers: self.tenant_identifiers, runner: configuration.runner, &block)
tenant_identifiers.each do |tenant_identifier|
switch(tenant_identifier: tenant_identifier, runner: runner, &block)
end
Expand All @@ -55,15 +55,15 @@ def each_tenant(tenant_identifiers: self.tenant_identifiers, runner: self.config
# @param block [Block] the code to execute
# @yield [Penthouse::Tenants::BaseTenant] the tenant instance
# @return [void]
def switch(tenant_identifier:, runner: self.configuration.runner, &block)
def switch(tenant_identifier:, runner: configuration.runner, &block)
runner.call(tenant_identifier: tenant_identifier, &block)
end

# Loads the tenant and creates their data store
# @param tenant_identifier [String, Symbol] the identifier for the tenant
# @see Penthouse::Tenants::BaseTenant#delete
# @return [void]
def create(tenant_identifier:, runner: self.configuration.runner, **options)
def create(tenant_identifier:, runner: configuration.runner, **options)
switch(tenant_identifier: tenant_identifier, runner: runner) do |tenant|
tenant.create(**options)
end
Expand All @@ -73,7 +73,7 @@ def create(tenant_identifier:, runner: self.configuration.runner, **options)
# @param tenant_identifier [String, Symbol] the identifier for the tenant
# @see Penthouse::Tenants::BaseTenant#delete
# @return [void]
def delete(tenant_identifier:, runner: self.configuration.runner, **options)
def delete(tenant_identifier:, runner: configuration.runner, **options)
switch(tenant_identifier: tenant_identifier, runner: runner) do |tenant|
tenant.delete(**options)
end
Expand All @@ -84,9 +84,9 @@ def delete(tenant_identifier:, runner: self.configuration.runner, **options)
# @return [void]
def configure(&block)
# allow the configuration by the block
block.yield(self.configuration)
block.yield(configuration)
# prevent modification of configuration once set
self.configuration.freeze
configuration.freeze
end

# Returns the current configuration of Penthouse
Expand Down
4 changes: 2 additions & 2 deletions lib/penthouse/active_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ module ActiveJob

class_methods do
def execute(job_data)
Penthouse.switch(job_data['tenant']) do
Penthouse.switch(job_data["tenant"]) do
super
end
end
end

def serialize
super.merge('tenant' => Penthouse.tenant)
super.merge("tenant" => Penthouse.tenant)
end
end
end
2 changes: 1 addition & 1 deletion lib/penthouse/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# application within that tenant.
#

require 'rack/request'
require "rack/request"

module Penthouse
class App
Expand Down
14 changes: 7 additions & 7 deletions lib/penthouse/migrator.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'active_record'
require 'active_support/core_ext/module/aliasing'
require "active_record"
require "active_support/core_ext/module/aliasing"

module Penthouse
module Migration
Expand All @@ -19,7 +19,7 @@ def announce_with_penthouse(message)
end

def current_tenant
"Tenant: #{Penthouse.tenant || '*** global ***'}"
"Tenant: #{Penthouse.tenant || "*** global ***"}"
end
end
end
Expand All @@ -45,9 +45,9 @@ class << self

# override any new Octopus methods with the new Penthouse ones
alias_method :migrate_with_octopus, :migrate_with_penthouse
alias_method :up_with_octopus, :up_with_penthouse
alias_method :down_with_octopus, :down_with_penthouse
alias_method :run_with_octopus, :run_with_penthouse
alias_method :up_with_octopus, :up_with_penthouse
alias_method :down_with_octopus, :down_with_penthouse
alias_method :run_with_octopus, :run_with_penthouse
end

alias_method :migrate_without_penthouse, :migrate
Expand All @@ -57,7 +57,7 @@ class << self
alias_method :migrations, :migrations_with_penthouse

# override any new Octopus methods with the new Penthouse ones
alias_method :migrate_with_octopus, :migrate_with_penthouse
alias_method :migrate_with_octopus, :migrate_with_penthouse
alias_method :migrations_with_octopus, :migrations_with_penthouse
end
end
Expand Down
2 changes: 0 additions & 2 deletions lib/penthouse/routers/base_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
module Penthouse
module Routers
class BaseRouter

# @abstract typically used by the App to receive a request and return a tenant that can be switched to
# @param request [Rack::Request] The request from the Rack app, used to determine the tenant
# @return [String, Symbol] A tenant identifier
# @raise [Penthouse::TenantNotFound] if the tenant cannot be found/switched to
def self.call(request)
raise NotImplementedError
end

end
end
end
2 changes: 0 additions & 2 deletions lib/penthouse/routers/subdomain_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
module Penthouse
module Routers
class SubdomainRouter < BaseRouter

# Determines the tenant identifier based on the sub-domain of the request
# @param request [Rack::Request] The request from the Rack app, used to determine the tenant
# @return [String, Symbol] A tenant identifier
def self.call(request)
request.host.split(".").first
end

end
end
end
Loading

0 comments on commit 721f390

Please sign in to comment.