<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/lintr-bot-lintrs-hester-egg/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.masalmon.eu/2018/03/30/lintr-bot/"> Maëlle</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Remember my blog post about <a rel="nofollow" href="http://www.masalmon.eu/2017/06/17/automatictools/" target="_blank">automatic tools for improving R packages</a>? One of these tools is <a rel="nofollow" href="https://github.com/jimhester/lintr" target="_blank">Jim Hester’s <code>lintr</code></a>, a package that performs static code analysis. In my experience it mostly helps identifying too long code lines and missing space, although it’s a bit more involved than that. In any case, <code>lintr</code> helps you maintain good code style, and as mentioned in that now old post of mine, you can add a <code>lintr</code> unit test to your package which will ensure you don’t get lazy over time.</p>
<p>Now say your package has a <code>lintr</code> unit test and lives on GitHub. What happens if someone makes a pull request and writes looong code lines? Continuous integration builds will fail but not only that… The contributor will get to know Lintr Bot, lintr’s Hester (<a rel="nofollow" href="https://en.wikipedia.org/wiki/Easter_egg_(media)" target="_blank">Easter</a>) egg!</p>
<p><span></span></p>
<h1>Lintr Bot, a lazy little thing?</h1>
<p>Lintr Bot has a <a rel="nofollow" href="https://github.com/lintr-bot" target="_blank">GitHub profile</a>. I am actually responsible for its avatar, because when I discovered it a while back I offered Jim to design it based <a rel="nofollow" href="https://pixabay.com/en/cute-cartoon-robot-funny-character-807306/" target="_blank">on this free image</a>. Now, Lintr Bot has a face but if you look at its GitHub activity, you might wonder, what does it even do? It’s perfectly fine for a human to have nearly no GitHub activity, but remember that Lintr Bot lives on GitHub only, so what does it do all day?</p>
<p>Well Lintr Bot goes around and comments on Pull Requests in R packages, see for instance <a rel="nofollow" href="https://github.com/ropensci/drake/pull/342#issuecomment-375929172" target="_blank">this comment</a>. As mentioned earlier, a contributor who forgets even a slight code style mistake will be reminded of it by Lintr Bot if the package has a <code>lintr</code> unit test. This is quite useful!</p>
<p>We might also wonder how often Lintr Bot actually works? After all, since GitHub activity timeline doesn’t show comments on Pull Requests, we’re at a loss when it comes to estimating how active this bot is…</p>
<h1>Lintr Bot’s year in review</h1>
<p>That’s where my <a rel="nofollow" href="http://www.masalmon.eu/2018/03/04/hrbrpkgs/" target="_blank"><code>ghrecipes</code> package</a>, presented in <a rel="nofollow" href="http://www.masalmon.eu/2018/03/04/hrbrpkgs/" target="_blank">my blog post about Bob Rudis’ R packages</a>, will come into play. I’ve been working on a function called <code>spy</code> which can return either Pull Requests or Issues an user commented on during a given period of time. As creepy as it might sound, it could help you trace back all the desperate comments you wrote when debugging something last week for instance, without your having had to track them in the first place. <code>ghrecipe::spy</code> is <a rel="nofollow" href="https://github.com/ropenscilabs/ghrecipes/blob/master/R/spy.R" target="_blank">a work in progress</a>, but let’s see what it can return me for Lintr Bot!</p>
<p>Note that there’s no way to filter for comments between a date range, well as far as I understand the “search” functionalities of GitHub V4 API, so I can only filter Pull Requests updated in a given range.</p>
<div>
<div>
<pre><code><span>lintrbot_act</span><span> </span><span>&lt;-</span><span> </span><span>ghrecipes</span><span>::</span><span>spy</span><span>(</span><span>user</span><span> </span><span>=</span><span> </span><span>&quot;lintr-bot&quot;</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;PullRequest&quot;</span><span>,</span><span>
</span><span>updated_after</span><span> </span><span>=</span><span> </span><span>&quot;2017-03-30&quot;</span><span>,</span><span>
</span><span>updated_before</span><span> </span><span>=</span><span> </span><span>&quot;2018-03-30&quot;</span><span>)</span><span>
</span><span>lintrbot_act</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>filter</span><span>(</span><span>lintrbot_act</span><span>,</span><span>
</span><span>as.Date</span><span>(</span><span>created_at</span><span>)</span><span> </span><span>>=</span><span> </span><span>anytime</span><span>::</span><span>anydate</span><span>(</span><span>&quot;2017-03-30&quot;</span><span>))</span><span>
</span></code></pre>
</div>
</div>
<p>We get 228 pull requests in one year! Lintr Bot is definitely <em>not</em> a lazy little thing!</p>
<p>Here are 5 Pull Requests that got a visit from Lintr Bot.</p>
<div>
<div>
<pre><code><span>knitr</span><span>::</span><span>kable</span><span>(</span><span>lintrbot_act</span><span>[</span><span>1</span><span>:</span><span>5</span><span>,])</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>owner</th>
<th>repo</th>
<th>title</th>
<th>created_at</th>
<th>state</th>
<th>author</th>
<th>url</th>
<th>no_comments</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr>
<td>PredictiveEcology</td>
<td>reproducible</td>
<td>mergeCache</td>
<td>2018-03-29 18:29:33</td>
<td>MERGED</td>
<td>eliotmcintire</td>
<td><a rel="nofollow" href="https://github.com/PredictiveEcology/reproducible/pull/18" target="_blank">https://github.com/PredictiveEcology/reproducible/pull/18</a></td>
<td>2</td>
<td>18</td>
</tr>
<tr>
<td>PredictiveEcology</td>
<td>SpaDES.core</td>
<td>change objectSize to objSize – name conflict with R.oo::objectSize</td>
<td>2018-03-26 23:48:22</td>
<td>MERGED</td>
<td>eliotmcintire</td>
<td><a rel="nofollow" href="https://github.com/PredictiveEcology/SpaDES.core/pull/57" target="_blank">https://github.com/PredictiveEcology/SpaDES.core/pull/57</a></td>
<td>1</td>
<td>57</td>
</tr>
<tr>
<td>PredictiveEcology</td>
<td>reproducible</td>
<td>memoise – loadFromRepo</td>
<td>2018-03-26 17:41:25</td>
<td>MERGED</td>
<td>eliotmcintire</td>
<td><a rel="nofollow" href="https://github.com/PredictiveEcology/reproducible/pull/17" target="_blank">https://github.com/PredictiveEcology/reproducible/pull/17</a></td>
<td>3</td>
<td>17</td>
</tr>
<tr>
<td>PredictiveEcology</td>
<td>quickPlot</td>
<td>thin fixes – bugfixes, SpatialPolygonsDataFrames</td>
<td>2018-03-26 05:32:12</td>
<td>MERGED</td>
<td>eliotmcintire</td>
<td><a rel="nofollow" href="https://github.com/PredictiveEcology/quickPlot/pull/13" target="_blank">https://github.com/PredictiveEcology/quickPlot/pull/13</a></td>
<td>2</td>
<td>13</td>
</tr>
<tr>
<td>ptl93</td>
<td>AEDA</td>
<td>added getEps</td>
<td>2018-03-25 17:12:44</td>
<td>MERGED</td>
<td>MiGraber</td>
<td><a rel="nofollow" href="https://github.com/ptl93/AEDA/pull/39" target="_blank">https://github.com/ptl93/AEDA/pull/39</a></td>
<td>5</td>
<td>39</td>
</tr>
</tbody>
</table>
<p>Let’s have a look at the time series of comments.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;ggplot2&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;hrbrthemes&quot;</span><span>)</span><span>
</span><span>ggplot</span><span>(</span><span>lintrbot_act</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_segment</span><span>(</span><span>aes</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>created_at</span><span>,</span><span> </span><span>xend</span><span> </span><span>=</span><span> </span><span>created_at</span><span>),</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>0</span><span>,</span><span> </span><span>yend</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span> </span><span>+</span><span>
</span><span>theme_ipsum</span><span>(</span><span>base_size</span><span> </span><span>=</span><span> </span><span>16</span><span>,</span><span>
</span><span>strip_text_size</span><span> </span><span>=</span><span> </span><span>16</span><span>)</span><span> </span><span>+</span><span>
</span><span>ggtitle</span><span>(</span><span>&quot;Lintr Bot's work events&quot;</span><span>,</span><span>
</span><span>subtitle</span><span> </span><span>=</span><span> </span><span>&quot;Each vertical line indicates Lintr Bot's commenting on a pull request&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="plot of chunk unnamed-chunk-3" src="https://i0.wp.com/www.masalmon.eu/figure/source/2018-03-30-lintr-bot/unnamed-chunk-3-1.png?w=456" data-recalc-dims="1"></p>
<p>So it seems that Lintr Bot works quite regularly, with some intense periods! I won’t look at the number of repos over time to differentiate activity due to more activity in a few repos or due to several repos, but I’m curious to see who was helped by Lintr Bot.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;magrittr&quot;</span><span>)</span><span>
</span><span>dplyr</span><span>::</span><span>group_by</span><span>(</span><span>lintrbot_act</span><span>,</span><span> </span><span>owner</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>summarize</span><span>(</span><span>repos</span><span> </span><span>=</span><span> </span><span>toString</span><span>(</span><span>unique</span><span>(</span><span>repo</span><span>)),</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>n</span><span>())</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>arrange</span><span>(</span><span>-</span><span> </span><span>n</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>filter</span><span>(</span><span>n</span><span> </span><span>>=</span><span> </span><span>5</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span></code></pre>
</div>
</div>
<table>
<thead>
<tr>
<th>owner</th>
<th>repos</th>
<th>n</th>
</tr>
</thead>
<tbody>
<tr>
<td>RTMC</td>
<td>tmc-rstudio, tmc-r-tester, tmc-r</td>
<td>64</td>
</tr>
<tr>
<td>mlr-org</td>
<td>mlr</td>
<td>38</td>
</tr>
<tr>
<td>PredictiveEcology</td>
<td>reproducible, SpaDES.core, quickPlot, SpaDES.tools, SpaDES.shiny</td>
<td>26</td>
</tr>
<tr>
<td>Azure</td>
<td>doAzureParallel</td>
<td>16</td>
</tr>
<tr>
<td>HealthCatalyst</td>
<td>healthcareai-r</td>
<td>16</td>
</tr>
<tr>
<td>neuropsychology</td>
<td>psycho.R</td>
<td>11</td>
</tr>
<tr>
<td>ropensci</td>
<td>drake</td>
<td>11</td>
</tr>
<tr>
<td>hbc</td>
<td>bcbioRNASeq, bcbioSingleCell</td>
<td>5</td>
</tr>
</tbody>
</table>
<p>I must say that besides the recently onboarded rOpenSci package <code>drake</code> by Will Landau, I don’t know any of these repos!</p>
<h1>Hire Lintr Bot?</h1>
<p>What about you? Would you let that cute little bot help you?</p>
<p>Note, a good package to improve code style automatically is <a rel="nofollow" href="https://github.com/r-lib/styler" target="_blank"><code>styler</code></a> by Kirill Müller and Lorenz Walthert, so if Lintr Bot has a lot to tell you, give <code>styler::style_pkg()</code> a try!</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.masalmon.eu/2018/03/30/lintr-bot/"> Maëlle</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/ByjIIN638fw" height="1"></a></div>