I'm creating a personal project with Ruby on Rails.
I'm trying to create a CI with Github Actions Capybara Selenium Service. Why selenium service? To make it closer to the project's docker-compose.
First, this is my workflow file:
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14.4
ports:
- 5432:5432
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
selenium:
image: selenium/standalone-chrome:3.141.59
ports:
- 4444:4444
steps:
-
name: Check out repository code
uses: actions/checkout@v3
-
name: 'Create web docker image'
run: docker build -t web . --target new_release
-
name: 'Create database'
run: docker run --env-file .docker/env_files/.env.ci --network="host" web bin/rails db:create db:migrate
-
name: 'Run unit tests'
run: docker run --env-file .docker/env_files/.env.ci --network="host" web bin/rails test
-
name: 'Run system tests'
run: docker run --env-file .docker/env_files/.env.ci --network="host" web bin/rails test:system
On the last step this error happens:
Selenium::WebDriver::Error::UnknownError: unknown error: net::ERR_CONNECTION_REFUSED
My interpretation is that the selenium service is unable to connect with the capybara server. So, let's talk about the capybara configuration of the project:
# frozen_string_literal: true
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
Capybara.register_driver(:chrome_remote) do |app|
Capybara::Selenium::Driver.new(
app,
browser: :remote,
url: ENV.fetch("SELENIUM_URL"),
capabilities: Selenium::WebDriver::Remote::Capabilities.chrome
)
end
Capybara.run_server = true
Capybara.server = :puma, { Silent: true }
Capybara.server_host = ENV.fetch("CAPYBARA_SERVER_HOST")
Capybara.server_port = ENV.fetch("CAPYBARA_SERVER_PORT")
Capybara.default_driver = :chrome_remote
Capybara.javascript_driver = :chrome_remote
Capybara.save_path = Rails.root.join("tmp/capybara")
driven_by :chrome_remote, using: :chrome, screen_size: [1400, 1400]
include FactoryBot::Syntax::Methods
end
And finally, the env file used on the ci:
CAPYBARA_SERVER_HOST=localhost
CAPYBARA_SERVER_PORT=4000
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=localhost
RAILS_ENV=test
SELENIUM_URL=http://localhost:4444/wd/hub
I tried not using --network="host", using the name of the services, but using that configuration I was unable to pass "Create database" step. I'm wondering why is not working, I can see the capybara creating the server using my environment variables:
Capybara starting Puma...
* Version 5.6.2 , codename: Birdie's Version
* Min threads: 0, max threads: 4
* Listening on http://127.0.0.1:4000
* Listening on http://[::1]:4000
But I'm lost, not sure what the connection is being refused. In the local environment, the tests pass perfectly. What do you think?
CodePudding user response:
Instead of using the services docker, I decided to use docker-compose. The file that did the trick:
version: "3.7"
services:
db:
image: postgres:14.4
ports:
- 5432:5432
env_file:
- ./.docker/env_files/.env
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- ./.docker/volumes/postgres_data:/var/lib/postgresql/data
web:
image: test
env_file:
- ./.docker/env_files/.env
build:
context: .
depends_on:
db:
condition: service_healthy
links:
- db
ports:
- 3000:3000
volumes:
- .:/opt/test:cached
stdin_open: true
tty: true
livereload:
image: test
depends_on:
- web
ports:
- 35729:35729
command: ["bundle", "exec", "guard", "-i"]
env_file:
- ./.docker/env_files/.env
volumes:
- .:/opt/test:cached
tailwindcsswatcher:
image: test
depends_on:
- web
ports:
- 3035:3035
command: ["bin/rails", "tailwindcss:watch"]
env_file:
- ./.docker/env_files/.env
volumes:
- .:/opt/test:cached
tty: true
selenium:
image: selenium/standalone-chrome:3.141.59
ports:
- 4444:4444
volumes:
postgres_data:
Now the ci.yml using the docker-compose:
name: CI
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
-
name: Check out repository code
uses: actions/checkout@v3
-
name: 'Create docker-compose file'
run: cp .docker/docker-compose.dev.yml docker-compose.yml
-
name: 'Create env file'
run: cp .docker/env_files/.env.dev .docker/env_files/.env
-
name: Build web container
run: docker-compose build web selenium
-
name: 'Create database'
run: docker-compose run --rm web bin/rails db:create db:migrate
-
name: 'Start container'
run: docker-compose up -d web selenium
-
name: 'Run unit tests'
run: docker-compose exec -T web bin/rails test
-
name: 'Run system tests'
run: docker-compose exec -T web bin/rails test:system