From 760615710ec6aa23a1b4bdfc9ec66d4340b4d312 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Thu, 22 May 2025 09:43:38 -0400 Subject: [PATCH 01/20] Move testing from CircleCI to Github Actions --- .circleci/config.yml | 23 ---- .../actions/build-webpack-assets/action.yml | 26 +++++ .../actions/install-node-modules/action.yml | 28 +++++ .github/actions/migrate/action.yml | 28 +++++ .github/actions/setup-ruby-deps/action.yml | 28 +++++ .github/workflows/tests-and-coverage.yml | 108 ++++++++++++++++++ .gitignore | 7 +- Gemfile | 4 +- coverage/coverage_baseline.txt | 1 + spec/spec_helper.rb | 23 ++-- spec/support/capybara.rb | 1 + 11 files changed, 236 insertions(+), 41 deletions(-) create mode 100644 .github/actions/build-webpack-assets/action.yml create mode 100644 .github/actions/install-node-modules/action.yml create mode 100644 .github/actions/migrate/action.yml create mode 100644 .github/actions/setup-ruby-deps/action.yml create mode 100644 .github/workflows/tests-and-coverage.yml create mode 100644 coverage/coverage_baseline.txt diff --git a/.circleci/config.yml b/.circleci/config.yml index 40167b88..de04bea2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,6 @@ executors: orbs: ruby: circleci/ruby@2.1.1 browser-tools: circleci/browser-tools@1.5.0 - coveralls: coveralls/coveralls@2.2.1 jobs: build: @@ -98,28 +97,6 @@ jobs: - run: bundle exec rails db:schema:load - run: bundle exec rails db:seed - # Run tests in parallel - - run: - name: Run Tests with Split by Timing Data - command: | - # Log the node index and total nodes - echo "Running tests on node $(circleci env subst '${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}')" - - # List the test files and split them by timings - TEST_FILES=$(find spec -type f -name "*_spec.rb" | circleci tests split --split-by=timings) - echo "Test files for this node: $TEST_FILES" - - # Run RSpec with the split test files - bundle exec rspec --format progress --format RspecJunitFormatter --out ~/treatment_database/test_results/rspec.xml $TEST_FILES - - # Store the test results (JUnit XML) for future runs - - store_test_results: - path: ~/treatment_database/test_results - - # Upload coverage results to Coveralls - - coveralls/upload: - parallel: true - workflows: version: 2 ci: diff --git a/.github/actions/build-webpack-assets/action.yml b/.github/actions/build-webpack-assets/action.yml new file mode 100644 index 00000000..20f12767 --- /dev/null +++ b/.github/actions/build-webpack-assets/action.yml @@ -0,0 +1,26 @@ +name: "Build Webpack Assets" +runs: + using: "composite" + steps: + # 1. Restore existing build cache + - name: Restore Webpack Build Cache + id: webpack-cache # give this step an ID + uses: actions/cache@v3 + with: + path: public/build + key: ${{ runner.os }}-webpack-build-${{ hashFiles('app/javascript/**/*','yarn.lock','package.json') }} + restore-keys: | + ${{ runner.os }}-webpack-build- + # 2. Build assets only on cache miss + - name: Build JavaScript & CSS Assets + if: steps.webpack-cache.outputs.cache-hit != 'true' + run: yarn build + shell: bash + + # 3. Save new build only on cache miss + - name: Save Webpack Build Cache + if: steps.webpack-cache.outputs.cache-hit != 'true' + uses: actions/cache@v3 + with: + path: public/build + key: ${{ runner.os }}-webpack-build-${{ hashFiles('app/javascript/**/*','yarn.lock','package.json') }} \ No newline at end of file diff --git a/.github/actions/install-node-modules/action.yml b/.github/actions/install-node-modules/action.yml new file mode 100644 index 00000000..56b06246 --- /dev/null +++ b/.github/actions/install-node-modules/action.yml @@ -0,0 +1,28 @@ +name: "Install Node Modules" +description: "Checks out code, sets up Node.js from .nvmrc with Yarn caching, and installs dependencies." +inputs: {} +runs: + using: "composite" + steps: + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + + - name: Restore node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node-modules- + - name: Install Dependencies + run: yarn install --frozen-lockfile + shell: bash + + - name: Save node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} \ No newline at end of file diff --git a/.github/actions/migrate/action.yml b/.github/actions/migrate/action.yml new file mode 100644 index 00000000..56b06246 --- /dev/null +++ b/.github/actions/migrate/action.yml @@ -0,0 +1,28 @@ +name: "Install Node Modules" +description: "Checks out code, sets up Node.js from .nvmrc with Yarn caching, and installs dependencies." +inputs: {} +runs: + using: "composite" + steps: + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + + - name: Restore node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node-modules- + - name: Install Dependencies + run: yarn install --frozen-lockfile + shell: bash + + - name: Save node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} \ No newline at end of file diff --git a/.github/actions/setup-ruby-deps/action.yml b/.github/actions/setup-ruby-deps/action.yml new file mode 100644 index 00000000..56b06246 --- /dev/null +++ b/.github/actions/setup-ruby-deps/action.yml @@ -0,0 +1,28 @@ +name: "Install Node Modules" +description: "Checks out code, sets up Node.js from .nvmrc with Yarn caching, and installs dependencies." +inputs: {} +runs: + using: "composite" + steps: + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' + cache: 'yarn' + + - name: Restore node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node-modules- + - name: Install Dependencies + run: yarn install --frozen-lockfile + shell: bash + + - name: Save node_modules cache + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} \ No newline at end of file diff --git a/.github/workflows/tests-and-coverage.yml b/.github/workflows/tests-and-coverage.yml new file mode 100644 index 00000000..f2f86307 --- /dev/null +++ b/.github/workflows/tests-and-coverage.yml @@ -0,0 +1,108 @@ +name: Tests & Coverage + +on: + pull_request: + types: + - opened + - synchronize + - reopened + +jobs: + tests: + runs-on: ubuntu-latest + + # Job-level defaults + env: + RAILS_ENV: test + + # Cancel stale runs on the same PR + concurrency: + group: ${{ github.workflow }}-PR${{ github.event.number }} + cancel-in-progress: true + + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Setup Chrome & capture paths + id: setup_chrome + uses: browser-actions/setup-chrome@v1 + with: + chrome-version: '133.0.6943.126' + install-chromedriver: true + install-dependencies: true + + - name: Export Chrome paths for CI + run: | + echo "CHROME_BIN=${{ steps.setup_chrome.outputs.chrome-path }}" >> $GITHUB_ENV + echo "CHROMEDRIVER_PATH=${{ steps.setup_chrome.outputs.chromedriver-path }}" >> $GITHUB_ENV + - name: Set up Ruby and Gems + uses: ./.github/actions/setup-ruby-deps + + - name: Install Node Modules + uses: ./.github/actions/install-node-modules + + - name: Build Webpack Assets + uses: ./.github/actions/build-webpack-assets + + - name: Run Database Migrations + uses: ./.github/actions/migrate + + - name: Run Tests with SimpleCov + run: | + bundle exec rspec \ + --format progress \ + --format RspecJunitFormatter \ + --out /tmp/test-results/rspec.xml + - name: Upload Coverage Artifact + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: coverage + + coverage: + needs: tests + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout PR branch for baseline update + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + fetch-depth: 0 + persist-credentials: true + + - name: Download Coverage Artifact + uses: actions/download-artifact@v4 + with: + name: coverage-report + path: . + + - name: Coverage Check + run: | + # Extract current coverage percentage + COVERAGE=$(grep -oE '[0-9]+\.[0-9]+%' coverage/index.html \ + | head -n1 \ + | tr -d '%') + echo "Current coverage: $COVERAGE%" + # Read the committed baseline + BASELINE=$(cat coverage/coverage_baseline.txt) + echo "Baseline coverage: $BASELINE%" + # Fail if coverage dropped + if (( $(echo "$COVERAGE < $BASELINE" | bc -l) )); then + echo "🚨 Coverage dropped: $COVERAGE% < $BASELINE%" + exit 1 + fi + # Bump baseline and push back to PR branch if coverage increased + if (( $(echo "$COVERAGE > $BASELINE" | bc -l) )); then + echo "$COVERAGE" > coverage/coverage_baseline.txt + git add coverage/coverage_baseline.txt + git config user.name "ci-bot" + git config user.email "ci-bot@example.com" + git commit -m "ci: update coverage baseline to $COVERAGE%" || true + git push origin HEAD:${{ github.head_ref }} || true + fi diff --git a/.gitignore b/.gitignore index 8d2948a8..45f80e86 100644 --- a/.gitignore +++ b/.gitignore @@ -36,8 +36,11 @@ # Ignore master key for decrypting credentials and more. /config/master.key -# Ignore the coverage folder -/coverage +# ignore everything in coverage +coverage/* + +# ...except the baseline file +!coverage/coverage_baseline.txt # Don't track .DS_Store on MacOS .DS_Store diff --git a/Gemfile b/Gemfile index 0890a39c..d4d70480 100644 --- a/Gemfile +++ b/Gemfile @@ -86,8 +86,6 @@ group :development, :test do gem 'coveralls_reborn' # Provides Ruby API for Coveralls.io code coverage reporting gem 'rubocop' # A Ruby static code analyzer and formatter gem 'rubocop-rails' # A RuboCop extension focused on enforcing Rails best practices - gem 'simplecov', require: false # Code coverage analysis tool for Ruby - gem 'simplecov-lcov', require: false # Formatter for SimpleCov that generates LCOV reports end group :development do @@ -108,6 +106,8 @@ group :test do gem 'rack-test' # Small, simple testing API for Rack apps gem 'rspec-rails', '~> 6.1.5' # RSpec for Rails 6+ gem 'shoulda-matchers', '~> 6.5' # Provides RSpec with additional matchers + gem 'simplecov', require: false # Code coverage analysis tool for Ruby + gem 'simplecov-lcov', require: false # Formatter for SimpleCov that generates LCOV reports end group :production do diff --git a/coverage/coverage_baseline.txt b/coverage/coverage_baseline.txt new file mode 100644 index 00000000..d0ada4a7 --- /dev/null +++ b/coverage/coverage_baseline.txt @@ -0,0 +1 @@ +99.54 \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f7ba496c..afe97eda 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,21 +5,16 @@ require 'coveralls' SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true -SimpleCov.start 'rails' do - add_filter '/spec/' # Exclude all files in the spec directory - add_filter '/lib/tasks/' # Exclude all files in the lib/tasks directory - add_filter '/lib/capistrano/' # Exclude all files in the lib/capistrano directory -end +SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter, + Coveralls::SimpleCov::Formatter + ]) -SimpleCov.at_exit do - SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( - [ - SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::LcovFormatter, - Coveralls::SimpleCov::Formatter - ] - ) - SimpleCov.result.format! +SimpleCov.start 'rails' do + add_filter '/spec/' + add_filter '/lib/tasks/' + add_filter '/lib/capistrano/' end require 'byebug' diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 038b664f..0a901ad0 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'capybara/rspec' require 'selenium-webdriver' From a87786255b579de47e99079066a9b241cab586f7 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Thu, 22 May 2025 09:47:43 -0400 Subject: [PATCH 02/20] Add usage_notes.md for github actions --- .github/usage_notes.md | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/usage_notes.md diff --git a/.github/usage_notes.md b/.github/usage_notes.md new file mode 100644 index 00000000..5a5bd0be --- /dev/null +++ b/.github/usage_notes.md @@ -0,0 +1,58 @@ +# GitHub Actions Structure & Usage Notes + +This document explains how our repository's GitHub Actions are organized and why we've structured custom actions the +way we have. It should serve as a reference for setting up and maintaining our CI/CD workflows. + +## Folder Structure + +### Our repository includes two key directories for GitHub Actions: + +#### .github/workflows/ +- Contains the workflow YAML files. +- These files define our CI/CD pipelines and are triggered by GitHub events (e.g., pull requests). +- Each file in this folder represents an independent workflow that appears as a separate check on the PR screen. + +#### .github/actions/ +- Contains custom or composite actions that we reuse across multiple workflows. +- By modularizing common tasks (such as setting up Ruby and installing dependencies), we avoid code duplication and + ensure consistency across our checks (e.g., tests, RuboCop, Brakeman, bundler-audit). + +## Custom Composite Actions +### Why Use a Directory with an action.yml File? +For custom composite actions, GitHub Actions expects them to be structured as a directory that contains an action.yml file. + +For example, our Ruby dependencies setup is located at: +`.github/actions/setup-ruby-deps/action.yml`. +This is preferred over a standalone file like `.github/actions/setup-ruby-deps.yml` because: + +#### Standard Structure: +- GitHub recognizes a composite action by looking for an action.yml file inside a dedicated directory. +- This is the official and recommended approach. + +#### Modularity and Reusability: +- Organizing our custom actions into their own directories makes them easy to reuse and maintain. +- Each action can include additional resources (scripts, documentation, etc.) if needed. + +## Example: Setup Ruby and Dependencies Composite Action +The composite action in `.github/actions/setup-ruby-deps/action.yml` performs the following: + +1. Checks out the repository code. +2. Sets up Ruby using ruby/setup-ruby with bundler caching enabled. +3. Runs bundle install to install gem dependencies. + +This composite action can be used in multiple workflows (e.g., tests, RuboCop, Brakeman) to avoid duplicating these steps. + +## Usage in a Workflow +For example, our RuboCop workflow (`.github/workflows/rubocop.yml`) would use the composite action like this: +```aiignore +jobs: + rubocop: + runs-on: ubuntu-latest + steps: + - name: Setup Ruby and Dependencies + uses: ./.github/actions/setup-ruby-deps + - name: Run RuboCop + run: bundle exec rubocop + +``` +This ensures that the same setup process is consistently applied across our workflows. \ No newline at end of file From 6a6c3dd9a674eccd571d8070416777afe24119ba Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:04:00 -0400 Subject: [PATCH 03/20] Add ruby installation to setup-ruby-deps/action.yml --- .github/actions/setup-ruby-deps/action.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-ruby-deps/action.yml b/.github/actions/setup-ruby-deps/action.yml index 56b06246..6754c32a 100644 --- a/.github/actions/setup-ruby-deps/action.yml +++ b/.github/actions/setup-ruby-deps/action.yml @@ -1,9 +1,16 @@ -name: "Install Node Modules" -description: "Checks out code, sets up Node.js from .nvmrc with Yarn caching, and installs dependencies." +name: "Setup Ruby & Node" +description: "Sets up Ruby from .ruby-version with Bundler caching, and Node.js from .nvmrc with Yarn caching." + inputs: {} runs: using: "composite" steps: + - name: Set up Ruby from .ruby-version + uses: ruby/setup-ruby@v1 + with: + ruby-version: .ruby-version + bundler-cache: true + - name: Set up Node.js uses: actions/setup-node@v3 with: @@ -25,4 +32,4 @@ runs: uses: actions/cache@v3 with: path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} \ No newline at end of file + key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} From 610ba0040f3dba4210a162b49e66b98bf115ff8c Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:11:16 -0400 Subject: [PATCH 04/20] Put correct file at .github/actions/migrate/action.yml --- .github/actions/migrate/action.yml | 33 ++++++++++-------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/.github/actions/migrate/action.yml b/.github/actions/migrate/action.yml index 56b06246..87605312 100644 --- a/.github/actions/migrate/action.yml +++ b/.github/actions/migrate/action.yml @@ -1,28 +1,17 @@ -name: "Install Node Modules" -description: "Checks out code, sets up Node.js from .nvmrc with Yarn caching, and installs dependencies." +name: "Run Database Migrations" +description: "Checks out code, sets up Ruby, and runs database migrations in the test environment." inputs: {} runs: using: "composite" steps: - - name: Set up Node.js - uses: actions/setup-node@v3 + - name: Checkout Code + uses: actions/checkout@v3 + - name: Set up Ruby with Bundler Cache + uses: ruby/setup-ruby@v1 with: - node-version-file: '.nvmrc' - cache: 'yarn' - - - name: Restore node_modules cache - uses: actions/cache@v3 - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-node-modules- - - name: Install Dependencies - run: yarn install --frozen-lockfile + bundler-cache: true + - name: Run Migrations + run: RAILS_ENV=test bundle exec rails db:migrate + env: + RAILS_ENV: test shell: bash - - - name: Save node_modules cache - uses: actions/cache@v3 - with: - path: node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock') }} \ No newline at end of file From e1e337f648e79a459bf723606527e48b105b06f6 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:22:47 -0400 Subject: [PATCH 05/20] Disable spring when running migrations --- .github/actions/migrate/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/migrate/action.yml b/.github/actions/migrate/action.yml index 87605312..3e8ed037 100644 --- a/.github/actions/migrate/action.yml +++ b/.github/actions/migrate/action.yml @@ -10,8 +10,8 @@ runs: uses: ruby/setup-ruby@v1 with: bundler-cache: true - - name: Run Migrations - run: RAILS_ENV=test bundle exec rails db:migrate + - name: Run Migrations (Spring disabled) + run: DISABLE_SPRING=1 bundle exec rails db:migrate env: RAILS_ENV: test shell: bash From df3e65e517d1a7431cf1a21b76ed8c93a024859c Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:30:28 -0400 Subject: [PATCH 06/20] Disable spring when running tests --- .github/workflows/tests-and-coverage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests-and-coverage.yml b/.github/workflows/tests-and-coverage.yml index f2f86307..a484d521 100644 --- a/.github/workflows/tests-and-coverage.yml +++ b/.github/workflows/tests-and-coverage.yml @@ -14,6 +14,7 @@ jobs: # Job-level defaults env: RAILS_ENV: test + DISABLE_SPRING: 1 # Cancel stale runs on the same PR concurrency: From 768d0c89c986089cceb99d9e62dbc285ace32490 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:42:03 -0400 Subject: [PATCH 07/20] Stop caching webpack assets and build every time --- .../actions/build-webpack-assets/action.yml | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/actions/build-webpack-assets/action.yml b/.github/actions/build-webpack-assets/action.yml index 20f12767..c9e9e52b 100644 --- a/.github/actions/build-webpack-assets/action.yml +++ b/.github/actions/build-webpack-assets/action.yml @@ -1,26 +1,14 @@ name: "Build Webpack Assets" +description: "Runs Webpack build to generate JavaScript and CSS assets." runs: using: "composite" steps: - # 1. Restore existing build cache - - name: Restore Webpack Build Cache - id: webpack-cache # give this step an ID - uses: actions/cache@v3 - with: - path: public/build - key: ${{ runner.os }}-webpack-build-${{ hashFiles('app/javascript/**/*','yarn.lock','package.json') }} - restore-keys: | - ${{ runner.os }}-webpack-build- - # 2. Build assets only on cache miss - name: Build JavaScript & CSS Assets - if: steps.webpack-cache.outputs.cache-hit != 'true' run: yarn build shell: bash - # 3. Save new build only on cache miss - - name: Save Webpack Build Cache - if: steps.webpack-cache.outputs.cache-hit != 'true' - uses: actions/cache@v3 - with: - path: public/build - key: ${{ runner.os }}-webpack-build-${{ hashFiles('app/javascript/**/*','yarn.lock','package.json') }} \ No newline at end of file + - name: Confirm manifest.json was generated + run: | + echo "Checking for public/build/manifest.json..." + test -f public/build/manifest.json || { echo "❌ manifest.json missing"; exit 1; } + shell: bash From 8e9d3897cb7956b34e42580fccf423d2747c7867 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:48:49 -0400 Subject: [PATCH 08/20] Remove checking out code from the migrate action --- .github/actions/migrate/action.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/actions/migrate/action.yml b/.github/actions/migrate/action.yml index 3e8ed037..7efe91cd 100644 --- a/.github/actions/migrate/action.yml +++ b/.github/actions/migrate/action.yml @@ -1,11 +1,9 @@ name: "Run Database Migrations" -description: "Checks out code, sets up Ruby, and runs database migrations in the test environment." +description: "Sets up Ruby, and runs database migrations in the test environment." inputs: {} runs: using: "composite" steps: - - name: Checkout Code - uses: actions/checkout@v3 - name: Set up Ruby with Bundler Cache uses: ruby/setup-ruby@v1 with: From 0bf466032ed4759746289fb63d5856a545fae27d Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 10:56:23 -0400 Subject: [PATCH 09/20] Make spec/support/capybara.rb look for ENV['CHROME_BIN'] variable --- spec/support/capybara.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 0a901ad0..bec845cf 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -7,6 +7,13 @@ Capybara.register_driver :selenium_chrome_headless_sandboxless do |app| # Build Chrome options options = Selenium::WebDriver::Chrome::Options.new + + # Force use of pinned Chrome binary if present (e.g., from GitHub Actions) + chrome_bin = ENV['CHROME_BIN'] + if chrome_bin && File.exist?(chrome_bin) + options.binary = chrome_bin + end + options.add_argument('--headless') options.add_argument('--disable-gpu') options.add_argument('--no-sandbox') From 89a03aa56d1189ed1b4ae68dac0f220c9f633fb4 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 16:17:43 -0400 Subject: [PATCH 10/20] Restore spec_helper to qa version --- spec/spec_helper.rb | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index afe97eda..f7ba496c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,16 +5,21 @@ require 'coveralls' SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true -SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([ - SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::LcovFormatter, - Coveralls::SimpleCov::Formatter - ]) - SimpleCov.start 'rails' do - add_filter '/spec/' - add_filter '/lib/tasks/' - add_filter '/lib/capistrano/' + add_filter '/spec/' # Exclude all files in the spec directory + add_filter '/lib/tasks/' # Exclude all files in the lib/tasks directory + add_filter '/lib/capistrano/' # Exclude all files in the lib/capistrano directory +end + +SimpleCov.at_exit do + SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( + [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter, + Coveralls::SimpleCov::Formatter + ] + ) + SimpleCov.result.format! end require 'byebug' From 307406fbd724e20276f1565fb6a6d8cf71422c91 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Fri, 23 May 2025 16:20:36 -0400 Subject: [PATCH 11/20] Restore Gemfile to qa version --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index d4d70480..0890a39c 100644 --- a/Gemfile +++ b/Gemfile @@ -86,6 +86,8 @@ group :development, :test do gem 'coveralls_reborn' # Provides Ruby API for Coveralls.io code coverage reporting gem 'rubocop' # A Ruby static code analyzer and formatter gem 'rubocop-rails' # A RuboCop extension focused on enforcing Rails best practices + gem 'simplecov', require: false # Code coverage analysis tool for Ruby + gem 'simplecov-lcov', require: false # Formatter for SimpleCov that generates LCOV reports end group :development do @@ -106,8 +108,6 @@ group :test do gem 'rack-test' # Small, simple testing API for Rack apps gem 'rspec-rails', '~> 6.1.5' # RSpec for Rails 6+ gem 'shoulda-matchers', '~> 6.5' # Provides RSpec with additional matchers - gem 'simplecov', require: false # Code coverage analysis tool for Ruby - gem 'simplecov-lcov', require: false # Formatter for SimpleCov that generates LCOV reports end group :production do From 29c0337c650f07e2e651f4e86717339ba808ea64 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:25:09 -0400 Subject: [PATCH 12/20] Add rubocop workflow --- .github/workflows/rubocop.yml | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/rubocop.yml diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml new file mode 100644 index 00000000..b4d93859 --- /dev/null +++ b/.github/workflows/rubocop.yml @@ -0,0 +1,51 @@ +name: Ensure Rubocop Passes + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + rubocop: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Ruby and install gems + uses: ./.github/actions/setup-ruby-deps + + - name: Restore Rubocop Cache + uses: actions/cache@v3 + with: + path: .rubocop_cache + key: rubocop-cache-${{ runner.os }}-${{ hashFiles('**/*.rb') }} + restore-keys: | + rubocop-cache-${{ runner.os }}- + + - name: Run Rubocop and Save Output + run: | + mkdir -p tmp + bundle exec rubocop --format offenses --out tmp/rubocop-output.txt + continue-on-error: true + shell: bash + + - name: Analyze Rubocop Output + run: | + if grep -q 'Offense:' tmp/rubocop-output.txt; then + echo "Rubocop found offenses." + exit 1 + else + echo "Rubocop passed without offenses." + fi + shell: bash + + - name: Upload Rubocop Report + uses: actions/upload-artifact@v4 + with: + name: rubocop-report + path: tmp/rubocop-output.txt + + - name: Save Rubocop Cache + uses: actions/cache@v3 + with: + path: .rubocop_cache + key: rubocop-cache-${{ runner.os }}-${{ hashFiles('**/*.rb') }} From 15e844ab21fd5398c9a7fd0be50364fec8df9f4e Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:29:26 -0400 Subject: [PATCH 13/20] Simplify Rubocop workflow to rely on native exit code and remove manual checks --- .github/workflows/rubocop.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index b4d93859..e2623c1e 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -25,17 +25,6 @@ jobs: run: | mkdir -p tmp bundle exec rubocop --format offenses --out tmp/rubocop-output.txt - continue-on-error: true - shell: bash - - - name: Analyze Rubocop Output - run: | - if grep -q 'Offense:' tmp/rubocop-output.txt; then - echo "Rubocop found offenses." - exit 1 - else - echo "Rubocop passed without offenses." - fi shell: bash - name: Upload Rubocop Report From 87f91e20fca2f3c8729ac438e1c7800aff886f3a Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:36:54 -0400 Subject: [PATCH 14/20] Remove extra 'require' statement(bug) --- .rubocop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index 4fb05715..6358ae25 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ require: - rubocop - - rubocop-rails + inherit_from: .rubocop_todo.yml plugins: From 95e6c924b3fd194ef402ca40ae2139f70fbfc56a Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:41:33 -0400 Subject: [PATCH 15/20] Use tee to output rubocop file --- .github/workflows/rubocop.yml | 2 +- spec/support/capybara.rb | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index e2623c1e..207b674e 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -24,7 +24,7 @@ jobs: - name: Run Rubocop and Save Output run: | mkdir -p tmp - bundle exec rubocop --format offenses --out tmp/rubocop-output.txt + bundle exec rubocop --format offenses | tee tmp/rubocop-output.txt shell: bash - name: Upload Rubocop Report diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index bec845cf..4a14def4 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -9,10 +9,8 @@ options = Selenium::WebDriver::Chrome::Options.new # Force use of pinned Chrome binary if present (e.g., from GitHub Actions) - chrome_bin = ENV['CHROME_BIN'] - if chrome_bin && File.exist?(chrome_bin) - options.binary = chrome_bin - end + chrome_bin = ENV.fetch('CHROME_BIN', nil) + options.binary = chrome_bin if chrome_bin && File.exist?(chrome_bin) options.add_argument('--headless') options.add_argument('--disable-gpu') From 891c1362a3284b5c84d3f9b3bf1500b612513c2e Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:44:50 -0400 Subject: [PATCH 16/20] Intentionally add Rubocop error --- .../controllers/abbreviated_treatment_reports_controller_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/controllers/abbreviated_treatment_reports_controller_spec.rb b/spec/controllers/abbreviated_treatment_reports_controller_spec.rb index f4d1f576..764c2076 100644 --- a/spec/controllers/abbreviated_treatment_reports_controller_spec.rb +++ b/spec/controllers/abbreviated_treatment_reports_controller_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true - require 'rails_helper' RSpec.describe AbbreviatedTreatmentReportsController, type: :controller do From 7f3eccade792a641b35fdc5b7a3a321181bb1b3a Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:48:41 -0400 Subject: [PATCH 17/20] Use format 'progress' for human-readable error output --- .github/workflows/rubocop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index 207b674e..51a9e68d 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -24,7 +24,7 @@ jobs: - name: Run Rubocop and Save Output run: | mkdir -p tmp - bundle exec rubocop --format offenses | tee tmp/rubocop-output.txt + bundle exec rubocop --format progress | tee tmp/rubocop-output.txt shell: bash - name: Upload Rubocop Report From 2f4992e74ad0c2e9aec3217e930ad4bcec12a67d Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 14:49:50 -0400 Subject: [PATCH 18/20] Fix testing rubocop error --- .../controllers/abbreviated_treatment_reports_controller_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/controllers/abbreviated_treatment_reports_controller_spec.rb b/spec/controllers/abbreviated_treatment_reports_controller_spec.rb index 764c2076..f4d1f576 100644 --- a/spec/controllers/abbreviated_treatment_reports_controller_spec.rb +++ b/spec/controllers/abbreviated_treatment_reports_controller_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require 'rails_helper' RSpec.describe AbbreviatedTreatmentReportsController, type: :controller do From 6b5dc7e63555e913ee55490780668a8241b12c22 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Mon, 2 Jun 2025 12:06:09 -0400 Subject: [PATCH 19/20] Gemfile.lock update after merging in qa --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 862db323..5ebb134b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -377,11 +377,11 @@ PLATFORMS aarch64-linux aarch64-linux-gnu aarch64-linux-musl - arm64-darwin-23 arm-linux arm-linux-gnu arm-linux-musl arm64-darwin + arm64-darwin-23 x86-linux x86-linux-gnu x86-linux-musl From 6fc3c82d1f53ec3aa8a56950792b5e03b0a36433 Mon Sep 17 00:00:00 2001 From: Glen Horton Date: Mon, 2 Jun 2025 17:15:31 -0400 Subject: [PATCH 20/20] Test for rubocop CI --- app/controllers/abbreviated_treatment_reports_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/abbreviated_treatment_reports_controller.rb b/app/controllers/abbreviated_treatment_reports_controller.rb index 3810c1a8..b0341e50 100644 --- a/app/controllers/abbreviated_treatment_reports_controller.rb +++ b/app/controllers/abbreviated_treatment_reports_controller.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - class AbbreviatedTreatmentReportsController < ApplicationController def create @abbreviated_treatment_report = AbbreviatedTreatmentReport.new