<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://marco-c.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://marco-c.github.io/" rel="alternate" type="text/html" /><updated>2026-02-27T17:50:10+00:00</updated><id>https://marco-c.github.io/feed.xml</id><title type="html">Marco Castelluccio</title><author><name>Marco Castelluccio</name></author><entry><title type="html">Implementing form filling and accessibility in the Firefox PDF viewer</title><link href="https://marco-c.github.io/2021/10/07/implementing-form-filling-and-accessibility-in-the-firefox-pdf-viewer.html" rel="alternate" type="text/html" title="Implementing form filling and accessibility in the Firefox PDF viewer" /><published>2021-10-07T00:00:00+00:00</published><updated>2021-10-07T00:00:00+00:00</updated><id>https://marco-c.github.io/2021/10/07/implementing-form-filling-and-accessibility-in-the-firefox-pdf-viewer</id><content type="html" xml:base="https://marco-c.github.io/2021/10/07/implementing-form-filling-and-accessibility-in-the-firefox-pdf-viewer.html"><![CDATA[]]></content><author><name>Marco Castelluccio</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">bugbug infrastructure: continuous integration, multi-stage deployments, training and production services</title><link href="https://marco-c.github.io/2021/09/20/bugbug-infrastructure.html" rel="alternate" type="text/html" title="bugbug infrastructure: continuous integration, multi-stage deployments, training and production services" /><published>2021-09-20T00:00:00+00:00</published><updated>2021-09-20T00:00:00+00:00</updated><id>https://marco-c.github.io/2021/09/20/bugbug-infrastructure</id><content type="html" xml:base="https://marco-c.github.io/2021/09/20/bugbug-infrastructure.html"><![CDATA[<p><a href="https://github.com/mozilla/bugbug">bugbug</a> started as a project <a href="https://marco-c.github.io/2019/01/18/bugbug.html">to automatically assign a type to bugs</a> (defect vs enhancement vs task, back when we introduced the “type” we needed a way to fill it for already existing bugs), and then evolved to be a platform to build ML models on bug reports: we now have many models, some of which are being used on Bugzilla, e.g. to assign a type, <a href="https://hacks.mozilla.org/2019/04/teaching-machines-to-triage-firefox-bugs/">to assign a component</a>, to close bugs detected as spam, to detect “regression” bugs, and so on.</p>

<p>Then, it evolved to be a platform to build ML models for generic software engineering purposes: we now no longer only have models that operate on bug reports, but also on test data, patches/commits (e.g. <a href="https://hacks.mozilla.org/2020/07/testing-firefox-more-efficiently-with-machine-learning/">to choose which tests to run for a given patch</a> and to evaluate the regression riskiness associated to a patch), and so on.</p>

<p>Its infrastructure also evolved over time and slowly became more complex. This post attempts to clarify its overall infrastructure, composed of multiple pipelines and multi-stage deployments.</p>

<p>The nice aspect of the continuous integration, deployment and production services of bugbug is that almost all of them are running completely on Taskcluster, with a common language to define tasks, resources, and so on.</p>

<p>In bugbug’s case, I consider a release as a code artifact (source code at a given tag in our repo) plus the ML models that were trained with that code artifact and the data that was used to train them.
This is because the results of a given model are influenced by all these aspects, not just the code as in other kinds of software.
Thus, in the remainder of this post, I will refer to “code artifact” or “code release” when talking about a new version of the source code, and to “release” when talking about a set of artifacts that were built with a specific snapshot (version) of the source code and with a specific snapshot of the data.</p>

<p>The overall infrastructure can be seen in this flowchart, where the nodes represent artifacts and the subgraphs represent the set of operations performed on them. The following sections of the blog post will then describe the components of the flowchart in more detail.
<img src="/assets/bugbug_infrastructure.svg" alt="Flowchart of the bugbug infrastructure" /></p>

<h3 id="continuous-integration-and-first-stage-training-pipeline-deployment">Continuous Integration and First Stage (Training Pipeline) Deployment</h3>

<p>Every pull request and push to the repository triggers <a href="https://github.com/mozilla/bugbug/blob/6e14270/.taskcluster.yml">a pipeline of Taskcluster</a> tasks to:</p>
<ul>
  <li>run tests for the library and its linked HTTP service;</li>
  <li>run static analysis and linting;</li>
  <li>build Python packages;</li>
  <li>build the frontend;</li>
  <li>build Docker images.</li>
</ul>

<p>Code releases are represented by tags. A push of a tag triggers additional tasks that perform:</p>
<ul>
  <li>integration tests;</li>
  <li>push of Docker images to DockerHub;</li>
  <li>release of a new version of the Python package on PyPI;</li>
  <li>update of the training pipeline definition.</li>
</ul>

<p>After a code release, the training pipeline which performs ML training is updated, but the HTTP service, the frontend and all the production pipelines that depend on the trained ML models (the actual release) are still on the previous version of the code (since they can’t be updated until the new models are trained).</p>

<h3 id="continuous-training-and-second-stage-ml-model-services-deployment">Continuous Training and Second Stage (ML Model Services) Deployment</h3>

