diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..aeba973 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,81 @@ +*.rbc +capybara-*.html +.bash* +.rspec +/db/*.sqlite3 +/db/*.sqlite3-journal +/db/*.sqlite3-[0-9]* +/public/system +/coverage/ +/spec/tmp +*.orig +rerun.txt +pickle-email-*.html + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# TODO Comment out this rule if you are OK with secrets being uploaded to the repo +config/initializers/secret_token.rb +config/master.key + +# Only include if you have production secrets in this file, which is no longer a Rails default +# config/secrets.yml + +# dotenv +# TODO Comment out this rule if environment variables can be committed +.env + +## Environment normalization: +/.bundle +/vendor/bundle + +# these should all be checked in to normalize the environment: +# Gemfile.lock, .ruby-version, .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# if using bower-rails ignore default bower_components path bower.json files +/vendor/assets/bower_components +*.bowerrc +bower.json + +# Ignore pow environment settings +.powenv + +# Ignore Byebug command history file. +.byebug_history + +# Ignore Bash history file. +.bash_history + +# Ignore node_modules +node_modules/ + +# Ignore precompiled javascript packs +/public/packs +/public/packs-test +/public/assets + +# Ignore yarn files +/yarn-error.log +yarn-debug.log* +.yarn-integrity + +# Ignore uploaded files in development +/storage/* +!/storage/.keep + +# Build/test artifacts +/artifacts/ + +# Ignore solr files +solr/*/data/* + +.irb_history + +.github diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 6cecc3d..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,159 +0,0 @@ -name: Build -on: [ push, pull_request, workflow_dispatch ] -env: - REGISTRY: ghcr.io - -jobs: - # TODO: DRY w/release.yml - setup: - runs-on: ubuntu-latest - - steps: - # See https://github.com/docker/build-push-action/blob/v2.10.0/TROUBLESHOOTING.md#repository-name-must-be-lowercase - - name: Sanitize image name - uses: actions/github-script@v6 - id: image-name - with: - result-encoding: string - script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase() - - - name: Get short SHA - run: | - echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV - - outputs: - base_image_name: ${{ steps.image-name.outputs.result }} - build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }} - - build: - if: github.event_name != 'release' - needs: setup - env: - BUILD_IMAGE: ${{ needs.setup.outputs.build_image }} - - runs-on: ubuntu-latest - - permissions: - packages: write - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Get build start time - run: | - echo BUILD_TIMESTAMP="$(date --utc --iso-8601=seconds)" >> $GITHUB_ENV - - - name: Build and push Docker image - uses: docker/build-push-action@v3 - with: - context: . - push: true - tags: ${{ env.BUILD_IMAGE }} - build-args: | - BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }} - BUILD_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - DOCKER_TAG=${{ env.BUILD_IMAGE }} - GIT_BRANCH=${{ github.ref_name }} - GIT_COMMIT=${{ github.sha }} - GIT_URL=${{ github.repositoryUrl }} - - outputs: - build_image: ${{ env.BUILD_IMAGE }} - - test: - if: github.event_name != 'release' - needs: build - - runs-on: ubuntu-latest - - container: - options: --init - image: ${{ needs.build.outputs.build_image }} - - defaults: - run: - working-directory: /opt/app - - services: - db: - image: postgres - env: - POSTGRES_USER: root - POSTGRES_PASSWORD: root - - # solr: - # image: solr:8 - # #restart: always - # ports: - # - 8983:8983 - # volumes: - # - ${{ github.workspace }}/solr:/var/solr/data/configsets/solr:delegated - - steps: - - name: Run tests - env: - RAILS_ENV: test - run: bundle exec rake check -t - - - name: Run style checks - run: bundle exec rubocop - - - name: Validate database migrations - env: - RAILS_ENV: test - DISABLE_DATABASE_ENVIRONMENT_CHECK: 1 - run: rails --trace db:drop db:create db:migrate - - - name: Upload artifacts - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: artifacts - path: | - /opt/app/artifacts/** - /tmp/solr*/server/logs - - - # TODO: DRY w/release.yml - push: - if: github.event_name != 'release' - - needs: [ setup, build, test ] - env: - BASE_IMAGE_NAME: ${{ needs.setup.outputs.base_image_name }} - BUILD_IMAGE: ${{ needs.build.outputs.build_image }} - - runs-on: ubuntu-latest - - permissions: - packages: write - - steps: - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.BASE_IMAGE_NAME }} - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Tag and push image - uses: akhilerm/tag-push-action@v2.1.0 - with: - src: ${{ env.BUILD_IMAGE }} - dst: | - ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/docker-ci.yml b/.github/workflows/docker-ci.yml new file mode 100644 index 0000000..c55ed92 --- /dev/null +++ b/.github/workflows/docker-ci.yml @@ -0,0 +1,14 @@ +name: Docker CI + +on: + push: + release: + workflow_dispatch: + +jobs: + build: + uses: BerkeleyLibrary/.github/.github/workflows/docker-build.yml@v1.0.0 + + test: + needs: build + uses: BerkeleyLibrary/.github/.github/workflows/docker-test.yml@v1.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 0798436..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Release - -on: - release: - types: - - published - workflow_dispatch: - workflow_run: - workflows: ["Build"] - types: ["completed"] - branches: - - main - -env: - REGISTRY: ghcr.io - -jobs: - setup: - runs-on: ubuntu-latest - steps: - - name: Sanitize image name - uses: actions/github-script@v6 - id: image-name - with: - result-encoding: string - script: return '${{ env.REGISTRY }}/${{ github.repository }}'.toLowerCase() - - - name: Get short SHA - run: | - echo SHORT_SHA="${GITHUB_SHA:0:7}" >> $GITHUB_ENV - - outputs: - base_image_name: ${{ steps.image-name.outputs.result }} - build_image: ${{ steps.image-name.outputs.result }}:${{ env.SHORT_SHA }} - - push: - if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} - runs-on: ubuntu-latest - needs: setup - permissions: - packages: write - env: - BASE_IMAGE_NAME: ${{ needs.setup.outputs.base_image_name }} - BUILD_IMAGE: ${{ needs.setup.outputs.build_image }} - steps: - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.BASE_IMAGE_NAME }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=semver,pattern={{major}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{version}} - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Tag and push image - uses: akhilerm/tag-push-action@v2.1.0 - with: - src: ${{ env.BUILD_IMAGE }} - dst: | - ${{ steps.meta.outputs.tags }} diff --git a/.rubocop.yml b/.rubocop.yml index a1f4c03..0134d79 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -345,9 +345,9 @@ Rails/RootJoinChain: # new in 2.13 Enabled: true # to skip default code generation -Layout/ClassLength: +Metrics/ClassLength: Enabled: false -Layout/MethodLength: +Metrics/MethodLength: Enabled: false -Layout/BlockLength: +Metrics/BlockLength: Enabled: false \ No newline at end of file diff --git a/.simplecov b/.simplecov index 77b091d..b9af16a 100644 --- a/.simplecov +++ b/.simplecov @@ -4,5 +4,5 @@ SimpleCov.start 'rails' do add_filter %w[/app/channels/ /app/jobs/ /bin/ /db/] coverage_dir 'artifacts' formatter SimpleCov::Formatter::RcovFormatter - minimum_coverage 100 + minimum_coverage 70 end diff --git a/Dockerfile b/Dockerfile index e9da79e..4073fcd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,14 +21,14 @@ RUN mkdir -p /opt/app \ && chown -R $APP_USER:$APP_USER /opt/app /usr/local/bundle # Get list of available packages -RUN apt-get update -qq +RUN apt-get update -qq # Install standard packages from the Debian repository RUN apt-get install -y --no-install-recommends \ bash \ curl \ default-jre \ - ca-certificates \ + ca-certificates \ nodejs \ libpq-dev \ libvips42 \ @@ -42,7 +42,7 @@ USER geodata WORKDIR /opt/app # Add binstubs to the path. -ENV PATH "/opt/app/bin:$PATH" +ENV PATH="/opt/app/bin:$PATH" # If run with no other arguments, the image will start the rails server by @@ -106,14 +106,14 @@ RUN rails assets:precompile assets:clean log:clear tmp:clear ARG BUILD_TIMESTAMP ARG BUILD_URL ARG DOCKER_TAG -ARG GIT_BRANCH -ARG GIT_COMMIT -ARG GIT_URL +ARG GIT_REF_NAME +ARG GIT_SHA +ARG GIT_REPOSITORY_URL # build arguments aren't persisted in the image, but ENV values are ENV BUILD_TIMESTAMP="${BUILD_TIMESTAMP}" ENV BUILD_URL="${BUILD_URL}" ENV DOCKER_TAG="${DOCKER_TAG}" -ENV GIT_BRANCH="${GIT_BRANCH}" -ENV GIT_COMMIT="${GIT_COMMIT}" -ENV GIT_URL="${GIT_URL}" +ENV GIT_REF_NAME="${GIT_REF_NAME}" +ENV GIT_SHA="${GIT_SHA}" +ENV GIT_REPOSITORY_URL="${GIT_REPOSITORY_URL}" diff --git a/Rakefile b/Rakefile index 0f01d9f..879ed29 100644 --- a/Rakefile +++ b/Rakefile @@ -33,34 +33,7 @@ task setup: %w[db:setup] # Check (setup + coverage) desc 'Set up, check test coverage' -task :check do - raise "Can't run specs; expected RAILS_ENV=\"test\", was #{Rails.env.inspect}" unless Rails.env.test? - - require 'solr_wrapper' - Rake::Task[:setup].invoke - SolrWrapper.wrap do |solr| - solr.with_collection(name: 'geodata-test', dir: "#{Rails.root}/config/solr") do - - # Rake::Task[:coverage].invoke - # Rake::Task['solr:restart'].invoke - Rake::Task['geoblacklight:index:seed'].invoke - # Rake::Task[:prepare_solr].invoke - Rake::Task[:spec].invoke - end - end -end - -# desc 'Set up, check test coverage' -# task :check do -# raise "Can't run specs; expected RAILS_ENV=\"test\", was #{Rails.env.inspect}" unless Rails.env.test? - -# Rake::Task[:setup].invoke -# # Rake::Task[:coverage].invoke -# # Rake::Task['solr:restart'].invoke -# # Rake::Task['geoblacklight:index:seed'].invoke -# #Rake::Task[:prepare_solr].invoke -# Rake::Task[:spec].invoke -# end +task check: %w[setup geoblacklight:index:seed spec] # clear rspec/rails default :spec task Rake::Task[:default].clear if Rake::Task.task_defined?(:default) diff --git a/bin/setup b/bin/setup index bfae919..e703ab1 100755 --- a/bin/setup +++ b/bin/setup @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require "fileutils" -# path to your application root. APP_ROOT = File.expand_path("..", __dir__) def system!(*args) @@ -9,30 +8,14 @@ def system!(*args) end FileUtils.chdir APP_ROOT do - # This script is a way to set up or update your development environment automatically. - # This script is idempotent, so that you can run it at any time and get an expectable outcome. - # Add necessary setup steps to this file. - - # puts "== Installing dependencies ==" - # system! "gem install bundler --conservative" - # system("bundle check") || system!("bundle install") - - # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # FileUtils.cp "config/database.yml.sample", "config/database.yml" - # end - - # puts "\n== Preparing database ==" - system! "bin/rails db:prepare RAILS_ENV=test" # test db was not automatically created + puts "\n== Preparing database ==" + system! "bin/rails db:prepare RAILS_ENV=test" system! "bin/rails db:prepare" - # system! "bin/rails db:setup" - - # puts "\n== Starting solr ==" - # system! 'bin/rails solr:restart' + puts "\n== Starting solr ==" system! 'bin/rails geoblacklight:index:seed' - # puts "\n== Removing old logs and tempfiles ==" + puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" puts "\n== Restarting application server ==" diff --git a/bin/test b/bin/test new file mode 100755 index 0000000..917a38b --- /dev/null +++ b/bin/test @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +require "fileutils" + +APP_ROOT = File.expand_path("..", __dir__) + +# Check test coverage when running rspec +ENV['COVERAGE'] = '1' + +# Test commands (to be exec'd in order) +TESTS = [ + %w(rspec -f html --out artifacts/rspec.html), + %w(rubocop -f html --out artifacts/rubocop.html), +] + +FileUtils.chdir APP_ROOT do + exit TESTS.reduce(true) { |passed, test| system(*test) && passed } +end diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 0000000..0434b2f --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,12 @@ +--- + +services: + app: + build: !reset + image: ${DOCKER_APP_IMAGE} + volumes: !reset + volumes: + - artifacts:/opt/app/artifacts + +volumes: + artifacts: diff --git a/docker-compose.yml b/docker-compose.yml index 79bafdb..5344502 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.8" +--- services: adminer: @@ -7,34 +7,33 @@ services: ports: - 8080:8080 + app: + build: + context: . + target: development + depends_on: + - db + - solr + ports: + - 3000:3000 + restart: always + environment: + - DATABASE_URL=postgres://root:root@db/geodata-dev?pool=5 + - SOLR_URL=http://solr:8983/solr/geodata-test + volumes: + - ./:/opt/app:delegated + db: image: postgres:12.2 restart: always environment: - POSTGRES_USER: root - POSTGRES_PASSWORD: root + - POSTGRES_USER=root + - POSTGRES_PASSWORD=root ports: - 5432:5432 solr: - image: solr:${SOLR_VERSION:-8.11.1} + build: solr restart: always ports: - 8983:8983 - volumes: - - ./solr:/var/solr/data/configsets/solr:delegated - - app: - build: - context: . - target: development - depends_on: - - db - ports: - - 3000:3000 - restart: always - environment: - DATABASE_URL: postgres://root:root@db/geodata-dev?pool=5 - SOLR_URL: http://solr:8983/solr/geodata-test - volumes: - - ./:/opt/app:delegated diff --git a/solr/Dockerfile b/solr/Dockerfile new file mode 100644 index 0000000..4c63a3c --- /dev/null +++ b/solr/Dockerfile @@ -0,0 +1,3 @@ +FROM solr:8 + +COPY --chown=solr . /var/solr/data/ diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 16d4c41..387fb1a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,11 +6,8 @@ # ------------------------------------------------------------ # Dependencies -# require 'colorize' -require 'simplecov' if ENV['COVERAGE'] -# require 'simplecov' -# require 'rspec_junit_formatter' -# SimpleCov.start 'rails' +require 'active_record' +require 'simplecov' if ActiveRecord::Type::Boolean.new.cast(ENV['COVERAGE']) # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config|