Skip to content

Commit

Permalink
devcontainer support for enroll/ma for arm based macs (#2468)
Browse files Browse the repository at this point in the history
* initial commit of devcontainer with cucumber support

* add brief readme

* rubocop

* had to create the gemset before using it

* fixed a missing slash bug on env, and adding a auto-restart for selenium chrome

* tweaking the healthcheck to be less agressive

* tweaking the healthcheck further, we don't want it to die at the middle

* workaround workspace mount
  • Loading branch information
polographer authored Oct 9, 2023
1 parent 840afca commit 47d0d86
Show file tree
Hide file tree
Showing 6 changed files with 397 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# # Note: You can use any Debian/Ubuntu based image you want.
# FROM mcr.microsoft.com/devcontainers/base:bullseye

ARG RUBY_VARIANT=2-bullseye

FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${RUBY_VARIANT}

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends libsodium23 python2.7 python-is-python2 yarn

ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

RUN su vscode -c '/bin/bash -l -c ". /etc/profile.d/rvm.sh && rvm install 2.6.5"'
RUN su vscode -c '/bin/bash -l -c ". /etc/profile.d/rvm.sh && rvm gemset create enroll"'
RUN su vscode -c '/bin/bash -l -c ". /etc/profile.d/rvm.sh && rvm use 2.6.5@enroll"'

USER vscode

# [Optional] Uncomment this section to install additional OS packages.

# [Optional] Uncomment this line to install additional gems.
# RUN sudo gem install bundler -v 1.17.3

# RUN gem update --system 3.3.26
47 changes: 47 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-outside-of-docker-compose
{
"name": "enroll/MA",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/enroll-ma/",
// "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",

// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
// "LOCAL_BASENAME": "${localWorkspaceFolderBasename}",
// "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
"LOCAL_WORKSPACE_FOLDER": "enroll-ma"
},

// "features": {
// // "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
// // "version": "20.10",
// // "enableNonRootDocker": "true",
// // "moby": "true"
// // },
// "ghcr.io/devcontainers/features/ruby:1": {"version":"2.6.5"},
// "ghcr.io/devcontainers/features/node:1": {"version":"14"},
// // "ghcr.io/devcontainers/features/python:1": {"version":"2.7.18"},
// "ghcr.io/devcontainers/features/common-utils:2": {"installZsh":"true", "configureZshAsDefaultShell":"true","upgradePackages":"true"}
// },
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
3000
],
"customizations": {
"vscode": {
"extensions": [
"GitHub.copilot",
"GitHub.vscode-pull-request-github"
]
}
},

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "docker --version",
// "postCreateCommand": "rvm install 2.6.5 && rvm use 2.6.5 && bundle install"
// "postCreateCommand": "cd $PWD"
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
102 changes: 102 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
version: '3.4'

services:
app:
platform: linux/amd64
build:
context: .
dockerfile: Dockerfile
args:
BUNDLER_VERSION_OVERRIDE: '2.0.1'
NODE_VERSION: '12'
RUBY_VARIANT: '2.6-bullseye'
RVM_OVERRIDE: '2.6.5'

volumes:
- /var/run/docker.sock:/var/run/docker-host.sock
# - ../../:/workspaces
- ../:/workspaces/enroll-ma
- ${PWD}/.devcontainer/patches/mongoid-enroll.yml:/workspaces/enroll-ma/config/mongoid.yml:ro
- ${PWD}/.devcontainer/patches/cucumber_env.rb:/workspaces/enroll-ma/features/support/env.rb:ro
command: sleep infinity

# Uncomment the next four lines if you will use a ptrace-based debuggers like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined

# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)
# chrome:
# image: seleniarm/node-chromium:latest
# shm_size: 2gb
# depends_on:
# - selenium-hub
# environment:
# - SE_EVENT_BUS_HOST=selenium-hub
# - SE_EVENT_BUS_PUBLISH_PORT=4442
# - SE_EVENT_BUS_SUBSCRIBE_PORT=4443

