.github/copilot-instructions.md: init
This commit is contained in:
parent
3ef0ec2065
commit
a708d89b2e
1 changed files with 166 additions and 0 deletions
166
.github/copilot-instructions.md
vendored
Normal file
166
.github/copilot-instructions.md
vendored
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
---
|
||||||
|
description: 'L4D Tools - Rails 8.1 application with Solid Queue, Hotwire stack'
|
||||||
|
applyTo: '**/*.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
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
```bash
|
||||||
|
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)
|
||||||
|
```ruby
|
||||||
|
# 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
|
||||||
|
```ruby
|
||||||
|
# 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
|
||||||
|
```javascript
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```erb
|
||||||
|
<!-- View: -->
|
||||||
|
<div data-controller="search">
|
||||||
|
<input type="text" data-search-target="input" data-action="input->search#search">
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Pattern (Minitest)
|
||||||
|
```ruby
|
||||||
|
# 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
|
||||||
Loading…
Reference in a new issue