<p>The <a href="https://github.com/mozilla/bugbug/blob/cb23f63/infra/data-pipeline.yml">training pipeline</a> runs on Taskcluster as a hook that is either triggered manually or on a cron.</p>

<p>The training pipeline consists of many tasks that:</p>
<ul>
  <li>retrieve data from multiple sources (version control system, bug tracking systems, Firefox CI, etc.);</li>
  <li>generation of intermediate artifacts that are used by later stages of the pipeline or by other pipelines or other services;</li>
  <li>training of ML models using the above (there are also training tasks that depend on other models to be trained and run first to generate intermediate artifacts);</li>
  <li>check training metrics to ensure there are no short term or long term regressions;</li>
  <li>run integration tests with the trained models;</li>
  <li>build Docker images with the trained models;</li>
  <li>push Docker images with the trained models;</li>
  <li>update the production pipelines definition.</li>
</ul>

<p>After a run of the training pipeline, the HTTP service and all the production pipelines are updated to the latest version of the code (if they weren’t already) and to the last version of the trained models.</p>

<h3 id="production-pipelines">Production pipelines</h3>

<p>There are multiple production pipelines (<a href="https://github.com/mozilla/bugbug/blob/2cad435/infra/landings-pipeline.yml">here’s an example</a>), that serve different objectives, all running on Taskcluster and triggered either on cron or by pulse messages from other services.</p>

<h3 id="frontend">Frontend</h3>

<p>The bugbug UI lives at <a href="https://changes.moz.tools/">https://changes.moz.tools/</a>, and it is simply a static frontend built in one of the production pipelines defined in Taskcluster.</p>

<p>The production pipeline performs a build and uploads the artifact to S3 via Taskcluster, which is then exposed at the URL mentioned earlier.</p>

<h3 id="http-service">HTTP Service</h3>

<p>The HTTP service is the only piece of the infrastructure that is not running on Taskcluster, but currently on Heroku.</p>

<p>The Docker images for the service are built as part of the training pipeline in Taskcluster, the trained ML models are included in the Docker images themselves. This way, it is possible to rollback to an earlier version of the code and models, should a new one present a regression.</p>

<p>There is one web worker that answers to requests from users, and multiple background workers that perform ML model evaluations. These must be done in the background because of performance reasons (the web worker must answer quickly). The ML evaluations themselves are quick, and so could be directly done in the web worker, but the input data preparation can be slow as it requires interaction with external services such as Bugzilla or a remote Mercurial server.</p>]]></content><author><name>Marco Castelluccio</name></author><category term="machine-learning" /><summary type="html"><![CDATA[bugbug started as a project to automatically assign a type to bugs (defect vs enhancement vs task, back when we introduced the “type” we needed a way to fill it for already existing bugs), and then evolved to be a platform to build ML models on bug reports: we now have many models, some of which are being used on Bugzilla, e.g. to assign a type, to assign a component, to close bugs detected as spam, to detect “regression” bugs, and so on.]]></summary></entry><entry><title type="html">On code coverage and regressions</title><link href="https://marco-c.github.io/2021/04/14/on-coverage-and-regressions.html" rel="alternate" type="text/html" title="On code coverage and regressions" /><published>2021-04-14T00:00:00+00:00</published><updated>2021-04-14T00:00:00+00:00</updated><id>https://marco-c.github.io/2021/04/14/on-coverage-and-regressions</id><content type="html" xml:base="https://marco-c.github.io/2021/04/14/on-coverage-and-regressions.html"><![CDATA[<p>There are two schools of thought when it comes to code coverage: those who think it is a useless metric and those who think the opposite (OK, I’m a bit exaggerating, there are people in the middle…).</p>

<p>I belong to the second “school”: I have always thought, intuitively, that patches without tests are more likely to cause postrelease regressions, and so having test coverage decreases risk.</p>

<p>A few days ago, I set out to confirm this intuition, and I found this interesting study: <a href="https://hal.inria.fr/hal-01653728/document">Code Coverage and Postrelease Defects: A Large-Scale Study on Open Source Projects</a>.</p>

<p>The authors showed (on projects that are very different from Firefox, but still…) that <strong>there was no correlation between project coverage and the amount of bugs that are introduced in the project</strong> and, more importantly, <strong>there was no correlation between file coverage and the amount of bugs that are introduced in the file</strong>.</p>

<h3 id="file-coverage-vs-patch-coverage">File coverage vs Patch coverage</h3>

<p>So, it seemed to show coverage is not a good predictor at all. I thought though: we are not as interested in existing bugs as we are interested in not introducing new ones. The study showed a file with high coverage has a similar possibility of having bugs than a file with low coverage, but… What happens if we look at things at the patch level?</p>

<p>Maybe those files are covered just incidentally (because their functions are called while running tests for other related files), but the tests were not specifically designed for them.</p>

<p>Maybe the tests were written hastily when those files got introduced, and so they are already full of bugs.</p>