# selenium-hub:
# image: seleniarm/hub:latest
# container_name: selenium-hub
# ports:
# - "4442:4442"
# - "4443:4443"
# - "4444:4444"

selenium-chrome:
hostname: selenium-chrome
image: seleniarm/standalone-chromium:latest
shm_size: 2gb
labels:
- "autoheal=true"
ports:
- "4444:4444"
- "7900:7900"
healthcheck:
test: '/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444'
interval: 120s
timeout: 60s
retries: 30
# start_period: 20s

autoheal:
image: willfarrell/autoheal:latest
tty: true
restart: unless-stopped
environment:
- AUTOHEAL_INTERVAL=120
- AUTOHEAL_START_PERIOD=300
- AUTOHEAL_DEFAULT_STOP_TIMEOUT=10
volumes:
- /var/run/docker.sock:/var/run/docker.sock

redis:
# hostname: redis
image: redis:7.0
ports:
- 6379
environment:
- ALLOW_EMPTY_PASSWORD=yes
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
mongodb:
image: mongo:4.2
hostname: mongodb
# mem_limit: 4000m #trying to replicate mongo memory on prod
volumes:
- mongodb:/data/db
- mongodb_config:/data/configdb
ports:
- 27017:27017
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongo mongodb:27017/test --quiet
# interval: 1s
# timeout: 5s
# retries: 30
# start_period: 20s
volumes:
mongodb:
mongodb_config:
119 changes: 119 additions & 0 deletions .devcontainer/patches/cucumber_env.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true

# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
# It is recommended to regenerate this file in the future when you upgrade to a
# newer version of cucumber-rails. Consider adding your own code to a new file
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
# files.
require_relative '../../spec/ivl_helper'

require 'selenium-webdriver'
require 'cucumber/rails'
require 'email_spec/cucumber'
require 'rspec/expectations'
require 'capybara/cucumber'
require 'capybara-screenshot/cucumber'
require 'cucumber/rspec/doubles'

Dir[File.expand_path("#{Rails.root}/lib/test/**/*.rb")].each { |f| load f }
require File.expand_path("#{File.dirname(__FILE__)}/../../config/environment")
require "rspec/rails"

# Capybara defaults to CSS3 selectors rather than XPath.
# If you'd prefer to use XPath, just uncomment this line and adjust any
# selectors in your step definitions to use the XPath syntax.
# Capybara.default_selector = :xpath

# By default, any exception happening in your Rails application will bubble up
# to Cucumber so that your scenario will fail. This is a different from how
# your application behaves in the production environment, where an error page will
# be rendered instead.
#
# Sometimes we want to override this default behaviour and allow Rails to rescue
# exceptions and display an error page (just like when the app is running in production).
# Typical scenarios where you want to do this is when you test your error pages.
# There are two ways to allow Rails to rescue exceptions:
#
# 1) Tag your scenario (or feature) with @allow-rescue
#
# 2) Set the value below to true. Beware that doing this globally is not
# recommended as it will mask a lot of errors for you!
#
ActionController::Base.allow_rescue = false

# Remove/comment out the lines below if your app doesn't have a database.
# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
begin
load "#{Rails.root}/db/seedfiles/english_translations_seed.rb"
DatabaseCleaner.strategy = :truncation, {:except => %w[translations]}
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end

# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios.
# See the DatabaseCleaner documentation for details. Example:
#
# Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do
# # { :except => [:widgets] } may not do what you expect here
# # as Cucumber::Rails::Database.javascript_strategy overrides
# # this setting.
# DatabaseCleaner.strategy = :truncation
# end
#
# Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do
# DatabaseCleaner.strategy = :transaction
# end
#

# Possible values are :truncation and :transaction
# The :transaction strategy is faster, but might give you threading problems.
# See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature
Cucumber::Rails::Database.javascript_strategy = :truncation

