diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da5c4ec..be0ea06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,6 @@ jobs: matrix: ruby-version: ['2.7.5'] experimental: [false] - include: - - ruby-version: 3.0.3 - experimental: true - steps: - name: Pin chrome uses: abhi1693/setup-browser@v0.3.4 @@ -63,7 +59,7 @@ jobs: bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Update rubygems run: | - gem update --system + gem install rubygems-update -v 3.4.22 gem install bundler:2.3.15 - name: Set up JDK 1.8 @@ -102,7 +98,7 @@ jobs: - name: Setup hyrax test environment run: | bundle exec rake hydra:test_server & - sleep 150 + sleep 180 # - name: Rubbocop # run: | # bundle exec rubocop diff --git a/.gitignore b/.gitignore index 4f48b30..fb12b9b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,7 @@ config/java.yml # Spring stuff bin/rspec bin/spring + +# env files +.env +coverage/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..74255f9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +FROM ruby:2.7.5 + +ARG RAILS_ENV +ARG SECRET_KEY_BASE + +# Necessary for bundler to operate properly +ENV LANG C.UTF-8 +ENV LC_ALL C.UTF-8 + +# add nodejs and yarn dependencies for the frontend +# RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \ +# curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ +# echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list + +# --allow-unauthenticated needed for yarn package +RUN apt-get update && apt-get upgrade -y && \ + apt-get install --no-install-recommends -y ca-certificates nodejs \ + build-essential libpq-dev libreoffice unzip ghostscript vim \ + ffmpeg \ + clamav-freshclam clamav-daemon libclamav-dev \ + libqt5webkit5-dev xvfb xauth default-jre-headless --fix-missing --allow-unauthenticated + +RUN apt-get install chromium -y + +# Increase stack size limit to help working with large works +ENV RUBY_THREAD_MACHINE_STACK_SIZE 8388608 + +RUN gem install rubygems-update -v 3.4.22 + +RUN mkdir /data +WORKDIR /data + +# Pre-install gems so we aren't reinstalling all the gems when literally any +# filesystem change happens +ADD Gemfile /data +ADD Gemfile.lock /data +RUN mkdir /data/build +ADD ./build/install_gems.sh /data/build +RUN ./build/install_gems.sh +RUN mkdir /data/pdfs + + +# Add the application code +ADD . /data + +# install node dependencies, after there are some included +#RUN yarn install diff --git a/Gemfile b/Gemfile index 0c9076e..cfadb94 100644 --- a/Gemfile +++ b/Gemfile @@ -15,8 +15,7 @@ gem 'puma', '~> 4.3' gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' -# See https://github.com/rails/execjs#readme for more supported runtimes -gem 'therubyracer', platforms: :ruby + # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks @@ -71,6 +70,7 @@ group :test do gem 'ffaker' gem 'ladle' gem 'capybara', '>= 2.15' + gem 'capybara-screenshot' gem 'selenium-webdriver' gem 'webdrivers', '~> 4.0', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index 2286373..9f6377c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,6 +164,9 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) + capybara-screenshot (1.0.26) + capybara (>= 1.0, < 4) + launchy carrierwave (1.3.2) activemodel (>= 4.0.0) activesupport (>= 4.0.0) @@ -486,6 +489,8 @@ GEM kaminari (~> 1.0) ladle (1.0.1) open4 (~> 1.0) + launchy (2.5.2) + addressable (~> 2.8) ld-patch (3.1.2) ebnf (~> 2.1) rdf (~> 3.1) @@ -508,7 +513,6 @@ GEM rdf (~> 3.0) legato (0.7.0) multi_json - libv8 (3.16.14.19) link_header (0.0.8) linkeddata (3.1.1) equivalent-xml (~> 0.6) @@ -711,7 +715,6 @@ GEM redis (>= 3.0.4) redlock (1.2.1) redis (>= 3.0.0, < 5.0) - ref (2.0.0) regexp_parser (2.0.3) representable (3.0.4) declarative (< 0.1.0) @@ -845,9 +848,6 @@ GEM sxp (1.1.0) rdf (~> 3.1) temple (0.8.2) - therubyracer (0.12.3) - libv8 (~> 3.16.14.15) - ref thor (1.2.1) thread_safe (0.3.6) tilt (2.0.10) @@ -894,6 +894,7 @@ DEPENDENCIES bootstrap-sass (~> 3.0) byebug capybara (>= 2.15) + capybara-screenshot coffee-rails (~> 4.2) devise devise-guests (~> 0.6) @@ -924,7 +925,6 @@ DEPENDENCIES simplecov-lcov (~> 0.8.0) solr_wrapper (~> 2.1.0) sqlite3 (~> 1.3.6) - therubyracer tufts-curation! turbolinks (~> 5) twitter-typeahead-rails (= 0.11.1.pre.corejavascript) diff --git a/README.md b/README.md index 7db80e4..7781e9f 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,20 @@ -# README +# Trove -This README would normally document whatever steps are necessary to get the -application up and running. +## About -Things you may want to cover: +Collections in Trove are available for use by Tufts University faculty and students, for teaching and research purposes. Collections will include images selected by faculty for teaching Art History courses. Faculty and students can create personal collections of images selected from those available in Trove. -* Ruby version -* System dependencies +## Running Test Locally -* Configuration +* MIRA test docker environment should be running already -* Database creation -* Database initialization +``` +docker-compose up test +docker exec -it trove_test_1 /bin/bash +xvfb-run -a bundle exec rake spec SPEC_OPTS="--tag ~noci_local" -* How to run the test suite +``` -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... +There are two testing tags, noci and noci_local some tests aren't working in the dockerized environment we'll re-address when we move to Ruby 3 diff --git a/build/entrypoint.sh b/build/entrypoint.sh new file mode 100755 index 0000000..6871a84 --- /dev/null +++ b/build/entrypoint.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +echo "Building ${RAILS_ENV}" + +# Remove previous servers pid +rm -f tmp/puma.pid + +# Guarantee gems are installed in case docker image is outdated +./build/install_gems.sh + +# Do not auto-migrate for production or staging environments +if [ "${RAILS_ENV}" != 'production' ] && [ "${RAILS_ENV}" != 'staging' ]; then + ./build/validate_migrated.sh +fi + +echo "Migration Validated" \ No newline at end of file diff --git a/build/install_gems.sh b/build/install_gems.sh new file mode 100755 index 0000000..ac98d3e --- /dev/null +++ b/build/install_gems.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "${RAILS_ENV}" = 'production' ] || [ "${RAILS_ENV}" = 'staging' ]; then + echo "Bundle install without development or test gems." + bundle install --without development test +else + bundle install --without production +fi diff --git a/build/validate_migrated.sh b/build/validate_migrated.sh new file mode 100755 index 0000000..e046f78 --- /dev/null +++ b/build/validate_migrated.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +if [ "${RAILS_ENV}" = 'production' ] || [ "${RAILS_ENV}" = 'staging' ]; then + echo "Cannot auto-migrate ${RAILS_ENV} database, exiting" + exit 1 +fi + +echo "Checking ${RAILS_ENV} database migration status and auto-migrating if necessary." +# If the migration status can't be read or is not fully migrated +# then update the database with latest migrations +if bundle exec rails db:migrate:status &> /dev/null; then + bundle exec rails db:migrate +fi +echo "Done checking ${RAILS_ENV} database migration status" \ No newline at end of file diff --git a/config/blacklight.yml.sample b/config/blacklight.yml.sample index 9ea3254..73e68c0 100644 --- a/config/blacklight.yml.sample +++ b/config/blacklight.yml.sample @@ -4,6 +4,3 @@ development: test: &test adapter: solr url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_TEST_PORT', 8985)}/solr/hydra-test" %> -production: - adapter: solr - url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:8983/solr/blacklight-core" %> diff --git a/config/database.yml.sample b/config/database.yml.sample index bbea42f..64bf575 100644 --- a/config/database.yml.sample +++ b/config/database.yml.sample @@ -1,31 +1,27 @@ -# SQLite version 3.x -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem 'sqlite3' -# default: &default adapter: mysql2 - encoding: utf8 - reconnect: false - pool: 20 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 + database: <%= ENV['DB_NAME'] %> + username: <%= ENV['DB_USERNAME'] %> + password: <%= ENV['DB_PASSWORD'] %> + host: <%= ENV['DB_HOST'] %> + port: <%= ENV['DB_PORT'] %> development: <<: *default - database: trove + database: <%= ENV.fetch('DB_NAME', 'tdl_on_hyrax') %> # 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: - adapter: mysql2 - database: trove_test - user: root - password: root - pool: 5 - timeout: 5000 + <<: *default + database: <%= ENV.fetch('DB_NAME', 'tdl_on_hyrax_test') %> + username: <%= ENV.fetch('DB_USERNAME', 'root') %> + password: <%= ENV.fetch('DB_PASSWORD', 'root') %> production: <<: *default - database: trove + encoding: unicode + pool: 50 diff --git a/config/env.apple-silicon.conf b/config/env.apple-silicon.conf new file mode 100644 index 0000000..4926778 --- /dev/null +++ b/config/env.apple-silicon.conf @@ -0,0 +1,10 @@ +#COMMON SETTINGS + +SERVER_PORTS="4000:4000" +SERVER_EXPOSE="4000" +TEST_PORTS="4101:4001" +TEST_EXPOSE="4111" + +# APPLE SILICONE SETTINGS +SELENIUM_IMAGE="seleniarm/standalone-chromium" +SELENIUM_PLATFORM="linux/arm64" \ No newline at end of file diff --git a/config/env.intel.conf b/config/env.intel.conf new file mode 100644 index 0000000..0b9c646 --- /dev/null +++ b/config/env.intel.conf @@ -0,0 +1,10 @@ +#COMMON SETTINGS + +SERVER_PORTS="4000:4000" +SERVER_EXPOSE="4000" +TEST_PORTS="4101:4001" +TEST_EXPOSE="4111" + +# INTEL SETTINGS +SELENIUM_IMAGE="selenium/standalone-chrome:3.141" +SELENIUM_PLATFORM="linux/amd64" \ No newline at end of file diff --git a/config/fedora.yml.sample b/config/fedora.yml.sample index 10c488e..5baa16c 100644 --- a/config/fedora.yml.sample +++ b/config/fedora.yml.sample @@ -1,15 +1,10 @@ development: user: fedoraAdmin password: fedoraAdmin - url: http://127.0.0.1:<%= ENV['FCREPO_DEVELOPMENT_PORT'] || 8984 %>/rest + url: <%= ENV['FEDORA_URL'] || "http://127.0.0.1:#{ENV.fetch('FCREPO_DEVELOPMENT_PORT', 8984)}/rest" %> base_path: /dev test: user: fedoraAdmin password: fedoraAdmin - url: http://127.0.0.1:<%= ENV['FCREPO_TEST_PORT'] || 8986 %>/rest + url: <%= ENV['FEDORA_URL'] || "http://127.0.0.1:#{ENV.fetch('FCREPO_TEST_PORT', 8986)}/rest" %> base_path: /test -production: - user: fedoraAdmin - password: fedoraAdmin - url: http://127.0.0.1:8983/fedora/rest - base_path: /prod diff --git a/config/ldap.yml.sample b/config/ldap.yml.sample index 8937728..3427a83 100644 --- a/config/ldap.yml.sample +++ b/config/ldap.yml.sample @@ -1,7 +1,6 @@ -## Authorizations -# Uncomment out the merging for each environment that you'd like to include. +# Uncomment out the merging for each enviornment that you'd like to include. # You can also just copy and paste the tree (do not include the "authorizations") to each -# environment if you need something different per enviornment. +# enviornment if you need something different per enviornment. authorizations: &AUTHORIZATIONS group_base: ou=groups,dc=test,dc=com ## Requires config.ldap_check_group_membership in devise.rb be true @@ -18,18 +17,17 @@ authorizations: &AUTHORIZATIONS objectClass: inetOrgPerson authorizationRole: postsAdmin -## Environment +## Enviornments development: - host: localhost + host: ldap.tufts.edu port: 636 - attribute: cn - base: ou=people,dc=test,dc=com - admin_user: cn=admin,dc=test,dc=com - admin_password: admin_password - ssl: false + attribute: uid + base: dc=tufts, dc=edu + admin_user: some_user + admin_password: some_password + ssl: true # <<: *AUTHORIZATIONS - test: host: localhost port: 3897 @@ -39,7 +37,6 @@ test: admin_password: admin_password ssl: false # <<: *AUTHORIZATIONS - production: host: localhost port: 636 diff --git a/config/secrets.yml.sample b/config/secrets.yml.sample index d33f04e..fd0e466 100644 --- a/config/secrets.yml.sample +++ b/config/secrets.yml.sample @@ -10,23 +10,13 @@ # Make sure the secrets in this file are kept private # if you're sharing your code publicly. -# Shared secrets are available across all environments. - -# shared: -# api_key: a1B2c3D4e5F6 - -# Environmental secrets are only available for that specific environment. - development: - secret_key_base: 2587324607eaeace6e44616ed90077357916024c7504fd2196e511cfc29dff863696d68991f90251bb994e5fe7d682d220d3c0c8b83e666c50c36d9d84717ed4 + secret_key_base: e1da67e2e2ce9800d7445cb839c27a9ac677bca7521f01cadb9716d75ceffcfce23d377aeea5a3e741a52c3b2349f24406d61784916a6b22c3a07a5589f6269c test: - secret_key_base: fb0e5387401e0aef4cd1fcd1f622fc7f1be6c756ebc13dd81f699694aaa843428f481552749623b87fb9429f8ee362080a51cf79ed17d24562e1b4cc12e41531 - -# Do not keep production secrets in the unencrypted secrets file. -# Instead, either read values from the environment. -# Or, use `bin/rails secrets:setup` to configure encrypted secrets -# and move the `production:` environment over there. + secret_key_base: 7f0c89448adf678e61e8e3368014925aed02975179a0be37b91a9cee0226f0fde6e19010163f8e47187726b560ef7bed2a6d7723b9509b135914fe0e51b9e79f +# Do not keep production secrets in the repository, +# instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/solr.yml.sample b/config/solr.yml.sample index 4cb3523..84fdd2f 100644 --- a/config/solr.yml.sample +++ b/config/solr.yml.sample @@ -1,7 +1,7 @@ # This is a sample config file that points to a solr server for each environment development: - url: http://127.0.0.1:<%= ENV['SOLR_TEST_PORT'] || 8983 %>/solr/hydra-development + url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_DEVELOPMENT_PORT', 8983)}/solr/hydra-development" %> test: - url: http://127.0.0.1:<%= ENV['SOLR_TEST_PORT'] || 8985 %>/solr/hydra-test + url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_TEST_PORT', 8985)}/solr/hydra-test" %> production: - url: http://your.production.server:8080/bl_solr/core0 + url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:8983/solr/nurax" %> diff --git a/config/tufts.yml.sample b/config/tufts.yml.sample index 0d30c02..f292b96 100644 --- a/config/tufts.yml.sample +++ b/config/tufts.yml.sample @@ -1,13 +1,13 @@ development: - export_path: '' + export_path: '/usr/local/hydra/mira-data/exports' ldap: name: email: active: test: - export_path: '' + export_path: '/data/pdfs' production: - export_path: '' + export_path: '/usr/local/hydra/mira-data/exports' ldap: name: email: diff --git a/config/tufts_export.yml.sample b/config/tufts_export.yml.sample deleted file mode 100644 index a15fbad..0000000 --- a/config/tufts_export.yml.sample +++ /dev/null @@ -1,6 +0,0 @@ -development: - export_path: '' -test: - export_path: '' -production: - export_path: '/usr/local/hydra/mira-data/exports' diff --git a/db/schema.rb b/db/schema.rb index 20f48d9..0259527 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20200114030718) do +ActiveRecord::Schema.define(version: 2020_01_14_030718) do - create_table "bookmarks", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "bookmarks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "user_id", null: false t.string "user_type" t.string "document_id" @@ -24,7 +24,7 @@ t.index ["user_id"], name: "index_bookmarks_on_user_id" end - create_table "checksum_audit_logs", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "checksum_audit_logs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "file_set_id" t.string "file_id" t.string "checked_uri" @@ -37,7 +37,7 @@ t.index ["file_set_id", "file_id"], name: "by_file_set_id_and_file_id" end - create_table "collection_branding_infos", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "collection_branding_infos", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "collection_id" t.string "role" t.string "local_path" @@ -49,8 +49,8 @@ t.datetime "updated_at", null: false end - create_table "collection_type_participants", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" do |t| - t.integer "hyrax_collection_type_id" + create_table "collection_type_participants", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| + t.bigint "hyrax_collection_type_id" t.string "agent_type" t.string "agent_id" t.string "access" @@ -59,7 +59,7 @@ t.index ["hyrax_collection_type_id"], name: "hyrax_collection_type_id" end - create_table "content_blocks", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "content_blocks", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name" t.text "value", limit: 16777215 t.datetime "created_at", null: false @@ -67,7 +67,7 @@ t.string "external_key" end - create_table "curation_concerns_operations", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "curation_concerns_operations", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "status" t.string "operation_type" t.string "job_class" @@ -88,7 +88,7 @@ t.index ["user_id"], name: "index_curation_concerns_operations_on_user_id" end - create_table "featured_works", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "featured_works", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "order", default: 5 t.string "work_id" t.datetime "created_at", null: false @@ -97,7 +97,7 @@ t.index ["work_id"], name: "index_featured_works_on_work_id" end - create_table "file_download_stats", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "file_download_stats", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.datetime "date" t.integer "downloads" t.string "file_id" @@ -108,7 +108,7 @@ t.index ["user_id"], name: "index_file_download_stats_on_user_id" end - create_table "file_view_stats", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "file_view_stats", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.datetime "date" t.integer "views" t.string "file_id" @@ -119,7 +119,7 @@ t.index ["user_id"], name: "index_file_view_stats_on_user_id" end - create_table "hyrax_collection_types", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" do |t| + create_table "hyrax_collection_types", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "title" t.text "description" t.string "machine_id" @@ -136,14 +136,14 @@ t.index ["machine_id"], name: "index_hyrax_collection_types_on_machine_id", unique: true end - create_table "hyrax_features", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "hyrax_features", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "key", null: false t.boolean "enabled", default: false, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "job_io_wrappers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "job_io_wrappers", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.bigint "user_id" t.bigint "uploaded_file_id" t.string "file_set_id" @@ -157,7 +157,7 @@ t.index ["user_id"], name: "index_job_io_wrappers_on_user_id" end - create_table "mailboxer_conversation_opt_outs", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "mailboxer_conversation_opt_outs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "unsubscriber_type" t.integer "unsubscriber_id" t.integer "conversation_id" @@ -165,13 +165,13 @@ t.index ["unsubscriber_id", "unsubscriber_type"], name: "index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type" end - create_table "mailboxer_conversations", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "mailboxer_conversations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "subject", default: "" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "mailboxer_notifications", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "mailboxer_notifications", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "type" t.text "body" t.string "subject", default: "" @@ -194,7 +194,7 @@ t.index ["type"], name: "index_mailboxer_notifications_on_type" end - create_table "mailboxer_receipts", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "mailboxer_receipts", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "receiver_type" t.integer "receiver_id" t.integer "notification_id", null: false @@ -211,7 +211,7 @@ t.index ["receiver_id", "receiver_type"], name: "index_mailboxer_receipts_on_receiver_id_and_receiver_type" end - create_table "minter_states", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "minter_states", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "namespace", default: "default", null: false t.string "template", null: false t.text "counters" @@ -222,7 +222,7 @@ t.index ["namespace"], name: "index_minter_states_on_namespace", unique: true end - create_table "permission_template_accesses", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "permission_template_accesses", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.bigint "permission_template_id" t.string "agent_type" t.string "agent_id" @@ -233,7 +233,7 @@ t.index ["permission_template_id"], name: "index_permission_template_accesses_on_permission_template_id" end - create_table "permission_templates", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "permission_templates", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "source_id" t.string "visibility" t.datetime "created_at", null: false @@ -243,7 +243,7 @@ t.index ["source_id"], name: "index_permission_templates_on_source_id", unique: true end - create_table "proxy_deposit_requests", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "proxy_deposit_requests", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "work_id", null: false t.bigint "sending_user_id", null: false t.bigint "receiving_user_id", null: false @@ -257,7 +257,7 @@ t.index ["sending_user_id"], name: "index_proxy_deposit_requests_on_sending_user_id" end - create_table "proxy_deposit_rights", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "proxy_deposit_rights", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.bigint "grantor_id" t.bigint "grantee_id" t.datetime "created_at", null: false @@ -266,11 +266,11 @@ t.index ["grantor_id"], name: "index_proxy_deposit_rights_on_grantor_id" end - create_table "roles", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name" end - create_table "roles_users", id: false, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "role_id" t.integer "user_id" t.index ["role_id", "user_id"], name: "index_roles_users_on_role_id_and_user_id" @@ -279,7 +279,7 @@ t.index ["user_id"], name: "index_roles_users_on_user_id" end - create_table "searches", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "searches", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.binary "query_params" t.integer "user_id" t.string "user_type" @@ -288,7 +288,7 @@ t.index ["user_id"], name: "index_searches_on_user_id" end - create_table "single_use_links", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "single_use_links", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "downloadKey" t.string "path" t.string "itemId" @@ -297,7 +297,7 @@ t.datetime "updated_at", null: false end - create_table "sipity_agents", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_agents", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "proxy_for_id", null: false t.string "proxy_for_type", null: false t.datetime "created_at", null: false @@ -305,7 +305,7 @@ t.index ["proxy_for_id", "proxy_for_type"], name: "sipity_agents_proxy_for", unique: true end - create_table "sipity_comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_comments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "entity_id", null: false t.integer "agent_id", null: false t.text "comment" @@ -316,7 +316,7 @@ t.index ["entity_id"], name: "index_sipity_comments_on_entity_id" end - create_table "sipity_entities", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_entities", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "proxy_for_global_id", null: false t.integer "workflow_id", null: false t.integer "workflow_state_id" @@ -327,7 +327,7 @@ t.index ["workflow_state_id"], name: "index_sipity_entities_on_workflow_state_id" end - create_table "sipity_entity_specific_responsibilities", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_entity_specific_responsibilities", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "workflow_role_id", null: false t.string "entity_id", null: false t.integer "agent_id", null: false @@ -339,7 +339,7 @@ t.index ["workflow_role_id"], name: "sipity_entity_specific_responsibilities_role" end - create_table "sipity_notifiable_contexts", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_notifiable_contexts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "scope_for_notification_id", null: false t.string "scope_for_notification_type", null: false t.string "reason_for_notification", null: false @@ -352,7 +352,7 @@ t.index ["scope_for_notification_id", "scope_for_notification_type"], name: "sipity_notifiable_contexts_concern" end - create_table "sipity_notification_recipients", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_notification_recipients", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "notification_id", null: false t.integer "role_id", null: false t.string "recipient_strategy", null: false @@ -364,7 +364,7 @@ t.index ["role_id"], name: "sipity_notification_recipients_role" end - create_table "sipity_notifications", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_notifications", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name", null: false t.string "notification_type", null: false t.datetime "created_at", null: false @@ -373,7 +373,7 @@ t.index ["notification_type"], name: "index_sipity_notifications_on_notification_type" end - create_table "sipity_roles", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_roles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name", null: false t.text "description" t.datetime "created_at", null: false @@ -381,7 +381,7 @@ t.index ["name"], name: "index_sipity_roles_on_name", unique: true end - create_table "sipity_workflow_actions", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_actions", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "workflow_id", null: false t.integer "resulting_workflow_state_id" t.string "name", null: false @@ -392,7 +392,7 @@ t.index ["workflow_id"], name: "sipity_workflow_actions_workflow" end - create_table "sipity_workflow_methods", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_methods", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "service_name", null: false t.integer "weight", null: false t.integer "workflow_action_id", null: false @@ -401,7 +401,7 @@ t.index ["workflow_action_id"], name: "index_sipity_workflow_methods_on_workflow_action_id" end - create_table "sipity_workflow_responsibilities", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_responsibilities", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "agent_id", null: false t.integer "workflow_role_id", null: false t.datetime "created_at", null: false @@ -409,7 +409,7 @@ t.index ["agent_id", "workflow_role_id"], name: "sipity_workflow_responsibilities_aggregate", unique: true end - create_table "sipity_workflow_roles", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_roles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "workflow_id", null: false t.integer "role_id", null: false t.datetime "created_at", null: false @@ -417,7 +417,7 @@ t.index ["workflow_id", "role_id"], name: "sipity_workflow_roles_aggregate", unique: true end - create_table "sipity_workflow_state_action_permissions", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_state_action_permissions", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "workflow_role_id", null: false t.integer "workflow_state_action_id", null: false t.datetime "created_at", null: false @@ -425,7 +425,7 @@ t.index ["workflow_role_id", "workflow_state_action_id"], name: "sipity_workflow_state_action_permissions_aggregate", unique: true end - create_table "sipity_workflow_state_actions", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_state_actions", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "originating_workflow_state_id", null: false t.integer "workflow_action_id", null: false t.datetime "created_at", null: false @@ -433,7 +433,7 @@ t.index ["originating_workflow_state_id", "workflow_action_id"], name: "sipity_workflow_state_actions_aggregate", unique: true end - create_table "sipity_workflow_states", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflow_states", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "workflow_id", null: false t.string "name", null: false t.datetime "created_at", null: false @@ -442,7 +442,7 @@ t.index ["workflow_id", "name"], name: "sipity_type_state_aggregate", unique: true end - create_table "sipity_workflows", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "sipity_workflows", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name", null: false t.string "label" t.text "description" @@ -454,13 +454,13 @@ t.index ["permission_template_id", "name"], name: "index_sipity_workflows_on_permission_template_and_name", unique: true end - create_table "tinymce_assets", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "tinymce_assets", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "file" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "top_level_collection_orders", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "top_level_collection_orders", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.text "order" t.string "user_id", null: false t.datetime "created_at", null: false @@ -468,14 +468,14 @@ t.index ["user_id"], name: "index_top_level_collection_orders_on_user_id" end - create_table "trophies", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "trophies", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "user_id" t.string "work_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "tufts_collection_orders", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| + create_table "tufts_collection_orders", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.text "order" t.string "collection_id", null: false t.integer "item_type", default: 0, null: false @@ -484,7 +484,7 @@ t.index ["collection_id", "item_type"], name: "index_tufts_collection_orders_on_collection_id_and_item_type", unique: true end - create_table "uploaded_files", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "uploaded_files", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "file" t.bigint "user_id" t.string "file_set_uri" @@ -494,7 +494,7 @@ t.index ["user_id"], name: "index_uploaded_files_on_user_id" end - create_table "user_stats", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "user_stats", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.integer "user_id" t.datetime "date" t.integer "file_views" @@ -505,7 +505,7 @@ t.index ["user_id"], name: "index_user_stats_on_user_id" end - create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" @@ -546,7 +546,7 @@ t.index ["username"], name: "index_users_on_username", unique: true end - create_table "version_committers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "version_committers", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "obj_id" t.string "datastream_id" t.string "version_id" @@ -555,7 +555,7 @@ t.datetime "updated_at", null: false end - create_table "work_view_stats", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| + create_table "work_view_stats", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.datetime "date" t.integer "work_views" t.string "work_id" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6de318e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,153 @@ +version: '3' + +networks: + external: + name: external-network + external: true + internal: + name: internal-network + external: true + +volumes: + db-dev: + fcrepo-dev: + solr-dev: + redis-dev: + bundled: + derivatives: + external: + name: mira_on_hyrax_derivatives + +services: + ## + # Basic Rails application build image + trove-app: &trove-app + build: + context: . + dockerfile: Dockerfile + user: root + volumes: + - .:/data # mount current directory into the image + - bundled:/usr/local/bundle + - derivatives:/data/tmp/derivatives + networks: + external: + internal: + # use tmpfs for tmp and log for performance and to allow + # multiple builds in parallel. Both directories are mounted + # into the image AFTER the working directory is mounted. + tmpfs: + - /data/log + + ## + # Development environment for application + trove-dev: &trove-dev + <<: *trove-app + environment: + - CACHE_PATH=/data/tmp/uploads/cache + - DB_NAME=development + - DB_HOST=trove-db-dev + - DB_PASSWORD=postgres + - DB_PORT='3306' + - DB_USERNAME=postgres + - DERIVATIVES_PATH=/data/tmp/derivatives + - FEDORA_URL=http://fcrepo-dev:8080/rest + - FITS_PATH=/opt/fits-1.0.5/fits.sh + - RAILS_ENV=development + - RAILS_LOG_TO_STDOUT=true + - REDIS_HOST=redis-dev + - REDIS_PORT=6379 + - SECRET_KEY_BASE=bobross + - SOLR_URL=http://solr-dev:8983/solr/development + - UPLOADS_PATH=/data/tmp/uploads + depends_on: + - trove-db-dev + - chrome + expose: + - 4000 + server: + <<: *trove-dev + command: > + bash -c "./build/entrypoint.sh && + bundle exec rails s -p 4000 -b '0.0.0.0'" + ports: + - "${SERVER_PORTS}" + expose: + - "${SERVER_EXPOSE}" + ## + # Test environment for application + test: &trove-test + <<: *trove-app + environment: + - CACHE_PATH=/data/tmp/uploads/cache + - IN_DOCKER=true + - HUB_URL=http://chrome:4444/wd/hub + - DB_NAME=test + - DB_HOST=trove-db-test + - DB_PASSWORD=postgres + - DB_PORT='3306' + - DB_USERNAME=postgres + - DERIVATIVES_PATH=/data/tmp/derivatives + - FEDORA_URL=http://fcrepo-test:8080/rest + - FITS_PATH=/opt/fits-1.0.5/fits.sh + - RAILS_ENV=test + - REDIS_HOST=redis-test + - REDIS_PORT=6379 + - SECRET_KEY_BASE=bobross + - SOLR_URL=http://solr-test:8983/solr/test + - UPLOADS_PATH=/data/tmp/uploads + - DISABLE_SPRING=1 + depends_on: + - trove-db-test + - chrome + volumes: + - .:/data # mount current directory into the image + - ./tmp:/tmp + - bundled:/usr/local/bundle + command: > + bash -c "./build/entrypoint.sh && + RAILS_ENV=test bundle exec rails s -p 4001 -b '0.0.0.0'" + ports: + - "${TEST_PORTS}" + expose: + - "${TEST_EXPOSE}" +## + # Mariadb database server + db: &db + image: mariadb:10 + networks: + internal: + trove-db-dev: + <<: *db + environment: + - MYSQL_DATABASE=development + - MYSQL_USER=postgres + - MYSQL_PASSWORD=postgres + - MYSQL_ROOT_PASSWORD=postgres + ports: + - 3397:3307 + volumes: + - db-dev:/var/lib/mysql + trove-db-test: + <<: *db + environment: + - MYSQL_DATABASE=test + - MYSQL_USER=postgres + - MYSQL_PASSWORD=postgres + - MYSQL_ROOT_PASSWORD=postgres + ports: + - 3418:3308 + tmpfs: /var/lib/mysql + chrome: + image: "${SELENIUM_IMAGE}" + platform: "${SELENIUM_PLATFORM}" + restart: always + logging: + driver: none + volumes: + - /dev/shm:/dev/shm + - ./tmp/downloads:/home/seluser/Downloads + shm_size: 2G + ports: + - "4484:4444" + - "5952:5900" \ No newline at end of file diff --git a/docs/future_notes.md b/docs/future_notes.md new file mode 100644 index 0000000..429fcb1 --- /dev/null +++ b/docs/future_notes.md @@ -0,0 +1,29 @@ +# Some ideas on supporting different chrome/java versions + +In trying this in trove it didn't work great because of the differences in ARM and x64 macs. + +## alternative java installation +``` +RUN wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public| apt-key add - \ + && apt-get update \ + && apt-get install -y temurin-8-jdk + +RUN update-java-alternatives --set /usr/lib/jvm/temurin-8-jdk-amd64 + +RUN apt-get update && apt-get install -y wget unzip libatk1.0-0 libgtk-3-0 libgbm1 +``` +## Download and extract Google Chrome + +attempts using thorium + +``` +RUN wget https://github.com/Alex313031/thorium/releases/download/M114.0.5735.134/thorium-browser_114.0.5735.134_amd64.zip && \ + unzip chrome-linux.zip -d /usr/local/bin/ && \ + rm chrome-linux.zip +``` +## Create a symbolic link to the Chrome binary +``` +RUN ln -s /usr/local/bin/thorium /usr/local/bin/google-chrome +RUN ln -s /usr/local/bin/thorium /usr/local/bin/chrome +RUN ln -s /usr/local/bin/thorium /usr/local/bin/chromium +``` \ No newline at end of file diff --git a/lib/tasks/load_collection_types.rake b/lib/tasks/load_collection_types.rake new file mode 100644 index 0000000..d626e25 --- /dev/null +++ b/lib/tasks/load_collection_types.rake @@ -0,0 +1,33 @@ +namespace :db do + desc "Load data into the hyrax_collection_types table" + task load_hyrax_data: :environment do + data = [ + [1,'User Collection','A User Collection can be created by any user to organize their works.','user_collection',1,1,1,1,0,0,0,0,1,'#705070'], + [2,'Admin Set','An aggregation of works that is intended to help with administrative control. Admin Sets provide a way of defining behaviors and policies around a set of works.','admin_set',0,0,1,0,1,1,1,1,0,'#405060'], + [3,'Course Collection','For Trove','course_collection',1,1,1,1,0,0,0,1,1,'#663333'], + [4,'Personal Collection','For Trove','personal_collection',1,1,1,1,0,0,0,1,1,'#663333'] + ] + + data.each do |row| + # Assuming you have a model named HyraxCollectionType corresponding to the table + Hyrax::CollectionType.create( + id: row[0], + title: row[1], + description: row[2], + machine_id: row[3], + nestable: row[4], + discoverable: row[5], + sharable: row[6], + allow_multiple_membership: row[7], + require_membership: row[8], + assigns_workflow: row[9], + assigns_visibility: row[10], + share_applies_to_new_works: row[11], + brandable: row[12], + badge_color: row[13] + ) + end + + puts "Data loaded into hyrax_collection_types table" + end + end diff --git a/preinit_new_environment.sh b/preinit_new_environment.sh new file mode 100755 index 0000000..c39e272 --- /dev/null +++ b/preinit_new_environment.sh @@ -0,0 +1,20 @@ + cp config/fedora.yml.sample config/fedora.yml + cp config/solr.yml.sample config/solr.yml + cp config/devise.yml.sample config/devise.yml + cp config/redis.yml.sample config/redis.yml + cp config/database.yml.sample config/database.yml + cp config/blacklight.yml.sample config/blacklight.yml + cp config/secrets.yml.sample config/secrets.yml + cp config/ldap.yml.sample config/ldap.yml + cp config/java.yml.sample config/java.yml + cp config/sidekiq.yml.sample config/sidekiq.yml.sample + cp config/tufts.yml.sample config/tufts.yml + +if [[ $(uname -m) == 'arm64' ]]; then + echo "copying m1 specific .env file" + cp config/env.apple-silicon.conf ./.env + else + echo "copying intel specific .env file" + cp config/env.intel.conf ./.env + fi + diff --git a/spec/exporters/pdf_collection_exporter_spec.rb b/spec/exporters/pdf_collection_exporter_spec.rb index 3832f94..c3fe3cc 100644 --- a/spec/exporters/pdf_collection_exporter_spec.rb +++ b/spec/exporters/pdf_collection_exporter_spec.rb @@ -19,7 +19,7 @@ after(:all) { destroy_export_dirs } # Ideally you don't test 3 things at once, but I don't want to run this 3 times. - it 'generates the file, returns the file path, deletes the leftover pptx file', noci: true, slow: true do + it 'generates the file, returns the file path, deletes the leftover pptx file', noci_local: true, noci: true, slow: true do export_file_path = exporter.export expect(export_file_path).to eq("#{target_dir}/#{exporter.pdf_file_name}") expect(export_file_path).to exist_on_filesystem diff --git a/spec/features/add_image_to_collection_from_image_spec.rb b/spec/features/add_image_to_collection_from_image_spec.rb index 02ec247..d48fe5d 100644 --- a/spec/features/add_image_to_collection_from_image_spec.rb +++ b/spec/features/add_image_to_collection_from_image_spec.rb @@ -28,7 +28,7 @@ def search_in_and_return_modal find('.collection-list-modal') end - scenario 'non-admins can add images only to their own collections', js: true do + scenario 'non-admins can add images only to their own collections', noci_local:true, js: true do my_coll your_coll c_coll @@ -44,7 +44,7 @@ def search_in_and_return_modal expect(my_coll.member_work_ids).to eq([image.id]) end - scenario 'admins can add images to all collections', js: true do + scenario 'admins can add images to all collections', noci_local: true, noci: true, js: true do user.add_role('admin') my_coll @@ -68,4 +68,4 @@ def search_in_and_return_modal expect(c_coll.member_work_ids).to eq([image.id]) end end -end \ No newline at end of file +end diff --git a/spec/features/breadcrumb_customizations_spec.rb b/spec/features/breadcrumb_customizations_spec.rb index 3a94518..097378a 100644 --- a/spec/features/breadcrumb_customizations_spec.rb +++ b/spec/features/breadcrumb_customizations_spec.rb @@ -7,7 +7,7 @@ let(:coll) { create(:personal_collection, user: user) } let(:image) { create(:image) } - scenario 'referring Collection should show in breadcrumbs on image pages' do + scenario 'referring Collection should show in breadcrumbs on image pages', js: true, noci_local: true do sign_in(user) coll.add_member_objects([image.id]) title = coll.title.first @@ -20,4 +20,4 @@ expect(bc).to have_content(title) expect(bc).to have_css("a[href=\"#{hyrax.collection_path(id: coll.id)}\"]") end -end \ No newline at end of file +end diff --git a/spec/features/collection_actions_spec.rb b/spec/features/collection_actions_spec.rb index a5f4d5f..09d98ba 100644 --- a/spec/features/collection_actions_spec.rb +++ b/spec/features/collection_actions_spec.rb @@ -28,7 +28,7 @@ def course_collections end context 'button existence and permissions' do - scenario 'show screen should have the right buttons and not the wrong ones' do + scenario 'show screen should have the right buttons and not the wrong ones', noci_local: true do visit collection_page buttons = find('.show-collection-buttons') expect(buttons).not_to have_content('Download PDF') @@ -45,7 +45,7 @@ def course_collections expect(buttons).to have_content('Download Powerpoint') end - scenario 'can copy and download other peoples collections, but cant manage them' do + scenario 'can copy and download other peoples collections, but cant manage them', noci_local: true do other_coll = create(:personal_collection) other_coll.add_member_objects([image.id]) @@ -58,7 +58,7 @@ def course_collections expect(buttons).to have_content('Download Powerpoint') end - scenario 'edit screen should have the right buttons and not the wrong ones' do + scenario 'edit screen should have the right buttons and not the wrong ones', noci_local: true do user.add_role('admin') visit dashboard_page @@ -157,4 +157,4 @@ def course_collections expect(cc.first.title).to eq(coll.title) end end -end \ No newline at end of file +end diff --git a/spec/features/collection_page_layout_changes_spec.rb b/spec/features/collection_page_layout_changes_spec.rb index a3870a7..6e146e1 100644 --- a/spec/features/collection_page_layout_changes_spec.rb +++ b/spec/features/collection_page_layout_changes_spec.rb @@ -56,7 +56,7 @@ expect(results).not_to have_content('Is part of:') end - scenario 'edit page' do + scenario 'edit page', js: true, noci_local: true do user.add_role('admin') # Need admin role for the Add Works buttons to appear visit hyrax.dashboard_collection_path(coll.id) diff --git a/spec/features/collection_sidebar_spec.rb b/spec/features/collection_sidebar_spec.rb index dad8521..84e5f64 100644 --- a/spec/features/collection_sidebar_spec.rb +++ b/spec/features/collection_sidebar_spec.rb @@ -56,7 +56,7 @@ end context 'adding a collection via + button' do - scenario 'collection appears in sidebar', slow: true do + scenario 'collection appears in sidebar', slow: true, noci_local: true do user.add_role('admin') visit('/') @@ -92,7 +92,7 @@ def rearrange_collections(arr_btn, collections) sleep 1 end - scenario 'Clicking the rearrange button enables/disables rearranging', js: true, slow: true do + scenario 'Clicking the rearrange button enables/disables rearranging', noci_local:true, js: true, slow: true do pers_coll visit('/') arr_btn = find('button.reorder-personal') @@ -110,7 +110,7 @@ def rearrange_collections(arr_btn, collections) # * Rearranging the sidebar generates a TopLevelCollectionOrder if it doesn't exist. # * Rearranging the sidebar updates the TopLevelCollectionOrder if it does exist. # * The TopLevelCollectionOrder matches the order of the ids in the HTML. - scenario 'Rearranging saves the order as a TopLevelCollectionOrder', js: true, slow: true do + scenario 'Rearranging saves the order as a TopLevelCollectionOrder', noci_local:true, js: true, slow: true do pers_coll create(:personal_collection, user: user) create(:personal_collection, user: user) diff --git a/spec/features/work_and_subcollection_orders_spec.rb b/spec/features/work_and_subcollection_orders_spec.rb index c35594c..50c708c 100644 --- a/spec/features/work_and_subcollection_orders_spec.rb +++ b/spec/features/work_and_subcollection_orders_spec.rb @@ -26,7 +26,7 @@ def get_subc_els_and_ids return list, list.map { |node| node['data-id'] } end - scenario 'rearranged work orders are persisted', slow: true, noci: true, js: true do + scenario 'rearranged work orders are persisted', slow: true, noci: true, js: true, noci_local: true do user.add_role('admin') coll @@ -52,7 +52,7 @@ def get_subc_els_and_ids expect(ids).to eq(new_order) end - scenario 'rearranged subcollection orders are persisted', slow: true, js: true do + scenario 'rearranged subcollection orders are persisted', noci_local: true, slow: true, js: true do coll create(:personal_collection, user: user, parent: coll) create(:personal_collection, user: user, parent: coll) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 7154051..6b9c31a 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -24,20 +24,54 @@ require 'spec_helper' require 'rspec/rails' +require 'capybara-screenshot/rspec' # Add additional requires below this line. Rails is not loaded until this point! require 'active_fedora/cleaner' - Capybara.server = :webrick +Capybara::Screenshot.autosave_on_failure = false + +if ENV['IN_DOCKER'].present? || ENV['HUB_URL'].present? + args = %w[disable-gpu no-sandbox whitelisted-ips window-size=1400,1400] + args.push('headless') if ActiveModel::Type::Boolean.new.cast(ENV['CHROME_HEADLESS_MODE']) + + capabilities = Selenium::WebDriver::Remote::Capabilities.chrome("goog:chromeOptions" => { args: args }) + + Capybara.register_driver :selenium_chrome_headless_sandboxless do |app| + driver = Capybara::Selenium::Driver.new(app, + browser: :remote, + desired_capabilities: capabilities, + url: ENV['HUB_URL']) + + # Fix for capybara vs remote files. Selenium handles this for us + driver.browser.file_detector = lambda do |argss| + str = argss.first.to_s + str if File.exist?(str) + end + + driver + end + + Capybara.server_host = '0.0.0.0' + Capybara.server_port = 3010 + Capybara.javascript_driver = :selenium_chrome_headless_sandboxless + ip = IPSocket.getaddress(Socket.gethostname) + Capybara.app_host = "http://#{ip}:#{Capybara.server_port}" + Capybara.default_driver = :selenium_chrome_headless_sandboxless +else + # this is for github actions only -Webdrivers::Chromedriver.required_version = '106.0.5249.21' -custom_chrome_path = '/opt/hostedtoolcache/chromium/1036826/x64/chrome' + Webdrivers::Chromedriver.required_version = '106.0.5249.21' + custom_chrome_path = '/opt/hostedtoolcache/chromium/1036826/x64/chrome' -# Adding chromedriver for js testing. + # Adding chromedriver for js testing. Capybara.register_driver :headless_chrome do |app| browser_options = ::Selenium::WebDriver::Chrome::Options.new browser_options.headless! browser_options.args << '--window-size=1920,1080' + browser_options.args << '--no-sandbox' + browser_options.args << '--disable-dev-shm-usage' + browser_options.args << '--disable-gpu' browser_options.binary = custom_chrome_path Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) end @@ -51,6 +85,11 @@ Capybara.javascript_driver = :headless_chrome +end + +# Change to :chrome for js test debugging + + # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are # run as spec files by default. This means that files in spec/support that end diff --git a/spec/services/tufts/export_manager_service_spec.rb b/spec/services/tufts/export_manager_service_spec.rb index 679a5a6..ea67694 100644 --- a/spec/services/tufts/export_manager_service_spec.rb +++ b/spec/services/tufts/export_manager_service_spec.rb @@ -14,11 +14,11 @@ after(:each) { destroy_export_dirs } - it 'is invalid if the directories cant be created' do - Tufts::ExportManagerService.export_base_path = '/' + it 'is invalid if the directories cant be created', noci_local: true do + Tufts::ExportManagerService.export_base_path = '/non-existant-dir' expect(ppt_manager.instance_variable_get(:@export_valid)).to be false - Tufts::ExportManagerService.export_base_path = @target_path + Tufts::ExportManagerService.export_base_path = Rails.root.join('tmp', 'exports').to_s end it 'is invalid with an invalid type' do @@ -26,8 +26,8 @@ .instance_variable_get(:@export_valid)).to be false end - it 'creates the test directories if they dont already exist' do - base_path = Tufts::ExportManagerService.export_base_path + it 'creates the test directories if they dont already exist', noci_local: true do + base_path = Rails.root.join('tmp', 'exports').to_s pdf_path = base_path + '/pdfs' pptx_path = base_path + '/ppts' @@ -38,7 +38,7 @@ end describe '#retrieve_asset' do - it 'generates the file if it doesnt already exist' do + it 'generates the file if it doesnt already exist', noci_local: true do ppt_manager full_path = ppt_manager.instance_variable_get(:@full_path) @@ -47,7 +47,7 @@ expect(full_path).to exist_on_filesystem end - it 'doesnt generate a file if it already exists' do + it 'doesnt generate a file if it already exists', noci_local: true, noci: true do ppt_files = ppt_manager.export_base_path + '/ppts/*' expect(Dir[ppt_files].count).to be 0 @@ -75,7 +75,7 @@ expect(ppt_manager.asset_exists?).to be true end - it 'returns false if asset doesnt exist' do + it 'returns false if asset doesnt exist', noci_local: true do expect(ppt_manager.asset_exists?).to be false end end @@ -87,8 +87,8 @@ end end - describe '#self.delete_all_assets', slow: true do - it 'deletes both pdf and ppt files for collection' do + describe '#self.delete_all_assets', noci_local: true, slow: true do + it 'deletes both pdf and ppt files for collection', noci_local: true, noci: true do pdf_manager = Tufts::ExportManagerService.new(collection, 'pdf') pdf_file = pdf_manager.instance_variable_get(:@full_path) pdf_manager.retrieve_asset @@ -105,4 +105,4 @@ expect(ppt_file).not_to exist_on_filesystem end end -end \ No newline at end of file +end diff --git a/spec/support/file_manager.rb b/spec/support/file_manager.rb index ae0e73b..aa13a42 100644 --- a/spec/support/file_manager.rb +++ b/spec/support/file_manager.rb @@ -7,7 +7,14 @@ def create_export_dirs end def destroy_export_dirs - FileUtils.rm_r(Tufts::ExportManagerService.export_base_path) if - File.exists?(Tufts::ExportManagerService.export_base_path) + yaml_config = + YAML.safe_load( + File.read( + Rails.root.join('config', 'tufts.yml') + ) + )[Rails.env] + + + FileUtils.rm_r(yaml_config['export_path']) if File.exists?(yaml_config['export_path']) end end diff --git a/spec/support/ldap_manager.rb b/spec/support/ldap_manager.rb index 0b42d9f..19e852f 100644 --- a/spec/support/ldap_manager.rb +++ b/spec/support/ldap_manager.rb @@ -9,6 +9,7 @@ def i_need_ldap unless(@ldap_running) @ldap_server = Ladle::Server.new( quiet: true, + timeout: 180, ldif: Rails.root.join("spec/fixtures/tufts_ldap.ldif") ).start