CI/CD with GitHub actions

Set up GitHub actions to run tests and linters and automerging for certain pull-requests
Icons/chart bar
Used 90 times
Created by
T TobiasBales

Usage

Run this command in your Rails app directory in the terminal:

rails app:template LOCATION="https://railsbytes.com/script/zJosd1"
Template Source

Review the code before running this template on your machine.

def create_script(filename, &block)
  create_file filename do <<~SH
    #!/usr/bin/env bash
    set -euo pipefail

    #{yield}
  SH
  end
  run `chmod +x #{filename}`
end

def add_to_script_if_installed(package, command)
  if file_contains?('Gemfile', package) || file_contains?('package.json', package)
    <<~SH
    
    echo "Running #{package}"
    #{command}
    SH
  end
end

def file_contains?(filename, string)
  File.foreach(filename).detect { |line| line.include?(string) }
end

create_script 'bin/linters_ci' do <<~SH
  #{add_to_script_if_installed 'rubocop', 'bundle exec rubocop'}
  #{add_to_script_if_installed 'annotate', 'bundle exec annotate --frozen'}
  #{add_to_script_if_installed 'erb_lint', 'bundle exec erblint --lint-all'}
  #{add_to_script_if_installed 'rails_best_practices', 'bundle exec rails_best_practices --config rails_best_practices.yml --silent'}
  #{add_to_script_if_installed 'database_consistency', 'bundle exec database_consistency'}
  #{add_to_script_if_installed 'fasterer', 'bundle exec fasterer'}
  #{add_to_script_if_installed 'eslint', 'npx eslint app'}
  #{add_to_script_if_installed 'stylelint', 'npx stylelint "app/**/*.?(s)css"'}
  SH
end


create_script 'bin/security_checks_ci' do <<~SH
  #{add_to_script_if_installed 'brakeman', 'bundle exec brakeman --run-all-checks --routes --no-pager --summary --no-progress --quiet'}
  #{add_to_script_if_installed 'bundler-audit', 'bundle exec bundle-audit update'}
  #{add_to_script_if_installed 'bundler-audit', 'bundle exec bundle-audit'}
  #{add_to_script_if_installed 'strong_versions', 'bundle exec strong_versions'}
  SH
end

create_file '.github/workflows/ci.yml' do <<~YAML
    name: CI
    on: [push]

    jobs:
      linters:
        name: Linters
        runs-on: ubuntu-latest
        services:
          postgres:
            image: postgres:11
            env:
              POSTGRES_USER: #{app_name}
              POSTGRES_PASSWORD: #{app_name}
              POSTGRES_DB: #{app_name}_test
            ports: ["5432:5432"]

        steps:
          - name: Checkout code
            uses: actions/checkout@v2
            with:
              fetch-depth: 0

          - name: Setup Ruby
            uses: ruby/setup-ruby@v1

          - name: Ruby gem cache
            uses: actions/cache@v1
            with:
              path: vendor/bundle
              key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
              restore-keys: |
                ${{ runner.os }}-gems-

          - name: Install gems
            run: |
              bundle config path vendor/bundle
              bundle config --local build.sassc --disable-march-tune-native
              bundle install --jobs 4 --retry 3

          - name: Setup Node
            uses: actions/setup-node@v1
            with:
              node-version: 10.13.0

          - name: Find yarn cache location
            id: yarn-cache
            run: echo "::set-output name=dir::$(yarn cache dir)"

          - name: JS package cache
            uses: actions/cache@v1
            with:
              path: ${{ steps.yarn-cache.outputs.dir }}
              key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
              restore-keys: |
                ${{ runner.os }}-yarn-

          - name: Install packages
            run: |
              yarn install --pure-lockfile
          
          - name: Setup db
            run: |
              bundle exec rails db:setup
              
          - uses: jwalton/gh-find-current-pr@v1
            id: findPr
            with:
              github-token: ${{ secrets.GITHUB_TOKEN }}

          - name: Run Pronto
            env: 
              PRONTO_GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
              PRONTO_PULL_REQUEST_ID: ${{ steps.findPr.outputs.pr }}
            run: |
              bundle exec pronto run --formatters=github_status github_pr --commit=origin/master --exit-code

          - name: Run linters
            run: |
              bin/linters_ci

          - name: Run security checks
            run: |
              bin/security_checks_ci

      tests:
        name: Tests
        runs-on: ubuntu-latest
        services:
          postgres:
            image: postgres:11
            env:
              POSTGRES_USER: #{app_name}
              POSTGRES_PASSWORD: #{app_name}
              POSTGRES_DB: #{app_name}_test
            ports: ["5432:5432"]

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

          - name: Setup Ruby
            uses: ruby/setup-ruby@v1

          - name: Ruby gem cache
            uses: actions/cache@v1
            with:
              path: vendor/bundle
              key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
              restore-keys: |
                ${{ runner.os }}-gems-

          - name: Install gems
            run: |
              bundle config path vendor/bundle
              bundle config --local build.sassc --disable-march-tune-native
              bundle install --jobs 4 --retry 3

          - name: Setup Node
            uses: actions/setup-node@v1
            with:
              node-version: 10.13.0

          - name: Find yarn cache location
            id: yarn-cache
            run: echo "::set-output name=dir::$(yarn cache dir)"

          - name: JS package cache
            uses: actions/cache@v1
            with:
              path: ${{ steps.yarn-cache.outputs.dir }}
              key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
              restore-keys: |
                ${{ runner.os }}-yarn-

          - name: Install packages
            run: |
              yarn install --pure-lockfile

          - name: Setup test database
            env:
              RAILS_ENV: test
            run: |
              bundle exec rails db:setup

          - name: Configure inotify
            run: |
              sudo sysctl fs.inotify.max_user_instances=524288
              sudo sysctl fs.inotify.max_user_watches=524288
              sudo sysctl fs.inotify.max_queued_events=524288
              sudo sysctl -p

          - name: Run tests
            run: bundle exec rails test
  YAML
end

create_file '.github/workflows/automerge' do <<~YAML
    name: automerge
    on:
      pull_request:
        types:
          - labeled
          - unlabeled
          - synchronize
          - opened
          - edited
          - ready_for_review
          - reopened
          - unlocked
      pull_request_review:
        types:
          - submitted
      check_suite:
        types:
          - completed
      status: {}
    jobs:
      automerge:
        runs-on: ubuntu-latest
        steps:
          - name: automerge
            uses: "docker://docker.pkg.github.com/pascalgn/automerge-action/automerge-action:c7859ab63774304798c4dd36ed106b59bbf728974117a9f350cac756d80d9e37"
            env:
              GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
              MERGE_LABELS: "automerge,!wip"
  YAML
end
Comments

Sign up or Login to leave a comment.