Capybara::Screenshot.webkit_options = { width: 2280, height: 1800 }
Capybara::Screenshot.prune_strategy = :keep_last_run
# Webdrivers.cache_time = 86_400

Capybara::Screenshot.register_driver(:selenium_chrome_custom) do |driver, path|
driver.browser.save_screenshot(path)
end

Capybara.register_driver :selenium_chrome_custom do |app|
options = Selenium::WebDriver::Chrome::Options.new
# options.headless!
options.add_argument("no-sandbox")
options.add_argument("--window-size=1024,768")
options.add_argument("--disable-dev-shm-usage")

# client = Selenium::WebDriver::Remote::Http::Default.new
# client.open_timeout = 120 # instead of the default 60
# client.read_timeout = 120 # instead of the default 60

Capybara::Selenium::Driver.new(app,
browser: :chrome,
url: "http://selenium-chrome:4444/wd/hub",
options: options)
end

selenium_app_host = ENV.fetch("SELENIUM_APP_HOST") do
Socket.ip_address_list
.find(&:ipv4_private?)
.ip_address
end

Capybara.configure do |config|
config.server = :puma, { Silent: true }
config.server_host = selenium_app_host
config.server_port = 4000
end


Capybara.default_driver = :selenium_chrome_custom
# Capybara.use_default_driver
# Capybara.current_driver = :selenium_chrome_custom

# https://thurlow.io/ruby/2020/11/06/remote-selenium-webdriver-servers-with-rails-capybara-and-rspec.html
puts "--------------------------------------------------------------------"
puts "the env.rb for cucumber was hacked by docker for running on M1 macs "
puts "--------------------------------------------------------------------"
puts "--------------------------------------------------------------------"
84 changes: 84 additions & 0 deletions .devcontainer/patches/mongoid-enroll.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
development:
clients:
# Defines the default session. (required)
default: &default_development
# Defines the name of the default database that Mongoid can connect to.
# (required).
database: mhc_enroll_development
# Provides the hosts the default session can connect to. Must be an array
# of host:port pairs. (required)
hosts:
- mongodb:27017
options:
# Change the default write concern. (default = { w: 1 })
# write:
# w: 1

# Change the default consistency model to primary, secondary.
# 'secondary' will send reads to secondaries, 'primary' sends everything
# to master. (default: primary)
# read: secondary_preferred

# How many times Moped should attempt to retry an operation after
# failure. (default: The number of nodes in the cluster)
# max_retries: 20

# The time in seconds that Moped should wait before retrying an
# operation on failure. (default: 0.25)
# retry_interval: 0.25

rocketjob:
<<: *default_development
rocketjob_slices:
<<: *default_development

# Configure Mongoid specific options. (optional)
options:
# Includes the root model name in json serialization. (default: false)
# include_root_in_json: false

# Include the _type field in serializaion. (default: false)
# include_type_for_serialization: false

# Preload all models in development, needed when models use
# inheritance. (default: false)
# preload_models: false

# Protect id and type from mass assignment. (default: true)
# protect_sensitive_fields: true

# Raise an error when performing a #find and the document is not found.
# (default: true)
# raise_not_found_error: true

# Raise an error when defining a scope with the same name as an
# existing method. (default: false)
# scope_overwrite_exception: false

# Use Active Support's time zone in conversions. (default: true)
# use_activesupport_time_zone: true

# Ensure all times are UTC in the app side. (default: false)
# use_utc: false
test:
clients:
default:
database: mhc_enroll_test<%= ENV['TEST_ENV_NUMBER'] %>
hosts:
- mongodb:27017
options:
# In the test environment we lower the retries and retry interval to
# low amounts for fast failures.
max_retries: 1
retry_interval: 0
production:
clients:
default:
database: mhc_enroll_production
hosts:
- mongodb:27017
options:
# In the test environment we lower the retries and retry interval to
# low amounts for fast failures.
max_retries: 1
retry_interval: 0
Loading

0 comments on commit 47d0d86

Please sign in to comment.