├── .buildkite └── pipeline.yml ├── .gitignore ├── .rspec ├── .travis.yml ├── Appraisals ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── gemfiles ├── rspec_3_0.gemfile ├── rspec_3_0.gemfile.lock ├── rspec_3_1.gemfile ├── rspec_3_1.gemfile.lock ├── rspec_3_2.gemfile ├── rspec_3_2.gemfile.lock ├── rspec_3_3.gemfile ├── rspec_3_3.gemfile.lock ├── rspec_3_4.gemfile ├── rspec_3_4.gemfile.lock ├── rspec_3_5.gemfile ├── rspec_3_5.gemfile.lock ├── rspec_3_6.gemfile ├── rspec_3_6.gemfile.lock ├── rspec_3_7.gemfile └── rspec_3_7.gemfile.lock ├── lib └── rspec │ ├── buildkite.rb │ └── buildkite │ ├── annotation_formatter.rb │ ├── recolorizer.rb │ └── version.rb ├── rspec-buildkite.gemspec └── spec ├── rspec └── buildkite_spec.rb └── spec_helper.rb /.buildkite/pipeline.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - command: bundle exec rake 3 | env: 4 | BUNDLE_AUTO_INSTALL: true 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | 10 | # rspec failure tracking 11 | .rspec_status 12 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --format RSpec::Buildkite::AnnotationFormatter 4 | --require spec_helper 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.6 5 | - 2.7 6 | - 3.0 7 | gemfile: 8 | - gemfiles/rspec_3_0.gemfile 9 | - gemfiles/rspec_3_1.gemfile 10 | - gemfiles/rspec_3_2.gemfile 11 | - gemfiles/rspec_3_3.gemfile 12 | - gemfiles/rspec_3_4.gemfile 13 | - gemfiles/rspec_3_5.gemfile 14 | - gemfiles/rspec_3_6.gemfile 15 | - gemfiles/rspec_3_7.gemfile 16 | -------------------------------------------------------------------------------- /Appraisals: -------------------------------------------------------------------------------- 1 | appraise "rspec-3-0" do 2 | gem "rspec", "~> 3.0.0" 3 | end 4 | 5 | appraise "rspec-3-1" do 6 | gem "rspec", "~> 3.1.0" 7 | end 8 | 9 | appraise "rspec-3-2" do 10 | gem "rspec", "~> 3.2.0" 11 | end 12 | 13 | appraise "rspec-3-3" do 14 | gem "rspec", "~> 3.3.0" 15 | end 16 | 17 | appraise "rspec-3-4" do 18 | gem "rspec", "~> 3.4.0" 19 | end 20 | 21 | appraise "rspec-3-5" do 22 | gem "rspec", "~> 3.5.0" 23 | end 24 | 25 | appraise "rspec-3-6" do 26 | gem "rspec", "~> 3.6.0" 27 | end 28 | 29 | appraise "rspec-3-7" do 30 | gem "rspec", "~> 3.7.0" 31 | end 32 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } 4 | 5 | # Specify your gem's dependencies in rspec-buildkite.gemspec 6 | gemspec 7 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (13.0.1) 17 | rspec (3.8.0) 18 | rspec-core (~> 3.8.0) 19 | rspec-expectations (~> 3.8.0) 20 | rspec-mocks (~> 3.8.0) 21 | rspec-core (3.8.0) 22 | rspec-support (~> 3.8.0) 23 | rspec-expectations (3.8.2) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.8.0) 26 | rspec-mocks (3.8.0) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.8.0) 29 | rspec-support (3.8.0) 30 | thor (0.20.3) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Samuel Cochran 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSpec Buildkite 2 | 3 | Output [RSpec][rspec] failure messages as [Buildkite annotations][buildkite-annotations] as soon as they happen so you can fix them while your build finishes. 4 | 5 | ![A Buildkite build still in progress with an annotation showing an RSpec failure][screenshot] 6 | 7 | [rspec]: http://rspec.info 8 | [buildkite-annotations]: https://buildkite.com/docs/agent/v3/cli-annotate 9 | [screenshot]: https://user-images.githubusercontent.com/14028/40577709-5b839e8a-614d-11e8-898b-575bb0cc02ba.png 10 | 11 | ## Installation 12 | 13 | Add the gem to your Gemfile, after rspec: 14 | 15 | ```ruby 16 | gem "rspec" 17 | gem "rspec-buildkite" 18 | ``` 19 | 20 | And then bundle: 21 | 22 | $ bundle 23 | 24 | Or install it yourself as: 25 | 26 | $ gem install rspec-buildkite 27 | 28 | ## Usage 29 | 30 | Add it to your `.rspec` alongside your favorite formatter: 31 | 32 | ``` 33 | --color 34 | --require spec_helper 35 | --format documentation 36 | --format RSpec::Buildkite::AnnotationFormatter 37 | ``` 38 | 39 | Now run your specs on Buildkite! 40 | 41 | ### Docker & Docker Compose 42 | 43 | If you run your RSpec builds inside Docker or Docker Compose then you'll need to make sure that buildkite-agent is available inside your container, and that some environment variables are propagated into the running containers. The buildkite-agent binary can be baked into your image, or mounted in as a volume. If you're using [the docker-compose-buildkite-plugin][dcbp] you can pass the environment using [plugin configuration][dcbp-env]. Or you can add them to the [environment section][dc-env] in your `docker-compose.yml`, or supply [env arguments][d-env] to your docker command. 44 | 45 | The following environment variables are required: 46 | 47 | - `BUILDKITE` 48 | - `BUILDKITE_BUILD_URL` 49 | - `BUILDKITE_JOB_ID` 50 | - `BUILDKITE_AGENT_ACCESS_TOKEN` 51 | 52 | [dcbp]: https://github.com/buildkite-plugins/docker-compose-buildkite-plugin 53 | [dcbp-env]: https://github.com/buildkite-plugins/docker-compose-buildkite-plugin#environment 54 | [dc-env]: https://docs.docker.com/compose/environment-variables/ 55 | [d-env]: https://docs.docker.com/engine/reference/run/#env-environment-variables 56 | 57 | ## Development 58 | 59 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 60 | 61 | 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 62 | 63 | ## Contributing 64 | 65 | Bug reports and pull requests are welcome on GitHub at https://github.com/buildkite/rspec-buildkite. 66 | 67 | ## License 68 | 69 | The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). 70 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | require "appraisal" 4 | 5 | RSpec::Core::RakeTask.new(:spec) 6 | 7 | task :default => :spec 8 | 9 | if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"] 10 | task :default => :appraisal 11 | end 12 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "rspec/buildkite" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start(__FILE__) 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | bundle exec appraisal 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.0.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_0.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.0.0) 18 | rspec-core (~> 3.0.0) 19 | rspec-expectations (~> 3.0.0) 20 | rspec-mocks (~> 3.0.0) 21 | rspec-core (3.0.4) 22 | rspec-support (~> 3.0.0) 23 | rspec-expectations (3.0.4) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.0.0) 26 | rspec-mocks (3.0.4) 27 | rspec-support (~> 3.0.0) 28 | rspec-support (3.0.4) 29 | thor (0.20.0) 30 | 31 | PLATFORMS 32 | ruby 33 | 34 | DEPENDENCIES 35 | appraisal 36 | bundler (~> 2.3) 37 | coderay 38 | rake 39 | rspec (~> 3.0.0) 40 | rspec-buildkite! 41 | 42 | BUNDLED WITH 43 | 2.3.17 44 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.1.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_1.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.1.0) 18 | rspec-core (~> 3.1.0) 19 | rspec-expectations (~> 3.1.0) 20 | rspec-mocks (~> 3.1.0) 21 | rspec-core (3.1.7) 22 | rspec-support (~> 3.1.0) 23 | rspec-expectations (3.1.2) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.1.0) 26 | rspec-mocks (3.1.3) 27 | rspec-support (~> 3.1.0) 28 | rspec-support (3.1.2) 29 | thor (0.20.0) 30 | 31 | PLATFORMS 32 | ruby 33 | 34 | DEPENDENCIES 35 | appraisal 36 | bundler (~> 2.3) 37 | coderay 38 | rake 39 | rspec (~> 3.1.0) 40 | rspec-buildkite! 41 | 42 | BUNDLED WITH 43 | 2.3.17 44 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.2.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_2.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.2.0) 18 | rspec-core (~> 3.2.0) 19 | rspec-expectations (~> 3.2.0) 20 | rspec-mocks (~> 3.2.0) 21 | rspec-core (3.2.3) 22 | rspec-support (~> 3.2.0) 23 | rspec-expectations (3.2.1) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.2.0) 26 | rspec-mocks (3.2.1) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.2.0) 29 | rspec-support (3.2.2) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.2.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.3.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_3.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.3.0) 18 | rspec-core (~> 3.3.0) 19 | rspec-expectations (~> 3.3.0) 20 | rspec-mocks (~> 3.3.0) 21 | rspec-core (3.3.2) 22 | rspec-support (~> 3.3.0) 23 | rspec-expectations (3.3.1) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.3.0) 26 | rspec-mocks (3.3.2) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.3.0) 29 | rspec-support (3.3.0) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.3.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.4.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_4.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.4.0) 18 | rspec-core (~> 3.4.0) 19 | rspec-expectations (~> 3.4.0) 20 | rspec-mocks (~> 3.4.0) 21 | rspec-core (3.4.4) 22 | rspec-support (~> 3.4.0) 23 | rspec-expectations (3.4.0) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.4.0) 26 | rspec-mocks (3.4.1) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.4.0) 29 | rspec-support (3.4.1) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.4.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.5.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_5.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.5.0) 18 | rspec-core (~> 3.5.0) 19 | rspec-expectations (~> 3.5.0) 20 | rspec-mocks (~> 3.5.0) 21 | rspec-core (3.5.4) 22 | rspec-support (~> 3.5.0) 23 | rspec-expectations (3.5.0) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.5.0) 26 | rspec-mocks (3.5.0) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.5.0) 29 | rspec-support (3.5.0) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.5.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_6.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.6.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_6.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.6.0) 18 | rspec-core (~> 3.6.0) 19 | rspec-expectations (~> 3.6.0) 20 | rspec-mocks (~> 3.6.0) 21 | rspec-core (3.6.0) 22 | rspec-support (~> 3.6.0) 23 | rspec-expectations (3.6.0) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.6.0) 26 | rspec-mocks (3.6.0) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.6.0) 29 | rspec-support (3.6.0) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.6.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_7.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rspec", "~> 3.7.0" 6 | 7 | gemspec path: "../" 8 | -------------------------------------------------------------------------------- /gemfiles/rspec_3_7.gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rspec-buildkite (0.1.6) 5 | rspec-core (~> 3.0) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | appraisal (2.2.0) 11 | bundler 12 | rake 13 | thor (>= 0.14.0) 14 | coderay (1.1.2) 15 | diff-lcs (1.3) 16 | rake (12.3.1) 17 | rspec (3.7.0) 18 | rspec-core (~> 3.7.0) 19 | rspec-expectations (~> 3.7.0) 20 | rspec-mocks (~> 3.7.0) 21 | rspec-core (3.7.1) 22 | rspec-support (~> 3.7.0) 23 | rspec-expectations (3.7.0) 24 | diff-lcs (>= 1.2.0, < 2.0) 25 | rspec-support (~> 3.7.0) 26 | rspec-mocks (3.7.0) 27 | diff-lcs (>= 1.2.0, < 2.0) 28 | rspec-support (~> 3.7.0) 29 | rspec-support (3.7.1) 30 | thor (0.20.0) 31 | 32 | PLATFORMS 33 | ruby 34 | 35 | DEPENDENCIES 36 | appraisal 37 | bundler (~> 2.3) 38 | coderay 39 | rake 40 | rspec (~> 3.7.0) 41 | rspec-buildkite! 42 | 43 | BUNDLED WITH 44 | 2.3.17 45 | -------------------------------------------------------------------------------- /lib/rspec/buildkite.rb: -------------------------------------------------------------------------------- 1 | require "rspec/buildkite/version" 2 | require "rspec/buildkite/annotation_formatter" 3 | -------------------------------------------------------------------------------- /lib/rspec/buildkite/annotation_formatter.rb: -------------------------------------------------------------------------------- 1 | require "thread" 2 | 3 | require "rspec/core" 4 | require "rspec/buildkite/recolorizer" 5 | 6 | module RSpec::Buildkite 7 | # Create a Buildkite annotation for RSpec failures 8 | # 9 | # Help folks fix their builds as soon as possible when failures crop up by 10 | # calling out failures in an annotation, even while the build is still running. 11 | # 12 | # Uses a background Thread so we don't block the build. 13 | # 14 | class AnnotationFormatter 15 | RSpec::Core::Formatters.register self, :example_failed 16 | 17 | def initialize(output) 18 | # We don't actually use this, but keep a reference anyway 19 | @output = output 20 | 21 | # Only setup if we're actually running on Buildkite 22 | if ENV["BUILDKITE"] 23 | @queue = Queue.new 24 | @thread = Thread.new(&method(:thread)) 25 | at_exit { @queue.push(:close); @thread.join } 26 | end 27 | end 28 | 29 | def example_failed(notification) 30 | return if @queue.nil? || RSpec.world.wants_to_quit 31 | 32 | @queue.push(notification) 33 | end 34 | 35 | private 36 | 37 | def thread 38 | while notification = @queue.pop 39 | break if notification == :close 40 | 41 | if notification 42 | system("buildkite-agent", "annotate", 43 | "--context", "rspec", 44 | "--style", "error", 45 | "--append", 46 | format_failure(notification), 47 | out: :close # only display errors 48 | ) or raise "buildkite-agent failed to run: #{$?}#{" (command not found)" if $?.exitstatus == 127}" 49 | end 50 | end 51 | rescue 52 | $stderr.puts "Warning: Couldn't create Buildkite annotations:\n" << 53 | " #{$!.to_s}\n" << 54 | " #{$!.backtrace.join("\n ")}" 55 | end 56 | 57 | def format_failure(notification) 58 | build_url = ENV["BUILDKITE_BUILD_URL"].to_s 59 | job_id = ENV["BUILDKITE_JOB_ID"].to_s 60 | job_url = "#{build_url}##{job_id}" 61 | 62 | %{
\n} << 63 | %{#{notification.description.encode(:xml => :text)}\n} << 64 | %{
#{Recolorizer.recolorize(notification.colorized_message_lines.join("\n").encode(:xml => :text))}
\n} << 65 | format_rerun(notification) << 66 | %{

in :attr)}>Job ##{job_id.encode(:xml => :text)}

