I have the following Github Action to run my tests for my Rails app (Rails 6.1.4, Ruby 3.1.3):
name: Ruby CI 💣
on:
push:
branches: [ develop, staging, master ]
pull_request:
branches: [ develop, staging, master ]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports: ['5432:5432']
options:
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout#v3
- name: Setup Ruby
uses: ruby/setup-ruby#v1
with:
bundler-cache: true
- name: Build and run test
env:
DATABASE_URL: postgres://postgres:#localhost:5432/test
RAILS_ENV: test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
PIPE_ENV: development
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
run: |
sudo apt-get -yqq install libpq-dev
gem install bundler:1.17.3
bundle install --jobs 4 --retry 3
bundle exec rails db:drop RAILS_ENV=test
bundle exec rails db:create RAILS_ENV=test
bundle exec rails db:migrate RAILS_ENV=test
bundle exec rake RAILS_ENV=test
The action seems to be working fine. The thing is that all my tests pass locally but some of them break on Github:
1) CashFlow cash_flow#index returns 200
Failure/Error: raise ParamsValidationError, errors.full_messages
ParamsValidationError:
missing_params
# ./app/forms/transactions/sale_create_form.rb:52:in `save'
# ./spec/requests/v1/cash_flow_spec.rb:42:in `block (3 levels) in <main>'
All of my tests that have an inclusion validation fails. But if I print the received value vs the expected value right inside the class, they match! No typos, no mistakes, nothing on my side.
module Transactions
class SaleCreateForm
include ActiveModel::Model
attr_accessor :organization,
:transaction,
:contact_id,
:products,
:amount,
:discount,
:concept,
:payment_type,
:payment_method,
:transaction_status,
:transaction_origin,
:transaction_category_id,
:pay_at,
:created_at
validates :payment_type, :payment_method, presence: true
validates :payment_type, inclusion: {
in: PaymentType.pluck(:slug),
message: :payment_type_error
}
validates :payment_method, inclusion: {
in: PaymentMethod.pluck(:slug),
message: :payment_method_error
}
...
This is what I got inside the method that executes the validation:
if invalid?
p PaymentType.pluck(:slug)
-> ["in-cash", "credit"]
p PaymentMethod.pluck(:slug)
-> ["cash", "on-credit", "card", "other", "bank"]
p #payment_type
-> "in-cash"
p #payment_method
-> "cash"
p errors.full_messages
-> ["Payment type in-cash is not a valid payment type", "Payment method cash is not a
valid payment method"]
end
All the values I pass on the test are the expected ones, and they pass locally on my machine. I also get errors for my webmock stubs that I don't get locally:
expected no Exception, got #<WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: POST ...-7032-4fc2-b924-be77e5056b65", nil]]
Any hint on what I can do to solve this is appreciated.
Related
I have been trying to create a Github Action where it runs my rails test as I push to my main branch. I run rails test on my terminal, and all of the tests passed, but when I try to run the tests in my main.yml file in my workflow on github, it fails only 2 tests, both relating to deleting an object with a relationship with another object (with a foreign key).
When I run my rails test through my terminal, this is my output
Running 74 tests in parallel using 2 processes
DEBUGGER: Attaching after process 42736 fork to child process 42753
DEBUGGER[bin/rails#42754]: Attaching after process 42736 fork to child process 42754
Started with run options --seed 10960
74/74: [=================================] 100% Time: 00:00:04, Time: 00:00:04
Finished in 5.09323s
74 tests, 135 assertions, 0 failures, 0 errors, 0 skips
When I push to my main branch on Github, this is my output for the tests
Running 74 tests in parallel using 2 processes
DEBUGGER: Attaching after process 3336 fork to child process 3357
DEBUGGER[bin/rails#3359]: Attaching after process 3336 fork to child process 3359
Started with run options --seed 27863
Progress: |=========ERROR ReviewsControllerTest#test_should_destroy_review (3.88s)
Minitest::UnexpectedError: DRb::DRbRemoteError: PG::ForeignKeyViolation: ERROR: update or delete on table "reviews" violates foreign key constraint "fk_rails_7314ea0830" on table "restaurants"
DETAIL: Key (id)=(1) is still referenced from table "restaurants".
(ActiveRecord::InvalidForeignKey)
app/controllers/reviews_controller.rb:52:in `destroy'
test/controllers/reviews_controller_test.rb:43:in `block (2 levels) in <class:ReviewsControllerTest>'
test/controllers/reviews_controller_test.rb:42:in `block in <class:ReviewsControllerTest>'
=========ERROR HalalItemsControllerTest#test_should_destroy_halal_item (4.09s)
Minitest::UnexpectedError: DRb::DRbRemoteError: PG::ForeignKeyViolation: ERROR: update or delete on table "halal_items" violates foreign key constraint "fk_rails_0fa9986d41" on table "restaurants"
DETAIL: Key (id)=(1) is still referenced from table "restaurants".
(ActiveRecord::InvalidForeignKey)
app/controllers/halal_items_controller.rb:52:in `destroy'
test/controllers/halal_items_controller_test.rb:43:in `block (2 levels) in <class:HalalItemsControllerTest>'
test/controllers/halal_items_controller_test.rb:42:in `block in <class:HalalItemsControllerTest>'
==================================================|
Finished in 5.04433s
74 tests, 131 assertions, 0 failures, 2 errors, 0 skips
Here is what my main.yml looks like
name: Ruby
on:
push:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:12
ports: ['5432:5432']
env:
POSTGRES_DB: **redacted**
POSTGRES_PASSWORD: **redacted**
POSTGRES_USER: **redacted**
steps:
- name: Checkout repo
uses: actions/checkout#main
- name: Setup Ruby
uses: ruby/setup-ruby#v1
- name: Install dependencies
run: |
sudo apt-get -yqq install libpq-dev
gem install bundler
- name: Install gems
run: |
bundle install --jobs 4 --retry 3
- name: Setup database
env:
DATABASE_URL: **redacted**
RAILS_ENV: test
DISABLE_SPRING: 1
run: bundle exec rails db:prepare
- name: Run tests
env:
DATABASE_URL: **redacted**
RAILS_ENV: test
DISABLE_SPRING: 1
run: bundle exec rails test
Here are the models for the reviews, halal items, and restaurants (some of the relations are not relevant for this question)
app/models/review.rb
class Review < ApplicationRecord
belongs_to :restaurant
belongs_to :user
belongs_to :halal_item
end
app/models/halal_items.rb
class HalalItem < ApplicationRecord
belongs_to :restaurant
has_many :reviews, dependent: :nullify
end
app/models/restaurants.rb
class Restaurant < ApplicationRecord
has_many :reviews, dependent: :nullify
has_many :halal_items, dependent: :nullify
end
Here are the tests that are failing in my Github action, but not locally (with the associated controller)
/test/controllers/halal_items_controller_test.rb
test "should destroy halal_item" do
assert_difference("HalalItem.count", -1) do
delete halal_item_url(#halal_item)
end
assert_redirected_to halal_items_url
end
/app/controllers/halal_items_controller.rb
def destroy
#halal_item.destroy # this was line that the test was failing on
respond_to do |format|
format.html { redirect_to halal_items_url, notice: "Halal item was successfully destroyed." }
format.json { head :no_content }
end
end
/test/controllers/reviews_controller_test.rb
test "should destroy review" do
assert_difference("Review.count", -1) do
delete review_url(#review)
end
assert_redirected_to reviews_url
end
/app/controllers/reviews_controller.rb
def destroy
#review.destroy # this was line that the test was failing on
respond_to do |format|
format.html { redirect_to reviews_url, notice: "Review was successfully destroyed." }
format.json { head :no_content }
end
end
I have a rails app with docker setup. I have two containers and i have verified they are on the same network but still i am getting error
PG::ConnectionBad: connection to server at "192.168.160.2", port 5432 failed: Operation timed out Is the server running on that host and accepting TCP/IP connections?
I have changed network too, also removed all images and volumes but still no luck.
Everything was working fine until I composed down the containers and when i tried to run again make setup command i started facing the issue.
Here is my docker-compose.yml
x-toolbox-environment: &toolbox-environment
- PROJECT=frameworq
- APPLICATION=portal
- AWS_REGION
- AWS_DEFAULT_REGION
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
- AWS_SECURITY_TOKEN
- AWS_SESSION_EXPIRATION
x-web-volumes: &web-volumes
- .:/app:cached
- bundle_cache:/usr/local/bundle
- rails_cache:/app/tmp/cache:cached
- public_cache:/app/public:cached
x-web-environment: &web-environment
- RAILS_PORT=4000
- MAILER_FROM=noreply#frameworq.com
- APP_DOMAIN=lvh.me
services:
web:
build: .
volumes: *web-volumes
ports:
- '4000:4000'
- '3035:3035'
environment: *web-environment
command: bash -c "bundle exec foreman s"
links:
- db
db:
image: postgres:12
ports:
- 5432:5432
volumes:
- postgres:/var/lib/postgresql:cached
environment:
POSTGRES_HOST_AUTH_METHOD: trust
toolbox:
image: partos/ecs_toolbox:latest
environment: *toolbox-environment
volumes:
- .:/app:cached
- /var/run/docker.sock:/var/run/docker.sock
- .aws:/root/.aws
remote:
build: ./docker/remote
environment: *toolbox-environment
entrypoint: ""
volumes:
- ./docker/remote:/app:cached
- .aws:/root/.aws
volumes:
bundle_cache:
rails_cache:
postgres:
public_cache:
localstack_data:
driver: local
database.yml
# # SQL Server (2012 or higher required)
# #
# # Install the adapters and driver
# # gem install tiny_tds
# # gem install activerecord-sqlserver-adapter
# #
# # Ensure the activerecord adapter and db driver gems are defined in your Gemfile
# # gem 'tiny_tds'
# # gem 'activerecord-sqlserver-adapter'
# #
# default: &default
# adapter: sqlserver
# encoding: utf8
# azure: false
# mode: dblib
# host: localhost
# username: sa
# password: this-is-the-kms-test-database-p2ssw0rd
# azure: &azure
# adapter: sqlserver
# encoding: utf8
# azure: true
# mode: dblib
# host: <%= Rails.application.credentials.database_host %>
# username: <%= Rails.application.credentials.database_user %>
# password: <%= Rails.application.credentials.database_password %>
# #----------
# development:
# <<: *default
# database: kmsDev
# legacy:
# <<: *azure
# database: kmsprod
# # 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.
# test:
# <<: *default
# database: kmsTest
# production:
# <<: *azure
# database: <%= ENV['DATABASE_NAME'] %>
default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV["DB_HOST"] %>
database: <%= ENV["DB_NAME"] %>
username: <%= ENV["DB_USERNAME"] %>
password: <%= ENV["DB_PASSWORD"] %>
port: <%= ENV["DB_PORT"] %>
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
host: <%= ENV.fetch("PGHOST") { 'db' } %>
database: <%= ENV.fetch("POSTGRES_DB") { 'frameworq_development' } %>
username: <%= ENV.fetch("POSTGRES_USER") { 'postgres' } %>
password: <%= ENV.fetch("POSTGRES_PASSWORD") { '' } %>
port: <%= ENV.fetch("PGPORT") { 5432 } %>
# 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.
test:
<<: *default
database: frameworq_test
host: <%= ENV.fetch("PGHOST") { 'db' } %>
database: <%= ENV.fetch("POSTGRES_DB") { 'frameworq_test' } %>
username: <%= ENV.fetch("POSTGRES_USER") { 'postgres' } %>
password: <%= ENV.fetch("POSTGRES_PASSWORD") { '' } %>
port: <%= ENV.fetch("PGPORT") { 5432 } %>
qa:
<<: *default
staging:
<<: *default
production:
<<: *default
Dockerfile
FROM ruby:3.0.4-alpine
RUN apk --update add --no-cache build-base bash git vim curl postgresql-dev openssl-dev nodejs npm yarn tzdata less \
imagemagick postgresql-client gcompat chromium chromium-chromedriver
RUN mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle update --bundler
RUN bundle install --jobs 5
ADD . /app
RUN yarn install
RUN RAILS_SECRET_KEY_BASE=secret_key_base RAILS_ENV=production bundle exec rails assets:precompile apipie:cache
EXPOSE 5000
VOLUME ["/app/public", "/usr/local/bundle"]
CMD bash -c "bundle exec puma -C config/puma.rb"
Makefile
# DEVELOPMENT TARGETS
setup: destroy_shell build_shell prepare_shell up
destroy_shell:
docker-compose down -v
build_shell:
docker-compose build
prepare_shell:
docker-compose run --rm web bash -c "make prepare"
up:
docker-compose run --rm --service-ports --use-aliases web
shell:
docker-compose run --rm web bash
toolbox:
docker-compose run --rm toolbox bash
prepare_bundle:
bundle -j 4
yarn
prepare_db_first_time:
bundle exec rails db:create db:schema:load
prepare_db:
bundle exec rails db:migrate:with_data
prepare_test_db:
bundle exec rails db:create db:schema:load
prepare: prepare_bundle prepare_db_first_time
check: test_web fix_lint_web lint_front
lint_web:
bundle exec rubocop
fix_lint_web:
bundle exec rubocop -A
test_web:
RAILS_ENV=test bundle exec rails assets:precompile && bundle exec rails test
test_compiled_web:
RAILS_ENV=test bundle exec rails test
prepare_test_assets:
# We're not using webpacker now, importmaps instead
# cp -R public/packs public/packs-test
RAILS_ENV=test bundle exec rails assets:precompile
test_web_with_db: prepare_test_assets prepare_test_db test_compiled_web
lint_front:
# We're using importmaps, not yarn now
# yarn install && yarn run eslint --fix app/javascript/
generate_ts_routes:
docker-compose run --rm web bash -c 'bundle exec rails ts:routes'
db-reset:
bundle exec rails db:drop
bundle exec rails db:create
bundle exec rails db:schema:load
bundle exec rails db:migrate
bundle exec rails db:seed
eslint:
# We're using importmaps, not yarn now
# NODE_ENV=development yarn install
# yarn eslint --ext .js --ext .jsx /app/app/javascript/
tailwind:
docker-compose run --rm web bash -c 'bin/rails tailwindcss:watch'
guard:
docker-compose run --rm web bash -c 'bundle exec guard'
console:
docker-compose run --rm web bash -c 'rails c'
taildev:
docker-compose run --rm web bash -c 'tail -f log/development.log'
tailstaging:
docker-compose run --rm web bash -c 'tail -f log/staging.log'
Im attempting to bring up the backend on this Ruby on Rails app using docker but am getting the following error after I try to run the following commands on my ssh'd ec2 instance.
[ec2-user#ip-10-10-3-155 ~]$ docker run --rm \
>-it --name *****-db-setup \
>839014*****.dkr.ecr.us-east-1.amazonaws.com/*****-backend:dev-latest \
>bundle exec rake db:drop db:create db:migrate
rake aborted!
PG::ConnectionBad: could not translate host name "db"
to address: Name or service not known
/usr/local/bundle/gems/pg-0.21.0/lib/pg.rb:56:in `initialize'
/usr/local/bundle/gems/pg-0.21.0/lib/pg.rb:56:in `new'
/usr/local/bundle/gems/pg-0.21.0/lib/pg.rb:56:in `connect'
/usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:695:in
`connect'
/usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:220:in
`initialize'
/usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:38:in `new'
/usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:38:in `postgresql_connection' /myapp/app/models/admin.rb:7:in `include'
/myapp/app/models/admin.rb:7:in `<class:Admin>'
/myapp/app/models/admin.rb:3:in `<top (required)>'
/usr/local/bundle/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:476:in
`load' .......Tasks: TOP => db:drop =>
db:check_protected_environments => environment
this is my env file I created
$ export AWS_ACCESS_KEY_ID=***********
$ export AWS_SECRET_ACCESS_KEY=***************************
$ export AWS_DEFAULT_REGION=us-east-1
$ export DB_USER=*****
$ export DB_PASS=****test1
$ export DB_NAME=*****_backend
$ export DB_HOST=tf-*****-backend-2021051***********.c8o12l*****.us-east-1.rds.amazonaws.com
$ export DB_PORT=5432
Docker-compose.yml
version: '3'
services:
db:
image: postgres
backend:
build: backend
# https://stackoverflow.com/a/38732187/42559
entrypoint: /myapp/entrypoint.sh
command: bundle exec unicorn -p 3001
volumes:
- ./backend/:/myapp
ports:
- "3001:3001"
depends_on:
- db
env_file:
- ./.env
frontend:
build: frontend
command: yarn server
volumes:
- ./frontend/:/app
- /app/node_modules
ports:
- "3000:3000"
depends_on:
- backend
This is the Database.yml
default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV.fetch("DB_HOST") { "db" } %>
username: <%= ENV.fetch("DB_USER") { "postgres" } %>
port: <%= ENV["DB_PORT"] %>
password: <%= ENV["DB_PASS"] %>
# For details on connection pooling, see Rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: backend_development
test:
<<: *default
database: backend_test
production:
<<: *default
database: <%= ENV["DB_NAME"] %>
From my observations and attempts I believe it due to how the Docker-compose.yml and env file are interacting or something with my ruby server. I already have the backend image in the EC2 instance repository, now im trying to convert it to a container and bring up the backend. Thanks for any insight provided in advance !
locally all tests are passing but I cannot get rspec to run on Codeship:
Script:
bundle exec rake db:drop db:create db:migrate
DB=catalog bundle exec rake db:drop db:create db:migrate
DB=catalog bundle exec rails db:test:prepare
bundle exec rspec
Codeship error:
Failure/Error: establish_connection :"catalog_#{Rails.env}"
ActiveRecord::AdapterNotSpecified:
'catalog_test' database is not configured. Available: ["development", "test"]
ActiveRecord::ConnectionNotEstablished:
No connection pool with 'CatalogRecord' found.
database.yml:
.
.
.
catalog_development:
<<: *default
database: catalog_development
catalog_test:
<<: *default
database: catalog_test
CatalogRecord
class CatalogRecord < ActiveRecord::Base
self.abstract_class = true
establish_connection :"catalog_#{Rails.env}"
end
Rails projects on CodeShip Basic will have their database.yml file overwritten in order to connect to default databases. I would check out the linked documentation on re-asserting your own database.yml variant.
I installed nkallen's cache-money gem per the github readme. I run into RecordNotFound exceptions during my tests. If I comment out the contents of config/initializers/cache-money.rb, the tests run fine. My cache-money.rb file is identical to that on the github instructions.
Here is the contents of my config/memcached.yml:
development:
ttl: 604800
namespace: cache-#{RAILS_ENV}
sessions: false
debug: true
servers: localhost:11211
test:
ttl: 604800
namespace: cache-#{RAILS_ENV}
sessions: false
debug: true
servers: localhost:11211
production:
ttl: 604800
namespace: cache-#{RAILS_ENV}
sessions: false
debug: false
servers: localhost:11211
I can't find any other documentation on how to configuration or install cache-money. I'd appreciate any insight or help to debugging this. Thanks in advance!
I put my cache-money config into /config/initializers/cache_money.rb:
if RAILS_ENV != 'development'
require 'cache_money'
config = YAML.load(IO.read(File.join(RAILS_ROOT, "config", "memcached.yml")))[RAILS_ENV]
$memcache = MemCache.new(config)
$memcache.servers = config['servers']
$local = Cash::Local.new($memcache)
$lock = Cash::Lock.new($memcache)
$cache = Cash::Transactional.new($local, $lock)
class ActiveRecord::Base
is_cached :repository => $cache
end
else
# If we're in development mode, we don't want to
# deal with cacheing oddities, so let's overrite
# cache-money's #index method to do nothing...
class ActiveRecord::Base
def self.index(*args)
end
end
end
No other setup was necessary. This works great for me.