Skip to content

Commit

Permalink
Default to creating GitHub CI files (#50508)
Browse files Browse the repository at this point in the history
* Default to creating GitHub CI files
  • Loading branch information
dhh committed Dec 31, 2023
1 parent e3da4fc commit 08a792b
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 1 deletion.
4 changes: 4 additions & 0 deletions railties/CHANGELOG.md
@@ -1,3 +1,7 @@
* Add GitHub CI files for dependabot, brakeman, rubocop, and running tests by default. Can be skipped with --skip-ci.

*DHH*

* Add brakeman gem by default for static analysis of security vulnerabilities. Allow skipping with --skip-brakeman option.

*vipulnsward*
Expand Down
7 changes: 7 additions & 0 deletions railties/lib/rails/generators/app_base.rb
Expand Up @@ -106,6 +106,9 @@ def self.add_shared_options_for(name)
class_option :skip_brakeman, type: :boolean, default: nil,
desc: "Skip brakeman setup"

class_option :skip_ci, type: :boolean, default: nil,
desc: "Skip GitHub CI files"

class_option :dev, type: :boolean, default: nil,
desc: "Set up the #{name} with Gemfile pointing to your Rails checkout"

Expand Down Expand Up @@ -393,6 +396,10 @@ def skip_brakeman?
options[:skip_brakeman]
end

def skip_ci?
options[:skip_ci]
end

class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
def initialize(name, version, comment, options = {}, commented_out = false)
super
Expand Down
11 changes: 11 additions & 0 deletions railties/lib/rails/generators/rails/app/app_generator.rb
Expand Up @@ -82,6 +82,12 @@ def dockerfiles
chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false
end

def cifiles
empty_directory ".github/workflows"
template "github/ci.yml", ".github/workflows/ci.yaml"
template "github/dependabot.yml", ".github/dependabot.yaml"
end

def rubocop
template "rubocop.yml", ".rubocop.yml"
end
Expand Down Expand Up @@ -377,6 +383,11 @@ def create_rubocop_file
build(:rubocop)
end

def create_cifiles
return if skip_ci?
build(:cifiles)
end

def create_config_files
build(:config)
end
Expand Down
105 changes: 105 additions & 0 deletions railties/lib/rails/generators/rails/app/templates/github/ci.yml.tt
@@ -0,0 +1,105 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
<%- unless skip_brakeman? -%>
scan:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true

- name: Scan for security vulnerabilities
run: bin/brakeman
<% end -%>
<%- unless skip_rubocop? -%>

lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- 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
<% end -%>

test:
runs-on: ubuntu-latest

<%- if options[:database] == "sqlite3" -%>
# services:
# redis:
# image: redis
# ports:
# - 6379:6379
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
<%- else -%>
services:
<%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
mysql:
image: mysql
env:
MYSQL_ALLOW_EMPTY_PASSWORD: true
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
<%- elsif options[:database] == "postgresql" -%>
postgres:
image: postgres
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=3
<%- end -%>

# redis:
# image: redis
# ports:
# - 6379:6379
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5

<%- end -%>
steps:
- name: Install packages
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable <%= (dockerfile_deploy_packages + [build_package_for_database]).join(" ") %>

- name: Checkout code
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true

- name: Run Tests
env:
RAILS_ENV: test
<%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
DATABASE_URL: mysql2://127.0.0.1:3306
<%- elsif options[:database] == "postgresql" -%>
DATABASE_URL: postgres://postgres:postgres@localhost:5432
<%- end -%>
# REDIS_URL: redis://localhost:6379/0
run: bin/rails db:setup test test:system
@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
14 changes: 13 additions & 1 deletion railties/test/generators/app_generator_test.rb
Expand Up @@ -653,13 +653,25 @@ def test_brakeman_is_skipped_if_required
end

def test_both_brakeman_and_rubocop_binstubs_are_skipped_if_required
puts destination_root
run_generator [destination_root, "--skip-brakeman", "--skip-rubocop"]

assert_no_file "bin/rubocop"
assert_no_file "bin/brakeman"
end

def test_inclusion_of_ci_files
run_generator
assert_file ".github/workflows/ci.yml"
assert_file ".github/dependabot.yml"
end

def test_ci_files_are_skipped_if_required
run_generator [destination_root, "--skip-ci"]

assert_no_file ".github/workflows/ci.yml"
assert_no_file ".github/dependabot.yml"
end

def test_usage_read_from_file
assert_called(File, :read, returns: "USAGE FROM FILE") do
assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc
Expand Down

0 comments on commit 08a792b

Please sign in to comment.