<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Wessman</title>
    <description>The latest articles on DEV Community by David Wessman (@davidwessman).</description>
    <link>https://dev.to/davidwessman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F411019%2F8bf61e16-f2ec-4c7d-a6bc-ebde79d2d924.jpg</url>
      <title>DEV Community: David Wessman</title>
      <link>https://dev.to/davidwessman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidwessman"/>
    <language>en</language>
    <item>
      <title>Blinka - Connecting Heroku CI to Github</title>
      <dc:creator>David Wessman</dc:creator>
      <pubDate>Wed, 10 Feb 2021 19:31:27 +0000</pubDate>
      <link>https://dev.to/davidwessman/blinka-connecting-heroku-ci-to-github-2ml2</link>
      <guid>https://dev.to/davidwessman/blinka-connecting-heroku-ci-to-github-2ml2</guid>
      <description>&lt;p&gt;Heroku CI (continuous integration) runs tests in an environment very similar to an Heroku application, the code is packaged into a slug and runs on a dyno.&lt;/p&gt;

&lt;p&gt;With Heroku's Github Integration it can automatically run CI-builds for every commit, then report back to Github with a pass or fail status and a link.&lt;br&gt;
The test results can be parsed if they are reported in the &lt;a href="https://wessman.co/tap-format"&gt;TAP-format&lt;/a&gt;, but it still stays on Heroku and is not visible on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--znF7-MPY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyzbye2vlejaobb1p32b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--znF7-MPY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyzbye2vlejaobb1p32b.png" alt="Heroku status reported to Github without any test results, just pass or fail."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if we could get the number or failing tests, error messages, backtraces and even screenshots directly to Github?&lt;/p&gt;

&lt;p&gt;This is why I built &lt;a href="https://www.blinka.app"&gt;Blinka🚦&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Configure your application for &lt;a href="https://devcenter.heroku.com/articles/heroku-ci"&gt;Heroku CI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://github.com/davidwessman/blinka_reporter"&gt;&lt;code&gt;blinka-reporter&lt;/code&gt;&lt;/a&gt; by adding it to &lt;code&gt;Gemfile&lt;/code&gt; using
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle add blinka-reporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Get &lt;code&gt;BLINKA_TEAM_ID&lt;/code&gt; and &lt;code&gt;BLINKA_TEAM_SECRET&lt;/code&gt; from &lt;a href="https://www.blinka.app"&gt;Blinka🚦&lt;/a&gt; - the only way to do this today is reaching out to me on Twitter &lt;a href="https://twitter.com/davidwessman"&gt;@davidwessman&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add the values from step 3 to Heroku CI environment variables.&lt;/li&gt;
&lt;li&gt;Add the Github App &lt;a href="https://github.com/apps/blinka-bot"&gt;blinka-bot&lt;/a&gt; to the repository.&lt;/li&gt;
&lt;li&gt;Add Blinka-configuration to the testing part of the Heroku configuration in &lt;code&gt;app.json&lt;/code&gt;. Mine looks like:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"environments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"addons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"heroku-postgresql:in-dyno"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"heroku-redis:in-dyno"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"buildpacks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/heroku/heroku-buildpack-google-chrome"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/heroku/heroku-buildpack-ruby"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"BLINKA_REPORT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"BLINKA_REPOSITORY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"davidwessman/synka"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"BLINKA_TAP"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"WD_CHROME_PATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/app/.apt/usr/bin/google-chrome-stable"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"formation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"standard-2x"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test-setup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bin/yarn &amp;amp;&amp;amp; bin/rails webpacker:compile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bin/rails test:system test"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Before &lt;code&gt;blinka-reporter&lt;/code&gt; version 0.3.3 you had to do the reporting separately, this is now handled by setting &lt;code&gt;BLINKA_REPORT=true&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;The gem &lt;a href="https://github.com/davidwessman/blinka_reporter"&gt;&lt;code&gt;blinka-reporter&lt;/code&gt;&lt;/a&gt; also supports outputting test results in TAP-format, without depending on anything but minitest.&lt;br&gt;
Enable by setting the envionment variable &lt;code&gt;BLINKA_TAP=true&lt;/code&gt;. This allows Heroku to parse the results and report them in their interface.&lt;/p&gt;

&lt;h1&gt;
  
  
  Results
&lt;/h1&gt;

&lt;h2&gt;
  
  
  With failing tests
&lt;/h2&gt;

