DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Pipeline of an Alexa Skill with GitHub Actions
  • Seamless CI/CD Integration: Playwright and GitHub Actions
  • Refining Automated Testing: Balancing Speed and Reliability in Modern Test Suites
  • Enhance Terraform Final Plan Output in GitHub Actions

Trending

  • Mastering Deployment Strategies: Navigating the Path to Seamless Software Releases
  • Navigating Double and Triple Extortion Tactics
  • Designing for Sustainability: The Rise of Green Software
  • Optimizing Serverless Computing with AWS Lambda Layers and CloudFormation
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Run RSpec on GitHub Actions in the Shortest Time Using Parallel Jobs

Run RSpec on GitHub Actions in the Shortest Time Using Parallel Jobs

How to run RSpec test files on GitHub Actions for Ruby on Rails app, using parallel jobs to get the shortest CI build time.

By 
Artur Trzop user avatar
Artur Trzop
·
Jan. 09, 21 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
7.1K Views

Join the DZone community and get the full member experience.

Join For Free

GitHub introduced their own CI server solution called GitHub Actions. You will learn how to set up your Ruby on Rails application on GitHub Actions with the YAML config file. To run your RSpec test suite faster, you will configure parallel jobs with matrix strategy on GitHub Actions.

Automate Your Workflow on GitHub Actions

GitHub Actions makes it easy to automate all your software workflows with world-class CI/CD. The building, testing, and deploying your code right from GitHub became available with simple YAML configuration.

You can even create a few YAML config files to run a different set of rules on your CI, like scheduling daily CI builds. But let’s focus strictly on how to get running tests for the Rails app on GitHub Actions.

Setup Ruby on Rails on GitHub Actions With YAML Config

In your project repository, you need to create a file: .github/workflows/main.yaml. Thanks to it, GitHub will run your CI build. You can find results of CI builds in the Actions tab for your GitHub repository.

In our case, the Rails application has a Postgres database, so you need to set up a service with a docker container to run Postgres DB.

YAML
 




x
15


 
1
# If you need DB like PostgreSQL then define service below.
2
# Example for Redis can be found here:
3
# https://github.com/actions/example-services/tree/master/.github/workflows
4
services:
5
  postgres:
6
    image: postgres:10.8
7
    env:
8
      POSTGRES_USER: postgres
9
      POSTGRES_PASSWORD: ""
10
      POSTGRES_DB: postgres
11
    ports:
12
    # will assign a random free host port
13
    - 5432/tcp
14
    # needed because the postgres container does not provide a healthcheck
15
    options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5



To be able to install the pg ruby gem from a project Gemfile, you will needlibpq-devlibrary in the Ubuntu system, hence the step to install it. libpq is a set of library functions that allow client programs to pass queries to the PostgreSQL backend server and to receive the results of these queries. We need it to compile pg gem. The next step will be installing our Ruby gems.

YAML
 




xxxxxxxxxx
1
17


 
1
# required to compile pg ruby gem
2
- name: install PostgreSQL client
3
  run: sudo apt-get install libpq-dev
4
 
          
5
- name: Build and create DB
6
  env:
7
    # use localhost for the host here because we have specified a container for the job.
8
    # If we were running the job on the VM this would be postgres
9
    PGHOST: localhost
10
    PGUSER: postgres
11
    PGPORT: ${ { job.services.postgres.ports[5432] }} # get randomly assigned published port
12
    RAILS_ENV: test
13
  run: |
14
    gem install bundler
15
    bundle config path vendor/bundle
16
    bundle install --jobs 4 --retry 3
17
    bin/rails db:setup


To run RSpec tests across parallel jobs, you need to set up the matrix feature, and thanks to that, run the whole test suite distributed across jobs.

Configuring a Build Matrix

A build matrix provides different configurations for the virtual environment to test. For instance, a workflow can run a job for more than one supported version of a language, operating system, etc. For each configuration, a copy of the job runs and reports status.

In case of running parallel tests, you want to run the Rails application on the same Ruby version and Ubuntu system. But you want to split the RSpec test suite into 2 sets, so half of the tests go to a first parallel job and the second half to another job.

To split tests, you can use Ruby gem Knapsack Pro that will split tests across parallel GitHub jobs in a dynamic way. Thanks to that, each parallel job will be consuming a set of tests fetched from Knapsack Pro API Queue to ensure each parallel job finishes work at a similar time. This allows for evenly distributed tests and no bottleneck in parallel jobs (no slow job). Your CI build will be as fast as possible.

In our case, you split tests across 2 parallel jobs, so you need to set 2 as matrix.ci_node_total. Then each parallel job should have an assigned index matrix.ci_node_index start from 0. The first parallel job gets index 0, and the second job gets index 1. This allows Knapsack Pro to know what tests should be executed on a particular job.

YAML
 




xxxxxxxxxx
1
12


 
1
# https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix
2
strategy:
3
  fail-fast: false
4
  matrix:
5
    # Set N number of parallel jobs you want to run tests on.
6
    # Use higher number if you have slow tests to split them on more parallel jobs.
7
    # Remember to update ci_node_index below to 0..N-1
8
    ci_node_total: [2]
9
    # set N-1 indexes for parallel jobs
10
    # When you run 2 parallel jobs then first job will have index 0,
11
    # the second job will have index 1 etc
12
    ci_node_index: [0, 1]