<p>What about if we look instead at whether there is a correlation between patch coverage and the number of regressions that are introduced by those patches?</p>

<p>Of course, correlation is not causation, but we can at least make the case that, when new code is not automatically tested, we should be more careful and review it in more detail, or increase manual testing, or delay it to a new release to get more beta testing.</p>

<h3 id="data-collection">Data collection</h3>

<p>Over the past few years, we have been collecting coverage data about Firefox patches.</p>

<p>It is not fully complete, as it doesn’t include Mac, it doesn’t include all possible Firefox configurations (e.g. Fission) and some languages like Python, but it does include the languages we use the most (JavaScript, C/C++, Rust), and it includes Linux and Windows (considering that a lot of Firefox code is cross-platform, I don’t see the missing Mac as a big limitation).</p>

<p>This means that we excluded the portions of the patches that touch Mac-specific code, Python code, etc., from the analysis.</p>

<p>I collected the data using <a href="https://github.com/mozilla/bugbug">bugbug</a> and set out to explore it. I got 10938 clean patches, and 2212 buggy ones.</p>

<h3 id="box-plots-of-bug-introducing-vs-clean-patch-code-coverage">Box plots of bug-introducing vs clean patch code coverage</h3>

<p>First, I plotted the data using a box plot:</p>
<figure>
  <img src="/assets/coverage_regressions_box_plot.png" alt="Box plots of the code coverage for bug-introducing vs clean patches" />
  <figcaption><b>Figure 1:</b> Box plots of the code coverage for bug-introducing vs clean patches.</figcaption>
</figure>

<p>It doesn’t tell me much. The median is higher in the case of “clean” patches though (~92% vs ~87%).</p>

<h3 id="scatter-plot-of-lines-addedcovered-by-bug-introducing-vs-clean-patches">Scatter plot of lines added/covered by bug-introducing vs clean patches</h3>

<p>Then, I plotted a scatter plot with “added lines” as the x-axis, “covered lines” as the y-axis, and color being “clean” or “buggy”. What I expected to find: more “clean” patches than “buggy” ones close to the line <code class="language-plaintext highlighter-rouge">f(added) = covered</code> (that is, covered == added).</p>
<figure>
  <img src="/assets/coverage_regressions_scatter_plot.png" alt="Scatter plot of lines added/covered by bug-introducing vs clean patches" />
  <figcaption><b>Figure 2:</b> Scatter plot of lines added/covered by bug-introducing vs clean patches.</figcaption>
</figure>

<p>There are a lot of outliers, so let’s zoom in a bit:</p>
<figure>
  <img src="/assets/coverage_regressions_scatter_plot_zoomed.png" alt="Zoomed scatter plot of lines added/covered by bug-introducing vs clean patches" />
  <figcaption><b>Figure 3:</b> Zoomed scatter plot of lines added/covered by bug-introducing vs clean patches.</figcaption>
</figure>

<p>It seems to partly match what I expected, but… hard to tell really.</p>

<h3 id="distributions-of-bug-introducing-vs-clean-patch-coverage">Distributions of bug-introducing vs clean patch coverage</h3>

<p>Next step, plotting two empirical distribution functions for the two distributions. These functions show the proportion of patches, in the two distributions, at or above a given level of coverage (e.g. for the distribution of “clean patches”, when x is 0.8, y is 0.4, which means that 80% of clean patches have more than 40% coverage):</p>
<figure>
  <img src="/assets/coverage_regressions_empirical_distribution_function.png" alt="Distributions of bug-introducing vs clean patch coverage" />
  <figcaption><b>Figure 1:</b> Distributions of bug-introducing vs clean patch coverage.</figcaption>
</figure>

<p><strong>Now, we can clearly see that while 45% of clean patches have 100% coverage, only around 25% of buggy patches have 100% coverage.</strong>
The proportion of patches that is between 100% and 80% coverage is similar, but non-buggy patches more often present higher coverage than buggy ones.
There are no meaningful differences for 40% of the patches (from 0.6 to 1.0 in the chart above).</p>

<h3 id="what-i-learned">What I learned</h3>

<p>To summarize, we can see that <strong>there is a correlation between coverage and bug proneness</strong>. In particular, fully covered patches more rarely cause post-release bugs.
Of course, correlation does not mean causation. We can’t tell for sure that writing tests for new code changes will reduce the riskiness of those changes, but we can definitely say that we can increase our attention level when changes are not covered by tests.</p>]]></content><author><name>Marco Castelluccio</name></author><category term="code-coverage" /><summary type="html"><![CDATA[There are two schools of thought when it comes to code coverage: those who think it is a useless metric and those who think the opposite (OK, I’m a bit exaggerating, there are people in the middle…).]]></summary></entry><entry><title type="html">How to collect Rust source-based code coverage</title><link href="https://marco-c.github.io/2020/11/24/rust-source-based-code-coverage.html" rel="alternate" type="text/html" title="How to collect Rust source-based code coverage" /><published>2020-11-24T00:00:00+00:00</published><updated>2020-11-24T00:00:00+00:00</updated><id>https://marco-c.github.io/2020/11/24/rust-source-based-code-coverage</id><content type="html" xml:base="https://marco-c.github.io/2020/11/24/rust-source-based-code-coverage.html"><![CDATA[<p><strong>TL;DR</strong>: For those of you who prefer an example to words, you can find a complete and simple one at <a href="https://github.com/marco-c/rust-code-coverage-sample">https://github.com/marco-c/rust-code-coverage-sample</a>.</p>