&lt;p&gt;The tests run on Heroku CI and with the TAP-format output we get some feedback in the Heroku interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7NhMNASi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dhbenuvjuto6zwosmzh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7NhMNASi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dhbenuvjuto6zwosmzh1.png" alt="Test results in Heroku CI interface with one failing test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test results are reported to &lt;a href="https://www.blinka.app"&gt;Blinka🚦&lt;/a&gt; which results in a Github Status:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CTAouzKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w3ivrzxgtf4op15kvwsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CTAouzKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w3ivrzxgtf4op15kvwsz.png" alt="Blinka reports number of tests passed, failed or skipped as a Github Status."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A comment with the results of the CI-run is posted:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--do7_We6R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qsd41p47jufxwapuv3kb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--do7_We6R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qsd41p47jufxwapuv3kb.png" alt="Blinka posts a comment on Github pull request with test results."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can even handle screenshots generated from a failing test, upload them to the service and include them in the comment:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ix7j9PgI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqbexe5bafau2ib64zyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ix7j9PgI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yqbexe5bafau2ib64zyu.png" alt="Blinka includes screenshot from failing test in the Github comment."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please reach out to me on Twitter if you want to learn more!&lt;/p&gt;

</description>
      <category>github</category>
      <category>heroku</category>
      <category>testing</category>
    </item>
    <item>
      <title>Rails Dual-boot + Dependabot = 💔?</title>
      <dc:creator>David Wessman</dc:creator>
      <pubDate>Sun, 13 Dec 2020 18:26:48 +0000</pubDate>
      <link>https://dev.to/davidwessman/rails-dual-boot-dependabot-37l3</link>
      <guid>https://dev.to/davidwessman/rails-dual-boot-dependabot-37l3</guid>
      <description>&lt;p&gt;There are &lt;strong&gt;two concepts&lt;/strong&gt; which greatly affected how I work with Rails development during the last couple of years, specifically with dependency management and preparing for upgrading to the next Rails version.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;first one&lt;/strong&gt; is &lt;a href="https://dependabot.com/"&gt;Dependabot&lt;/a&gt; which opens pull-requests to update one dependency at a time. This way of working felt natural at once and allowed me to be on top of dependency updates instead of being scared of it 👻.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;second one&lt;/strong&gt; is dual-booting my Rails applications using separate lock-files, I was introduced to this concept by &lt;a href="https://fastruby.io"&gt;fastruby.io&lt;/a&gt; and their blog post &lt;a href="https://www.fastruby.io/blog/upgrade-rails/dual-boot/dual-boot-with-rails-6-0-beta.html"&gt;Getting Ready for Rails 6.0: How to Dual Boot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unfortunately&lt;/strong&gt; the two do not work well together out of the box 💔.&lt;/p&gt;

&lt;p&gt;When using dual-booting of Rails, we specify the dependencies in the &lt;code&gt;Gemfile&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;next?&lt;/span&gt;
  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"Gemfile.next"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;next&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="c1"&gt;# Specific override for next&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 6.0'&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rubyzip'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 3'&lt;/span&gt; &lt;span class="c1"&gt;# Allow freer version&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 5.2'&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rubyzip'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt; 2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt; 3'&lt;/span&gt; &lt;span class="c1"&gt;# Lock this to specific version compatible with Rails 5.2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'webpacker'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 5.1.0'&lt;/span&gt; &lt;span class="c1"&gt;# Same version for Rails 5.2 and 6.0.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to prepare working with higher versions of specific gems if needed.&lt;br&gt;
The &lt;code&gt;next?&lt;/code&gt;-block is used if the Gemfile we use is called &lt;code&gt;Gemfile.next&lt;/code&gt;.&lt;br&gt;
In order to use this we create a symbolic link, so our gemfiles in the project folder look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Dec 13 13:07 Gemfile
Dec 13 12:57 Gemfile.lock
Dec 13 12:57 Gemfile.next -&amp;gt; Gemfile
Dec 13 13:08 Gemfile.next.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means &lt;code&gt;Gemfile.next&lt;/code&gt; will refer to our usual &lt;code&gt;Gemfile&lt;/code&gt; but &lt;code&gt;next?&lt;/code&gt; will be true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;When &lt;strong&gt;Dependabot&lt;/strong&gt; updates our dependencies it is configured to find &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;Gemfile.lock&lt;/code&gt; and see if they need updating.&lt;/p&gt;

&lt;p&gt;Lets say that &lt;code&gt;webpacker&lt;/code&gt; releases a new version and needs to be updated to version &lt;code&gt;5.2&lt;/code&gt;, if we have a version requirement in the &lt;code&gt;Gemfile&lt;/code&gt; that does not allow to update to the latest version, then Dependabot will update both &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;Gemfile.lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since &lt;strong&gt;Dependabot&lt;/strong&gt; does not update &lt;code&gt;Gemfile.next.lock&lt;/code&gt; it will get out of sync with our &lt;code&gt;Gemfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile - updated by Dependabot&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'webpacker'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 5.2.0'&lt;/span&gt;

