name: CI permissions: contents: read on: pull_request: push: branches: [main] jobs: scan_ruby: runs-on: ubuntu-latest permissions: contents: read security-events: write steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Scan for common Rails security vulnerabilities using static analysis continue-on-error: true run: bin/brakeman --no-pager -f sarif -o brakeman.sarif.json - name: Upload SARIF to GitHub Code Scanning uses: github/codeql-action/upload-sarif@v4 with: sarif_file: brakeman.sarif.json scan_js: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Scan for security vulnerabilities in JavaScript dependencies run: bin/importmap audit lint: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Lint code for consistent style run: bin/rubocop -f github frontend: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Bun uses: oven-sh/setup-bun@v2 - name: Install JavaScript dependencies run: bun install --frozen-lockfile - name: Run Svelte type checks run: bun run check:svelte - name: Run Svelte formatting checks run: bun run format:svelte:check zeitwerk: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Run Rails Zeitwerk check run: bin/rails zeitwerk:check test: runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: app_test steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Run tests env: RAILS_ENV: test TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test PGHOST: localhost PGUSER: postgres PGPASSWORD: postgres run: | bin/rails db:create RAILS_ENV=test bin/rails db:schema:load RAILS_ENV=test bin/rails test - name: Ensure Swagger docs are up to date env: RAILS_ENV: test TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test PGHOST: localhost PGUSER: postgres PGPASSWORD: postgres run: | bin/rails rswag:specs:swaggerize git diff --exit-code swagger/v1/swagger.yaml test_system: runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: app_test steps: - name: Checkout code uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: .ruby-version bundler-cache: true - name: Set up Bun uses: oven-sh/setup-bun@v2 # Pin Chrome to version 133 to avoid flaky system test failures. # Chrome 134+ has a known bug causing intermittent Selenium/Capybara failures # where session paths don't update correctly after visit() calls. # See: https://github.com/teamcapybara/capybara/issues/2800 # Remove this pin once the upstream issue is resolved. - name: Setup Chrome id: setup-chrome uses: browser-actions/setup-chrome@latest with: chrome-version: 133 install-chromedriver: true - name: Install JavaScript dependencies run: bun install --frozen-lockfile - name: Pre-build Vite assets for test run: bin/vite build env: RAILS_ENV: test - name: Run system tests env: RAILS_ENV: test TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test PGHOST: localhost PGUSER: postgres PGPASSWORD: postgres CHROME_BIN: ${{ steps.setup-chrome.outputs.chrome-path }} CHROMEDRIVER_BIN: ${{ steps.setup-chrome.outputs.chromedriver-path }} run: | bin/rails db:create RAILS_ENV=test bin/rails db:schema:load RAILS_ENV=test bin/rails test:system - name: Keep screenshots from failed system tests uses: actions/upload-artifact@v7 if: failure() with: name: screenshots path: ${{ github.workspace }}/tmp/screenshots if-no-files-found: ignore