<p>Source-based code coverage was <a href="https://github.com/rust-lang/rust/issues/34701#issuecomment-723178087">recently introduced</a> in Rust. It is more precise than the gcov-based coverage, with fewer workarounds needed. Its only drawback is that it makes the profiled program slower than with gcov-based coverage.</p>

<p>In this post, I will show you a simple example on how to set up source-based coverage on a Rust project, and how to generate a report using <a href="https://github.com/mozilla/grcov">grcov</a> (in a readable format or in a JSON format which can be parsed to generate custom reports or upload results to Coveralls/Codecov).</p>

<h3 id="install-requirements">Install requirements</h3>

<p>First of all, let’s install grcov:</p>
<pre style="background-color:black;color:white;">
cargo install grcov
</pre>

<p>Second, let’s install the llvm-tools Rust component (which grcov will use to parse coverage artifacts):</p>
<pre style="background-color:black;color:white;">
rustup component add llvm-tools-preview
</pre>
<p>At the time of writing, the component is called <code class="language-plaintext highlighter-rouge">llvm-tools-preview</code>. It might be renamed to <code class="language-plaintext highlighter-rouge">llvm-tools</code> soon.</p>

<h3 id="build">Build</h3>
<p>Let’s say we have a simple project, where our main.rs is:</p>

<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">fmt</span><span class="p">::</span><span class="n">Debug</span><span class="p">;</span>

