l4d.tools/.github/copilot-instructions.md
CroneKorkN a708d89b2e
Some checks are pending
CI / scan_ruby (push) Waiting to run
CI / scan_js (push) Waiting to run
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / system-test (push) Waiting to run
.github/copilot-instructions.md: init
2026-01-18 12:41:33 +01:00

6.2 KiB

description applyTo
L4D Tools - Rails 8.1 application with Solid Queue, Hotwire stack **/*.rb

L4D Tools - AI Coding Guide

Project Overview

l4d_tools is a Rails 8.1 application using modern Rails conventions. Key architectural decisions:

  • Database: SQLite (development), supports production deployment via Kamal/Docker
  • Job Processing: Solid Queue (replaces Sidekiq) - background jobs embedded with app via :solid_queue plugin in Puma
  • Frontend Stack: Hotwire (Turbo + Stimulus) with importmap-rails and Propshaft
  • Testing: Minitest with Capybara for system tests (parallelized workers)
  • Deployment: Kamal-based Docker containerization with private registry support
  • Security Scanning: Brakeman (security), Rubocop-rails-omakase (style), Bundler-audit (gems)

Critical Developer Workflows

Initial Setup

bin/setup                    # Installs gems, prepares DB, starts server
bin/setup --reset            # Full reset including DB wipe
bin/setup --skip-server      # Setup without starting server

Development Commands

bin/dev                      # Start Rails server (port 3000)
bin/rails console            # REPL with app context
bin/rails test               # Full test suite (parallel workers)
bin/rails test test/path     # Specific test file/directory
bundle exec brakeman         # Security vulnerability scan
bundle exec rubocop -a       # Auto-fix style violations

Database Management

bin/rails db:prepare         # Create/migrate DB
bin/rails db:reset           # Wipe and re-seed
bin/rails db:migrate         # Apply pending migrations
bin/rails db:rollback        # Revert last migration

Deployment (Kamal/Docker)

  • Config: config/deploy.yml - registry, servers, environment variables
  • Secrets: .kamal/secrets file (contains RAILS_MASTER_KEY)
  • Registry: Private registry at localhost:5555 for deployment target
  • Job Processing: SOLID_QUEUE_IN_PUMA=true runs supervisor in web process (single-server only)
  • Build: docker build -t l4d_tools . builds production image

Architecture & Key Components

Job Processing (Solid Queue)

  • Location: app/jobs/
  • Pattern: Inherit from ApplicationJob < ActiveJob::Base
  • Configuration: config/queue.yml defines adapters and queues
  • Execution: Jobs run synchronously in test mode; async in development/production
  • Puma Integration: plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] in config/puma.rb
  • Usage: MyJob.perform_later(args) for async; MyJob.perform_now(args) for testing

Frontend (Hotwire)

  • Turbo: Rapid page transitions via AJAX without full reloads
  • Stimulus: Minimal DOM binding framework; controllers in app/javascript/controllers/
  • Asset Pipeline: Propshaft + importmap-rails; no build step needed
  • Entry Point: app/javascript/application.js loads all controllers
  • Naming: data-controller="hello" maps to HelloController in app/javascript/controllers/hello_controller.js

Database & Models

  • Schema: db/schema.rb auto-generated from migrations (commit to VCS)
  • Migrations: Generate via bin/rails generate migration CreateTableName
  • Patterns: Use model scopes for complex queries; keep migrations simple and reversible
  • Fixtures: YAML files in test/fixtures/*.yml auto-loaded by Minitest

Testing Structure

  • Unit Tests: test/models/, test/helpers/, test/controllers/
  • Integration Tests: test/integration/
  • System Tests: Full browser tests via Capybara/Selenium
  • Parallelization: Enabled by default; workers scale to CPU count
  • Fixtures: Auto-loaded and available as lowercase underscore-separated variables (e.g., posts(:one))

Project-Specific Guidelines

  • Follow RuboCop-rails-omakase style guide strictly; run rubocop -a to auto-fix
  • Use snake_case for variables/methods, CamelCase for classes
  • Extract reusable business logic into app/services/ to keep models lean
  • Use Solid Queue perform_later for background work; never block HTTP requests
  • Prefer Turbo Frames for dynamic UI updates over full page reloads
  • Write tests using fixtures; auto-loaded into test instance variables
  • Use bin/rails test to run full suite with parallel workers
  • Keep config/routes.rb simple; add routes only when adding controller actions
  • Store secrets in Rails.application.credentials (encrypted via master.key)
  • Debug with byebug or Rails logger; avoid puts for production debugging

Common Patterns

Job Enqueue (Solid Queue)

# app/jobs/my_job.rb
class MyJob < ApplicationJob
  queue_as :default

  def perform(arg1, arg2)
    # async work here
  end
end

# Trigger: MyJob.perform_later(arg1, arg2)
# Test: MyJob.perform_now(arg1, arg2)

Model Scopes & Queries

# app/models/post.rb
class Post < ApplicationRecord
  scope :published, -> { where(published: true) }
  scope :recent, -> { order(created_at: :desc) }

  def self.active; where(active: true); end
end

# Usage: Post.published.recent

Stimulus Controller

// app/javascript/controllers/search_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["input"]

  search() {
    console.log(this.inputTarget.value)
  }
}
<!-- View: -->
<div data-controller="search">
  <input type="text" data-search-target="input" data-action="input->search#search">
</div>

Test Pattern (Minitest)

# test/models/post_test.rb
class PostTest < ActiveSupport::TestCase
  fixtures :posts  # Auto-loads test/fixtures/posts.yml

  test "post is valid" do
    assert posts(:one).valid?
  end
end

Security & Production Readiness

  • Brakeman scans detect security issues; fix all warnings before merge
  • Bundler-audit tracks vulnerable gems; update versions regularly
  • Strong parameters required for all user input in controllers
  • RAILS_MASTER_KEY (from config/master.key) must be set in Docker via secrets
  • SQLite adequate for single-server; use PostgreSQL for multi-server scaling
  • Content Security Policy configured in config/initializers/content_security_policy.rb
  • Never commit master.key or .kamal/secrets; set RAILS_MASTER_KEY via environment