From 760615710ec6aa23a1b4bdfc9ec66d4340b4d312 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Thu, 22 May 2025 09:43:38 -0400 Subject: [PATCH 01/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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 d4239a474c41fc506aeccc171889811c4c6e2f63 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 15:11:40 -0400 Subject: [PATCH 12/25] Add GitHub Actions workflow to run bundler-audit and fail on high-risk issues --- .github/workflows/bundler-audit.yml | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/bundler-audit.yml diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml new file mode 100644 index 00000000..a26926e7 --- /dev/null +++ b/.github/workflows/bundler-audit.yml @@ -0,0 +1,43 @@ +name: Ensure Bundler-Audit Passes + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + bundler-audit: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Ruby and install gems + uses: ./.github/actions/setup-ruby-deps + + - name: Run Bundler-Audit + run: | + mkdir -p tmp + bundle exec bundler-audit check --update > tmp/bundler-audit-output.txt + AUDIT_EXIT=$? + if [ $AUDIT_EXIT -ne 0 ] && [ $AUDIT_EXIT -ne 1 ]; then + echo "bundler-audit failed unexpectedly (exit code $AUDIT_EXIT)" + exit $AUDIT_EXIT + fi + shell: bash + + - name: Analyze Bundler-Audit Output + run: | + if grep -Eq '^Name:|Critical|High' tmp/bundler-audit-output.txt; then + echo "High or Critical vulnerabilities detected!" + cat tmp/bundler-audit-output.txt + exit 1 + else + echo "No High or Critical vulnerabilities detected." + fi + shell: bash + + - name: Upload Bundler-Audit Report + uses: actions/upload-artifact@v4 + with: + name: bundler-audit-report + path: tmp/bundler-audit-output.txt From c6614305bebc7105bf3afc5bafdd5de919834b3b Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 15:16:20 -0400 Subject: [PATCH 13/25] Intentionally un-ignore CVE-2022-25765 --- .bundler-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index 8aa41a51..1b5aa1bb 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,3 +1,3 @@ --- ignore: - - CVE-2022-25765 +# - CVE-2022-25765 From 95f5eb418990d4c467c002e64bb73007396327fc Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 15:23:23 -0400 Subject: [PATCH 14/25] Allow bundler-audit to exit with code 1 for vulnerability findings without failing the step --- .bundler-audit.yml | 2 +- .github/workflows/bundler-audit.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index 1b5aa1bb..8aa41a51 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,3 +1,3 @@ --- ignore: -# - CVE-2022-25765 + - CVE-2022-25765 diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml index a26926e7..f0d98ffa 100644 --- a/.github/workflows/bundler-audit.yml +++ b/.github/workflows/bundler-audit.yml @@ -17,8 +17,11 @@ jobs: - name: Run Bundler-Audit run: | mkdir -p tmp + # Allow bundler-audit to return 1 (vulnerabilities found) without failing the step + set +e bundle exec bundler-audit check --update > tmp/bundler-audit-output.txt AUDIT_EXIT=$? + set -e if [ $AUDIT_EXIT -ne 0 ] && [ $AUDIT_EXIT -ne 1 ]; then echo "bundler-audit failed unexpectedly (exit code $AUDIT_EXIT)" exit $AUDIT_EXIT From c8fdf01fea7d1cefe54781e1836d464102b6fdd9 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Tue, 27 May 2025 15:42:58 -0400 Subject: [PATCH 15/25] Remove obsolete bundler-audit ignore, add nokogiri ignore --- .bundler-audit.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index 8aa41a51..086a2833 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,3 +1,4 @@ --- ignore: - - CVE-2022-25765 + # Need to update Nokogiri to >= 1.18.4 + - GHSA-mrxw-mxhj-p664 From 18c0436cee7f8641c715d21a26e1b54178908871 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:38:27 -0400 Subject: [PATCH 16/25] Update regex check for Critical/High, intentionally fail with a high-level vulnerability --- .github/workflows/bundler-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml index f0d98ffa..65d3f9cc 100644 --- a/.github/workflows/bundler-audit.yml +++ b/.github/workflows/bundler-audit.yml @@ -30,7 +30,7 @@ jobs: - name: Analyze Bundler-Audit Output run: | - if grep -Eq '^Name:|Critical|High' tmp/bundler-audit-output.txt; then + if grep -Eq 'Critical|High' tmp/bundler-audit-output.txt; then echo "High or Critical vulnerabilities detected!" cat tmp/bundler-audit-output.txt exit 1 From 7335a0e9a309ddf3e2782b03048ab3cd8e6a74a0 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:40:49 -0400 Subject: [PATCH 17/25] Remove .bundler-audit file --- .bundler-audit.yml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .bundler-audit.yml diff --git a/.bundler-audit.yml b/.bundler-audit.yml deleted file mode 100644 index 086a2833..00000000 --- a/.bundler-audit.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -ignore: - # Need to update Nokogiri to >= 1.18.4 - - GHSA-mrxw-mxhj-p664 From a294f2896a4bbfdc52707a65796827ffa8b714b4 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:46:59 -0400 Subject: [PATCH 18/25] Re-add .bundler_audit.yml --- .bundler-audit.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .bundler-audit.yml diff --git a/.bundler-audit.yml b/.bundler-audit.yml new file mode 100644 index 00000000..ad4e701e --- /dev/null +++ b/.bundler-audit.yml @@ -0,0 +1,3 @@ +--- +ignore: + - GHSA-mrxw-mxhj-p664 From d2bf1fa66a7dcca217d705f2ee5be4ad20f4d71c Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:50:14 -0400 Subject: [PATCH 19/25] Look for Criticality: Critical/High --- .github/workflows/bundler-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml index 65d3f9cc..90c591f8 100644 --- a/.github/workflows/bundler-audit.yml +++ b/.github/workflows/bundler-audit.yml @@ -30,7 +30,7 @@ jobs: - name: Analyze Bundler-Audit Output run: | - if grep -Eq 'Critical|High' tmp/bundler-audit-output.txt; then + if grep -Eq '^Criticality:\s*(Critical|High)' tmp/bundler-audit-output.txt; then echo "High or Critical vulnerabilities detected!" cat tmp/bundler-audit-output.txt exit 1 From 4fd13567e36f4f06c4c52cc7514a6539725f1fa7 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:51:58 -0400 Subject: [PATCH 20/25] Don't ignore known vulnerability --- .bundler-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index ad4e701e..49877bd1 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,3 +1,3 @@ --- ignore: - - GHSA-mrxw-mxhj-p664 + # - GHSA-mrxw-mxhj-p664 From 8379942eb8413740dbc7afb1eefed99f6059254f Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:53:27 -0400 Subject: [PATCH 21/25] Add fake issue to ignore --- .bundler-audit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index 49877bd1..6d35264d 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,3 +1,4 @@ --- ignore: # - GHSA-mrxw-mxhj-p664 + - GHSA-abcd-efgh-p1234 From 7a69f00e4157652399f959b67cc8aa50a3a905b0 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:53:45 -0400 Subject: [PATCH 22/25] Add fake issue to ignore --- .bundler-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index 6d35264d..e7282fc0 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,4 +1,4 @@ --- ignore: # - GHSA-mrxw-mxhj-p664 - - GHSA-abcd-efgh-p1234 + - GQSA-abcd-efgh-p1234 From bd4c0650c122ba3ff48c2f67392d90455e89e2b5 Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Wed, 28 May 2025 16:56:37 -0400 Subject: [PATCH 23/25] Restore correct .bundler-audit ignore --- .bundler-audit.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bundler-audit.yml b/.bundler-audit.yml index e7282fc0..d1402f6a 100644 --- a/.bundler-audit.yml +++ b/.bundler-audit.yml @@ -1,4 +1,4 @@ --- ignore: - # - GHSA-mrxw-mxhj-p664 - - GQSA-abcd-efgh-p1234 + # Nokogiri needs to be upgraded >= 1.18.4 + - GHSA-mrxw-mxhj-p664 From ef361de0984fc64b5b59418bd7a6e81fd9b4cd4e Mon Sep 17 00:00:00 2001 From: Janell-Huyck Date: Mon, 2 Jun 2025 12:07:19 -0400 Subject: [PATCH 24/25] Update Gemfile 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 acff8bf178a14a0a55cfd7181fa33c6ee1685d91 Mon Sep 17 00:00:00 2001 From: Glen Horton Date: Mon, 2 Jun 2025 17:22:56 -0400 Subject: [PATCH 25/25] test 144 --- .bundler-audit.yml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .bundler-audit.yml diff --git a/.bundler-audit.yml b/.bundler-audit.yml deleted file mode 100644 index d1402f6a..00000000 --- a/.bundler-audit.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -ignore: - # Nokogiri needs to be upgraded >= 1.18.4 - - GHSA-mrxw-mxhj-p664