<span class="nd">#[derive(Debug)]</span>
<span class="k">pub</span> <span class="k">struct</span> <span class="n">Ciao</span> <span class="p">{</span>
    <span class="k">pub</span> <span class="n">saluto</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="p">}</span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">ciao</span> <span class="o">=</span> <span class="n">Ciao</span><span class="p">{</span> <span class="n">saluto</span><span class="p">:</span> <span class="nn">String</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="s">"salve"</span><span class="p">)</span> <span class="p">};</span>

    <span class="nd">assert!</span><span class="p">(</span><span class="n">ciao</span><span class="py">.saluto</span> <span class="o">==</span> <span class="s">"salve"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>In order to make Rust generate an instrumented binary, we need to use the <code class="language-plaintext highlighter-rouge">-Zinstrument-coverage</code> flag (Nightly only for now!):</p>
<pre style="background-color:black;color:white;">
export RUSTFLAGS="-Zinstrument-coverage"
</pre>

<p>Now, build with <code class="language-plaintext highlighter-rouge">cargo build</code>.</p>

<p>The compiled instrumented binary will appear under target/debug/:</p>
<pre style="background-color:black;color:white;">
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    └── debug
        └── rust-code-coverage-sample
</pre>

<p>The instrumented binary contains information about the structure of the source file (functions, branches, basic blocks, and so on).</p>

<h3 id="run">Run</h3>
<p>Now, the instrumented executable can be executed (<code class="language-plaintext highlighter-rouge">cargo run</code>, <code class="language-plaintext highlighter-rouge">cargo test</code>, or whatever). A new file with the extension ‘profraw’ will be generated. It contains the coverage counters associated with your binary file (how many times a line was executed, how many times a branch was taken, and so on). You can define your own name for the output file (might be necessary in some complex test scenarios like we have on grcov) using the <code class="language-plaintext highlighter-rouge">LLVM_PROFILE_FILE</code> environment variable.</p>

<pre style="background-color:black;color:white;">
LLVM_PROFILE_FILE="your_name-%p-%m.profraw"
</pre>
<p>%p (process ID) and %m (binary signature) are useful to make sure each process and each binary has its own file.</p>

<p>Your tree will now look like this:</p>
<pre style="background-color:black;color:white;">
.
├── Cargo.lock
├── Cargo.toml
├── default.profraw
├── src
│   └── main.rs
└── target
    └── debug
        └── rust-code-coverage-sample
</pre>

<p>At this point, we just need a way to parse the profraw file and the associated information from the binary.</p>

<h3 id="parse-with-grcov">Parse with grcov</h3>
<p><a href="https://github.com/mozilla/grcov">grcov</a> can be downloaded from GitHub (<a href="https://github.com/mozilla/grcov/releases">from the Releases page</a>).</p>

<p>Simply execute grcov in the root of your repository, with the <code class="language-plaintext highlighter-rouge">--binary-path</code> option pointing to the directory containing your binaries (e.g. <code class="language-plaintext highlighter-rouge">./target/debug</code>). The <code class="language-plaintext highlighter-rouge">-t</code> option allows you to specify the output format:</p>
<ul>
  <li>“html” for a HTML report;</li>
  <li>“lcov” for the LCOV format, which you can then translate to a HTML report using genhtml;</li>
  <li>“coveralls” for a JSON format compatible with Coveralls/Codecov;</li>
  <li>“coveralls+” for an extension of the former, with addition of function information.
There are <a href="https://github.com/mozilla/grcov#alternative-reports">other formats</a> too.</li>
</ul>

<p>Example:</p>
<pre style="background-color:black;color:white;">
grcov . --binary-path PATH_TO_YOUR_BINARIES_DIRECTORY -s . -t html --branch --ignore-not-existing -o ./coverage/
</pre>

<p>This is the output:</p>
<iframe src="/assets/source_based_coverage/src/main.rs.html" width="100%" height="300">
  <p>Your browser does not support iframes.</p>
</iframe>

<p>This would be the output with gcov-based coverage:</p>
<iframe src="/assets/gcov_coverage/src/main.rs.html" width="100%" height="300">
  <p>Your browser does not support iframes.</p>
</iframe>

<p>You can also run grcov outside of your repository, you just need to pass the path to the directory where the profraw files are and the directory where the source is (normally they are the same, but if you have a complex CI setup like we have at Mozilla, they might be totally separate):</p>
<pre style="background-color:black;color:white;">
grcov PATHS_TO_PROFRAW_DIRECTORIES --binary-path PATH_TO_YOUR_BINARIES_DIRECTORY -s PATH_TO_YOUR_SOURCE_CODE -t html --branch --ignore-not-existing -o ./coverage/
</pre>

<p>grcov has other options too, simply run it with no parameters to list them.</p>

<p>In the <a href="https://github.com/mozilla/grcov#grcov-with-travis">grcov’s docs</a>, there are also examples on how to integrate code coverage with some CI services.</p>]]></content><author><name>Marco Castelluccio</name></author><category term="code-coverage" /><summary type="html"><![CDATA[TL;DR: For those of you who prefer an example to words, you can find a complete and simple one at https://github.com/marco-c/rust-code-coverage-sample.]]></summary></entry><entry><title type="html">Testing Firefox more efficiently with machine learning</title><link href="https://marco-c.github.io/2020/07/09/testing-firefox-more-efficiently-with-machine-learning.html" rel="alternate" type="text/html" title="Testing Firefox more efficiently with machine learning" /><published>2020-07-09T00:00:00+00:00</published><updated>2020-07-09T00:00:00+00:00</updated><id>https://marco-c.github.io/2020/07/09/testing-firefox-more-efficiently-with-machine-learning</id><content type="html" xml:base="https://marco-c.github.io/2020/07/09/testing-firefox-more-efficiently-with-machine-learning.html"><![CDATA[]]></content><author><name>Marco Castelluccio</name></author><category term="machine-learning" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Teaching machines to triage Firefox bugs</title><link href="https://marco-c.github.io/2019/04/09/teaching-machines-to-triage-firefox-bugs.html" rel="alternate" type="text/html" title="Teaching machines to triage Firefox bugs" /><published>2019-04-09T00:00:00+00:00</published><updated>2019-04-09T00:00:00+00:00</updated><id>https://marco-c.github.io/2019/04/09/teaching-machines-to-triage-firefox-bugs</id><content type="html" xml:base="https://marco-c.github.io/2019/04/09/teaching-machines-to-triage-firefox-bugs.html"><![CDATA[]]></content><author><name>Marco Castelluccio</name></author><category term="machine-learning" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Code Coverage on Phabricator</title><link href="https://marco-c.github.io/2019/01/21/code-coverage-phabricator.html" rel="alternate" type="text/html" title="Code Coverage on Phabricator" /><published>2019-01-21T00:00:00+00:00</published><updated>2019-01-21T00:00:00+00:00</updated><id>https://marco-c.github.io/2019/01/21/code-coverage-phabricator</id><content type="html" xml:base="https://marco-c.github.io/2019/01/21/code-coverage-phabricator.html"><![CDATA[<p>We have recently implemented a solution to integrate code coverage results into Phabricator.</p>

<p>Coverage information is uploaded either automatically for revisions after they are landed in mozilla-central (for example for release managers when looking at uplift requests), or on-demand for in-progress revisions.</p>

<p>For revisions under review, in order to upload coverage you just need to trigger a try push containing code coverage builds and tests, e.g. by using:</p>
<pre style="background-color:black;color:white;">
$ mach try fuzzy --full
</pre>
<p>and selecting the relevant ccov builds and test suites. In the future, we will also likely automatically trigger coverage try builds for revisions we deem to be risky, alongside the on-demand option.</p>

<p>Here is an example of a <a href="https://treeherder.mozilla.org/#/jobs?repo=try&amp;revision=38213b49dc00cd108dfa9a246045ed677c34de91">try build</a> which produced the coverage information for <a href="https://phabricator.services.mozilla.com/D14758">my revision</a>:</p>
<figure>
  <img src="/assets/code-coverage-on-phabricator-try-build.png" alt="Try build which produced the coverage information" />
  <figcaption><b>Figure 1:</b> Try build which produced the coverage information.</figcaption>
</figure>

<p>Once the try build and linked tests finish, the coverage artifacts get parsed and uploaded to the Phabricator revisions corresponding to the commits in the try push. The analysis works on <em>all</em> commits in the try push that are linked to Phabricator revisions. Stacks of revisions are supported as well.</p>

<p>The coverage information is shown on Phabricator both at a high-level view, in the <em>Revision Contents</em> section, and at a detailed view in the <em>Diff</em> section.</p>

<p>The <em>Revision Contents</em> section contains a list of the files modified by the revision, showing both the coverage percentage of the whole file and the coverage percentage of touched lines. Here’s the screenshot of the section from my revision:</p>
<figure>
  <img src="/assets/code-coverage-on-phabricator-revision-contents.png" alt="Code coverage summary in the 'Revision Contents' section on Phabricator" />
  <figcaption><b>Figure 2:</b> Code coverage summary in the 'Revision Contents' section on Phabricator.</figcaption>
</figure>

<p>The <em>Diff</em> section instead shows the coverage line per line, coloring the bar on the right-hand side. <span style="color:#d86"><strong>Orange</strong></span> corresponds to <span style="color:#d86"><strong>uncovered lines</strong></span>, <span style="color:#def"><strong>light blue</strong></span> corresponds to <span style="color:#def"><strong>non-executable lines</strong></span> (e.g. a comment, a definition, and so on), <span style="color:#6bf"><strong>dark blue</strong></span> corresponds to <span style="color:#6bf"><strong>covered lines</strong></span>. When hovering the bar, the corresponding line is highlighted in the same color.
The following screenshots show excerpts of my revision, with covered, uncovered and non-executable lines:</p>

<figure>
  <img src="/assets/code-coverage-on-phabricator-covered-line.png" alt="Example of an added line which was covered by tests" />
  <figcaption><b>Figure 3:</b> Example of an added line which was covered by tests.</figcaption>
</figure>

<figure>
  <img src="/assets/code-coverage-on-phabricator-uncovered-line.png" alt="Example of a line which was not covered by tests" />
  <figcaption><b>Figure 4:</b> Example of a line which was not covered by tests.</figcaption>
</figure>]]></content><author><name>Marco Castelluccio</name></author><category term="code-coverage" /><summary type="html"><![CDATA[We have recently implemented a solution to integrate code coverage results into Phabricator.]]></summary></entry><entry><title type="html">“It’s not a bug, it’s a feature.” - Differentiating between bugs and non-bugs using machine learning</title><link href="https://marco-c.github.io/2019/01/18/bugbug.html" rel="alternate" type="text/html" title="“It’s not a bug, it’s a feature.” - Differentiating between bugs and non-bugs using machine learning" /><published>2019-01-18T00:00:00+00:00</published><updated>2019-01-18T00:00:00+00:00</updated><id>https://marco-c.github.io/2019/01/18/bugbug</id><content type="html" xml:base="https://marco-c.github.io/2019/01/18/bugbug.html"><![CDATA[<p><a href="https://bugzilla.mozilla.org">Bugzilla</a> is a noisy data source: bugs are used to track anything, from <em>Create a LDAP account for contributor X</em> to <em>Printing page Y doesn’t work</em>. This makes it hard to know which bugs are bugs and which bugs are not bugs but e.g. feature requests, or meta bugs, or refactorings, and so on. To ease reading the next paragraphs, I’ll refer as <code class="language-plaintext highlighter-rouge">bugbug</code> to bugs that are actually bugs, as <code class="language-plaintext highlighter-rouge">fakebug</code> to bugs that are not actually bugs, and as <code class="language-plaintext highlighter-rouge">bug</code> to all Bugzilla bugs (<code class="language-plaintext highlighter-rouge">bugbug</code> + <code class="language-plaintext highlighter-rouge">fakebug</code>).</p>