You need to specify also API token for Knapsack Pro; for RSpec, it will be KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC.

Then you can run tests with Knapsack Pro in Queue Mode for RSpec:

bundle exec rake knapsack_pro:queue:rspec


Full GitHub Actions config file for Rails tests

Here you can find the full YAML configuration file for GitHub Actions and Ruby on Rails project.

I also recorded a video showing how it all works and how CI builds with parallel jobs are configured on GitHub Actions.


YAML
 




xxxxxxxxxx
1
95


 
1
# .github/workflows/main.yaml
2
name: Main
3
 
          
4
on: [push]
5
 
          
6
jobs:
7
  vm-job:
8
    runs-on: ubuntu-latest
9
 
          
10
    # If you need DB like PostgreSQL then define service below.
11
    # Example for Redis can be found here:
12
    # https://github.com/actions/example-services/tree/master/.github/workflows
13
    services:
14
      postgres:
15
        image: postgres:10.8
16
        env:
17
          POSTGRES_USER: postgres
18
          POSTGRES_PASSWORD: ""
19
          POSTGRES_DB: postgres
20
        ports:
21
        # will assign a random free host port
22
        - 5432/tcp
23
        # needed because the postgres container does not provide a healthcheck
24
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
25
 
          
26
    # https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix
27
    strategy:
28
      fail-fast: false
29
      matrix:
30
        # Set N number of parallel jobs you want to run tests on.
31
        # Use higher number if you have slow tests to split them on more parallel jobs.
32
        # Remember to update ci_node_index below to 0..N-1
33
        ci_node_total: [2]
34
        # set N-1 indexes for parallel jobs
35
        # When you run 2 parallel jobs then first job will have index 0, the second job will have index 1 etc
36
        ci_node_index: [0, 1]
37
 
          
38
    steps:
39
    - uses: actions/checkout@v1
40
 
          
41
    - name: Set up Ruby 2.6
42
      uses: actions/setup-ruby@v1
43
      with:
44
        ruby-version: 2.6.5
45
        
46
    - uses: actions/cache@v1
47
      with:
48
        path: vendor/bundle
49
        key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
50
        restore-keys: |
51
          ${{ runner.os }}-gems-
52
    # required to compile pg ruby gem
53
    - name: install PostgreSQL client
54
      run: sudo apt-get install libpq-dev
55
 
          
56
    - name: Build and create DB
57
      env:
58
        # use localhost for the host here because we have specified a container for the job.
59
        # If we were running the job on the VM this would be postgres
60
        PGHOST: localhost
61
        PGUSER: postgres
62
        PGPORT: ${{ job.services.postgres.ports[5432] }} # get randomly assigned published port
63
        RAILS_ENV: test
64
      run: |
65
        gem install bundler
66
        bundle config path vendor/bundle
67
        bundle install --jobs 4 --retry 3
68
        bin/rails db:setup
69
    - name: Run tests
70
      env:
71
        PGHOST: localhost
72
        PGUSER: postgres
73
        PGPORT: ${{ job.services.postgres.ports[5432] }} # get randomly assigned published port
74
        RAILS_ENV: test
75
        KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC }}
76
        KNAPSACK_PRO_TEST_SUITE_TOKEN_CUCUMBER: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_CUCUMBER }}
77
        KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST }}
78
        KNAPSACK_PRO_TEST_SUITE_TEST_UNIT: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_TEST_UNIT }}
79
        KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_SPINACH }}
80
        KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
81
        KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
82
        # if you use Knapsack Pro Queue Mode you must set below env variable
83
        # to be able to retry CI build and run previously recorded tests
84
        KNAPSACK_PRO_FIXED_QUEUE_SPLIT: true
85
      run: |
86
        # run tests in Knapsack Pro Regular Mode
87
        bundle exec rake knapsack_pro:rspec
88
        bundle exec rake knapsack_pro:cucumber
89
        bundle exec rake knapsack_pro:minitest
90
        bundle exec rake knapsack_pro:test_unit
91
        bundle exec rake knapsack_pro:spinach
92
        # you can use Knapsack Pro in Queue Mode once recorded first CI build with Regular Mode
93
        bundle exec rake knapsack_pro:queue:rspec
94
        bundle exec rake knapsack_pro:queue:cucumber
95
        bundle exec rake knapsack_pro:queue:minitest



Dynamic Test Suite Split With Queue Mode

If you would like to better understand how Queue Mode works in Knapsack Pro and what other problems it solves, you will find useful information in the below video:


Also, check out another article describing the parallelisation setup for GitHub Actions for Rails with MySQL, Redis, and Elasticsearch or learn how to auto split slow RSpec test files by test examples.

I hope you find this helpful.

If you are currently considering moving to GitHub Actions, definitely check out our Comparison of GitHub Actions to other CI solutions. The most popular ones include Github Actions vs Circle CI, Github Actions vs Jenkins, and Github Actions vs Travis CI.

GitHub career Continuous Integration/Deployment Testing Test suite YAML

Published at DZone with permission of Artur Trzop. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Pipeline of an Alexa Skill with GitHub Actions
  • Seamless CI/CD Integration: Playwright and GitHub Actions
  • Refining Automated Testing: Balancing Speed and Reliability in Modern Test Suites
  • Enhance Terraform Final Plan Output in GitHub Actions

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!