\n} << 67 | %{
} << 68 | %{\n\n\n} 69 | end 70 | 71 | def format_rerun(notification) 72 | %{
} <<
73 |       %{rspec #{notification.example.location_rerun_argument.encode(:xml => :text)}} <<
74 |       %{ # #{notification.example.full_description.encode(:xml => :text)}} <<
75 |       %{
\n} 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /lib/rspec/buildkite/recolorizer.rb: -------------------------------------------------------------------------------- 1 | module RSpec::Buildkite 2 | module Recolorizer 3 | module_function 4 | 5 | # Re-color an ANSI-colorized string using terminal CSS classes: 6 | # https://github.com/buildkite/terminal/blob/05a77905c468b9150cac41298fdb8a0735024d42/style.go#L34 7 | def recolorize(string) 8 | level = 0 9 | string.gsub(/\e\[(\d+(?:;\d+)*)m/) do 10 | "".tap do |buffer| 11 | codes = $1.split(";").map(&:to_i) 12 | 13 | classes = [] 14 | while code = codes.shift 15 | case code 16 | when 0 17 | classes.clear 18 | buffer << ("" * level) 19 | level = 0 20 | when 1..5, 9, 30..37 21 | classes << "term-fg#{code}" 22 | when 38 23 | if codes[0] == 5 24 | codes.shift 25 | if codes[0] 26 | classes << "term-fgx#{codes.shift}" 27 | end 28 | end 29 | when 40..47 30 | classes << "term-bg#{code}" 31 | when 48 32 | if codes[0] == 5 33 | codes.shift 34 | if codes[0] 35 | classes << "term-bgx#{codes.shift}" 36 | end 37 | end 38 | when 90..97 39 | classes << "term-fgi#{code}" 40 | when 100..107 41 | classes << "term-bgi#{code}" 42 | end 43 | end 44 | 45 | if classes.any? 46 | level += 1 47 | buffer << %{ :attr)}>} 48 | end 49 | end 50 | end << ("" * level) 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/rspec/buildkite/version.rb: -------------------------------------------------------------------------------- 1 | module RSpec 2 | module Buildkite 3 | VERSION = "0.1.6" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /rspec-buildkite.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path("lib", __dir__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require "rspec/buildkite/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rspec-buildkite" 7 | spec.version = RSpec::Buildkite::VERSION 8 | spec.author = "Samuel Cochran" 9 | spec.email = "sj26@sj26.com" 10 | 11 | spec.summary = %q{RSpec formatter creating Buildkite annotations for failures} 12 | spec.homepage = "https://github.com/buildkite/rspec-buildkite" 13 | spec.license = "MIT" 14 | 15 | spec.files = Dir["README.md", "LICENSE.txt", "lib/**/*"] 16 | 17 | spec.required_ruby_version = ">= 2.2" 18 | 19 | spec.add_dependency "rspec-core", "~> 3.0" 20 | 21 | spec.add_development_dependency "bundler", "~> 2.3" 22 | spec.add_development_dependency "rake" 23 | spec.add_development_dependency "rspec", "~> 3.0" 24 | spec.add_development_dependency "coderay" 25 | spec.add_development_dependency "appraisal" 26 | end 27 | -------------------------------------------------------------------------------- /spec/rspec/buildkite_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe RSpec::Buildkite do 2 | it "has a version number" do 3 | expect(RSpec::Buildkite::VERSION).not_to be nil 4 | end 5 | 6 | it "does something useful" do 7 | sleep(5) 8 | expect(false).to eq(true) 9 | sleep(5) 10 | end 11 | 12 | it "fails several times" do 13 | sleep(5) 14 | expect(false).to eq(true) 15 | sleep(5) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | require "coderay" 3 | require "rspec/buildkite" 4 | 5 | RSpec.configure do |config| 6 | # Enable flags like --only-failures and --next-failure 7 | config.example_status_persistence_file_path = ".rspec_status" 8 | 9 | # Disable RSpec exposing methods globally on `Module` and `main` 10 | config.disable_monkey_patching! 11 | 12 | config.expect_with :rspec do |c| 13 | c.syntax = :expect 14 | end 15 | end 16 | --------------------------------------------------------------------------------