<p>Why do we need to tell if a bug is actually a bug? There are several reasons, the main two being:</p>
<ul>
  <li><strong>Quality metrics</strong>: to analyze the quality of a project, to measure the churn of a given release, it can be useful to know, for example, how many bugbugs are filed in a given release cycle. If we don’t know which bugs are bugbugs and which are feature requests, we can’t precisely measure how many problems are found (= bugbugs filed) in a given component for a given release, we can only know the overall number, confusing bugbugs and feature work;</li>
  <li><strong>Bug prediction</strong>: given the development history of the project, one can try to predict, with some measure of accuracy, which changes are risky and more likely to lead to regressions in the future. In order to do that, of course, you need to know which changes introduced problems in the past. If you can’t identify problems (i.e. bugbugs), then you can’t identify changes that introduced them!</li>
</ul>

<p>On BMO, we have some optional keywords to identify regressions vs features, but they are not used consistently (and, being optional, they can’t be. We can work on improving the practices, but we can’t reach perfection when there is human involvement). So, we need another way to identify them. A possibility is to use handwritten rules (‘<em>mozregression</em>’ in comment → regression; ‘<em>support</em>’ in title → feature), which can be precise up to a certain accuracy level, but any improvement over that requires hard manual labor. Another option is to use machine learning techniques, leaving the hard work of extracting information from bug features to the machines!</p>

