<?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: BamPeers</title>
    <description>The latest articles on DEV Community by BamPeers (@bampeers).</description>
    <link>https://dev.to/bampeers</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%2Forganization%2Fprofile_image%2F4016%2F8c7867d4-4c78-45dd-988b-c9348a7919f0.png</url>
      <title>DEV Community: BamPeers</title>
      <link>https://dev.to/bampeers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bampeers"/>
    <language>en</language>
    <item>
      <title>Rust CI with GitHub Actions</title>
      <dc:creator>Candy</dc:creator>
      <pubDate>Sun, 09 May 2021 07:38:20 +0000</pubDate>
      <link>https://dev.to/bampeers/rust-ci-with-github-actions-1ne9</link>
      <guid>https://dev.to/bampeers/rust-ci-with-github-actions-1ne9</guid>
      <description>&lt;p&gt;CI(Continuous Integration) is a concept that would interest most developers in a collaborative environment. CI automates the post-coding process of building and testing rather than doing it manually.&lt;/p&gt;

&lt;p&gt;Through CI, developers can smoothly integrate their code with other people’s code. This allows developers to focus on coding without wasting their time on integration, which in turn increases productivity.&lt;/p&gt;

&lt;p&gt;However, setting up CI can be troublesome and time-consuming, so developers have to decide the extent their CI process will cover.&lt;/p&gt;

&lt;p&gt;In our case, we implemented a CI workflow for the Rust projects on GitHub Actions which includes linting, testing, code coverage reporting on CodeCov, and building for release.&lt;/p&gt;

&lt;p&gt;Through this article, we hope you can have an easier time implementing CI for your Rust projects. &lt;/p&gt;

&lt;h1&gt;
  
  
  Related Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;: A feature on GitHub that allows users to &lt;em&gt;act(run a script)&lt;/em&gt; on event triggers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/actions-rs" rel="noopener noreferrer"&gt;action-rs&lt;/a&gt;: A collection of commonly used GitHub Actions for Rust projects&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.codecov.io" rel="noopener noreferrer"&gt;CodeCov&lt;/a&gt;: A service that visualizes code coverage reports&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;

&lt;p&gt;Example project using the workflow is uploaded in: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/BamPeers" rel="noopener noreferrer"&gt;
        BamPeers
      &lt;/a&gt; / &lt;a href="https://github.com/BamPeers/rust-ci-github-actions-workflow" rel="noopener noreferrer"&gt;
        rust-ci-github-actions-workflow
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Rust project template with CI workflow in GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Root Directory
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;.gitignore: A list of files for git to ignore&lt;/li&gt;
&lt;li&gt;Cargo.toml: The manifest file for this cargo package&lt;/li&gt;
&lt;li&gt;README.md: The project manual&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  .github/workflows/
&lt;/h2&gt;

&lt;p&gt;This directory contains the workflow files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check-and-lint.yaml : Workflow for linting the code by running cargo check, fmt, and clippy&lt;/li&gt;
&lt;li&gt;release-packaging.yaml : Workflow for building the file and uploading the result as a downloadable artifact&lt;/li&gt;
&lt;li&gt;test.yaml : Workflow for running tests, measuring code coverage, and uploading respective results to GitHub and CodeCov&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  src/
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;lib.rs : A stub library file that includes an example function and test code&lt;/li&gt;
&lt;li&gt;main.rs : The main executable that runs and prints the result of the function in lib.rs&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Workflows
&lt;/h1&gt;

&lt;p&gt;The following is a simple explanation of the included workflows. Check out our project &lt;a href="https://github.com/BamPeers/rust-ci-github-actions-workflow" rel="noopener noreferrer"&gt;README&lt;/a&gt; for a more detailed explanation.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Check and Lint&lt;/strong&gt; and &lt;strong&gt;Test with Code Coverage&lt;/strong&gt; workflows run on pull requests and on pushing to the main branch. The &lt;strong&gt;Release Packaging&lt;/strong&gt; workflow runs on pushing to the main branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check and Lint (check-and-lint.yaml)
&lt;/h2&gt;

&lt;p&gt;This workflow checks for compiler errors and code style inconsistencies.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Check job&lt;/strong&gt; runs &lt;code&gt;cargo check&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Rustfmt job&lt;/strong&gt; runs &lt;code&gt;cargo fmt --check&lt;/code&gt;. You can add a &lt;code&gt;rustfmt.toml&lt;/code&gt; or &lt;code&gt;.rustfmt.toml&lt;/code&gt; to configure the code style.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Clippy job&lt;/strong&gt; runs &lt;a href="https://github.com/rust-lang/rust-clippy" rel="noopener noreferrer"&gt;clippy&lt;/a&gt; through &lt;a href="https://github.com/actions-rs/clippy-check" rel="noopener noreferrer"&gt;actions-rs/clippy-check@v1&lt;/a&gt;.&lt;br&gt;
You can add a &lt;code&gt;clippy.toml&lt;/code&gt; or &lt;code&gt;.clippy.toml&lt;/code&gt; to configure the style.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test with Code Coverage (test.yaml)
&lt;/h2&gt;

&lt;p&gt;This workflow runs tests, outputs test results, and publishes code coverage results on &lt;a href="https://codecov.io/" rel="noopener noreferrer"&gt;CodeCov&lt;/a&gt;.&lt;br&gt;
Publishing test results and code coverage data is done in one job to avoid running the tests twice.&lt;/p&gt;

