Tests: replace TravisCI with GitHub Actions
After years of providing an awesome service for free, which we are very grateful for, TravisCI will be dropping their free plan on Dec 31. So, we are switching to GHA. Drops multi-db (foo/bar) tests. Managing three databases per RDBMS was turning into a huge hassle, and they needed to be rewritten anyway for rails 6, per Eileen's talk.
This commit is contained in:
parent
799b590c2b
commit
5c95fca5cf
|
@ -73,6 +73,16 @@ createuser --superuser postgres
|
|||
DB=postgres bundle exec appraisal rails-5.2 rake
|
||||
```
|
||||
|
||||
## The dummy_app
|
||||
|
||||
In the rare event you need a `console` in the `dummy_app`:
|
||||
|
||||
```
|
||||
cd spec/dummy_app
|
||||
cp config/database.mysql.yml config/database.yml
|
||||
BUNDLE_GEMFILE='../../gemfiles/rails_5.2.gemfile' bin/rails console -e test
|
||||
```
|
||||
|
||||
## Adding new schema
|
||||
|
||||
Edit `spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb`. Migration
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
name: gha-workflow-pt-test
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
|
||||
# Linting is a separate job, primary because it only needs to be done once,
|
||||
# and secondarily because jobs are performed concurrently.
|
||||
gha-job-pt-lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup ruby
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
# Set to `TargetRubyVersion` in `.rubocopy.yml`
|
||||
ruby-version: 2.4
|
||||
- name: Bundle
|
||||
run: |
|
||||
gem install bundler
|
||||
bundle install --jobs 4 --retry 3
|
||||
- name: Lint
|
||||
run: bundle exec rubocop
|
||||
|
||||
# The test job is a matrix of ruby/rails versions.
|
||||
gha-job-pt-test:
|
||||
name: Ruby ${{ matrix.ruby }}, ${{ matrix.gemfile }}.gemfile
|
||||
runs-on: ubuntu-18.04
|
||||
services:
|
||||
gha-service-pt-mysql:
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: paper_trail_test
|
||||
image: mysql:8.0
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=3
|
||||
ports:
|
||||
- 3306:3306
|
||||
gha-service-pt-postgres:
|
||||
env:
|
||||
POSTGRES_PASSWORD: asdfasdf
|
||||
image: postgres
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
strategy:
|
||||
# Unlike TravisCI, the database will not be part of the matrix. Each
|
||||
# sub-job in the matrix tests all three databases. Alternatively, we could
|
||||
# have set this up with each database as a separate job, but then we'd be
|
||||
# duplicating the matrix configuration three times.
|
||||
matrix:
|
||||
gemfile: [ 'rails_5.2', 'rails_6.0', 'rails_6.1' ]
|
||||
|
||||
# To keep matrix size down, only test highest and lowest rubies. In
|
||||
# `.rubocopy.yml`, set `TargetRubyVersion`, to the lowest ruby version
|
||||
# tested here.
|
||||
ruby: [ '2.4', '2.7' ]
|
||||
|
||||
exclude:
|
||||
# rails 6 requires ruby >= 2.5.0
|
||||
- ruby: '2.4'
|
||||
gemfile: 'rails_6.0'
|
||||
- ruby: '2.4'
|
||||
gemfile: 'rails_6.1'
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup ruby
|
||||
uses: actions/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
- name: Test connection to postgres, print lists of dbs, users
|
||||
run: |
|
||||
psql \
|
||||
--command '\l' \
|
||||
--command '\du' \
|
||||
--host=$POSTGRES_HOST \
|
||||
--port=$POSTGRES_PORT \
|
||||
--username=postgres \
|
||||
postgres
|
||||
env:
|
||||
PGPASSWORD: asdfasdf
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_PORT: 5432
|
||||
- name: Test connection to mysql
|
||||
run: |
|
||||
mysql \
|
||||
--execute='show databases;' \
|
||||
--host=$MYSQL_HOST \
|
||||
--protocol=TCP \
|
||||
--port=$MYSQL_PORT \
|
||||
--user=$MYSQL_USER \
|
||||
$MYSQL_DATABASE
|
||||
env:
|
||||
MYSQL_DATABASE: paper_trail_test
|
||||
MYSQL_HOST: localhost
|
||||
MYSQL_PORT: 3306
|
||||
MYSQL_USER: root
|
||||
- name: Bundle
|
||||
run: |
|
||||
gem install bundler
|
||||
bundle install --jobs 4 --retry 3
|
||||
env:
|
||||
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
||||
|
||||
# MySQL db was created above, sqlite will be created during test suite,
|
||||
# when migrations occur, so we only need to create the postgres db. I
|
||||
# tried something like `cd .....dummy_app && ....db:create`, but couldn't
|
||||
# get that to work.
|
||||
- name: Create postgres database
|
||||
run: |
|
||||
createdb \
|
||||
--host=$POSTGRES_HOST \
|
||||
--port=$POSTGRES_PORT \
|
||||
--username=postgres \
|
||||
paper_trail_test
|
||||
env:
|
||||
PGPASSWORD: asdfasdf
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_PORT: 5432
|
||||
|
||||
# The following three steps finally run the tests. We use `rake
|
||||
# install_database_yml spec` instead of `rake` (default) because the
|
||||
# default includes rubocop, which we run (once) as a separate job. See
|
||||
# above.
|
||||
- name: Test, sqlite
|
||||
run: bundle exec rake install_database_yml spec
|
||||
env:
|
||||
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
||||
DB: sqlite
|
||||
- name: Test, mysql
|
||||
run: bundle exec rake install_database_yml spec
|
||||
env:
|
||||
BACKTRACE: 1
|
||||
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
||||
DB: mysql
|
||||
PT_CI_DATABASE: paper_trail
|
||||
PT_CI_DB_USER: root
|
||||
PT_CI_DB_HOST: 127.0.0.1
|
||||
PT_CI_DB_PORT: 3306
|
||||
- name: Test, postgres
|
||||
run: bundle exec rake install_database_yml spec
|
||||
env:
|
||||
BACKTRACE: 1
|
||||
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
||||
DB: postgres
|
||||
PT_CI_DATABASE: paper_trail
|
||||
PT_CI_DB_USER: postgres
|
||||
PT_CI_DB_PASSWORD: asdfasdf
|
||||
PT_CI_DB_HOST: 127.0.0.1
|
||||
PT_CI_DB_PORT: 5432
|
|
@ -18,7 +18,7 @@ AllCops:
|
|||
# Enable pending cops so we can adopt the code before they are switched on.
|
||||
NewCops: enable
|
||||
|
||||
# Set to lowest supported version
|
||||
# Set to lowest supported version of ruby
|
||||
TargetRubyVersion: 2.4
|
||||
|
||||
Bundler/OrderedGems:
|
||||
|
|
37
.travis.yml
37
.travis.yml
|
@ -1,37 +0,0 @@
|
|||
language: ruby
|
||||
cache: bundler
|
||||
|
||||
# For ruby, we test the highest and lowest minor versions only.
|
||||
rvm:
|
||||
- 2.4
|
||||
- 2.7
|
||||
|
||||
env:
|
||||
global:
|
||||
- TRAVIS=true
|
||||
matrix:
|
||||
- DB=mysql
|
||||
- DB=postgres
|
||||
- DB=sqlite
|
||||
|
||||
# Travis recommend we use the VM infrastructure (`sudo: required`)
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
- gem update bundler
|
||||
|
||||
gemfile:
|
||||
- gemfiles/rails_5.2.gemfile
|
||||
- gemfiles/rails_6.0.gemfile
|
||||
- gemfiles/rails_6.1.gemfile
|
||||
matrix:
|
||||
exclude:
|
||||
# rails 6 requires ruby >= 2.5.0
|
||||
- rvm: 2.4
|
||||
gemfile: gemfiles/rails_6.0.gemfile
|
||||
- rvm: 2.4
|
||||
gemfile: gemfiles/rails_6.1.gemfile
|
||||
fast_finish: true
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
57
Rakefile
57
Rakefile
|
@ -1,24 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
ENV["DB"] ||= "sqlite"
|
||||
|
||||
require "fileutils"
|
||||
require "bundler"
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
desc "Delete generated files and databases"
|
||||
task :clean do
|
||||
desc "Copy the database.DB.yml per ENV['DB']"
|
||||
task :install_database_yml do
|
||||
puts format("installing database.yml for %s", ENV["DB"])
|
||||
|
||||
# It's tempting to use `git clean` here, but this rake task will be run by
|
||||
# people working on changes that haven't been committed yet, so we have to
|
||||
# be more selective with what we delete.
|
||||
::FileUtils.rm("spec/dummy_app/db/database.yml", force: true)
|
||||
|
||||
FileUtils.cp(
|
||||
"spec/dummy_app/config/database.#{ENV['DB']}.yml",
|
||||
"spec/dummy_app/config/database.yml"
|
||||
)
|
||||
end
|
||||
|
||||
desc "Delete generated files and databases"
|
||||
task :clean do
|
||||
puts format("dropping %s database", ENV["DB"])
|
||||
case ENV["DB"]
|
||||
when "mysql"
|
||||
%w[test foo bar].each do |db|
|
||||
system("mysqladmin drop -f paper_trail_#{db} > /dev/null 2>&1")
|
||||
end
|
||||
# TODO: only works locally. doesn't respect database.yml
|
||||
system "mysqladmin drop -f paper_trail_test > /dev/null 2>&1"
|
||||
when "postgres"
|
||||
%w[test foo bar].each do |db|
|
||||
system("dropdb --if-exists paper_trail_#{db} > /dev/null 2>&1")
|
||||
end
|
||||
# TODO: only works locally. doesn't respect database.yml
|
||||
system "dropdb --if-exists paper_trail_test > /dev/null 2>&1"
|
||||
when nil, "sqlite"
|
||||
::FileUtils.rm(::Dir.glob("spec/dummy_app/db/*.sqlite3"))
|
||||
else
|
||||
|
@ -26,28 +38,21 @@ task :clean do
|
|||
end
|
||||
end
|
||||
|
||||
desc "Write a database.yml for the specified RDBMS"
|
||||
task prepare: [:clean] do
|
||||
ENV["DB"] ||= "sqlite"
|
||||
FileUtils.cp(
|
||||
"spec/dummy_app/config/database.#{ENV['DB']}.yml",
|
||||
"spec/dummy_app/config/database.yml"
|
||||
)
|
||||
desc <<~EOS
|
||||
Write a database.yml for the specified RDBMS, and create database. Does not
|
||||
migrate. Migration happens later in spec_helper.
|
||||
EOS
|
||||
task prepare: %i[clean install_database_yml] do
|
||||
puts format("creating %s database", ENV["DB"])
|
||||
case ENV["DB"]
|
||||
when "mysql"
|
||||
%w[test foo bar].each do |db|
|
||||
system("mysqladmin create paper_trail_#{db}")
|
||||
# Migration happens later in spec_helper.
|
||||
end
|
||||
# TODO: only works locally. doesn't respect database.yml
|
||||
system "mysqladmin create paper_trail_test"
|
||||
when "postgres"
|
||||
%w[test foo bar].each do |db|
|
||||
system("createdb paper_trail_#{db}")
|
||||
# Migration happens later in spec_helper.
|
||||
end
|
||||
# TODO: only works locally. doesn't respect database.yml
|
||||
system "createdb paper_trail_test"
|
||||
when nil, "sqlite"
|
||||
# noop. test.sqlite3 will be created when migration happens in spec_helper.
|
||||
# Shortly thereafter, foo and bar.sqlite3 are created when
|
||||
# spec/support/alt_db_init.rb is `require`d.
|
||||
# noop. test.sqlite3 will be created when migration happens
|
||||
nil
|
||||
else
|
||||
raise "Don't know how to create specified DB: #{ENV['DB']}"
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
APP_PATH = File.expand_path("../config/application", __dir__)
|
||||
require_relative "../config/boot"
|
||||
require "rails/commands"
|
|
@ -1,19 +1,12 @@
|
|||
test: &test
|
||||
adapter: mysql2
|
||||
encoding: utf8
|
||||
database: paper_trail_test
|
||||
database: <%= ENV.fetch('PT_CI_DATABASE', 'paper_trail') %>_test
|
||||
pool: 5
|
||||
username: root
|
||||
username: <%= ENV.fetch('PT_CI_DB_USER', 'root') %>
|
||||
host: <%= ENV.fetch('PT_CI_DB_HOST', 'localhost') %>
|
||||
port: <%= ENV.fetch('PT_CI_DB_PORT', 3306) %>
|
||||
protocol: TCP
|
||||
|
||||
# password deliberately blank
|
||||
password:
|
||||
host: localhost
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
foo:
|
||||
<<: *test
|
||||
database: paper_trail_foo
|
||||
|
||||
bar:
|
||||
<<: *test
|
||||
database: paper_trail_bar
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
test: &test
|
||||
adapter: postgresql
|
||||
database: paper_trail_test
|
||||
username: postgres
|
||||
password:
|
||||
host: localhost
|
||||
port: 5432
|
||||
|
||||
foo:
|
||||
<<: *test
|
||||
database: paper_trail_foo
|
||||
|
||||
bar:
|
||||
<<: *test
|
||||
database: paper_trail_bar
|
||||
database: <%= ENV.fetch('PT_CI_DATABASE', 'paper_trail') %>_test
|
||||
username: <%= ENV.fetch('PT_CI_DB_USER', 'postgres') %>
|
||||
password: <%= ENV.fetch('PT_CI_DB_PASSWORD', '') %>
|
||||
host: <%= ENV.fetch('PT_CI_DB_HOST', 'localhost') %>
|
||||
port: <%= ENV.fetch('PT_CI_DB_PORT', 5432) %>
|
||||
protocol: TCP
|
||||
|
|
|
@ -5,11 +5,3 @@ test: &test
|
|||
pool: 5
|
||||
timeout: 5000
|
||||
database: db/test.sqlite3
|
||||
|
||||
foo:
|
||||
<<: *test
|
||||
database: db/test-foo.sqlite3
|
||||
|
||||
bar:
|
||||
<<: *test
|
||||
database: db/test-bar.sqlite3
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
require "support/alt_db_init"
|
||||
|
||||
RSpec.describe PaperTrail::VersionConcern do
|
||||
it "allows included class to have different connections" do
|
||||
expect(Foo::Version.connection).not_to eq(Bar::Version.connection)
|
||||
end
|
||||
|
||||
it "allows custom version class to share connection with superclass" do
|
||||
expect(Foo::Version.connection).to eq(Foo::Document.connection)
|
||||
expect(Bar::Version.connection).to eq(Bar::Document.connection)
|
||||
end
|
||||
|
||||
it "can be used with class_name option" do
|
||||
expect(Foo::Document.version_class_name).to eq("Foo::Version")
|
||||
expect(Bar::Document.version_class_name).to eq("Bar::Version")
|
||||
end
|
||||
|
||||
describe "persistence", versioning: true do
|
||||
it "stores versions in the correct corresponding db location" do
|
||||
foo_doc = Foo::Document.create!(name: "foobar")
|
||||
bar_doc = Bar::Document.create!(name: "raboof")
|
||||
expect(foo_doc.versions.first).to be_instance_of(Foo::Version)
|
||||
expect(bar_doc.versions.first).to be_instance_of(Bar::Version)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,62 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "paper_trail_spec_migrator"
|
||||
|
||||
# This file copies the test database into locations for the `Foo` and `Bar`
|
||||
# namespace, then defines those namespaces, then establishes the sqlite3
|
||||
# connection for the namespaces to simulate an application with multiple
|
||||
# database connections.
|
||||
|
||||
# This is all going to change in rails 6. See "RailsConf 2018: Keynote: The
|
||||
# Future of Rails 6: Scalable by Default by Eileen Uchitelle"
|
||||
# https://www.youtube.com/watch?v=8evXWvM4oXM
|
||||
|
||||
# Load database yaml to use
|
||||
configs = YAML.load_file("#{Rails.root}/config/database.yml")
|
||||
|
||||
# If we are testing with sqlite make it quick
|
||||
db_directory = "#{Rails.root}/db"
|
||||
|
||||
# Set up alternate databases
|
||||
if ENV["DB"] == "sqlite"
|
||||
FileUtils.cp "#{db_directory}/test.sqlite3", "#{db_directory}/test-foo.sqlite3"
|
||||
FileUtils.cp "#{db_directory}/test.sqlite3", "#{db_directory}/test-bar.sqlite3"
|
||||
end
|
||||
|
||||
module Foo
|
||||
class Base < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
||||
|
||||
class Version < Base
|
||||
include PaperTrail::VersionConcern
|
||||
end
|
||||
|
||||
class Document < Base
|
||||
has_paper_trail versions: { class_name: "Foo::Version" }
|
||||
end
|
||||
end
|
||||
|
||||
Foo::Base.configurations = configs
|
||||
Foo::Base.establish_connection(:foo)
|
||||
ActiveRecord::Base.establish_connection(:foo)
|
||||
::PaperTrailSpecMigrator.new.migrate
|
||||
|
||||
module Bar
|
||||
class Base < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
||||
|
||||
class Version < Base
|
||||
include PaperTrail::VersionConcern
|
||||
end
|
||||
|
||||
class Document < Base
|
||||
has_paper_trail versions: { class_name: "Bar::Version" }
|
||||
end
|
||||
end
|
||||
|
||||
Bar::Base.configurations = configs
|
||||
Bar::Base.establish_connection(:bar)
|
||||
ActiveRecord::Base.establish_connection(:bar)
|
||||
::PaperTrailSpecMigrator.new.migrate
|
Loading…
Reference in New Issue