<p>The <strong><a href="https://github.com/mozilla/bugbug">bugbug project</a></strong> is trying to do just that, at first with a very simple ML architecture.</p>

<p>We have a set of 1913 bugs, manually labelled between the two possible classes (bugbug vs nobug). We augment this manually labelled set with Bugzilla bugs containing the keywords ‘regression’ or ‘feature’, which are basically labelled already.
The augmented data set contains 10818 bugs. Unfortunately we can’t use all of them indistinctly, as the dataset is unbalanced towards bugbugs, which would skew the results of the classifier, so we simply perform random under-sampling to reduce the number of bugbug examples.
In the end, we have 1928 bugs.</p>

<p>We split the dataset into a training set of 1735 bugs and a test set of 193 bugs (90% - 10%).</p>

<p>We extract features both from bug fields (such as keywords, number of attachments, presence of a crash signature, and so on), bug title and comments.</p>

<p>To extract features from text (title and comments), we use a simple <a href="https://en.wikipedia.org/wiki/Bag-of-words_model">BoW model</a> with 1-grams, using <a href="https://en.wikipedia.org/wiki/Tf%E2%80%93idf">TF-IDF</a> to lower the importance of very common words in the corpus and stop word removal mainly to speed up the training phase (stop word removal should not be needed for accuracy in our case since we are using a gradient boosting model, but it can speed up the training phase and it eases experimenting with other models which would really need it).</p>

<p>We are then training a gradient boosting model (these models usually work quite well for shallow features) on top of the extracted features.</p>

<figure>
  <img src="/assets/bugbug_model.svg" alt="Architecture view" />
  <figcaption><b>Figure 1</b>: A high-level overview of the architecture.</figcaption>
</figure>

<p>This very simple approach, in a handful of lines of code, achieves ~93% accuracy. There’s a lot of room for improvement in the algorithm (it was, after all, written in a few hours…), so I’m confident we can get even better results.</p>

<p>This is just the first step: in the near future we are going to implement improvements in Bugzilla directly and in linked tooling so that we can stop guessing and have very accurate data.</p>

<p>Since the inception of bugbug, we have also added additional experimental models for other related problems (e.g. detecting if a bug is a good candidate for tracking, or predicting the component of a bug), turning bugbug into a platform for quickly building and experimenting with new machine learning applications on Bugzilla data (and maybe soon VCS data too). We have many other ideas to implement, if you are interested take a look at the open issues on our repo!</p>]]></content><author><name>Marco Castelluccio</name></author><category term="machine-learning" /><summary type="html"><![CDATA[Bugzilla is a noisy data source: bugs are used to track anything, from Create a LDAP account for contributor X to Printing page Y doesn’t work. This makes it hard to know which bugs are bugs and which bugs are not bugs but e.g. feature requests, or meta bugs, or refactorings, and so on. To ease reading the next paragraphs, I’ll refer as bugbug to bugs that are actually bugs, as fakebug to bugs that are not actually bugs, and as bug to all Bugzilla bugs (bugbug + fakebug).]]></summary></entry><entry><title type="html">Searchfox in Phabricator extension</title><link href="https://marco-c.github.io/2018/10/18/searchfox-in-phabricator.html" rel="alternate" type="text/html" title="Searchfox in Phabricator extension" /><published>2018-10-18T00:00:00+00:00</published><updated>2018-10-18T00:00:00+00:00</updated><id>https://marco-c.github.io/2018/10/18/searchfox-in-phabricator</id><content type="html" xml:base="https://marco-c.github.io/2018/10/18/searchfox-in-phabricator.html"><![CDATA[<p>Being able to search code while reviewing can be really useful, but unfortunately it’s not so straightforward. Many people resort to loading the patch under review in an IDE in order to be able to search code.</p>

<p>Being able to do it directly in the browser can make the workflow much smoother.</p>

<p>To support this use case, I’ve built an extension for Phabricator that integrates <a href="https://searchfox.org/">Searchfox</a> code search functionality directly in Phabricator differentials. This way reviewers can benefit from <strong>hovers</strong>, <strong>go-to-definition</strong> and <strong>find-references</strong> without having to resort to the IDE or without having to manually navigate to the code on searchfox.org or dxr.mozilla.org. Moreover, compared to searchfox.org or dxr.mozilla.org, the extension highlights both the pre-patch view and the post-patch view, so reviewers can see how pre-existing variables/functions are being used after the patch.</p>

<p>To summarize, the features of the extension currently are:</p>
<ol>
  <li>Highlight keywords when you hover them, highlighting them both in the pre-patch and in the post-patch view;</li>
  <li>When you press on a keyword, it offers options to search for the definition, callers, and so on (the results are opened on Searchfox in a new tab).</li>
</ol>

<p>Here’s a screenshot from the extension in action:</p>
<figure>
  <img src="/assets/phabricator-mozsearch-addon.png" alt="Screenshot of Searchfox in Phabricator" />
  <figcaption><b>Figure 1</b>: Screenshot of Searchfox in Phabricator.</figcaption>
