├── .circleci ├── config.yml └── test-deploy.yml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── BUG.md │ ├── FEATURE_REQUEST.md │ └── config.yml └── PULL_REQUEST_TEMPLATE │ └── PULL_REQUEST.md ├── .gitignore ├── .yamllint ├── LICENSE ├── README.md ├── sample ├── .gitignore ├── .rspec ├── Gemfile ├── Gemfile.lock ├── bin │ ├── bundle │ ├── htmldiff │ ├── ldiff │ └── rspec ├── lib │ └── trial.rb └── spec │ ├── spec_helper.rb │ └── trial_spec.rb └── src ├── @orb.yml ├── commands ├── install-deps.yml ├── install.yml ├── rspec-test.yml └── rubocop-check.yml ├── examples ├── install_ruby.yml └── ruby_rails_sample_app.yml ├── executors └── default.yml └── scripts ├── determine-lockfile.sh ├── install-bundler.sh ├── install-deps.sh ├── install-ruby.sh ├── install-rvm.sh ├── rspec-test.sh └── rubocop-check.sh /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | setup: true 3 | orbs: 4 | orb-tools: circleci/orb-tools@12.0 5 | shellcheck: circleci/shellcheck@3.1 6 | 7 | filters: &filters 8 | tags: 9 | only: /.*/ 10 | 11 | workflows: 12 | lint-pack: 13 | jobs: 14 | - orb-tools/lint: 15 | filters: *filters 16 | - orb-tools/pack: 17 | filters: *filters 18 | - orb-tools/review: 19 | exclude: RC010 20 | filters: *filters 21 | - shellcheck/check: 22 | exclude: SC2086,SC2016,SC2002 23 | filters: *filters 24 | # Triggers the next workflow in the Orb Development Kit. 25 | - orb-tools/continue: 26 | orb_name: ruby 27 | pipeline_number: << pipeline.number >> 28 | vcs_type: << pipeline.project.type >> 29 | requires: [orb-tools/lint, orb-tools/review, orb-tools/pack, shellcheck/check] 30 | filters: *filters 31 | -------------------------------------------------------------------------------- /.circleci/test-deploy.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | orb-tools: circleci/orb-tools@12.0 4 | ruby: {} 5 | 6 | filters: &filters 7 | tags: 8 | only: /.*/ 9 | 10 | release-filters: &release-filters 11 | branches: 12 | ignore: /.*/ 13 | tags: 14 | only: /^v[0-9]+\.[0-9]+\.[0-9]+$/ 15 | 16 | executors: 17 | ubuntu: 18 | parameters: 19 | image: 20 | description: Enter the version that should be user for the machine executor. 21 | type: string 22 | machine: 23 | image: << parameters.image >> 24 | 25 | jobs: 26 | install-deps: 27 | parameters: 28 | executor: 29 | type: executor 30 | default: ruby/default 31 | executor: <> 32 | steps: 33 | - checkout 34 | - ruby/install-deps: 35 | app-dir: sample 36 | with-cache: false 37 | test-openssl-installed: 38 | docker: 39 | - image: cimg/node:16.18.0 40 | steps: 41 | - run: 42 | name: Install OpenSSL 1.1.1 43 | command: | 44 | wget https://openssl.org/source/openssl-1.1.1.tar.gz 45 | tar -xzvf openssl-1.1.1.tar.gz 46 | cd openssl-1.1.1 47 | ./config 48 | make 49 | sudo make install 50 | - ruby/install: 51 | version: 2.7.6 52 | openssl-path: /usr/local/ssl 53 | test-openssl-3: 54 | docker: 55 | - image: cimg/node:16.18.0 56 | steps: 57 | - checkout 58 | - ruby/install: 59 | version: 2.7.6 60 | - ruby/install-deps: 61 | app-dir: sample 62 | with-cache: false 63 | - ruby/install-deps: 64 | app-dir: sample 65 | - ruby/rspec-test: 66 | app-dir: sample 67 | integration-tests: 68 | docker: 69 | # NOTE: the specific Ruby version required is based on https://github.com/CircleCI-Public/circleci-demo-ruby-rails 70 | # See https://github.com/CircleCI-Public/circleci-demo-ruby-rails/blob/2033c5f8da3010941127e0f9133925bd8efc7a79/Gemfile#L10 71 | # When the project's Ruby version requirement is updated, we will need to update here as well. 72 | - image: cimg/ruby:2.7.5-node 73 | - image: cimg/postgres:14.2 74 | environment: 75 | POSTGRES_USER: circleci-demo-ruby 76 | POSTGRES_DB: rails_blog_test 77 | POSTGRES_PASSWORD: "" 78 | parallelism: 2 79 | environment: 80 | BUNDLE_JOBS: "3" 81 | BUNDLE_RETRY: "3" 82 | PGHOST: 127.0.0.1 83 | PGUSER: circleci-demo-ruby 84 | PGPASSWORD: "" 85 | RAILS_ENV: test 86 | steps: 87 | - run: git clone https://github.com/CircleCI-Public/circleci-demo-ruby-rails.git . 88 | - ruby/install-deps: 89 | clean-bundle: true 90 | key: "gems-v6" 91 | - restore_cache: 92 | keys: 93 | - rails-demo-yarn-v3-{{ checksum "yarn.lock" }} 94 | - run: 95 | name: Yarn Install 96 | command: yarn install --cache-folder ~/.cache/yarn 97 | # Store yarn / webpacker cache 98 | - save_cache: 99 | key: rails-demo-yarn-v3-{{ checksum "yarn.lock" }} 100 | paths: 101 | - ~/.cache/yarn 102 | - run: 103 | name: Wait for DB 104 | command: dockerize -wait tcp://localhost:5432 -timeout 1m 105 | - run: 106 | name: Database setup 107 | command: bundle exec rails db:schema:load --trace 108 | - ruby/rspec-test: 109 | label: RSpec Tests with Single Glob 110 | - ruby/rspec-test: 111 | label: RSpec Tests with Multiple Globs 112 | include: "spec/**/*_spec.rb,spec/**/*_spec.rb" 113 | - ruby/rspec-test: 114 | label: RSpec Tests with seed 115 | order: "rand:1234" 116 | - ruby/rubocop-check: 117 | label: Run Rubocop default parameters. 118 | - ruby/rubocop-check: 119 | label: Run Rubocop default json. 120 | out-file-name: check-results.json 121 | format: json 122 | - ruby/rubocop-check: 123 | label: Run Rubocop with the parallel flag. 124 | parallel: true 125 | install-on-macos: 126 | parameters: 127 | version: 128 | description: Version to install 129 | type: string 130 | macos: 131 | xcode: 15.3.0 132 | steps: 133 | - ruby/install: 134 | version: << parameters.version >> 135 | - run: 136 | name: "Test Install" 137 | command: ruby --version | grep << parameters.version >> 138 | install-on-machine: 139 | parameters: 140 | image: 141 | description: Enter the version that should be used for the machine executor. 142 | type: string 143 | version: 144 | description: Version to install 145 | type: string 146 | executor: 147 | name: ubuntu 148 | image: << parameters.image >> 149 | steps: 150 | - ruby/install: 151 | version: << parameters.version >> 152 | - run: 153 | name: "Test Install" 154 | command: ruby --version | grep << parameters.version >> 155 | install-on-docker: 156 | parameters: 157 | image: 158 | description: Enter the version that should be used for the machine executor. 159 | type: string 160 | version: 161 | description: Version to install 162 | type: string 163 | docker: 164 | - image: <> 165 | steps: 166 | - run: apt update -y && apt install curl gnupg2 procps -y 167 | - ruby/install: 168 | version: << parameters.version >> 169 | - run: 170 | name: "Test Install" 171 | command: ruby --version | grep << parameters.version >> 172 | install-on-node: 173 | docker: 174 | - image: cimg/node:current 175 | steps: 176 | - ruby/install: 177 | version: "2.6" 178 | - run: 179 | name: "Test Install" 180 | command: ruby --version | grep "2.6" 181 | install-from-env-var: 182 | docker: 183 | - image: cimg/node:current 184 | steps: 185 | - run: 186 | name: Set RUBY_VERSION env var 187 | command: | 188 | echo "export RUBY_VERSION='2.7.0'" >> $BASH_ENV 189 | - ruby/install: 190 | version: "${RUBY_VERSION}" 191 | - run: 192 | name: "Test Install" 193 | command: ruby --version | grep "2.7.0" 194 | - store_artifacts: 195 | path: /home/circleci/.rvm/log 196 | install-already-present-version: 197 | parameters: 198 | version: 199 | type: string 200 | docker: 201 | - image: cimg/ruby:<> 202 | steps: 203 | - ruby/install: 204 | version: <> 205 | workflows: 206 | test-deploy: 207 | jobs: 208 | # Make sure to include "filters: *filters" in every test job you want to run as part of your deployment. 209 | - install-already-present-version: 210 | filters: *filters 211 | matrix: 212 | parameters: 213 | version: [3.4.2, 2.7.6, 3.0.7] 214 | - install-deps: 215 | name: install-deps-medium 216 | executor: 217 | name: ruby/default 218 | resource_class: medium 219 | filters: *filters 220 | - install-deps: 221 | name: install-deps-large 222 | executor: 223 | name: ruby/default 224 | resource_class: large 225 | filters: *filters 226 | - integration-tests: 227 | filters: *filters 228 | - test-openssl-installed: 229 | filters: *filters 230 | post-steps: 231 | - run: | 232 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 233 | - install-on-macos: 234 | post-steps: 235 | - run: 236 | command: | 237 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 238 | matrix: 239 | parameters: 240 | version: ["2.7.6", "3.0.7", "3.1.6", "3.2.5", "3.3.5"] 241 | filters: *filters 242 | - install-on-machine: 243 | post-steps: 244 | - run: 245 | command: | 246 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 247 | matrix: 248 | parameters: 249 | image: [ubuntu-2004:202111-02,ubuntu-2004:current] 250 | version: ["2.7.6", "3.0.7", "3.1.6", "3.2.5", "2.6", "3.3.5"] 251 | filters: *filters 252 | - install-on-docker: 253 | post-steps: 254 | - run: 255 | command: | 256 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 257 | matrix: 258 | parameters: 259 | image: ["debian:bookworm-slim"] 260 | version: ["2.7.6", "3.0.7", "3.1.6", "3.2.5", "2.6", "3.3.5"] 261 | filters: *filters 262 | - test-openssl-3: 263 | post-steps: 264 | - run: 265 | command: | 266 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 267 | filters: *filters 268 | - install-on-node: 269 | filters: *filters 270 | post-steps: 271 | - run: 272 | command: | 273 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 274 | - install-from-env-var: 275 | post-steps: 276 | - run: 277 | command: | 278 | ruby -ropenssl -e 'if OpenSSL::OPENSSL_VERSION.include?("OpenSSL 1.1.1"); puts "Version 1.1.1 detected"; else; puts "Different version detected: #{OpenSSL::OPENSSL_VERSION}"; exit 0; end' 279 | filters: *filters 280 | - orb-tools/pack: 281 | filters: *release-filters 282 | - orb-tools/publish: 283 | orb_name: circleci/ruby 284 | vcs_type: << pipeline.project.type >> 285 | pub_type: production 286 | enable_pr_comment: true 287 | github_token: GHI_TOKEN 288 | requires: 289 | - orb-tools/pack 290 | - integration-tests 291 | - install-on-machine 292 | - install-on-node 293 | - install-from-env-var 294 | - test-openssl-3 295 | context: orb-publisher 296 | filters: *release-filters 297 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Ping these folks when changes are made to this repository 2 | * @CircleCI-Public/orb-publishers 3 | 4 | # We can also add orb-specifc codeowners at some point if desirable 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41E Bug report" 3 | about: Report any bugs encountered while using this orb. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Orb version: 11 | 12 | 19 | 20 | ## What happened: 21 | 22 | 26 | 27 | ## Expected behavior: 28 | 29 | 30 | 31 | ## Additional Information: 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature Request" 3 | about: Propose changes to the orb. 4 | title: '' 5 | labels: feature_request 6 | assignees: '' 7 | --- 8 | 9 | ## Describe Request: 10 | 11 | ## Examples: 12 | 13 | ## Supporting Documentation Links: 14 | 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/PULL_REQUEST.md: -------------------------------------------------------------------------------- 1 | 2 | **SEMVER Update Type:** 3 | - [ ] Major 4 | - [ ] Minor 5 | - [ ] Patch 6 | 7 | ## Description: 8 | 9 | 13 | 14 | ## Motivation: 15 | 16 | 19 | 20 | **Closes Issues:** 21 | - ISSUE URL 22 | 23 | ## Checklist: 24 | 25 | 30 | 31 | - [ ] All new jobs, commands, executors, parameters have descriptions. 32 | - [ ] Usage Example version numbers have been updated. 33 | - [ ] Changelog has been updated. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | orb.yml 2 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | extends: relaxed 2 | 3 | rules: 4 | line-length: 5 | max: 200 6 | allow-non-breakable-inline-mappings: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Circle Internet Services, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ruby Orb 2 | [![CircleCI Build Status](https://circleci.com/gh/CircleCI-Public/ruby-orb.svg?style=shield "CircleCI Build Status")](https://circleci.com/gh/CircleCI-Public/ruby-orb) [![CircleCI Orb Version](https://badges.circleci.com/orbs/circleci/ruby.svg)](https://circleci.com/orbs/registry/orb/circleci/ruby) [![GitHub License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/CircleCI-Public/ruby-orb/master/LICENSE) [![CircleCI Community](https://img.shields.io/badge/community-CircleCI%20Discuss-343434.svg)](https://discuss.circleci.com/c/ecosystem/orbs) 3 | 4 | Easily cache and install your Ruby Gems automatically, run parallel RSpec tests or Rubocop checking, or just install Ruby. 5 | 6 | 7 | ## Usage 8 | 9 | Example use-cases are provided on the orb [registry page](https://circleci.com/orbs/registry/orb/circleci/ruby#usage-examples). Source for these examples can be found within the `src/examples` directory. 10 | 11 | **Example** 12 | 13 | View the CircleCI Ruby Rails Demo app complete with full config utilizing our Node and Ruby orbs. 14 | https://github.com/CircleCI-Public/circleci-demo-ruby-rails/ 15 | 16 | 17 | ## Resources 18 | 19 | [CircleCI Orb Registry Page](https://circleci.com/orbs/registry/orb/circleci/ruby) - The official registry page of this orb for all versions, executors, commands, and jobs described. 20 | [CircleCI Orb Docs](https://circleci.com/docs/2.0/orb-intro/#section=configuration) - Docs for using and creating CircleCI Orbs. 21 | 22 | ### How to Contribute 23 | 24 | We welcome [issues](https://github.com/CircleCI-Public/ruby-orb/issues) to and [pull requests](https://github.com/CircleCI-Public/ruby-orb/pulls) against this repository! 25 | 26 | ### How to Publish An Update 27 | 1. Merge pull requests with desired changes to the main branch. 28 | - For the best experience, squash-and-merge and use [Conventional Commit Messages](https://conventionalcommits.org/). 29 | 2. Find the current version of the orb. 30 | - You can run `circleci orb info circleci/ruby | grep "Latest"` to see the current version. 31 | 3. Create a [new Release](https://github.com/CircleCI-Public/ruby-orb/releases/new) on GitHub. 32 | - Click "Choose a tag" and _create_ a new [semantically versioned](http://semver.org/) tag. (ex: v1.0.0) 33 | - We will have an opportunity to change this before we publish if needed after the next step. 34 | 4. Click _"+ Auto-generate release notes"_. 35 | - This will create a summary of all of the merged pull requests since the previous release. 36 | - If you have used _[Conventional Commit Messages](https://conventionalcommits.org/)_ it will be easy to determine what types of changes were made, allowing you to ensure the correct version tag is being published. 37 | 5. Now ensure the version tag selected is semantically accurate based on the changes included. 38 | 6. Click _"Publish Release"_. 39 | - This will push a new tag and trigger your publishing pipeline on CircleCI. 40 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /spec/examples.txt 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | 13 | # Used by dotenv library to load environment variables. 14 | # .env 15 | 16 | # Ignore Byebug command history file. 17 | .byebug_history 18 | 19 | ## Specific to RubyMotion: 20 | .dat* 21 | .repl_history 22 | build/ 23 | *.bridgesupport 24 | build-iPhoneOS/ 25 | build-iPhoneSimulator/ 26 | 27 | ## Specific to RubyMotion (use of CocoaPods): 28 | # 29 | # We recommend against adding the Pods directory to your .gitignore. However 30 | # you should judge for yourself, the pros and cons are mentioned at: 31 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 32 | # 33 | # vendor/Pods/ 34 | 35 | ## Documentation cache and generated files: 36 | /.yardoc/ 37 | /_yardoc/ 38 | /doc/ 39 | /rdoc/ 40 | 41 | ## Environment normalization: 42 | /.bundle/ 43 | /vendor/bundle 44 | /lib/bundler/man/ 45 | 46 | # for a library or gem, you might want to ignore these files since the code is 47 | # intended to run in multiple environments; otherwise, check them in: 48 | # Gemfile.lock 49 | # .ruby-version 50 | # .ruby-gemset 51 | 52 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 53 | .rvmrc 54 | 55 | # Used by RuboCop. Remote config files pulled in from inherit_from directive. 56 | # .rubocop-https?--* 57 | -------------------------------------------------------------------------------- /sample/.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | -------------------------------------------------------------------------------- /sample/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'rspec', '~> 3.0' 4 | gem 'rspec_junit_formatter' 5 | -------------------------------------------------------------------------------- /sample/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | diff-lcs (1.5.0) 5 | rspec (3.11.0) 6 | rspec-core (~> 3.11.0) 7 | rspec-expectations (~> 3.11.0) 8 | rspec-mocks (~> 3.11.0) 9 | rspec-core (3.11.0) 10 | rspec-support (~> 3.11.0) 11 | rspec-expectations (3.11.1) 12 | diff-lcs (>= 1.2.0, < 2.0) 13 | rspec-support (~> 3.11.0) 14 | rspec-mocks (3.11.1) 15 | diff-lcs (>= 1.2.0, < 2.0) 16 | rspec-support (~> 3.11.0) 17 | rspec-support (3.11.1) 18 | rspec_junit_formatter (0.6.0) 19 | rspec-core (>= 2, < 4, != 2.12.0) 20 | 21 | PLATFORMS 22 | arm64-darwin-21 23 | x86_64-darwin-21 24 | x86_64-linux 25 | 26 | DEPENDENCIES 27 | rspec (~> 3.0) 28 | rspec_junit_formatter 29 | 30 | BUNDLED WITH 31 | 2.3.23 32 | -------------------------------------------------------------------------------- /sample/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../Gemfile", __dir__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_requirement 64 | @bundler_requirement ||= 65 | env_var_version || cli_arg_version || 66 | bundler_requirement_for(lockfile_version) 67 | end 68 | 69 | def bundler_requirement_for(version) 70 | return "#{Gem::Requirement.default}.a" unless version 71 | 72 | bundler_gem_version = Gem::Version.new(version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /sample/bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("diff-lcs", "htmldiff") 28 | -------------------------------------------------------------------------------- /sample/bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("diff-lcs", "ldiff") 28 | -------------------------------------------------------------------------------- /sample/bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rspec-core", "rspec") 28 | -------------------------------------------------------------------------------- /sample/lib/trial.rb: -------------------------------------------------------------------------------- 1 | class Trial 2 | def hello 3 | "Hello, world!" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /sample/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file was generated by the `rspec --init` command. Conventionally, all 2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 3 | # The generated `.rspec` file contains `--require spec_helper` which will cause 4 | # this file to always be loaded, without a need to explicitly require it in any 5 | # files. 6 | # 7 | # Given that it is always loaded, you are encouraged to keep this file as 8 | # light-weight as possible. Requiring heavyweight dependencies from this file 9 | # will add to the boot time of your test suite on EVERY test run, even for an 10 | # individual file that may not need all of that loaded. Instead, consider making 11 | # a separate helper file that requires the additional dependencies and performs 12 | # the additional setup, and require it from the spec files that actually need 13 | # it. 14 | # 15 | # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 16 | RSpec.configure do |config| 17 | # rspec-expectations config goes here. You can use an alternate 18 | # assertion/expectation library such as wrong or the stdlib/minitest 19 | # assertions if you prefer. 20 | config.expect_with :rspec do |expectations| 21 | # This option will default to `true` in RSpec 4. It makes the `description` 22 | # and `failure_message` of custom matchers include text for helper methods 23 | # defined using `chain`, e.g.: 24 | # be_bigger_than(2).and_smaller_than(4).description 25 | # # => "be bigger than 2 and smaller than 4" 26 | # ...rather than: 27 | # # => "be bigger than 2" 28 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 29 | end 30 | 31 | # rspec-mocks config goes here. You can use an alternate test double 32 | # library (such as bogus or mocha) by changing the `mock_with` option here. 33 | config.mock_with :rspec do |mocks| 34 | # Prevents you from mocking or stubbing a method that does not exist on 35 | # a real object. This is generally recommended, and will default to 36 | # `true` in RSpec 4. 37 | mocks.verify_partial_doubles = true 38 | end 39 | 40 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will 41 | # have no way to turn it off -- the option exists only for backwards 42 | # compatibility in RSpec 3). It causes shared context metadata to be 43 | # inherited by the metadata hash of host groups and examples, rather than 44 | # triggering implicit auto-inclusion in groups with matching metadata. 45 | config.shared_context_metadata_behavior = :apply_to_host_groups 46 | 47 | # The settings below are suggested to provide a good initial experience 48 | # with RSpec, but feel free to customize to your heart's content. 49 | =begin 50 | # This allows you to limit a spec run to individual examples or groups 51 | # you care about by tagging them with `:focus` metadata. When nothing 52 | # is tagged with `:focus`, all examples get run. RSpec also provides 53 | # aliases for `it`, `describe`, and `context` that include `:focus` 54 | # metadata: `fit`, `fdescribe` and `fcontext`, respectively. 55 | config.filter_run_when_matching :focus 56 | 57 | # Allows RSpec to persist some state between runs in order to support 58 | # the `--only-failures` and `--next-failure` CLI options. We recommend 59 | # you configure your source control system to ignore this file. 60 | config.example_status_persistence_file_path = "spec/examples.txt" 61 | 62 | # Limits the available syntax to the non-monkey patched syntax that is 63 | # recommended. For more details, see: 64 | # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode 65 | config.disable_monkey_patching! 66 | 67 | # This setting enables warnings. It's recommended, but in some cases may 68 | # be too noisy due to issues in dependencies. 69 | config.warnings = true 70 | 71 | # Many RSpec users commonly either run the entire suite or an individual 72 | # file, and it's useful to allow more verbose output when running an 73 | # individual spec file. 74 | if config.files_to_run.one? 75 | # Use the documentation formatter for detailed output, 76 | # unless a formatter has already been configured 77 | # (e.g. via a command-line flag). 78 | config.default_formatter = "doc" 79 | end 80 | 81 | # Print the 10 slowest examples and example groups at the 82 | # end of the spec run, to help surface which specs are running 83 | # particularly slow. 84 | config.profile_examples = 10 85 | 86 | # Run specs in random order to surface order dependencies. If you find an 87 | # order dependency and want to debug it, you can fix the order by providing 88 | # the seed, which is printed after each run. 89 | # --seed 1234 90 | config.order = :random 91 | 92 | # Seed global randomization in this process using the `--seed` CLI option. 93 | # Setting this allows you to use `--seed` to deterministically reproduce 94 | # test failures related to randomization by passing the same `--seed` value 95 | # as the one that triggered the failure. 96 | Kernel.srand config.seed 97 | =end 98 | end 99 | -------------------------------------------------------------------------------- /sample/spec/trial_spec.rb: -------------------------------------------------------------------------------- 1 | require 'trial' 2 | 3 | RSpec.describe Trial, '#hello' do 4 | context 'for a new project' do 5 | it 'greets the world' do 6 | trial = Trial.new 7 | expect(trial.hello).to eq 'Hello, world!' 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /src/@orb.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | description: > 4 | Easily cache and install your Ruby Gems automatically, run parallel Rspec tests, or just install Ruby. 5 | 6 | display: 7 | source_url: https://github.com/CircleCI-Public/ruby-orb 8 | home_url: https://www.ruby-lang.org/ 9 | -------------------------------------------------------------------------------- /src/commands/install-deps.yml: -------------------------------------------------------------------------------- 1 | description: "Install gems with Bundler." 2 | parameters: 3 | with-cache: 4 | type: boolean 5 | default: true 6 | description: Enable automatic caching of your gemfile dependencies for increased speed. 7 | clean-bundle: 8 | description: > 9 | Run `bundle clean --force` after `bundle install` to clean Bundler before saving dependencies to cache. 10 | By default, it is set to false. 11 | default: false 12 | type: boolean 13 | key: 14 | description: "The cache key to use. The key is immutable." 15 | type: string 16 | default: "gems-v1" 17 | path: 18 | description: > 19 | Installation path. 20 | By default, it will run bundle with `--deployment` flag and installs gems to the vendor/bundle directory. 21 | default: "./vendor/bundle" 22 | type: string 23 | bundler-version: 24 | description: > 25 | Configure which version of bundler to install and utilize. 26 | By default, it gets the bundler version from Gemfile.lock, but if it is not working use this to override. 27 | default: "" 28 | type: string 29 | app-dir: 30 | description: > 31 | Path to the directory containing your Gemfile file. Not needed if Gemfile lives in the root. 32 | default: . 33 | type: string 34 | include-arch-in-cache-key: 35 | type: boolean 36 | default: true 37 | description: > 38 | If true, this cache bucket will only apply to jobs running on the same architecture. 39 | include-branch-in-cache-key: 40 | type: boolean 41 | default: true 42 | description: > 43 | If true, this cache bucket will only apply to jobs within the same branch. 44 | override-cache-file: 45 | type: string 46 | default: "" 47 | description: > 48 | Specify an alternative file to use in the cache key 49 | gemfile: 50 | description: Name of your Gemfile file. 51 | default: Gemfile 52 | type: string 53 | pre-install-steps: 54 | description: > 55 | Steps that will be executed between installing bundler, and running bundle install 56 | type: steps 57 | default: [] 58 | no_output_timeout: 59 | description: > 60 | Specify a timeout for the bundle install command. By default, it is set to 10 minutes. 61 | default: 10m 62 | type: string 63 | steps: 64 | - run: 65 | name: Determine lock file 66 | working_directory: <> 67 | environment: 68 | PARAM_GEMFILE: << parameters.gemfile >> 69 | PARAM_OVERRIDE_LOCKFILE: << parameters.override-cache-file >> 70 | command: << include(scripts/determine-lockfile.sh) >> 71 | - when: 72 | condition: <> 73 | steps: 74 | - restore_cache: 75 | keys: 76 | - << parameters.key >>-<<#parameters.include-arch-in-cache-key>>{{ arch }}-<><<#parameters.include-branch-in-cache-key>>{{ .Branch }}-<>{{ checksum "/tmp/ruby-project-lockfile" }} 77 | - << parameters.key >>-<<#parameters.include-arch-in-cache-key>>{{ arch }}-<><<#parameters.include-branch-in-cache-key>>{{ .Branch }}-<> 78 | - run: 79 | name: Install Bundler 80 | working_directory: <> 81 | environment: 82 | PARAM_GEMFILE: << parameters.gemfile >> 83 | PARAM_BUNDLER_VERSION: << parameters.bundler-version >> 84 | command: << include(scripts/install-bundler.sh) >> 85 | - steps: << parameters.pre-install-steps >> 86 | - run: 87 | name: Bundle Install <<^parameters.with-cache>>(No Cache)<> 88 | working_directory: <> 89 | environment: 90 | PARAM_GEMFILE: << parameters.gemfile >> 91 | PARAM_PATH: << parameters.path >> 92 | PARAM_CLEAN_BUNDLE: << parameters.clean-bundle >> 93 | command: << include(scripts/install-deps.sh) >> 94 | no_output_timeout: << parameters.no_output_timeout >> 95 | - when: 96 | condition: << parameters.with-cache >> 97 | steps: 98 | - save_cache: 99 | key: << parameters.key >>-<<#parameters.include-arch-in-cache-key>>{{ arch }}-<><<#parameters.include-branch-in-cache-key>>{{ .Branch }}-<>{{ checksum "/tmp/ruby-project-lockfile" }} 100 | paths: 101 | - <>/<< parameters.path >> 102 | -------------------------------------------------------------------------------- /src/commands/install.yml: -------------------------------------------------------------------------------- 1 | description: "Install Ruby within a build. To be used in a Linux distro with Apt available." 2 | parameters: 3 | version: 4 | description: > 5 | Ruby version. 6 | This can be a literal value (e.g, `2.7.5`). 7 | You can also pass in a string to be evaluated. 8 | For example, `${MY_RUBY_VERSION}` or `$(cat foo/bar/.ruby-version)`. 9 | type: string 10 | openssl-path: 11 | description: > 12 | Directory where OpenSSL is intalled. 13 | This will overwrite the value of --with-openssl-dir in the rvm install commmand. 14 | Set this if you need to use an OpenSSL version different to 1.0.1 (rvm default). 15 | The version must be already installed. 16 | type: string 17 | default: "" 18 | steps: 19 | - run: 20 | name: "Install/Verify Ruby Version Manager" 21 | command: << include(scripts/install-rvm.sh) >> 22 | 23 | - run: 24 | name: "Install Ruby v<< parameters.version >> via RVM" 25 | environment: 26 | PARAM_VERSION: << parameters.version >> 27 | PARAM_OPENSSL_PATH: << parameters.openssl-path >> 28 | command: << include(scripts/install-ruby.sh) >> 29 | -------------------------------------------------------------------------------- /src/commands/rspec-test.yml: -------------------------------------------------------------------------------- 1 | description: "Test with RSpec. You have to add `gem 'rspec_junit_formatter'` to your Gemfile. Enable parallelism on CircleCI for faster testing." 2 | parameters: 3 | include: 4 | default: "spec/**/*_spec.rb" 5 | description: > 6 | Glob to define where your test files are kept within your repository. 7 | Should multiple globs be required, they must be passed in a comma separated string (e.g.: "{spec/**/*_spec.rb,spec2/**/*_spec.rb}"). 8 | type: string 9 | label: 10 | default: "RSpec Tests" 11 | description: "Task label" 12 | type: string 13 | out-path: 14 | default: "/tmp/test-results/rspec" 15 | description: Where to save the rspec.xml file. Will automatically be saved to test_results and artifacts on CircleCI. 16 | type: string 17 | app-dir: 18 | description: > 19 | Path to the directory containing your Gemfile file. Not needed if Gemfile lives in the root. 20 | default: . 21 | type: string 22 | order: 23 | default: "" 24 | description: > 25 | Use the order parameter to tell RSpec how to order the files, groups, and examples. 26 | Available options can be found at: https://rspec.info/features/3-12/rspec-core/command-line/order 27 | type: string 28 | tag: 29 | default: "" 30 | description: > 31 | Use the tag parameter to tell RSpec to run only examples with (or without) a specified tag. 32 | Available options can be found at: https://rspec.info/features/3-12/rspec-core/command-line/tag 33 | type: string 34 | no_output_timeout: 35 | type: string 36 | description: > 37 | Allows you to specify the no_output_timeout for the rspec test. Defaults to 10m. 38 | default: "10m" 39 | rerun-fail: 40 | default: true 41 | description: > 42 | Enabling the option uses circleci tests run command and allows the "Rerun failed tests only" feature. 43 | This feature helps optimize test execution by re-running only the failed tests from previous test run data. 44 | More information can be found at: https://circleci.com/docs/rerun-failed-tests-only 45 | type: boolean 46 | steps: 47 | - run: 48 | name: <> 49 | environment: 50 | PARAM_OUT_PATH: <> 51 | PARAM_INCLUDE: <> 52 | PARAM_ORDER: <> 53 | PARAM_TAG: <> 54 | PARAM_RERUN_FAIL: <> 55 | command: <> 56 | no_output_timeout: <> 57 | working_directory: <> 58 | - store_test_results: 59 | path: <> 60 | - store_artifacts: 61 | path: <> 62 | destination: test-results 63 | -------------------------------------------------------------------------------- /src/commands/rubocop-check.yml: -------------------------------------------------------------------------------- 1 | description: "Check the code by Rubocop. You have to add `gem 'rubocop'` to your Gemfile. Enable parallelism on CircleCI for faster checking." 2 | parameters: 3 | label: 4 | default: "Rubocop Checks" 5 | description: "Task label" 6 | type: string 7 | format: 8 | description: "Customize the formatter for rubocop https://docs.rubocop.org/rubocop/0.88/formatters.html" 9 | default: "progress" 10 | type: string 11 | check-path: 12 | default: "." 13 | type: string 14 | out-path: 15 | description: "Customize the directory of output file" 16 | default: "/tmp/rubocop-results" 17 | type: string 18 | out-file-name: 19 | description: "Customize the name of the output file" 20 | default: check-results.xml 21 | type: string 22 | app-dir: 23 | description: > 24 | Path to the directory containing your Gemfile file. Not needed if Gemfile lives in the root. 25 | default: . 26 | type: string 27 | parallel: 28 | description: > 29 | Use available CPUs to execute inspection in parallel. 30 | default: true 31 | type: boolean 32 | steps: 33 | - run: 34 | name: <> 35 | environment: 36 | PARAM_OUT_PATH: <> 37 | PARAM_FILE_OUT: <> 38 | PARAM_CHECK_PATH: <> 39 | PARAM_FORMAT: <> 40 | PARAM_PARALLEL: <> 41 | command: <> 42 | working_directory: <> 43 | -------------------------------------------------------------------------------- /src/examples/install_ruby.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | For environments where Ruby is not pre-installed. (Recommended: It is faster and more deterministic to use a Docker image with Ruby pre-installed. Installing Ruby at run-time is not advised unless required.) 3 | usage: 4 | version: 2.1 5 | orbs: 6 | ruby: circleci/ruby@x.y #Ensure you are using the latest version of the orb 7 | jobs: 8 | build: 9 | docker: 10 | - image: cimg/base:stable # This image does not contain Ruby 11 | steps: 12 | - checkout 13 | - ruby/install: 14 | version: "2.7" # optionally specify a version 15 | - run: echo "Ruby 2.7 has been installed" 16 | -------------------------------------------------------------------------------- /src/examples/ruby_rails_sample_app.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Build and test a full Ruby Rails application with a Postgres database using RSpec. 3 | View the full sample application source: https://github.com/CircleCI-Public/circleci-demo-ruby-rails/ 4 | usage: 5 | version: 2.1 6 | orbs: 7 | ruby: circleci/ruby@x.y # use the latest Ruby orb version 8 | node: circleci/node@x.y # use the latest Nodeorb version 9 | jobs: 10 | build: 11 | docker: 12 | - image: cimg/ruby:2.7-node 13 | steps: 14 | - checkout 15 | - ruby/install-deps 16 | # Store bundle cache 17 | - node/install-packages: 18 | pkg-manager: yarn 19 | cache-key: "yarn.lock" 20 | checking: 21 | docker: 22 | - image: cimg/ruby:2.7-node 23 | steps: 24 | - checkout 25 | - ruby/install-deps 26 | - ruby/rubocop-check: 27 | label: "Inspecting with Rubocop" 28 | format: progress 29 | 30 | test: 31 | parallelism: 3 # OPTIONAL: Split and run your tests in parallel 32 | docker: 33 | - image: cimg/ruby:2.7-node 34 | - image: circleci/postgres:9.5-alpine 35 | environment: 36 | POSTGRES_USER: circleci-demo-ruby 37 | POSTGRES_DB: rails_blog_test 38 | POSTGRES_PASSWORD: "" 39 | environment: 40 | BUNDLE_JOBS: "3" 41 | BUNDLE_RETRY: "3" 42 | PGHOST: 127.0.0.1 43 | PGUSER: circleci-demo-ruby 44 | PGPASSWORD: "" 45 | RAILS_ENV: test 46 | steps: 47 | - checkout 48 | - ruby/install-deps 49 | - node/install-packages: 50 | pkg-manager: yarn 51 | cache-key: "yarn.lock" 52 | - run: 53 | name: Wait for DB 54 | command: dockerize -wait tcp://localhost:5432 -timeout 1m 55 | - run: 56 | name: Database setup 57 | command: bundle exec rails db:schema:load --trace 58 | # Run rspec in parallel 59 | - ruby/rspec-test: 60 | include: "spec/**/*_spec.rb" 61 | workflows: 62 | build_and_test: 63 | jobs: 64 | - build 65 | - checking 66 | - test: 67 | requires: 68 | - build 69 | -------------------------------------------------------------------------------- /src/executors/default.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Select the version of Ruby to use. Uses CircleCI's highly cached convenience images built for CI. 3 | Any available tag from this list can be used: https://hub.docker.com/r/cimg/ruby/tags 4 | parameters: 5 | tag: 6 | description: "The `cimg/ruby` Docker image version tag." 7 | type: string 8 | default: "2.7" 9 | resource_class: 10 | description: The resources_class of the instance to run on. Defaults to Medium. 11 | type: string 12 | default: "medium" 13 | 14 | docker: 15 | - image: cimg/ruby:<< parameters.tag >> 16 | resource_class: << parameters.resource_class >> 17 | -------------------------------------------------------------------------------- /src/scripts/determine-lockfile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TARGET_DIR="/tmp" 4 | if [ -n "$HOMEDRIVE" ]; then 5 | TARGET_DIR="$HOMEDRIVE\\tmp" 6 | fi 7 | 8 | # Link corresponding lock file to a temporary file used by cache commands 9 | if [ -n "$PARAM_OVERRIDE_LOCKFILE" ] && [ -f "$PARAM_OVERRIDE_LOCKFILE" ]; then 10 | echo "Using $PARAM_OVERRIDE_LOCKFILE as lock file" 11 | cp "$PARAM_OVERRIDE_LOCKFILE" $TARGET_DIR/ruby-project-lockfile 12 | elif [[ "$PARAM_GEMFILE" == *.rb ]]; then 13 | GEMS_LOCKED="${PARAM_GEMFILE%.rb}.locked" 14 | 15 | if [ -f "$GEMS_LOCKED" ]; then 16 | echo "Using $GEMS_LOCKED as lock file" 17 | cp "$GEMS_LOCKED" $TARGET_DIR/ruby-project-lockfile 18 | else 19 | echo "Could not find $GEMS_LOCKED file" 20 | fi 21 | elif [ -f "$PARAM_GEMFILE.lock" ]; then 22 | echo "Using $PARAM_GEMFILE.lock as lock file" 23 | cp "$PARAM_GEMFILE.lock" $TARGET_DIR/ruby-project-lockfile 24 | else 25 | echo "Unable to determine lock file for $PARAM_GEMFILE." 26 | fi 27 | -------------------------------------------------------------------------------- /src/scripts/install-bundler.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TARGET_DIR="/tmp" 4 | if [ -n "$HOMEDRIVE" ]; then 5 | TARGET_DIR="$HOMEDRIVE\\tmp" 6 | fi 7 | 8 | if test -f "$TARGET_DIR/ruby-project-lockfile"; then 9 | APP_BUNDLER_VERSION=$(cat "$TARGET_DIR/ruby-project-lockfile" | tail -1 | tr -d " ") 10 | if [ -z "$APP_BUNDLER_VERSION" ]; then 11 | echo "Could not find bundler version from lockfile. Please use bundler-version parameter" 12 | else 13 | echo "Lock file detected bundler version $APP_BUNDLER_VERSION" 14 | fi 15 | fi 16 | 17 | if [ -n "$PARAM_BUNDLER_VERSION" ]; then 18 | echo "Found bundler-version parameter to override" 19 | APP_BUNDLER_VERSION="$PARAM_BUNDLER_VERSION" 20 | fi 21 | 22 | if ! bundle version | grep -q $APP_BUNDLER_VERSION; then 23 | echo "Installing bundler $APP_BUNDLER_VERSION" 24 | gem install bundler:$APP_BUNDLER_VERSION 25 | else 26 | echo "bundler $APP_BUNDLER_VERSION is already installed." 27 | fi 28 | -------------------------------------------------------------------------------- /src/scripts/install-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | GEMFILE_ABS_PATH="$(cd "$(dirname "$PARAM_GEMFILE")" && pwd -P)/$(basename "$PARAM_GEMFILE")" 3 | 4 | echo "$(cd "$(dirname LICENSE)" && pwd -P)/$(basename LICENSE)" 5 | if bundle config set > /dev/null 2>&1; then 6 | if [ "$PARAM_PATH" == "./vendor/bundle" ]; then 7 | bundle config deployment 'true' 8 | fi 9 | bundle config gemfile "$GEMFILE_ABS_PATH" 10 | bundle config path "$PARAM_PATH" 11 | 12 | if [ -d /opt/circleci/.rvm ]; then 13 | RVM_HOME=/opt/circleci/.rvm 14 | else 15 | # Most circle builds run as a root user, in which case rvm gets installed in /usr/local/rvm instead of $HOME/.rvm 16 | RVM_HOME=$HOME/.rvm 17 | if [ ! -f "$RVM_HOME/scripts/rvm" ]; then 18 | RVM_HOME=/usr/local/rvm 19 | fi 20 | fi 21 | 22 | if [ -d "$RVM_HOME/usr/ssl" ]; then 23 | echo "Detected rvm ssl version. Configuring bundle package with openssl dir $RVM_HOME/usr." 24 | bundle config build.openssl --with-openssl-dir="$RVM_HOME/usr" 25 | fi 26 | else 27 | if [ "$PARAM_PATH" == "./vendor/bundle" ]; then 28 | bundle config set deployment 'true' 29 | fi 30 | bundle config set gemfile "$GEMFILE_ABS_PATH" 31 | bundle config set path "$PARAM_PATH" 32 | 33 | if [ -d "$RVM_HOME/usr/ssl" ]; then 34 | echo "Detected rvm ssl version. Configuring bundle package with openssl dir $RVM_HOME/usr." 35 | bundle config set build.openssl --with-openssl-dir="$RVM_HOME/usr" 36 | fi 37 | fi 38 | 39 | if [ "$PARAM_CLEAN_BUNDLE" = true ]; then 40 | bundle check || (bundle install && bundle clean --force) 41 | else 42 | bundle check || bundle install 43 | fi 44 | -------------------------------------------------------------------------------- /src/scripts/install-ruby.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | PARAM_RUBY_VERSION=$(eval echo "${PARAM_VERSION}") 3 | RUBY_VERSION_MAJOR=$(echo "$PARAM_RUBY_VERSION" | cut -d. -f1) 4 | RUBY_VERSION_MINOR=$(echo "$PARAM_RUBY_VERSION" | cut -d. -f2) 5 | detected_platform="$(uname -s | tr '[:upper:]' '[:lower:]')" 6 | 7 | if command -v ruby >/dev/null 2>&1; then 8 | if ruby --version | grep -q "$PARAM_RUBY_VERSION"; then 9 | echo "Ruby $PARAM_RUBY_VERSION is already installed, exitting." 10 | exit 0 11 | fi 12 | fi 13 | 14 | # When on MacOS, and versions minor or equal to 3.0.x. These are the versions depending on OpenSSL 1.1 15 | if [[ "$RUBY_VERSION_MAJOR" -le 2 || ( "$RUBY_VERSION_MAJOR" -eq 3 && "$RUBY_VERSION_MINOR" -eq 0 ) ]]; then 16 | if [[ "$detected_platform" = "darwin" ]]; then 17 | rbenv install $PARAM_RUBY_VERSION 18 | rbenv global $PARAM_RUBY_VERSION 19 | exit 0 20 | else 21 | if [ -n "$PARAM_OPENSSL_PATH" ]; then 22 | echo "Using path $PARAM_OPENSSL_PATH for OpenSSL" 23 | WITH_OPENSSL="--with-openssl-dir=$PARAM_OPENSSL_PATH" 24 | elif ! openssl version | grep -q -E '1\.[0-9]+\.[0-9]+'; then 25 | echo "Did not find supported openssl version. Installing Openssl rvm package." 26 | rvm pkg install openssl 27 | # location of RVM is expected to be available at RVM_HOME env var 28 | WITH_OPENSSL="--with-openssl-dir=$RVM_HOME/usr" 29 | fi 30 | fi 31 | else 32 | rvm autolibs enable 33 | fi 34 | 35 | rvm get master 36 | rvm install "$PARAM_RUBY_VERSION" "$WITH_OPENSSL" 37 | rvm use "$PARAM_RUBY_VERSION" 38 | 39 | RUBY_PATH="$(rvm $PARAM_RUBY_VERSION 1> /dev/null 2> /dev/null && rvm env --path)" 40 | printf '%s\n' "source $RUBY_PATH" >> "$BASH_ENV" 41 | -------------------------------------------------------------------------------- /src/scripts/install-rvm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | detected_platform="$(uname -s | tr '[:upper:]' '[:lower:]')" 4 | if [ "$detected_platform" = "darwin" ]; then 5 | brew install gpg2 6 | fi 7 | 8 | 9 | # Disable IPv6 10 | mkdir -p ~/.gnupg/ 11 | find ~/.gnupg -type d -exec chmod 700 {} \; 12 | echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf 13 | 14 | # get keys to validate install https://rvm.io/rvm/security 15 | # https://stackoverflow.com/questions/69344989/gpg-no-keyserver-available 16 | declare -a keyservers=( 17 | "keys.openpgp.org" 18 | "hkp://keyserver.ubuntu.com:80" 19 | "keyserver.ubuntu.com" 20 | "ha.pool.sks-keyservers.net" 21 | "hkp://ha.pool.sks-keyservers.net:80" 22 | "p80.pool.sks-keyservers.net" 23 | "hkp://p80.pool.sks-keyservers.net:80" 24 | "pgp.mit.edu" 25 | "hkp://pgp.mit.edu:80" 26 | ) 27 | 28 | gpg_key_downloaded="false" 29 | for server in "${keyservers[@]}"; do 30 | echo "Fetching GPG keys from ${server}:" 31 | 32 | if gpg --keyserver $server --keyserver-options timeout=10 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB 33 | then 34 | echo "- GPG keys successfully added from server '${server}'" 35 | gpg_key_downloaded="true" 36 | break 37 | else 38 | echo "- Network error: Unable to receive GPG keys from server '${server}'." 39 | fi 40 | done 41 | if [ "$gpg_key_downloaded" = "false" ]; then 42 | echo "Unable to receive GPG keys from any of the known GPG keyservers. Trying to import them from rvm.io." 43 | # https://rvm.io/rvm/security#alternatives 44 | 45 | if curl -sSL https://rvm.io/mpapis.asc | gpg --import - && curl -sSL https://rvm.io/pkuczynski.asc | gpg --import - 46 | then 47 | echo "- GPG keys successfully imported directly from rvm.io server" 48 | else 49 | echo "- Could not get keys from rvm.io server either, FAILING" 50 | exit 1 51 | fi 52 | fi 53 | 54 | # https://rvm.io/rvm/security#trust-our-keys 55 | echo 409B6B1796C275462A1703113804BB82D39DC0E3:6: | gpg --import-ownertrust 56 | echo 7D2BAF1CF37B13E2069D6956105BD0E739499BDB:6: | gpg --import-ownertrust 57 | 58 | ## Update if RVM is installed and exit 59 | if [ -x "$(command -v rvm -v)" ]; then 60 | rvm get head 61 | exit 0 62 | fi 63 | 64 | curl -sSL "https://get.rvm.io" | bash -s stable 65 | 66 | # check for machine image specific path 67 | if [ -d /opt/circleci/.rvm ]; then 68 | echo "Setting PATH up for system install" 69 | # this should be what needs to be added to that $BASH_ENV since this is what's in bash_profile - i dont know when $HOME is set 70 | echo 'export PATH=$PATH:/opt/circleci/.rvm/bin' >> $BASH_ENV 71 | echo "source /opt/circleci/.rvm/scripts/rvm" >> $BASH_ENV 72 | # this will source if anyone logs in noninteractively, nvm setup only adds nvm to the path, to get the rubygems later you need to source this again 73 | echo "source /opt/circleci/.rvm/scripts/rvm" >> ~/.bashrc 74 | echo "export RVM_HOME=/opt/circleci/.rvm" >> $BASH_ENV 75 | else 76 | # Most circle builds run as a root user, in which case rvm gets installed in /usr/local/rvm instead of $HOME/.rvm 77 | RVM_HOME=$HOME/.rvm 78 | if [ -f "$RVM_HOME/scripts/rvm" ]; then 79 | echo "Using $RVM_HOME" 80 | else 81 | RVM_HOME=/usr/local/rvm 82 | echo "Using $RVM_HOME" 83 | fi 84 | echo "export RVM_HOME=$RVM_HOME" >> $BASH_ENV 85 | 86 | echo "Setting PATH up for local install" 87 | # this should be what needs to be added to that $BASH_ENV since this is what's in bash_profile - i dont know when $HOME is set 88 | echo 'export PATH=$PATH:$RVM_HOME/bin' >> $BASH_ENV 89 | echo "source $RVM_HOME/scripts/rvm" >> $BASH_ENV 90 | # this will source if anyone logs in noninteractively, nvm setup only adds nvm to the path, to get the rubygems later you need to source this again 91 | echo "source $RVM_HOME/scripts/rvm" >> ~/.bashrc 92 | fi 93 | 94 | # check if it seems like they're using rbenv already 95 | if command -v rbenv &> /dev/null && [ -f ".ruby-version" ] 96 | then 97 | echo -e "\e[91m" 98 | cat <<'SUGGESTION' 99 | 100 | ####################################################################### 101 | # WARNING 102 | ####################################################################### 103 | 104 | We've detected that you're running on a system that has the rbenv ruby 105 | version manager already installed, and you have a .ruby-version file in 106 | the current working directory. 107 | 108 | The circleci/ruby orb (that's currently executing) uses RVM to install 109 | ruby. Using more than one ruby version manager at once can, depending 110 | on the configuration of your system, cause issues. 111 | 112 | To install ruby with rbenv without using the circleci/ruby's "install" 113 | command, you can simply run a step that executes: 114 | 115 | rbenv install 116 | 117 | Which will install the version of ruby that is specified in the 118 | .ruby-version file. 119 | 120 | ####################################################################### 121 | 122 | SUGGESTION 123 | echo -e "\e[0m" 124 | fi 125 | -------------------------------------------------------------------------------- /src/scripts/rspec-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$CIRCLE_NODE_TOTAL" -eq 1 ]; then 4 | printf '%s\n' "Your job parallelism is set to 1." 5 | printf '%s\n' "The split test by timings requires at least 2 nodes to generate historical timing data." 6 | printf '%s\n' "Consider increasing your job parallelism to 2 or more." 7 | printf '%s\n' "See https://circleci.com/docs/2.0/parallelism-faster-jobs/#using-the-circleci-cli-to-split-tests for more information." 8 | fi 9 | 10 | # Disable bash glob expansion 11 | # Without this, the glob parameter will be expanded before the split command is run 12 | set -o noglob 13 | 14 | if ! mkdir -p "$PARAM_OUT_PATH"; then 15 | printf '%s\n' "Failed to create output directory: \"$PARAM_OUT_PATH\"" 16 | exit 1 17 | fi 18 | 19 | # store it as an array in the globs variable 20 | read -ra globs <<< "$PARAM_INCLUDE" 21 | 22 | prepare_split_files() { 23 | # Backup IFS 24 | readonly old_ifs="$IFS" 25 | 26 | # Split globs per comma and run the CLI split command 27 | IFS="," 28 | split_files=$(circleci tests glob "${globs[@]}" | circleci tests split --split-by=timings) 29 | 30 | # Convert list of test files to array 31 | # This is necessary because the split command returns a list of files separated by newline 32 | while IFS= read -r line; do test_files+=("$line"); done <<< "$split_files" 33 | 34 | # Rollback IFS 35 | IFS="$old_ifs" 36 | } 37 | 38 | args=() 39 | 40 | if [ -n "$PARAM_ORDER" ]; then 41 | args+=(--order "$PARAM_ORDER") 42 | fi 43 | 44 | if [ -n "$PARAM_TAG" ]; then 45 | args+=(--tag "$PARAM_TAG") 46 | fi 47 | 48 | # Parse array of test files to string separated by single space and run tests 49 | # Leaving set -x here because it's useful for debugging what files are being tested 50 | set -x 51 | if [ "$PARAM_RERUN_FAIL" = 1 ]; then 52 | circleci tests glob "${globs[@]}" | circleci tests run --command "xargs bundle exec rspec --profile 10 --format RspecJunitFormatter --out \"$PARAM_OUT_PATH\"/results.xml --format progress ${args[*]}" --verbose --split-by=timings 53 | else 54 | prepare_split_files 55 | bundle exec rspec "${test_files[@]}" --profile 10 --format RspecJunitFormatter --out "$PARAM_OUT_PATH"/results.xml --format progress "${args[@]}" 56 | fi 57 | set +x 58 | -------------------------------------------------------------------------------- /src/scripts/rubocop-check.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p "$PARAM_OUT_PATH" 4 | 5 | RUBOCOP_VERSION=$(bundle exec rubocop -v) 6 | RUBOCOP_VERSION_MAJOR=$(echo "$RUBOCOP_VERSION" | cut -d. -f1) 7 | RUBOCOP_VERSION_MINOR=$(echo "$RUBOCOP_VERSION" | cut -d. -f2) 8 | 9 | if [ "$PARAM_PARALLEL" -eq 1 ]; then 10 | bundle exec rubocop "$PARAM_CHECK_PATH" \ 11 | --format "$PARAM_FORMAT" \ 12 | --parallel \ 13 | --out $"$PARAM_OUT_PATH"/"$PARAM_FILE_OUT" 14 | else 15 | if [ "$RUBOCOP_VERSION_MAJOR" -gt 1 ] || { [ "$RUBOCOP_VERSION_MAJOR" -eq 1 ] && [ "$RUBOCOP_VERSION_MINOR" -ge 13 ]; }; then 16 | bundle exec rubocop "$PARAM_CHECK_PATH" \ 17 | --format "$PARAM_FORMAT" \ 18 | --no-parallel \ 19 | --out $"$PARAM_OUT_PATH"/"$PARAM_FILE_OUT" 20 | else 21 | bundle exec rubocop "$PARAM_CHECK_PATH" \ 22 | --format "$PARAM_FORMAT" \ 23 | --out $"$PARAM_OUT_PATH"/"$PARAM_FILE_OUT" 24 | fi 25 | fi 26 | --------------------------------------------------------------------------------