&lt;p&gt;The environment variables for the job are set as shown below:&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;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;PROJECT_NAME_UNDERSCORE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rust_ci_github_actions_workflow&lt;/span&gt;
    &lt;span class="na"&gt;CARGO_INCREMENTAL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;RUSTFLAGS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort&lt;/span&gt;
    &lt;span class="na"&gt;RUSTDOCFLAGS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-Cpanic=abort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PROJECT_NAME_UNDERSCORE&lt;/code&gt; environment variable should be replaced with your project name with - as _. Other environment variables are for code coverage.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Test job&lt;/strong&gt;, first, looks for a cache of the dependencies based on the hash of &lt;code&gt;Cargo.lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, it runs &lt;code&gt;cargo test&lt;/code&gt; on nightly Rust and uses &lt;code&gt;cargo2junit&lt;/code&gt; to generate a JUnit format test result. And, it runs &lt;code&gt;grcov&lt;/code&gt; and &lt;code&gt;rust-covfix&lt;/code&gt; to generate proper code coverage data:&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="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 test result and coverage report&lt;/span&gt;
    &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;cargo install cargo2junit grcov rust-covfix;&lt;/span&gt;
        &lt;span class="s"&gt;cargo test --features coverage $CARGO_OPTIONS -- -Z unstable-options --format json | cargo2junit &amp;gt; results.xml;&lt;/span&gt;
        &lt;span class="s"&gt;zip -0 ccov.zip `find . \( -name "$PROJECT_NAME_UNDERSCORE*.gc*" \) -print`;&lt;/span&gt;
        &lt;span class="s"&gt;grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore "/*" --ignore "tests/*" -o lcov.info;&lt;/span&gt;
        &lt;span class="s"&gt;rust-covfix -o lcov_correct.info lcov.info;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test results are uploaded through &lt;a href="https://github.com/EnricoMi/publish-unit-test-result-action" rel="noopener noreferrer"&gt;EnricoMi/publish-unit-test-result-action@v1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Code coverage results are uploaded to CodeCov through &lt;a href="https://github.com/codecov/codecov-action" rel="noopener noreferrer"&gt;codecov/codecov-action@v1&lt;/a&gt;. For private repositories, add your token from CodeCov repository setting to GitHub Secrets and uncomment the line: &lt;code&gt;token: ${{ secrets.CODECOV_TOKEN }}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release Packaging (release-packaging.yaml)
&lt;/h2&gt;

&lt;p&gt;This workflow builds the package in release mode and uploads the resulting file as a GitHub artifact.&lt;/p&gt;

&lt;p&gt;The included job uploads the project binary in &lt;code&gt;target/release&lt;/code&gt; as an artifact through &lt;a href="https://github.com/actions/upload-artifact" rel="noopener noreferrer"&gt;actions/upload-artifact@v2&lt;/a&gt;.&lt;br&gt;
You can configure which files to upload.&lt;/p&gt;

&lt;h1&gt;
  
  
  Outcome
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/BamPeers/rust-ci-github-actions-workflow/pull/1" rel="noopener noreferrer"&gt;Example pull request&lt;/a&gt; with a failing test and clippy warning can be found in our repository. &lt;br&gt;
Any failing job will block merging&lt;/p&gt;

&lt;h2&gt;
  
  
  Clippy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The action outputs result (&lt;strong&gt;Clippy Output&lt;/strong&gt; added to a random workflow).
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmtp0h9an82orf366f5a.png" alt="Screen Shot 2021-05-01 at 6.06.28 PM"&gt;
&lt;/li&gt;
&lt;li&gt;For pull requests, it adds annotations on the diff.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fld7ym1xfiibdqeob3otv.png" alt="Screen Shot 2021-05-01 at 7.43.44 PM"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test Result
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The action outputs the test result (&lt;strong&gt;Test Results&lt;/strong&gt; added to a random workflow).
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe65gc2awy7pc5m9u7rm5.png" alt="Screen Shot 2021-05-01 at 6.05.25 PM"&gt;
&lt;/li&gt;
&lt;li&gt;For pull requests, the action adds a comment containing the test results.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkk2baz1fakm8exu1pqcr.png" alt="Screen Shot 2021-05-01 at 7.00.21 PM"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code coverage
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code coverage results can be seen on your CodeCov repository.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyh4punhp9vzvo45uj78.png" alt="Screen Shot 2021-05-01 at 6.56.49 PM"&gt;
&lt;/li&gt;
&lt;li&gt;For pull requests, the action adds a comment containing the code coverage report.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2rwexgtiw5eala1hu0b.png" alt="Screen Shot 2021-05-01 at 7.00.33 PM"&gt;
&lt;/li&gt;
&lt;li&gt;You can also add a CodeCov badge on your README to display the coverage percentage like we did on ours. It can be found in the &lt;code&gt;Setting &amp;gt; Badge&lt;/code&gt; section of your CodeCov repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Release Packaging
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Artifacts can be downloaded from the Summary tab of the workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GitHub Pull Request Checks
&lt;/h2&gt;

&lt;p&gt;You can set status checks as required for merging in &lt;code&gt;Settings &amp;gt; Branches &amp;gt; Branch protection rules&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06j2mfk60rpz142jn70c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06j2mfk60rpz142jn70c.png" alt="Screen Shot 2021-05-01 at 7.47.38 PM"&gt;&lt;/a&gt;&lt;br&gt;
When one or more jobs fail, the PR merge box will look something like below:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6hhkf0batw7un4pbpzzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6hhkf0batw7un4pbpzzh.png" alt="Screen Shot 2021-05-01 at 7.46.21 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We introduced CI for our Rust project through GitHub Actions. With this, the lint-build-test(+code coverage) process starts automatically when we push our code. &lt;/p&gt;

&lt;p&gt;Questions and suggestions are welcome in the comment section.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>githubactions</category>
      <category>ci</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
