Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ jobs:
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Setup test database
run: cd test/dummy && bundle exec rake db:migrate RAILS_ENV=test
- name: Run tests
- name: Run tests (includes prepare_dummy)
run: bundle exec rake test
lint:
runs-on: ubuntu-latest
Expand All @@ -39,3 +37,20 @@ jobs:
run: bundle install
- name: bundle exec standardrb
run: bundle exec standardrb
security:
runs-on: ubuntu-latest
name: Security - Brakeman (Rails ${{ matrix.rails }})
strategy:
matrix:
rails: ["~> 8.0.0", "~> 8.1.0"]
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.4
bundler-cache: true
- name: bundle install
run: bundle install
- name: Run Brakeman vendor scan
run: RAILS_VERSION="${{ matrix.rails }}" bundle exec rake brakeman:vendor_scan
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ GEM
ast (2.4.3)
base64 (0.3.0)
bigdecimal (3.3.1)
brakeman (7.1.1)
racc
builder (3.3.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.4)
Expand Down Expand Up @@ -256,6 +258,7 @@ PLATFORMS
ruby

DEPENDENCIES
brakeman
bunko!
irb
minitest (~> 5.16)
Expand Down
132 changes: 132 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,138 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Testing

Bunko uses a unique approach to testing: **generated files are regenerated before every test run**.

### How It Works

The `test/dummy` Rails application uses a mix of **generated** and **hand-crafted** files:

```bash
rake test
# 1. Runs bunko:install (creates migrations, models, initializer)
# 2. Runs db:migrate (sets up database)
# 3. Runs bunko:setup (generates controllers and views from .tt templates)
# 4. Runs test suite
```

**Files regenerated on every test run** (`.gitignore`d):
- `app/models/post.rb` and `post_type.rb` - From install templates
- `app/controllers/blog_controller.rb` - From setup template
- `app/controllers/pages_controller.rb` - From setup template
- `app/views/blog/**/*.erb` - From setup templates
- `app/views/shared/**/*.erb` - From setup templates
- `config/initializers/bunko.rb` - From install template
- `db/migrate/*_create_bunko_*.rb` - From install templates

**Files committed for specific test purposes:**
- `app/controllers/docs_controller.rb` - Custom `per_page: 5` for pagination tests
- `app/controllers/articles_controller.rb` - For routing tests
- `app/controllers/videos_controller.rb` - For routing tests
- `app/controllers/all_content_controller.rb` - For collection tests
- `app/controllers/long_reads_controller.rb` - For collection tests
- `app/controllers/nonexistent_controller.rb` - For error handling tests
- `app/controllers/legal/pages_controller.rb` - For namespaced routing tests
- `config/initializers/bunko_test_config.rb` - Adds test-specific post_types and collections
- `config/routes.rb` - Test routes and root route

### Why This Approach?

**Benefits:**
- ✅ Tests verify templates generate working code
- ✅ Template changes are automatically tested
- ✅ No stale committed files getting out of sync
- ✅ If a template breaks, tests fail immediately

**Example:** If someone modifies `lib/tasks/templates/controller.rb.tt` and introduces a bug, the test suite catches it because controllers are regenerated from that template.

### Running Tests

```bash
# Run all tests (includes prepare step)
bundle exec rake test

# Run a specific test file
bundle exec ruby test/models/post_slug_test.rb

# Run with coverage
bundle exec rake test

# Run linter
bundle exec rake standard
```

### Test Structure

```
test/
├── models/ # Post and PostType behavior tests
├── controllers/ # Collection concern and pagination tests
├── routing/ # Routing DSL tests
├── tasks/ # Generator and rake task tests
├── configuration/ # Configuration system tests
└── dummy/ # Minimal Rails app (mix of generated + committed files)
├── app/
│ ├── models/ # ⚡ Generated on test run
│ ├── controllers/
│ │ ├── blog_controller.rb # ⚡ Generated from template
│ │ ├── docs_controller.rb # ✓ Committed (custom per_page)
│ │ ├── articles_controller.rb # ✓ Committed (test routes)
│ │ └── ... # ✓ More test controllers
│ └── views/
│ ├── blog/ # ⚡ Generated from templates
│ └── shared/ # ⚡ Generated from templates
└── config/
├── routes.rb # ✓ Committed (test routes + root route)
└── initializers/
├── bunko.rb # ⚡ Generated from install template
└── bunko_test_config.rb # ✓ Committed (test-specific config)
```

**Legend:**
- ⚡ = Regenerated on every test run (`.gitignore`d)
- ✓ = Committed (hand-crafted for specific test scenarios)

### CI Testing

GitHub Actions runs the full test suite on every PR:
- Ruby versions: 3.2, 3.3, 3.4, 3.5
- All tests with fresh generated code
- StandardRB linting
- Brakeman security scans (Rails 8.0.x and 8.1.x)

## Security

Bunko includes automated security scanning using [Brakeman](https://brakemanscanner.org/).

**What we scan:**
- ✅ Gem source code (models, controllers, routing)
- ✅ Generated code from templates (controllers, views)
- ✅ Tested against Rails 8.0.x and 8.1.x

**CI Security Checks:**

Every PR triggers parallel scans across Rails versions. Builds fail if security warnings are detected.

**Run scans locally:**

```bash
bundle exec rake brakeman:vendor_scan
RAILS_VERSION="~> 8.1.0" bundle exec rake brakeman:vendor_scan
```

**Reporting Security Issues:**

Please report vulnerabilities privately via email rather than public GitHub issues.

**Security Best Practices:**

1. Sanitize user input with Rails' `sanitize` helper
2. Use strong parameters in controllers
3. Keep Rails and Bunko updated
4. Review generated code from `bunko:setup`

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/kanejamison/bunko. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to be kind and respectful.
Expand Down
38 changes: 37 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,45 @@

require "bundler/gem_tasks"
require "minitest/test_task"
require "standard/rake"

# Load brakeman vendor scan task
load "lib/tasks/brakeman_vendor.rake"

# Prepare test/dummy app before running tests
desc "Prepare test/dummy app (install, migrate, setup)"
task :prepare_dummy do
dummy_path = "test/dummy"

puts "Preparing test/dummy app..."

# Run bunko:install
Dir.chdir(dummy_path) do
sh "rake bunko:install RAILS_ENV=test"
end

# Run migrations
Dir.chdir(dummy_path) do
sh "rake db:migrate RAILS_ENV=test"
end

# Run bunko:setup
Dir.chdir(dummy_path) do
sh "rake bunko:setup RAILS_ENV=test"
end

# Clean test database to avoid conflicts with test fixtures
Dir.chdir(dummy_path) do
sh "rake db:test:prepare RAILS_ENV=test"
end

puts "✓ test/dummy app ready"
end

# Create test task
Minitest::TestTask.create

require "standard/rake"
# Make test task depend on prepare_dummy
task test: :prepare_dummy

task default: %i[test standard]
1 change: 1 addition & 0 deletions bunko.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ Gem::Specification.new do |spec|

# Development dependencies
spec.add_development_dependency "sqlite3", "~> 2.0"
spec.add_development_dependency "brakeman"
end
Loading