&lt;span class="c1"&gt;# Gemfile.lock - updated by Dependabot&lt;/span&gt;
&lt;span class="n"&gt;webpacker&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Gemfile.next.lock - not updated&lt;/span&gt;
&lt;span class="n"&gt;webpacker&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works in development, but in deployment using &lt;code&gt;BUNDLE_DEPLOYMENT=1&lt;/code&gt; we get an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% &lt;span class="nv"&gt;BUNDLE_DEPLOYMENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;BUNDLE_GEMFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Gemfile.next bundle
You are trying to &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="k"&gt;in &lt;/span&gt;deployment mode after changing
your Gemfile. Run &lt;span class="sb"&gt;`&lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; elsewhere and add the
updated Gemfile.next.lock to version control.

If this is a development machine, remove the &amp;lt;project-path&amp;gt;/Gemfile.next freeze
by running &lt;span class="sb"&gt;`&lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-deployment&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

The dependencies &lt;span class="k"&gt;in &lt;/span&gt;your gemfile changed

You have added to the Gemfile:
&lt;span class="k"&gt;*&lt;/span&gt; webpacker &lt;span class="o"&gt;(&lt;/span&gt;~&amp;gt; 5.2&lt;span class="o"&gt;)&lt;/span&gt;

You have deleted from the Gemfile:
&lt;span class="k"&gt;*&lt;/span&gt; webpacker &lt;span class="o"&gt;(&lt;/span&gt;~&amp;gt; 5.1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There have been discussions about using multiple Gemfiles on &lt;strong&gt;Dependabot&lt;/strong&gt;, but the proposed solution did not work well with symbolic links in the Github API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dependabot/dependabot-core/issues/2106"&gt;dependabot/dependabot-core#2106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dependabot/dependabot-core/issues/2231"&gt;dependabot/dependabot-core#2231&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Instead of trying to configure &lt;strong&gt;Dependabot&lt;/strong&gt; differently I wrote a &lt;a href="https://github.com/features/actions"&gt;&lt;strong&gt;Github Action&lt;/strong&gt;&lt;/a&gt; to update the &lt;code&gt;Gemfile.next.lock&lt;/code&gt; anytime &lt;code&gt;Gemfile.lock&lt;/code&gt; is updated.&lt;/p&gt;

&lt;p&gt;The steps in the Action are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger on every pull-request.&lt;/li&gt;
&lt;li&gt;Check if &lt;code&gt;Gemfile.lock&lt;/code&gt; was updated.&lt;/li&gt;
&lt;li&gt;Generate an access token using a Github App, based on &lt;a href="https://dev.to/dtinth/authenticating-as-a-github-app-in-a-github-actions-workflow-27co"&gt;this article&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Checkout the code using the generated access token.&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;ruby&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Update dependencies using &lt;a href="https://bundler.io/"&gt;Bundler&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Commit if there are any changes using &lt;a href="https://github.com/EndBug/add-and-commit"&gt;EndBug/add-and-commit&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/davidwessman/d7e2d4b15619802a595cc96a2f583927"&gt;Here is a gist&lt;/a&gt; and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update next&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gemfile.lock"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-20.04&lt;/span&gt;

    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;BUNDLE_GEMFILE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gemfile.next&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate token&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generate_token&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tibdex/github-app-token@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;app_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.APP_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;private_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PRIVATE_KEY }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.generate_token.outputs.token }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Ruby&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby/setup-ruby@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gems Cache&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gem-cache&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vendor/bundle&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-gem-${{ hashFiles('Gemfile.next.lock') }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-gem-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Gemfile.next&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;bundle update --minor --conservative&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EndBug/add-and-commit@v6&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gemfile.next.lock&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Updated&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Gemfile.next.lock'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above action should be saved as &lt;code&gt;.github/workflows/&amp;lt;workflow-name&amp;gt;.yml&lt;/code&gt; to get automatic updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future work
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The bundle strategy can probably be tweaked to something other than &lt;code&gt;bundle update --minor --conservative&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please get in touch with me on twitter &lt;a href="https://twitter.com/davidwessman"&gt;@davidwessman&lt;/a&gt; if you have any questions or suggestions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2020-12-13
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When using a &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;, the added commit cannot trigger Github Actions again. This can be solved by using a Personal access token (PAT) as I learned from Github user &lt;a href="https://github.com/airtower-luna"&gt;airtower-luna&lt;/a&gt; (Thank you!) in this &lt;a href="https://github.community/t/commit-generated-in-one-workflow-does-not-trigger-pull-request-workflow/147696"&gt;discussion&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2021-01-14
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The initial setup used the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; from the Github Action, and it cannot be used to trigger another Github Action job.&lt;/li&gt;
&lt;li&gt;Added a setup using an access token from a Github App, allowing new jobs to be triggered.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>dependabot</category>
      <category>dualboot</category>
      <category>github</category>
    </item>
    <item>
      <title>Error when converting PDF to image on Github Actions</title>
      <dc:creator>David Wessman</dc:creator>
      <pubDate>Thu, 15 Oct 2020 13:19:44 +0000</pubDate>
      <link>https://dev.to/davidwessman/error-when-converting-pdf-to-image-on-github-actions-2m5m</link>
      <guid>https://dev.to/davidwessman/error-when-converting-pdf-to-image-on-github-actions-2m5m</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Error:
Documents::UploadJobTest#test_#perform_creates_an_activity_for_document:
MiniMagick::Error: &lt;span class="sb"&gt;`&lt;/span&gt;convert /tmp/shrine20201009-22018-5itpj9.pdf[0] &lt;span class="nt"&gt;-auto-orient&lt;/span&gt; /tmp/image_processing20201009-22018-1uk39lv.png&lt;span class="sb"&gt;`&lt;/span&gt; failed with error:
convert-im6.q16: not authorized &lt;span class="sb"&gt;`&lt;/span&gt;/tmp/shrine20201009-22018-5itpj9.pdf&lt;span class="s1"&gt;' @ error/constitute.c/ReadImage/412.
convert-im6.q16: no images defined `/tmp/image_processing20201009-22018-1uk39lv.png'&lt;/span&gt; @ error/convert.c/ConvertImageCommand/3258.

    app/uploaders/document_uploader.rb:13:in &lt;span class="sb"&gt;`&lt;/span&gt;block &lt;span class="k"&gt;in&lt;/span&gt; &amp;lt;class:DocumentUploader&amp;gt;&lt;span class="s1"&gt;'
    test/jobs/documents/documents_upload_job_test.rb:8:in `block in &amp;lt;class:UploadJobTest&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my Ruby on Rails application, this error is raised when using &lt;a href="https://github.com/minimagick/minimagick"&gt;MiniMagick&lt;/a&gt; to convert a &lt;strong&gt;PDF&lt;/strong&gt; into an image.&lt;br&gt;
MiniMagick uses &lt;a href="https://imagemagick.org"&gt;ImageMagick&lt;/a&gt; which uses &lt;a href="https://imagemagick.org"&gt;Ghostscript&lt;/a&gt; for anything related to postscript files - for example PDFs.&lt;/p&gt;

&lt;p&gt;Due to a &lt;a href="https://www.kb.cert.org/vuls/id/332928/"&gt;security vulnerability in Ghostscript &amp;lt; 9.24&lt;/a&gt;, ImageMagick changed the default policy to not allow conversions using Ghostscript.&lt;br&gt;
Even if Ghostscript has fixed the vulnerability, the ImageMagick policy has not been changed.&lt;/p&gt;

&lt;p&gt;In my application I use MiniMagick via a gem called &lt;a href="https://shrinerb.com"&gt;Shrine&lt;/a&gt; where a &lt;strong&gt;PDF&lt;/strong&gt; is processed to get a thumbnail. To read more about this, please visit the &lt;a href="https://shrinerb.com/docs/processing"&gt;Shrine documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On Github Actions the default linux image is &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on"&gt;Ubuntu 18.04 (20.04 in preview)&lt;/a&gt;.&lt;br&gt;
Ubuntu 18.04 should have an updated version of Ghostscript, but still has a policy for ImageMagick that disallows conversion from &lt;strong&gt;PDF&lt;/strong&gt; to an image.&lt;/p&gt;
&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;My solution was inspired by this &lt;a href="https://stackoverflow.com/a/61721903/4762756"&gt;StackOverflow answer&lt;/a&gt;.&lt;br&gt;
It can be added to a Github Action like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ---&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;job01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt; &lt;span class="c1"&gt;# ubuntu-18.04&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Change ImageMagick policy to allow pdf-&amp;gt;png conversion.&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sudo sed -i 's/^.*policy.*coder.*none.*PDF.*//' /etc/ImageMagick-6/policy.xml&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;more steps&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Mac OS
&lt;/h1&gt;

&lt;p&gt;If you experience this error on Mac OS it can be helpful to reinstall ImageMagick and Ghostscript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew uninstall ghostscript imagemagick
brew &lt;span class="nb"&gt;install &lt;/span&gt;ghostscript imagemagick

gs &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="c"&gt;# make sure it is &amp;gt; 9.24 (9.53.3 on my machine currently.)&lt;/span&gt;
magick &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="c"&gt;# make sure the row `Delegates` includes `gslib`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>github</category>
      <category>actions</category>
      <category>rails</category>
      <category>imagemagick</category>
    </item>
    <item>
      <title>Rails: Minitest results output in TAP-format for Heroku CI</title>
      <dc:creator>David Wessman</dc:creator>
      <pubDate>Sat, 18 Jul 2020 20:31:38 +0000</pubDate>
      <link>https://dev.to/davidwessman/rails-minitest-results-output-in-tap-format-for-heroku-ci-46d3</link>
      <guid>https://dev.to/davidwessman/rails-minitest-results-output-in-tap-format-for-heroku-ci-46d3</guid>
      <description>&lt;p&gt;When using &lt;a href="https://devcenter.heroku.com/articles/heroku-ci"&gt;Heroku CI&lt;/a&gt; for automatic testing, the default output is just pass or fail without any parsing of how many tests passed or what errors where found.&lt;/p&gt;

&lt;p&gt;This can be improved if you output the results in the &lt;a href="https://testanything.org"&gt;Test Anything Protocol-format (TAP-format)&lt;/a&gt; according to &lt;a href="https://devcenter.heroku.com/articles/testpack-api#output"&gt;Heroku&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This format is not built into the test frameworks used in Ruby on Rails. Therefore I had to write my own test reporter.&lt;/p&gt;

&lt;p&gt;I chose to implement this for Minitest and decided to use the gem &lt;br&gt;
&lt;a href="https://github.com/kern/minitest-reporters"&gt;&lt;code&gt;minitest-reporters&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Expected outcome
&lt;/h1&gt;

&lt;p&gt;I have a small project where the test suit looks like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U2d6VbSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h45ugpmogej1rghoiyvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U2d6VbSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h45ugpmogej1rghoiyvx.png" alt="Output of test results without formatting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To adhere to the TAP-format I need it to also output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TAP version 13
1..7
ok 1 - AccountsControllerTest - test_renders_users_account
ok 2 - AccountsControllerTest - test_require_login
ok 3 - CallbacksMessagesControllerTest - test_handle_status_callback
ok 4 - MessagesControllerTest - test_should_create_message
ok 5 - ContactsControllerTest - test_should_create_contact
ok 6 - ContactsControllerTest - test_should_update_contact
ok 7 - ContactsControllerTest - test_show_contact
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;I created a custom reporter called &lt;code&gt;TapReporter&lt;/code&gt; by inspecting a standard reporter from the &lt;code&gt;minitest-reporters&lt;/code&gt; gem called &lt;code&gt;ProgressReporter&lt;/code&gt; (&lt;a href="https://github.com/kern/minitest-reporters/blob/master/lib/minitest/reporters/progress_reporter.rb"&gt;see source&lt;/a&gt;):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2QEI1AOs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/shx6xdze5btcjk4ds0t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2QEI1AOs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/shx6xdze5btcjk4ds0t9.png" alt="Output of test results with TAP-formatting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution on Heroku
&lt;/h1&gt;

&lt;h3&gt;
  
  
  A failing test
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bTF_pH2x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vtim1fgwo41i3egwa7ap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bTF_pH2x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vtim1fgwo41i3egwa7ap.png" alt="A failing test on Heroku"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Successful tests
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Td6BAhRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tmjcrjjwllbm8iisbset.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Td6BAhRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tmjcrjjwllbm8iisbset.png" alt="Successful tests on Heroku"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Keywords
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://testanything.org"&gt;Ruby on Rails&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dashboard.heroku.com"&gt;Heroku&lt;/a&gt; - Platform as a Service, useful for hosting web applications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://codeship.com/continuous-integration-essentials"&gt;Continuous integration (CI)&lt;/a&gt; - in this post it mostly refers to automated testing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://testanything.org"&gt;Test anything protocol(TAP)&lt;/a&gt; - a protocol for test results.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://testanything.org"&gt;Minitest&lt;/a&gt; - a test framework for ruby.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>testing</category>
      <category>heroku</category>
      <category>tap</category>
    </item>
  </channel>
</rss>