</figure>

<p>I’m planning to add support for sticky highlighting and blame information (when hovering on the line number on the left side). 
Indeed, being able to look at the past history of a line is another sought after feature by reviewers.</p>

<p>You can find the extension on AMO, at <a href="https://addons.mozilla.org/addon/searchfox-phabricator/">https://addons.mozilla.org/addon/searchfox-phabricator/</a>.</p>

<p>The source code, admittedly not great as it was written as an experiment, lives at <a href="https://github.com/marco-c/mozsearch-phabricator-addon">https://github.com/marco-c/mozsearch-phabricator-addon</a>.</p>

<p>Should you find any issues, please file them on <a href="https://github.com/marco-c/mozsearch-phabricator-addon/issues">https://github.com/marco-c/mozsearch-phabricator-addon/issues</a>.</p>]]></content><author><name>Marco Castelluccio</name></author><category term="review" /><summary type="html"><![CDATA[Being able to search code while reviewing can be really useful, but unfortunately it’s not so straightforward. Many people resort to loading the patch under review in an IDE in order to be able to search code.]]></summary></entry><entry><title type="html">Using requestIdleCallback for long running computations</title><link href="https://marco-c.github.io/2018/10/16/using-requestidlecallback-for-long-running-computations.html" rel="alternate" type="text/html" title="Using requestIdleCallback for long running computations" /><published>2018-10-16T00:00:00+00:00</published><updated>2018-10-16T00:00:00+00:00</updated><id>https://marco-c.github.io/2018/10/16/using-requestidlecallback-for-long-running-computations</id><content type="html" xml:base="https://marco-c.github.io/2018/10/16/using-requestidlecallback-for-long-running-computations.html"><![CDATA[<p>One of the ways developers have tipically tried to keep a smooth web application, without interfering with the browser’s animation and response to input, is to use a Web Worker for long running computations. For example, in the Prism.js (a library for syntax highlighting) API there’s an <code class="language-plaintext highlighter-rouge">async</code> parameter to choose <cite>“Whether to use Web Workers to improve performance and avoid blocking the UI when highlighting very large chunks of code”</cite>.</p>

<p>This is perfectly fine, but web workers are not so easy to use or debug. To take Prism.js again as an example, the option I mentioned earlier is false by default. Why?</p>
<blockquote>
  <p>In most cases, you will want to highlight reasonably sized chunks of code, and this will not be needed. Furthermore, using Web Workers is actually slower than synchronously highlighting, due to the overhead of creating and terminating the Worker. It just appears faster in these cases because it doesn’t block the main thread. In addition, since Web Workers operate on files instead of objects, plugins that hook on core parts of Prism (e.g. modify language definitions) will not work unless included in the same file (using the builder in the Download page will protect you from this pitfall). Lastly, Web Workers cannot interact with the DOM and most other APIs (e.g. the console), so they are notoriously hard to debug.”</p>
</blockquote>

<p>Another alternative to achieve the same result, without using Web Workers and making things more difficult, is to use <a href="https://developer.mozilla.org/docs/Web/API/Window/requestIdleCallback">requestIdleCallback</a>. This function allows a callback to be scheduled when the browser is idle, enabling us to perform background work / low priority work on the main thread without impacting animations / input response. N.B.: This will still be slower than synchronous, but might be cheaper than a Web Worker since you don’t have to pay the price of the Worker initialization.</p>

<p>Here’s an example, using <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise">promises</a> and <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function">asynchronous functions</a> we can also avoid callback hell and keep using normal loops.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">idle</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="nx">resolve</span> <span class="o">=&gt;</span> <span class="nx">requestIdleCallback</span><span class="p">(</span><span class="nx">resolve</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nx">work</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">let</span> <span class="nx">deadline</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">idle</span><span class="p">();</span>

  <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">job</span> <span class="k">of</span> <span class="nx">jobs</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">deadline</span><span class="p">.</span><span class="nx">timeRemaining</span><span class="p">()</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">deadline</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">idle</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">// Do something with `job`...</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>I’m doing something similar in my <a href="https://addons.mozilla.org/it/firefox/addon/searchfox-phabricator/">Searchfox in Phabricator extension</a>, to operate on one source line at a time and avoid slowing down the normal Phabricator operation. <a href="https://github.com/marco-c/mozsearch-phabricator-addon/blob/9cc24d3d104940863aed1adf417ad41b8aaffdfe/phabricator.js#L161">Here’s where I’m doing it</a>.</p>]]></content><author><name>Marco Castelluccio</name></author><category term="javascript" /><summary type="html"><![CDATA[One of the ways developers have tipically tried to keep a smooth web application, without interfering with the browser’s animation and response to input, is to use a Web Worker for long running computations. For example, in the Prism.js (a library for syntax highlighting) API there’s an async parameter to choose “Whether to use Web Workers to improve performance and avoid blocking the UI when highlighting very large chunks of code”.]]></summary></entry></feed>